Gate reef web ports on exposure grants
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02669-87ee-7a31-b111-edc95a16e0fa
This commit is contained in:
parent
c569fe168a
commit
61c6082ea8
9 changed files with 228 additions and 46 deletions
66
scripts/validate-reef-exposure.py
Executable file
66
scripts/validate-reef-exposure.py
Executable file
|
|
@ -0,0 +1,66 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Validate requested public web ports against an ADR-0008 reef declaration."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import yaml
|
||||
|
||||
|
||||
class GrantError(ValueError):
|
||||
pass
|
||||
|
||||
|
||||
def validate(payload: Any, ports: list[int]) -> dict[str, Any]:
|
||||
if not isinstance(payload, dict):
|
||||
raise GrantError("reef declaration must be a YAML object")
|
||||
if any(port == 6443 for port in ports):
|
||||
raise GrantError("6443 is operator-only and cannot be publicly granted")
|
||||
if any(port not in {80, 443} for port in ports):
|
||||
raise GrantError("the public web gate accepts only ports 80 and 443")
|
||||
if not payload.get("primary_rail") and not payload.get("hosted_rails"):
|
||||
raise GrantError("provider-delegated reefs cannot publish a public listener")
|
||||
exposure = payload.get("exposure") or {}
|
||||
if exposure.get("posture") != "public":
|
||||
raise GrantError("reef exposure.posture must be public")
|
||||
grants = exposure.get("grants") or []
|
||||
for port in ports:
|
||||
matches = [grant for grant in grants if isinstance(grant, dict) and grant.get("port") in {port, str(port)}]
|
||||
if not matches:
|
||||
raise GrantError(f"reef has no substrate grant for port {port}")
|
||||
grant = matches[0]
|
||||
missing = [field for field in ("reason", "approved_on", "residual_risk_owner") if not grant.get(field)]
|
||||
if missing:
|
||||
raise GrantError(f"port {port} grant is missing {', '.join(missing)}")
|
||||
return {
|
||||
"reef_id": payload.get("reef_id"),
|
||||
"posture": "public",
|
||||
"validated_ports": sorted(set(ports)),
|
||||
}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--reef-declaration", type=Path, required=True)
|
||||
parser.add_argument("--ports", required=True, help="Comma-separated ports; only 80 and 443 are grantable")
|
||||
args = parser.parse_args()
|
||||
try:
|
||||
ports = [int(value) for value in args.ports.split(",") if value]
|
||||
if not ports:
|
||||
raise GrantError("at least one requested port is required")
|
||||
payload = yaml.safe_load(args.reef_declaration.read_text(encoding="utf-8"))
|
||||
result = validate(payload, ports)
|
||||
except (OSError, yaml.YAMLError, ValueError) as exc:
|
||||
print(f"reef exposure validation failed: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
print(json.dumps(result, sort_keys=True))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue