3ea36ef3ab
Squash merge of phase/03-l2-modules-and-core-scripts; 4 L2s + 5 core scripts; verify_phase03.sh green.
51 lines
1.3 KiB
Python
Executable File
51 lines
1.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""policy_checker.py — REQ-07 / D-025
|
|
|
|
Reads a contract.yaml and enforces the single Phase-03 policy rule:
|
|
`public-ingress: true` is forbidden.
|
|
|
|
Input: argv[1] = path to a contract.yaml file.
|
|
Output: stdout "POLICY_PASS" or "POLICY_VIOLATION:PUBLIC_INGRESS"
|
|
Exit: 0 on pass, 1 on violation.
|
|
|
|
Idempotent, no side effects (no file writes). Treats an absent or falsy
|
|
`public-ingress` key as a pass.
|
|
"""
|
|
import sys
|
|
import yaml
|
|
|
|
|
|
def main() -> int:
|
|
if len(sys.argv) < 2:
|
|
print("usage: policy_checker.py <contract.yaml>", file=sys.stderr)
|
|
return 2
|
|
|
|
contract_path = sys.argv[1]
|
|
|
|
try:
|
|
with open(contract_path, "r", encoding="utf-8") as fh:
|
|
contract = yaml.safe_load(fh)
|
|
except FileNotFoundError:
|
|
print(f"contract not found: {contract_path}", file=sys.stderr)
|
|
return 2
|
|
except yaml.YAMLError as exc:
|
|
print(f"invalid yaml: {exc}", file=sys.stderr)
|
|
return 2
|
|
|
|
# Treat missing/non-mapping as no policy violation.
|
|
if not isinstance(contract, dict):
|
|
print("POLICY_PASS")
|
|
return 0
|
|
|
|
public_ingress = contract.get("public-ingress", False)
|
|
|
|
if public_ingress is True:
|
|
print("POLICY_VIOLATION:PUBLIC_INGRESS")
|
|
return 1
|
|
|
|
print("POLICY_PASS")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main()) |