fix(iwooos): normalize wazuh receipt timestamps
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m27s
CD Pipeline / build-and-deploy (push) Successful in 6m55s
CD Pipeline / post-deploy-checks (push) Successful in 1m55s

This commit is contained in:
ogt
2026-07-11 11:39:44 +08:00
parent e52019ba4d
commit 4bc97290b9
2 changed files with 45 additions and 4 deletions

View File

@@ -10,7 +10,7 @@ from __future__ import annotations
import json import json
from collections.abc import Mapping from collections.abc import Mapping
from datetime import datetime from datetime import UTC, datetime
from typing import Any from typing import Any
from sqlalchemy import text from sqlalchemy import text
@@ -484,5 +484,26 @@ def _latest_receipt_at(data: Mapping[str, Any]) -> str | None:
] ]
if not values: if not values:
return None return None
latest = max(values) normalized = [
return latest.isoformat() if isinstance(latest, datetime) else str(latest) parsed
for value in values
if (parsed := _utc_receipt_datetime(value)) is not None
]
if normalized:
return max(normalized).isoformat()
return max(str(value) for value in values)
def _utc_receipt_datetime(value: Any) -> datetime | None:
if isinstance(value, datetime):
parsed = value
elif isinstance(value, str):
try:
parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
except ValueError:
return None
else:
return None
if parsed.tzinfo is None:
parsed = parsed.replace(tzinfo=UTC)
return parsed.astimezone(UTC)

View File

@@ -2,7 +2,7 @@ from __future__ import annotations
import os import os
from contextlib import asynccontextmanager from contextlib import asynccontextmanager
from datetime import datetime from datetime import UTC, datetime
from pathlib import Path from pathlib import Path
from unittest.mock import AsyncMock, MagicMock from unittest.mock import AsyncMock, MagicMock
@@ -208,6 +208,26 @@ def test_wazuh_posture_catalog_and_playbook_are_bounded_no_write() -> None:
assert wazuh_manager["criticality"] == "P0" assert wazuh_manager["criticality"] == "P0"
def test_wazuh_runtime_readback_normalizes_mixed_receipt_timezones() -> None:
row = _complete_row()
row["candidate_created_at"] = datetime(2026, 7, 11, 3, 36)
row["check_created_at"] = datetime(
2026,
7,
11,
3,
37,
tzinfo=UTC,
)
payload = build_iwooos_wazuh_controlled_executor_runtime_readback(
row,
executor_enabled=True,
)
assert payload["latest_receipt_at"] == "2026-07-11T03:37:00+00:00"
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_wazuh_posture_scheduler_enqueues_after_mcp_and_log_evidence( async def test_wazuh_posture_scheduler_enqueues_after_mcp_and_log_evidence(
monkeypatch: pytest.MonkeyPatch, monkeypatch: pytest.MonkeyPatch,