157 lines
4.7 KiB
Python
157 lines
4.7 KiB
Python
#!/usr/bin/env python3
|
|
"""CLI boundary for shell/native runtimes to consume Assurance Kernel policy."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
HARNESS_ROOT = Path(__file__).resolve().parents[2]
|
|
sys.path.insert(0, str(HARNESS_ROOT))
|
|
|
|
from kernel.adapters import NativeHarnessAdapter # noqa: E402
|
|
from kernel.contracts import validate_bundle # noqa: E402
|
|
from kernel.policy import ( # noqa: E402
|
|
H2GateContext,
|
|
evaluate_h2_gate,
|
|
evaluate_registry_configuration,
|
|
evaluate_risk,
|
|
evaluate_trust_capabilities,
|
|
)
|
|
|
|
|
|
def _print(payload: object) -> None:
|
|
print(json.dumps(payload, sort_keys=True, separators=(",", ":")))
|
|
|
|
|
|
def _read_content(path: str | None) -> str:
|
|
if not path:
|
|
return ""
|
|
with open(path, encoding="utf-8") as handle:
|
|
return handle.read()
|
|
|
|
|
|
def _append_jsonl(path: str, payload: object) -> None:
|
|
target = Path(path)
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
data = (json.dumps(payload, sort_keys=True, separators=(",", ":")) + "\n").encode("utf-8")
|
|
fd = os.open(str(target), os.O_WRONLY | os.O_CREAT | os.O_APPEND, 0o600)
|
|
try:
|
|
try:
|
|
import fcntl
|
|
fcntl.flock(fd, fcntl.LOCK_EX)
|
|
except (ImportError, OSError):
|
|
pass
|
|
os.write(fd, data)
|
|
os.fsync(fd)
|
|
finally:
|
|
os.close(fd)
|
|
|
|
|
|
def cmd_risk(args: argparse.Namespace) -> int:
|
|
payload = evaluate_risk(
|
|
action=args.action,
|
|
tool=args.tool,
|
|
resource=args.resource,
|
|
command=args.command,
|
|
content=_read_content(args.content_file),
|
|
actor=args.actor,
|
|
environment=args.environment,
|
|
)
|
|
_print(payload)
|
|
return 0
|
|
|
|
|
|
def cmd_registry(args: argparse.Namespace) -> int:
|
|
payload = evaluate_registry_configuration(args.mode, args.profile, args.explicit)
|
|
if args.evidence_log:
|
|
_append_jsonl(args.evidence_log, payload)
|
|
_print(payload)
|
|
return 0 if payload["valid"] else 2
|
|
|
|
|
|
def cmd_h2(args: argparse.Namespace) -> int:
|
|
context = H2GateContext(
|
|
mode=args.mode,
|
|
actor=args.actor,
|
|
action=args.action,
|
|
tool=args.tool,
|
|
execution_id=args.execution_id,
|
|
enforcement_path=args.enforcement_path,
|
|
idempotency_key=args.idempotency_key,
|
|
timeout_seconds=args.timeout,
|
|
)
|
|
payload = evaluate_h2_gate(args.gate, context, bash_path=args.bash)
|
|
if args.evidence_log:
|
|
_append_jsonl(args.evidence_log, payload)
|
|
_print(payload)
|
|
return 0 if payload["execution_allowed"] else 2
|
|
|
|
|
|
def cmd_trust(_args: argparse.Namespace) -> int:
|
|
payload = evaluate_trust_capabilities()
|
|
_print(payload)
|
|
return 0 if payload["ready"] else 2
|
|
|
|
|
|
def cmd_native(args: argparse.Namespace) -> int:
|
|
event = json.load(sys.stdin) if args.event_file == "-" else json.load(open(args.event_file, encoding="utf-8"))
|
|
payload = NativeHarnessAdapter().map_execution(event)
|
|
errors = validate_bundle(payload)
|
|
if errors:
|
|
_print({"valid": False, "errors": errors, "bundle": payload})
|
|
return 2
|
|
_print(payload)
|
|
return 0
|
|
|
|
|
|
def parser() -> argparse.ArgumentParser:
|
|
root = argparse.ArgumentParser()
|
|
sub = root.add_subparsers(dest="command", required=True)
|
|
risk = sub.add_parser("risk")
|
|
for name in ("action", "tool", "resource", "command", "actor", "environment"):
|
|
risk.add_argument(f"--{name}", default="")
|
|
risk.add_argument("--content-file")
|
|
risk.set_defaults(func=cmd_risk)
|
|
|
|
registry = sub.add_parser("registry-config")
|
|
registry.add_argument("--mode", default="observe")
|
|
registry.add_argument("--profile", default="development")
|
|
registry.add_argument("--explicit")
|
|
registry.add_argument("--evidence-log")
|
|
registry.set_defaults(func=cmd_registry)
|
|
|
|
h2 = sub.add_parser("h2-gate")
|
|
h2.add_argument("--gate", required=True)
|
|
h2.add_argument("--mode", choices=("observe", "enforce"), required=True)
|
|
h2.add_argument("--actor", default="")
|
|
h2.add_argument("--action", required=True)
|
|
h2.add_argument("--tool", required=True)
|
|
h2.add_argument("--execution-id", required=True)
|
|
h2.add_argument("--enforcement-path", required=True)
|
|
h2.add_argument("--idempotency-key", required=True)
|
|
h2.add_argument("--timeout", type=float, default=8.0)
|
|
h2.add_argument("--bash", default="bash")
|
|
h2.add_argument("--evidence-log")
|
|
h2.set_defaults(func=cmd_h2)
|
|
|
|
trust = sub.add_parser("trust-capabilities")
|
|
trust.set_defaults(func=cmd_trust)
|
|
|
|
native = sub.add_parser("adapt-native")
|
|
native.add_argument("event_file")
|
|
native.set_defaults(func=cmd_native)
|
|
return root
|
|
|
|
|
|
def main() -> int:
|
|
args = parser().parse_args()
|
|
return int(args.func(args))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|