my-homelab-configs/scripts/agent-sandbox

83 lines
2.5 KiB
Python
Executable File

#!/usr/bin/env python3
"""Classify proposed agent commands against the homelab sandbox policy."""
from __future__ import annotations
import argparse
import csv
import json
import sys
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[1]
POLICY_FILE = REPO_ROOT / "infra" / "agent-sandbox" / "policy.tsv"
def load_policy() -> list[dict[str, str]]:
with POLICY_FILE.open(encoding="utf-8", newline="") as handle:
return list(csv.DictReader(handle, delimiter="\t"))
def classify(command: str) -> dict[str, str]:
normalized = " ".join(command.strip().split())
best: dict[str, str] | None = None
for rule in load_policy():
pattern = rule["pattern"]
if pattern in normalized:
if best is None or len(pattern) > len(best["pattern"]):
best = rule
if best is None:
return {
"command": normalized,
"decision": "approval",
"pattern": "default",
"reason": "Unknown command; require explicit approval before execution.",
}
return {
"command": normalized,
"decision": best["decision"],
"pattern": best["pattern"],
"reason": best["reason"],
}
def print_result(result: dict[str, str]) -> int:
print("Agent Sandbox")
print("=============")
print(f"command: {result['command']}")
print(f"decision: {result['decision']}")
print(f"matched: {result['pattern']}")
print(f"reason: {result['reason']}")
if result["decision"] == "allow":
return 0
if result["decision"] == "approval":
return 2
return 3
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
subparsers = parser.add_subparsers(dest="command", required=True)
check_parser = subparsers.add_parser("check")
check_parser.add_argument("candidate", nargs="+")
check_parser.add_argument("--json", action="store_true")
subparsers.add_parser("policy")
args = parser.parse_args()
if args.command == "policy":
for rule in load_policy():
print(f"{rule['decision']:8} {rule['pattern']} - {rule['reason']}")
return 0
if args.command == "check":
result = classify(" ".join(args.candidate))
if args.json:
print(json.dumps(result, indent=2, sort_keys=True))
return 0 if result["decision"] == "allow" else 2
return print_result(result)
return 2
if __name__ == "__main__":
raise SystemExit(main())