rail-kubernetes/tests/test_private_exposure.py
codex 004f1c4dc1 Enforce private-by-default rail exposure
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a02669-87ee-7a31-b111-edc95a16e0fa
2026-08-22 12:34:25 +02:00

133 lines
3.7 KiB
Python

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()