- Complete Cloudflare Terraform configuration (DNS, WAF, tunnels, access) - WAF Intelligence MCP server with threat analysis and ML classification - GitOps automation with PR workflows and drift detection - Observatory monitoring stack with Prometheus/Grafana - IDE operator rules for governed development - Security playbooks and compliance frameworks - Autonomous remediation and state reconciliation
173 lines
5.1 KiB
Python
173 lines
5.1 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Autonomous Remediator — Cloudflare Autonomic Mesh Engine
|
|
Pure technical (D1) implementation
|
|
|
|
Runs continuously (systemd service) and performs:
|
|
- DNS auto-remediation (re-proxy, restore records)
|
|
- WAF baseline enforcement
|
|
- Access policy enforcement (MFA, no bypass)
|
|
- Tunnel health remediation (restart, rekey optional)
|
|
- Drift correction using Terraform
|
|
|
|
Outputs VaultMesh receipts for each correction.
|
|
"""
|
|
|
|
import os
|
|
import json
|
|
import time
|
|
import subprocess
|
|
import requests
|
|
from datetime import datetime, timezone
|
|
|
|
CF_API = "https://api.cloudflare.com/client/v4"
|
|
CF_TOKEN = os.getenv("CF_API_TOKEN")
|
|
CF_ACCOUNT = os.getenv("CF_ACCOUNT_ID")
|
|
TF_DIR = os.getenv("TF_DIR", "./terraform")
|
|
RECEIPT_DIR = os.getenv("VM_RECEIPT_DIR", "./receipts")
|
|
|
|
HEADERS = {
|
|
"Authorization": f"Bearer {CF_TOKEN}",
|
|
"Content-Type": "application/json",
|
|
}
|
|
|
|
os.makedirs(RECEIPT_DIR, exist_ok=True)
|
|
|
|
|
|
def cf(endpoint, method="GET", data=None):
|
|
url = f"{CF_API}{endpoint}"
|
|
if method == "GET":
|
|
r = requests.get(url, headers=HEADERS)
|
|
else:
|
|
r = requests.request(method, url, headers=HEADERS, json=data)
|
|
r.raise_for_status()
|
|
return r.json().get("result", {})
|
|
|
|
|
|
def emit_receipt(action, details):
|
|
ts = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
path = f"{RECEIPT_DIR}/auto-{action}-{ts}.json"
|
|
with open(path, "w") as f:
|
|
json.dump({"ts": ts, "action": action, "details": details}, f, indent=2)
|
|
print(f"[REMEDIATOR] Receipt emitted: {path}")
|
|
|
|
|
|
# ------------------------------
|
|
# DNS Remediation
|
|
# ------------------------------
|
|
|
|
def fix_dns():
|
|
zones = cf("/zones")
|
|
for z in zones:
|
|
zid = z["id"]
|
|
zname = z["name"]
|
|
recs = cf(f"/zones/{zid}/dns_records")
|
|
|
|
for r in recs:
|
|
# Re-proxy unproxied A/AAAA
|
|
if r["type"] in ("A", "AAAA") and not r.get("proxied"):
|
|
print(f"[DNS] Re-proxying {r['name']} in {zname}")
|
|
cf(f"/zones/{zid}/dns_records/{r['id']}", method="PUT",
|
|
data={"type": r["type"], "name": r["name"], "content": r["content"], "proxied": True})
|
|
emit_receipt("dns_reproxy", {"zone": zname, "record": r})
|
|
|
|
# Enforce DNSSEC
|
|
dnssec = cf(f"/zones/{zid}/dnssec")
|
|
if dnssec.get("status") != "active":
|
|
print(f"[DNS] Enabling DNSSEC for {zname}")
|
|
cf(f"/zones/{zid}/dnssec", method="PATCH", data={"status": "active"})
|
|
emit_receipt("dnssec_enable", {"zone": zname})
|
|
|
|
|
|
# ------------------------------
|
|
# WAF Enforcement
|
|
# ------------------------------
|
|
|
|
def enforce_waf():
|
|
zones = cf("/zones")
|
|
for z in zones:
|
|
zid = z["id"]
|
|
zname = z["name"]
|
|
pkgs = cf(f"/zones/{zid}/firewall/waf/packages")
|
|
|
|
# Ensure OWASP ruleset is present
|
|
if not any("owasp" in p.get("name", "").lower() for p in pkgs):
|
|
emit_receipt("missing_owasp", {"zone": zname})
|
|
print(f"[WAF] Missing OWASP ruleset in {zname}")
|
|
|
|
|
|
# ------------------------------
|
|
# Access Policy Enforcement
|
|
# ------------------------------
|
|
|
|
def enforce_access():
|
|
policies = cf(f"/accounts/{CF_ACCOUNT}/access/policies")
|
|
for p in policies:
|
|
changed = False
|
|
pid = p["id"]
|
|
|
|
# Enforce MFA requirement
|
|
for rule in p.get("rules", []):
|
|
if not rule.get("require_mfa"):
|
|
rule["require_mfa"] = True
|
|
changed = True
|
|
|
|
# No bypass allowed
|
|
if p.get("decision") == "bypass":
|
|
p["decision"] = "allow"
|
|
changed = True
|
|
|
|
if changed:
|
|
print(f"[ACCESS] Correcting policy {pid}")
|
|
cf(f"/accounts/{CF_ACCOUNT}/access/policies/{pid}", method="PUT", data=p)
|
|
emit_receipt("access_policy_fix", {"policy_id": pid})
|
|
|
|
|
|
# ------------------------------
|
|
# Tunnel Health Remediation
|
|
# ------------------------------
|
|
|
|
def fix_tunnels():
|
|
tunnels = cf(f"/accounts/{CF_ACCOUNT}/cfd_tunnel")
|
|
for t in tunnels:
|
|
if t.get("status") in ("degraded", "reconnecting", "down"):
|
|
tid = t["id"]
|
|
print(f"[TUNNEL] Restart recommended for {tid}")
|
|
# Informational only — actual restart is manual or via systemd
|
|
emit_receipt("tunnel_unhealthy", t)
|
|
|
|
|
|
# ------------------------------
|
|
# Terraform Drift Correction
|
|
# ------------------------------
|
|
|
|
def correct_terraform_drift():
|
|
print("[TF] Running terraform plan to detect drift...")
|
|
proc = subprocess.run(["terraform", "-chdir", TF_DIR, "plan"], capture_output=True, text=True)
|
|
|
|
if "No changes" not in proc.stdout:
|
|
print("[TF] Drift detected — applying corrective action")
|
|
subprocess.run(["terraform", "-chdir", TF_DIR, "apply", "-auto-approve"])
|
|
emit_receipt("terraform_drift_fix", {"output": proc.stdout})
|
|
|
|
|
|
# ------------------------------
|
|
# Main Loop
|
|
# ------------------------------
|
|
|
|
def main():
|
|
print("[REMEDIATOR] Autonomic Mesh running...")
|
|
|
|
while True:
|
|
fix_dns()
|
|
enforce_waf()
|
|
enforce_access()
|
|
fix_tunnels()
|
|
correct_terraform_drift()
|
|
|
|
print("[REMEDIATOR] Cycle complete. Sleeping 5 minutes...")
|
|
time.sleep(300)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |