The asset sync fetched active agents only, and the sync-driven reconcile inactivates every agent id the sync does not report. Since INACTIVE assets are hidden from every CVE view, a host that was merely switched off lost all its findings at the next sync — while Wazuh itself kept listing the agent and its vulnerabilities. Holiday, sick leave or a spare laptop in a drawer looked exactly like a decommissioned machine. Root cause confirmed: not the 30-day soft-inactive window (which never got a chance to apply here), but the connection-state filter feeding seen_ids. - sync fetches ALL agents, paginated; disconnected ones stay in seen_ids - last_seen now carries Wazuh's lastKeepAlive instead of "when we synced", so there is a real stamp to measure against - per-agent status comes from status_for_last_seen(): ACTIVE inside the window, INACTIVE outside — replaces the binary connected/disconnected test - reconcile_asset_lifecycle uses max(last_scan, last_seen): a host that keeps checking in but cannot be scanned while offline no longer ages out early - window default 30 -> 42 days, one setting for both paths; migration 044 rewrites only rows still holding the old default - agents registered but never connected are skipped instead of imported tests/test_asset_grace_window.py covers the window edges, UTC keepalive parsing, the newest-stamp reconcile, and guards the sync against a status filter being reintroduced.
37 lines
1.0 KiB
Python
37 lines
1.0 KiB
Python
"""Widen the asset inactivity window from 30 to 42 days (six weeks)
|
|
|
|
Revision ID: 044
|
|
Revises: 043
|
|
Create Date: 2026-08-17 10:00:00.000000
|
|
|
|
The window now governs the Wazuh sync too: a disconnected agent keeps its
|
|
findings visible until the window closes, instead of losing them at the next
|
|
sync. Four weeks is too tight for a three-week absence plus a weekend, so the
|
|
default moves to six.
|
|
|
|
Only rows still holding the old default '30' are rewritten — an operator who
|
|
deliberately set another value keeps it. Assets whose stored settings row does
|
|
not exist at all pick up the new code default (asset_lifecycle._DEFAULT_DAYS).
|
|
"""
|
|
from alembic import op
|
|
|
|
|
|
revision = "044"
|
|
down_revision = "043"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.execute(
|
|
"UPDATE settings SET value = '42' "
|
|
"WHERE key = 'asset_inactive_after_days' AND trim(value) = '30'"
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.execute(
|
|
"UPDATE settings SET value = '30' "
|
|
"WHERE key = 'asset_inactive_after_days' AND trim(value) = '42'"
|
|
)
|