CI Test Suite / Run Component Tests & Pipeline Verification (push) Failing after 1m18s
150 lines
5.7 KiB
Python
150 lines
5.7 KiB
Python
"""
|
|
Comprehensive unit tests for LOGAR Server FastAPI endpoints, state management, and log processing.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
import shutil
|
|
import tempfile
|
|
import sqlite3
|
|
import unittest
|
|
from unittest.mock import MagicMock, patch
|
|
from fastapi.testclient import TestClient
|
|
|
|
from src.hub import Server
|
|
from src.hub.auth_manager import SessionManager
|
|
|
|
|
|
class TestHubServerDeep(unittest.TestCase):
|
|
def setUp(self):
|
|
self.temp_dir = tempfile.mkdtemp()
|
|
self.cert_dir = os.path.join(self.temp_dir, "certs")
|
|
os.makedirs(self.cert_dir, exist_ok=True)
|
|
self.db_path = os.path.join(self.temp_dir, "test_server.db")
|
|
self.config_path = os.path.join(self.temp_dir, "server_config.json")
|
|
|
|
# Initialize test state
|
|
Server.StorageEngine.init_db(self.db_path, enrollment_secret="test_secret", max_seats=50)
|
|
Server.SERVER_STATE["config"] = {
|
|
"db_path": self.db_path,
|
|
"enrollment_secret": "test_secret",
|
|
"max_seats": 50,
|
|
"cert_dir": self.cert_dir,
|
|
"encrypt_at_rest": False
|
|
}
|
|
# Generate and load CA
|
|
ca_cert, ca_key, ca_pem, _ = Server.enrollment.generate_ca_if_needed(cert_dir=self.cert_dir)
|
|
Server.SERVER_STATE["ca_cert"] = ca_cert
|
|
Server.SERVER_STATE["ca_key"] = ca_key
|
|
Server.SERVER_STATE["ca_cert_pem"] = ca_pem
|
|
|
|
self.session_token = SessionManager.generate_session_token("admin", db_path=self.db_path)
|
|
self.client = TestClient(Server.app, cookies={SessionManager.SESSION_COOKIE_NAME: self.session_token})
|
|
|
|
def tearDown(self):
|
|
shutil.rmtree(self.temp_dir, ignore_errors=True)
|
|
|
|
def test_server_status_and_update_routes(self):
|
|
"""Tests /api/update/status and /api/server/update/status routes."""
|
|
resp = self.client.get("/api/update/status")
|
|
self.assertEqual(resp.status_code, 200)
|
|
data = resp.json()
|
|
self.assertIn("hosted_packages", data)
|
|
|
|
def test_client_enrollment_and_action_endpoints(self):
|
|
"""Tests /api/client/enroll and /api/client/revoke/approve/delete endpoints."""
|
|
# Ensure license in DB is marked active with seats
|
|
conn = sqlite3.connect(self.db_path)
|
|
conn.execute("UPDATE license_config SET max_seats = 50, license_status = 'active' WHERE id = 1")
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
# Enroll client
|
|
enroll_payload = {
|
|
"client_id": "test_agent_deep_01",
|
|
"hostname": "workstation-01",
|
|
"os": "windows",
|
|
"enrollment_secret": "test_secret"
|
|
}
|
|
resp = self.client.post("/api/client/enroll", json=enroll_payload)
|
|
self.assertEqual(resp.status_code, 200)
|
|
data = resp.json()
|
|
self.assertEqual(data.get("status"), "success")
|
|
self.assertIn("client_cert", data)
|
|
self.assertIn("client_key", data)
|
|
|
|
# Check client list
|
|
resp_list = self.client.get("/api/clients")
|
|
self.assertEqual(resp_list.status_code, 200)
|
|
clients_data = resp_list.json()
|
|
self.assertGreaterEqual(clients_data.get("active_seats", 0), 1)
|
|
|
|
# Client action: revoke
|
|
resp_rev = self.client.post("/api/client/revoke", json={"client_id": "test_agent_deep_01"})
|
|
self.assertEqual(resp_rev.status_code, 200)
|
|
self.assertEqual(resp_rev.json().get("status"), "revoked")
|
|
|
|
# Reactivate
|
|
resp_app = self.client.post("/api/client/approve", json={"client_id": "test_agent_deep_01"})
|
|
self.assertEqual(resp_app.status_code, 200)
|
|
self.assertEqual(resp_app.json().get("status"), "active")
|
|
|
|
# Delete
|
|
resp_del = self.client.post("/api/client/delete", json={"client_id": "test_agent_deep_01"})
|
|
self.assertEqual(resp_del.status_code, 200)
|
|
|
|
def test_hermes_tokens_and_auth_routes(self):
|
|
"""Tests Hermes API token creation, listing, and revoking."""
|
|
# Create token
|
|
tok_payload = {"name": "Test Integration Agent"}
|
|
resp = self.client.post("/api/hermes/tokens/create", json=tok_payload)
|
|
self.assertEqual(resp.status_code, 200)
|
|
tok_data = resp.json()
|
|
token_val = tok_data.get("token")
|
|
self.assertIsNotNone(token_val)
|
|
|
|
# Revoke token
|
|
resp_rev = self.client.post("/api/hermes/tokens/revoke", json={"token": token_val})
|
|
self.assertEqual(resp_rev.status_code, 200)
|
|
|
|
def test_process_ingested_logs_and_temporal_tracking(self):
|
|
"""Tests processing ingested log entries, deduplication, and anomaly promotion."""
|
|
payload = {
|
|
"server": "web-prod-01",
|
|
"timestamp": "2026-01-01T12:00:00Z",
|
|
"logs": [
|
|
{
|
|
"site_name": "Default-Site",
|
|
"server": "web-prod-01",
|
|
"signature": "SECURITY_4625_BRUTEFORCE",
|
|
"severity": "CRITICAL",
|
|
"message": "Repeated failed logon attempts detected from 10.0.0.99",
|
|
"os_type": "windows",
|
|
"timestamp": "2026-01-01T12:00:00Z"
|
|
}
|
|
]
|
|
}
|
|
res = Server.process_ingested_logs(
|
|
payload=payload,
|
|
db_path=self.db_path,
|
|
window_hours=24,
|
|
min_runs=1
|
|
)
|
|
self.assertEqual(res.get("processed"), 1)
|
|
|
|
# Query database directly to confirm issue recorded
|
|
conn = sqlite3.connect(self.db_path)
|
|
c = conn.cursor()
|
|
c.execute("SELECT signature, severity, run_count FROM active_issues")
|
|
row = c.fetchone()
|
|
conn.close()
|
|
self.assertIsNotNone(row)
|
|
self.assertEqual(row[0], "SECURITY_4625_BRUTEFORCE")
|
|
self.assertEqual(row[1], "CRITICAL")
|
|
self.assertEqual(row[2], 1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|