from __future__ import annotations import sys import tempfile import unittest from pathlib import Path ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT / "tools")) from exposure import ExposureError, validate_rendered_exposure # noqa: E402 PRIVATE = """apiVersion: v1 kind: Service metadata: {name: example} spec: {type: ClusterIP} """ PUBLIC = """apiVersion: networking.k8s.io/v1 kind: Ingress metadata: {name: example} spec: rules: - host: app.example.test """ class ExposureTests(unittest.TestCase): def declarations(self, rapp: str, reef: str): temp = tempfile.TemporaryDirectory() root = Path(temp.name) rapp_path = root / "rapp.yaml" reef_path = root / "reef.yaml" rapp_path.write_text(rapp, encoding="utf-8") reef_path.write_text(reef, encoding="utf-8") return rapp_path, reef_path, temp def test_private_manifest_needs_no_declarations(self) -> None: result = validate_rendered_exposure(PRIVATE) self.assertEqual("private", result["posture"]) def test_public_manifest_fails_without_declarations(self) -> None: with self.assertRaisesRegex(ExposureError, "rapp-declaration"): validate_rendered_exposure(PUBLIC) def test_matching_grants_pass(self) -> None: rapp, reef, temp = self.declarations( """exposure: posture: public binding_admission: production-approved grant: hostname: app.example.test reason: test approved_on: '2026-08-22' residual_risk_owner: test """, """exposure: posture: public grants: - port: 443 reason: test approved_on: '2026-08-22' residual_risk_owner: test """, ) self.addCleanup(temp.cleanup) result = validate_rendered_exposure(PUBLIC, rapp_declaration=rapp, reef_declaration=reef) self.assertEqual(["app.example.test"], result["public_hosts"]) def test_unapproved_binding_fails(self) -> None: rapp, reef, temp = self.declarations( """exposure: posture: public binding_admission: verified grant: {hostname: app.example.test} """, """exposure: posture: public grants: [{port: 443}] """, ) self.addCleanup(temp.cleanup) with self.assertRaisesRegex(ExposureError, "production-approved"): validate_rendered_exposure(PUBLIC, rapp_declaration=rapp, reef_declaration=reef) def test_mismatched_hostname_fails(self) -> None: rapp, reef, temp = self.declarations( """exposure: posture: public binding_admission: production-approved grant: hostname: other.example.test reason: test approved_on: '2026-08-22' residual_risk_owner: test """, """exposure: posture: public grants: - port: 443 reason: test approved_on: '2026-08-22' residual_risk_owner: test """, ) self.addCleanup(temp.cleanup) with self.assertRaisesRegex(ExposureError, "does not name"): validate_rendered_exposure(PUBLIC, rapp_declaration=rapp, reef_declaration=reef) def test_incomplete_grant_fails(self) -> None: rapp, reef, temp = self.declarations( """exposure: posture: public binding_admission: production-approved grant: {hostname: app.example.test} """, """exposure: posture: public grants: - port: 443 reason: test approved_on: '2026-08-22' residual_risk_owner: test """, ) self.addCleanup(temp.cleanup) with self.assertRaisesRegex(ExposureError, "rapp grant is missing"): validate_rendered_exposure(PUBLIC, rapp_declaration=rapp, reef_declaration=reef) if __name__ == "__main__": unittest.main()