feat(iwooos): flag empty Wazuh agent registry
This commit is contained in:
@@ -19,6 +19,7 @@ def test_iwooos_wazuh_compat_route_returns_disabled_boundary_by_default(monkeypa
|
||||
monkeypatch.delenv("WAZUH_API_BASE_URL", raising=False)
|
||||
monkeypatch.delenv("WAZUH_API_USERNAME", raising=False)
|
||||
monkeypatch.delenv("WAZUH_API_PASSWORD", raising=False)
|
||||
monkeypatch.delenv("IWOOOS_WAZUH_EXPECTED_MIN_AGENT_COUNT", raising=False)
|
||||
|
||||
response = _client().get("/api/iwooos/wazuh")
|
||||
|
||||
@@ -28,6 +29,7 @@ def test_iwooos_wazuh_compat_route_returns_disabled_boundary_by_default(monkeypa
|
||||
assert data["status"] == "disabled_waiting_iwooos_wazuh_owner_gate"
|
||||
assert data["configured"] is False
|
||||
assert data["summary"]["runtime_gate_count"] == 0
|
||||
assert data["summary"]["agent_visibility_no_false_green_count"] == 1
|
||||
assert data["boundaries"]["active_response_authorized"] is False
|
||||
assert data["boundaries"]["host_write_authorized"] is False
|
||||
assert data["boundaries"]["raw_wazuh_payload_storage_allowed"] is False
|
||||
@@ -39,6 +41,7 @@ def test_iwooos_wazuh_v1_route_rejects_missing_server_side_env(monkeypatch: pyte
|
||||
monkeypatch.setenv("WAZUH_API_BASE_URL", "")
|
||||
monkeypatch.setenv("WAZUH_API_USERNAME", "")
|
||||
monkeypatch.setenv("WAZUH_API_PASSWORD", "")
|
||||
monkeypatch.delenv("IWOOOS_WAZUH_EXPECTED_MIN_AGENT_COUNT", raising=False)
|
||||
|
||||
response = _client().get("/api/v1/iwooos/wazuh")
|
||||
|
||||
@@ -54,6 +57,7 @@ def test_iwooos_wazuh_rejects_non_https_base_url(monkeypatch: pytest.MonkeyPatch
|
||||
monkeypatch.setenv("WAZUH_API_BASE_URL", "http://wazuh.example.test:55000")
|
||||
monkeypatch.setenv("WAZUH_API_USERNAME", "readonly")
|
||||
monkeypatch.setenv("WAZUH_API_PASSWORD", "placeholder")
|
||||
monkeypatch.delenv("IWOOOS_WAZUH_EXPECTED_MIN_AGENT_COUNT", raising=False)
|
||||
|
||||
response = _client().get("/api/iwooos/wazuh")
|
||||
|
||||
@@ -68,6 +72,7 @@ def test_iwooos_wazuh_live_response_is_metadata_only(monkeypatch: pytest.MonkeyP
|
||||
monkeypatch.setenv("WAZUH_API_BASE_URL", "https://wazuh.example.test:55000")
|
||||
monkeypatch.setenv("WAZUH_API_USERNAME", "readonly")
|
||||
monkeypatch.setenv("WAZUH_API_PASSWORD", "placeholder")
|
||||
monkeypatch.delenv("IWOOOS_WAZUH_EXPECTED_MIN_AGENT_COUNT", raising=False)
|
||||
|
||||
def handler(request: httpx.Request) -> httpx.Response:
|
||||
if request.url.path == "/security/user/authenticate":
|
||||
@@ -113,6 +118,9 @@ def test_iwooos_wazuh_live_response_is_metadata_only(monkeypatch: pytest.MonkeyP
|
||||
assert data["status"] == "readonly_metadata_available"
|
||||
assert data["configured"] is True
|
||||
assert data["summary"]["agent_total"] == 2
|
||||
assert data["summary"]["agent_registry_empty_count"] == 0
|
||||
assert data["summary"]["agent_below_expected_minimum_count"] == 0
|
||||
assert data["summary"]["agent_visibility_no_false_green_count"] == 1
|
||||
assert data["summary"]["runtime_gate_count"] == 0
|
||||
assert data["agents"] == [
|
||||
{
|
||||
@@ -125,3 +133,104 @@ def test_iwooos_wazuh_live_response_is_metadata_only(monkeypatch: pytest.MonkeyP
|
||||
assert "host-110-private-name" not in response.text
|
||||
assert "192.168.0.110" not in response.text
|
||||
assert "token-value" not in response.text
|
||||
|
||||
|
||||
def test_iwooos_wazuh_marks_empty_agent_registry_as_degraded(monkeypatch: pytest.MonkeyPatch):
|
||||
monkeypatch.setenv("IWOOOS_WAZUH_READONLY_ENABLED", "true")
|
||||
monkeypatch.setenv("WAZUH_API_BASE_URL", "https://wazuh.example.test:55000")
|
||||
monkeypatch.setenv("WAZUH_API_USERNAME", "readonly")
|
||||
monkeypatch.setenv("WAZUH_API_PASSWORD", "placeholder")
|
||||
monkeypatch.delenv("IWOOOS_WAZUH_EXPECTED_MIN_AGENT_COUNT", raising=False)
|
||||
|
||||
def handler(request: httpx.Request) -> httpx.Response:
|
||||
if request.url.path == "/security/user/authenticate":
|
||||
return httpx.Response(200, json={"data": {"token": "token-value"}})
|
||||
if request.url.path == "/agents/summary/status":
|
||||
return httpx.Response(
|
||||
200,
|
||||
json={"data": {"connection": {"total": 0, "active": 0, "disconnected": 0, "pending": 0}}},
|
||||
)
|
||||
if request.url.path == "/agents":
|
||||
return httpx.Response(200, json={"data": {"affected_items": []}})
|
||||
return httpx.Response(404)
|
||||
|
||||
transport = httpx.MockTransport(handler)
|
||||
original_async_client = httpx.AsyncClient
|
||||
|
||||
def client_factory(*args, **kwargs):
|
||||
kwargs["transport"] = transport
|
||||
return original_async_client(*args, **kwargs)
|
||||
|
||||
monkeypatch.setattr(httpx, "AsyncClient", client_factory)
|
||||
|
||||
response = _client().get("/api/iwooos/wazuh")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["status"] == "wazuh_agent_registry_empty"
|
||||
assert data["summary"]["agent_total"] == 0
|
||||
assert data["summary"]["agent_registry_empty_count"] == 1
|
||||
assert data["summary"]["agent_below_expected_minimum_count"] == 0
|
||||
assert data["summary"]["agent_visibility_no_false_green_count"] == 1
|
||||
assert data["summary"]["runtime_gate_count"] == 0
|
||||
assert data["agents"] == []
|
||||
assert "token-value" not in response.text
|
||||
|
||||
|
||||
def test_iwooos_wazuh_marks_agent_count_below_expected_as_degraded(monkeypatch: pytest.MonkeyPatch):
|
||||
monkeypatch.setenv("IWOOOS_WAZUH_READONLY_ENABLED", "true")
|
||||
monkeypatch.setenv("WAZUH_API_BASE_URL", "https://wazuh.example.test:55000")
|
||||
monkeypatch.setenv("WAZUH_API_USERNAME", "readonly")
|
||||
monkeypatch.setenv("WAZUH_API_PASSWORD", "placeholder")
|
||||
monkeypatch.setenv("IWOOOS_WAZUH_EXPECTED_MIN_AGENT_COUNT", "2")
|
||||
|
||||
def handler(request: httpx.Request) -> httpx.Response:
|
||||
if request.url.path == "/security/user/authenticate":
|
||||
return httpx.Response(200, json={"data": {"token": "token-value"}})
|
||||
if request.url.path == "/agents/summary/status":
|
||||
return httpx.Response(
|
||||
200,
|
||||
json={"data": {"connection": {"total": 1, "active": 1, "disconnected": 0, "pending": 0}}},
|
||||
)
|
||||
if request.url.path == "/agents":
|
||||
return httpx.Response(
|
||||
200,
|
||||
json={
|
||||
"data": {
|
||||
"affected_items": [
|
||||
{
|
||||
"id": "001",
|
||||
"name": "private-host-name",
|
||||
"ip": "192.168.0.110",
|
||||
"status": "active",
|
||||
"os": {"platform": "linux"},
|
||||
"lastKeepAlive": "2026-06-24T13:00:00Z",
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
)
|
||||
return httpx.Response(404)
|
||||
|
||||
transport = httpx.MockTransport(handler)
|
||||
original_async_client = httpx.AsyncClient
|
||||
|
||||
def client_factory(*args, **kwargs):
|
||||
kwargs["transport"] = transport
|
||||
return original_async_client(*args, **kwargs)
|
||||
|
||||
monkeypatch.setattr(httpx, "AsyncClient", client_factory)
|
||||
|
||||
response = _client().get("/api/iwooos/wazuh")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["status"] == "wazuh_agent_registry_below_expected"
|
||||
assert data["summary"]["expected_min_agent_count"] == 2
|
||||
assert data["summary"]["agent_total"] == 1
|
||||
assert data["summary"]["agent_registry_empty_count"] == 0
|
||||
assert data["summary"]["agent_below_expected_minimum_count"] == 1
|
||||
assert data["summary"]["runtime_gate_count"] == 0
|
||||
assert "private-host-name" not in response.text
|
||||
assert "192.168.0.110" not in response.text
|
||||
assert "token-value" not in response.text
|
||||
|
||||
Reference in New Issue
Block a user