Initial curated ITWorx_MCP_Hub source from 368fba691ea8d23403b4d56b53b5ec670d7c5020
This commit is contained in:
commit
cb5be898ea
663 files changed
+82674
No files matched your search
@@ -0,0 +1,125 @@
|
||||
"""WP-230E: the session-store production decision is enforced, not just documented.
|
||||
|
||||
See docs/02-security/SESSION_STORE_DECISION.md. Two things are tested:
|
||||
|
||||
1. scripts/compose_release_check.py actually fails the release gate if
|
||||
control-api is ever scaled beyond one replica (the concrete enforcement
|
||||
mechanism the decision doc points to), not just that the doc says so.
|
||||
2. The documented single-instance consequence -- a restart invalidates
|
||||
every session -- is a real, observable property of SessionStore, not an
|
||||
assumption.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import tempfile
|
||||
import unittest
|
||||
from datetime import UTC, datetime
|
||||
from pathlib import Path
|
||||
|
||||
import yaml # type: ignore[import-untyped]
|
||||
|
||||
from scripts.compose_release_check import check_compose
|
||||
from services.control_api.auth.bff import SessionStore
|
||||
from services.control_api.auth.errors import SessionExpired
|
||||
from services.control_api.auth.models import (
|
||||
AuthenticatedPrincipal,
|
||||
ManagementRole,
|
||||
PrincipalKind,
|
||||
TokenSet,
|
||||
)
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
REAL_COMPOSE = ROOT / "infrastructure" / "compose" / "docker-compose.yml"
|
||||
|
||||
|
||||
def _minimal_compose(extra_control_api: dict[str, object] | None = None) -> dict[str, object]:
|
||||
control_api: dict[str, object] = {"image": "local/itworx-mcp-hub-control:dev"}
|
||||
if extra_control_api:
|
||||
control_api.update(extra_control_api)
|
||||
return {
|
||||
"name": "itworx-mcp-hub",
|
||||
"services": {
|
||||
"control-api": control_api,
|
||||
"docker-read-broker": {
|
||||
"image": "local/itworx-mcp-hub-broker:dev",
|
||||
"volumes": ["/var/run/docker.sock:/var/run/docker.sock:ro"],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class ComposeSingleInstanceEnforcementTests(unittest.TestCase):
|
||||
def _check(self, document: dict[str, object]) -> dict[str, object]:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path = Path(directory) / "docker-compose.yml"
|
||||
path.write_text(yaml.safe_dump(document), encoding="utf-8")
|
||||
return check_compose(path)
|
||||
|
||||
def test_control_api_scaled_to_two_replicas_fails_the_gate(self) -> None:
|
||||
result = self._check(_minimal_compose({"deploy": {"replicas": 2}}))
|
||||
self.assertIn("control-api", result["singleInstanceViolations"])
|
||||
self.assertFalse(result["pass"])
|
||||
|
||||
def test_control_api_with_no_deploy_block_passes(self) -> None:
|
||||
result = self._check(_minimal_compose())
|
||||
self.assertEqual(result["singleInstanceViolations"], [])
|
||||
self.assertTrue(result["pass"])
|
||||
|
||||
def test_control_api_explicitly_pinned_to_one_replica_passes(self) -> None:
|
||||
result = self._check(_minimal_compose({"deploy": {"replicas": 1}}))
|
||||
self.assertEqual(result["singleInstanceViolations"], [])
|
||||
self.assertTrue(result["pass"])
|
||||
|
||||
def test_real_compose_file_does_not_scale_control_api(self) -> None:
|
||||
result = check_compose(REAL_COMPOSE)
|
||||
self.assertEqual(result["singleInstanceViolations"], [])
|
||||
|
||||
|
||||
class SessionStoreRestartBehaviorTests(unittest.TestCase):
|
||||
"""Proves the documented consequence of the in-memory decision is real:
|
||||
the store has no persistence, so a process restart (modeled here as
|
||||
constructing a fresh SessionStore -- the same thing a real restart does,
|
||||
a brand-new empty dict) invalidates every session that existed before
|
||||
it, rather than silently reusing stale state."""
|
||||
|
||||
def _principal(self) -> AuthenticatedPrincipal:
|
||||
return AuthenticatedPrincipal(
|
||||
kind=PrincipalKind.MANAGEMENT_USER,
|
||||
subject="user-1",
|
||||
issuer="https://fake.oidc.test",
|
||||
audience=("itworx-mcp-hub",),
|
||||
client_id=None,
|
||||
roles=frozenset({ManagementRole.VIEWER}),
|
||||
issued_at=datetime(2026, 1, 1, tzinfo=UTC),
|
||||
expires_at=datetime(2030, 1, 1, tzinfo=UTC),
|
||||
)
|
||||
|
||||
def _store(self) -> SessionStore:
|
||||
return SessionStore(
|
||||
ttl_seconds=3600, cookie_name="hub_session", same_site="lax", secure=True
|
||||
)
|
||||
|
||||
def test_session_does_not_survive_a_simulated_restart(self) -> None:
|
||||
first_process = self._store()
|
||||
cookie = first_process.create(
|
||||
self._principal(),
|
||||
TokenSet(access_token="access", id_token=None, refresh_token=None), # noqa: S106
|
||||
)
|
||||
|
||||
second_process = self._store()
|
||||
with self.assertRaises(SessionExpired):
|
||||
second_process.get(cookie.value)
|
||||
|
||||
def test_the_same_process_still_recognizes_its_own_session(self) -> None:
|
||||
store = self._store()
|
||||
cookie = store.create(
|
||||
self._principal(),
|
||||
TokenSet(access_token="access", id_token=None, refresh_token=None), # noqa: S106
|
||||
)
|
||||
record = store.get(cookie.value)
|
||||
self.assertEqual(record.csrf_token, cookie.csrf_token)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user