Files
mukul975 c47eed6a64 Production hardening: security fixes, code quality, 724 skills complete
- Fix 25 shell=True subprocess calls with list-based commands
- Fix 49 verify=False in defensive skills (env-var override)
- Add timeout to 231 HTTP/subprocess/socket calls
- Fix 6 SQL injection patterns with whitelist validation
- Replace 8 __import__() with standard imports
- Remove 701 unused imports across 442 files
- Add authorized-testing disclaimers to all offensive skills
- Complete 11 incomplete skill directories
- Expand 10 stub SKILL.md files with full content
- Fix 2 YAML parse errors in frontmatter
- Fix 5 pre-existing syntax errors
- Convert 22 hardcoded paths/ports to environment variables
- Back up 21 redundant skill pairs to .bak
- Fix 2 global declaration errors
- 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE)
- 0 compile errors across all 724 agent.py files
2026-03-19 13:26:49 +01:00

109 lines
4.2 KiB
Python

#!/usr/bin/env python3
"""OPA Gatekeeper Policy Enforcement Agent - audits constraint templates and violation status."""
import json
import argparse
import logging
import subprocess
from collections import defaultdict
from datetime import datetime
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
def kubectl_json(args_list):
cmd = ["kubectl"] + args_list + ["-o", "json"]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
return json.loads(result.stdout) if result.returncode == 0 else {}
def get_constraint_templates():
return kubectl_json(["get", "constrainttemplates"])
def get_constraints():
templates = get_constraint_templates()
constraints = []
for item in templates.get("items", []):
kind = item.get("metadata", {}).get("name", "")
result = kubectl_json(["get", kind])
for c in result.get("items", []):
constraints.append(c)
return constraints
def audit_constraint_violations(constraints):
violations = []
for constraint in constraints:
name = constraint.get("metadata", {}).get("name", "")
kind = constraint.get("kind", "")
status = constraint.get("status", {})
total = status.get("totalViolations", 0)
violation_list = status.get("violations", [])
if total > 0:
violations.append({
"constraint": name, "kind": kind, "total_violations": total,
"enforcement_action": constraint.get("spec", {}).get("enforcementAction", "deny"),
"sample_violations": violation_list[:5],
})
return sorted(violations, key=lambda x: x["total_violations"], reverse=True)
def analyze_policy_coverage(constraints):
categories = defaultdict(int)
enforcement = defaultdict(int)
for c in constraints:
categories[c.get("kind", "unknown")] += 1
enforcement[c.get("spec", {}).get("enforcementAction", "deny")] += 1
return {"total_constraints": len(constraints), "by_template": dict(categories), "by_enforcement_action": dict(enforcement)}
def check_audit_status():
cmd = ["kubectl", "get", "pods", "-n", "gatekeeper-system", "-o", "json"]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
pods = json.loads(result.stdout) if result.returncode == 0 else {}
pod_status = []
for pod in pods.get("items", []):
name = pod.get("metadata", {}).get("name", "")
phase = pod.get("status", {}).get("phase", "")
ready = all(c.get("ready", False) for c in pod.get("status", {}).get("containerStatuses", []))
pod_status.append({"name": name, "phase": phase, "ready": ready})
return pod_status
def generate_report(templates, constraints, violations, coverage, pod_status):
return {
"timestamp": datetime.utcnow().isoformat(),
"constraint_templates": len(templates.get("items", [])),
"active_constraints": len(constraints),
"policy_coverage": coverage,
"total_violations": sum(v["total_violations"] for v in violations),
"constraints_with_violations": len(violations),
"top_violations": violations[:15],
"gatekeeper_pods": pod_status,
"gatekeeper_healthy": all(p["ready"] for p in pod_status) if pod_status else False,
}
def main():
parser = argparse.ArgumentParser(description="OPA Gatekeeper Policy Enforcement Audit Agent")
parser.add_argument("--output", default="gatekeeper_audit_report.json")
args = parser.parse_args()
templates = get_constraint_templates()
constraints = get_constraints()
violations = audit_constraint_violations(constraints)
coverage = analyze_policy_coverage(constraints)
pod_status = check_audit_status()
report = generate_report(templates, constraints, violations, coverage, pod_status)
with open(args.output, "w") as f:
json.dump(report, f, indent=2, default=str)
logger.info("Gatekeeper: %d templates, %d constraints, %d violations",
report["constraint_templates"], report["active_constraints"], report["total_violations"])
print(json.dumps(report, indent=2, default=str))
if __name__ == "__main__":
main()