chore(home): mirror from kalinamall (9883e6a) with papatramp URLs
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
"""Ingest idempotency and HTTP status contract."""
|
||||
|
||||
import uuid
|
||||
|
||||
from app.services.schema_validate import validate_event_payload
|
||||
|
||||
VALID_EVENT = {
|
||||
"schema_version": "1.0",
|
||||
"event_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"occurred_at": "2026-05-27T10:00:00+03:00",
|
||||
"source": {"product": "ssh-monitor", "product_version": "1.2.3-SAC"},
|
||||
"host": {"hostname": "test-host", "os_family": "linux"},
|
||||
"category": "agent",
|
||||
"type": "agent.test",
|
||||
"severity": "info",
|
||||
"title": "Test",
|
||||
"summary": "pytest ingest",
|
||||
}
|
||||
|
||||
|
||||
def test_schema_rejects_non_uuid_event_id():
|
||||
bad = {**VALID_EVENT, "event_id": "not-a-uuid"}
|
||||
errors = validate_event_payload(bad)
|
||||
assert errors
|
||||
|
||||
|
||||
def test_schema_rejects_missing_event_id():
|
||||
payload = {k: v for k, v in VALID_EVENT.items() if k != "event_id"}
|
||||
errors = validate_event_payload(payload)
|
||||
assert errors
|
||||
|
||||
|
||||
def test_ingest_created_201(client, auth_headers):
|
||||
event_id = str(uuid.uuid4())
|
||||
payload = {**VALID_EVENT, "event_id": event_id}
|
||||
r = client.post("/api/v1/events", json=payload, headers=auth_headers)
|
||||
assert r.status_code == 201
|
||||
data = r.json()
|
||||
assert data["created"] is True
|
||||
assert data["status"] == "created"
|
||||
assert data["event_id"] == event_id
|
||||
|
||||
|
||||
def test_ingest_duplicate_409(client, auth_headers):
|
||||
event_id = str(uuid.uuid4())
|
||||
payload = {**VALID_EVENT, "event_id": event_id}
|
||||
assert client.post("/api/v1/events", json=payload, headers=auth_headers).status_code == 201
|
||||
r = client.post("/api/v1/events", json=payload, headers=auth_headers)
|
||||
assert r.status_code == 409
|
||||
data = r.json()
|
||||
assert data["created"] is False
|
||||
assert data["status"] == "duplicate"
|
||||
assert data["event_id"] == event_id
|
||||
|
||||
|
||||
def test_ingest_rdp_lifecycle_201(client, auth_headers):
|
||||
event_id = str(uuid.uuid4())
|
||||
payload = {
|
||||
**VALID_EVENT,
|
||||
"event_id": event_id,
|
||||
"source": {"product": "rdp-login-monitor", "product_version": "1.2.11-SAC"},
|
||||
"host": {"hostname": "K6A-DC3", "os_family": "windows"},
|
||||
"type": "agent.lifecycle",
|
||||
"title": "RDP login monitor started",
|
||||
"summary": "Мониторинг запущен на K6A-DC3, версия 1.2.11-SAC",
|
||||
"details": {"lifecycle": "started"},
|
||||
}
|
||||
r = client.post("/api/v1/events", json=payload, headers=auth_headers)
|
||||
assert r.status_code == 201
|
||||
assert r.json()["event_id"] == event_id
|
||||
|
||||
|
||||
def test_ingest_host_display_name_updated(client, auth_headers, db_session):
|
||||
from sqlalchemy import select
|
||||
|
||||
from app.models import Host
|
||||
|
||||
event_id = str(uuid.uuid4())
|
||||
payload = {
|
||||
**VALID_EVENT,
|
||||
"event_id": event_id,
|
||||
"host": {
|
||||
"hostname": "short-name",
|
||||
"display_name": "UNMS Kalina",
|
||||
"os_family": "linux",
|
||||
},
|
||||
}
|
||||
assert client.post("/api/v1/events", json=payload, headers=auth_headers).status_code == 201
|
||||
host = db_session.scalar(select(Host).where(Host.hostname == "short-name"))
|
||||
assert host is not None
|
||||
assert host.display_name == "UNMS Kalina"
|
||||
|
||||
payload2 = {
|
||||
**payload,
|
||||
"event_id": str(uuid.uuid4()),
|
||||
"host": {"hostname": "short-name", "display_name": "Kalina UNMS", "os_family": "linux"},
|
||||
}
|
||||
assert client.post("/api/v1/events", json=payload2, headers=auth_headers).status_code == 201
|
||||
db_session.refresh(host)
|
||||
assert host.display_name == "Kalina UNMS"
|
||||
|
||||
|
||||
def test_ingest_invalid_payload_422(client, auth_headers):
|
||||
r = client.post(
|
||||
"/api/v1/events",
|
||||
json={"event_id": "bad", "summary": "x"},
|
||||
headers=auth_headers,
|
||||
)
|
||||
assert r.status_code == 422
|
||||
assert "schema_errors" in r.json()["detail"]
|
||||
|
||||
|
||||
def test_ingest_daily_report_calls_notify_daily_report(client, auth_headers):
|
||||
from unittest.mock import patch
|
||||
|
||||
from app.api.v1 import events as events_api
|
||||
|
||||
event_id = str(uuid.uuid4())
|
||||
payload = {
|
||||
**VALID_EVENT,
|
||||
"event_id": event_id,
|
||||
"category": "report",
|
||||
"type": "report.daily.ssh",
|
||||
"severity": "info",
|
||||
"title": "Daily SSH report",
|
||||
"summary": "stats",
|
||||
"details": {"generated_by": "agent", "report_body": "line1"},
|
||||
}
|
||||
with patch.object(events_api, "schedule_notify_daily_report") as mock_daily:
|
||||
with patch.object(events_api, "notify_event") as mock_event:
|
||||
r = client.post("/api/v1/events", json=payload, headers=auth_headers)
|
||||
assert r.status_code == 201
|
||||
mock_daily.assert_called_once()
|
||||
mock_event.assert_not_called()
|
||||
|
||||
|
||||
def test_ingest_lifecycle_defers_notify(client, auth_headers):
|
||||
from unittest.mock import patch
|
||||
|
||||
from app.api.v1 import events as events_api
|
||||
|
||||
event_id = str(uuid.uuid4())
|
||||
payload = {
|
||||
**VALID_EVENT,
|
||||
"event_id": event_id,
|
||||
"type": "agent.lifecycle",
|
||||
"title": "started",
|
||||
"summary": "agent started",
|
||||
"details": {"lifecycle": "started"},
|
||||
}
|
||||
with patch.object(events_api, "schedule_notify_lifecycle") as mock_defer:
|
||||
with patch.object(events_api, "notify_lifecycle") as mock_sync:
|
||||
r = client.post("/api/v1/events", json=payload, headers=auth_headers)
|
||||
assert r.status_code == 201
|
||||
mock_defer.assert_called_once()
|
||||
mock_sync.assert_not_called()
|
||||
|
||||
|
||||
def test_ingest_auth_login_defers_notify(client, auth_headers):
|
||||
from unittest.mock import patch
|
||||
|
||||
from app.api.v1 import events as events_api
|
||||
|
||||
event_id = str(uuid.uuid4())
|
||||
payload = {
|
||||
**VALID_EVENT,
|
||||
"event_id": event_id,
|
||||
"category": "auth",
|
||||
"type": "ssh.login.success",
|
||||
"severity": "info",
|
||||
"title": "SSH login",
|
||||
"summary": "user@host",
|
||||
}
|
||||
with patch.object(events_api, "schedule_notify_auth_login") as mock_defer:
|
||||
with patch.object(events_api, "notify_auth_login") as mock_sync:
|
||||
r = client.post("/api/v1/events", json=payload, headers=auth_headers)
|
||||
assert r.status_code == 201
|
||||
mock_defer.assert_called_once()
|
||||
mock_sync.assert_not_called()
|
||||
|
||||
Reference in New Issue
Block a user