Claude 24f816b6a3
Consolidate 22 sibling repos into layered organism structure
Place useful parts of the surrounding repos into sica-fondt by layer, per the
body model (Ada = membrane; brain/endocrine/capabilities/knowledge non-Ada):

- brain/        LLM reasoning + providers (dapr, hermes, MoMoA)
- capabilities/ REPRAG sidecars: hermes tools/skills, dapr tools, parallel
                dispatch, A51 channels, and the OSINT cluster
- knowledge/    LORAG corpus: 754 cyber-skills, agency personas, secure-coding,
                MITRE ATT&CK data
- reference/    defensive threat-reference (C3, shhbruh doc) + AdaYaml parser

License handling: AGPL sources (worldosint, advanced_evolution, mercury,
Reticulum) and GPL DeTTECT are SPEC-only clean-room/port descriptions — no
copyleft code copied. MIT/Apache/data parts copied as working trees.

Safety: shhbruh escape/persistence material and C3 covert-C2 kept as reference
only, not wired into the running organism. See CONSOLIDATION.md.

https://claude.ai/code/session_01UehUqEXXJJCsHoA4voCU5c
2026-06-10 06:53:01 +00:00

128 lines
4.3 KiB
Python

#!/usr/bin/env python3
"""Zscaler Private Access (ZPA) ZTNA audit agent using ZPA API."""
import json
import sys
import argparse
from datetime import datetime
try:
import requests
except ImportError:
print("Install: pip install requests")
sys.exit(1)
class ZPAClient:
"""Zscaler Private Access API client."""
def __init__(self, client_id, client_secret, customer_id):
self.base_url = "https://config.private.zscaler.com"
self.customer_id = customer_id
self.token = self._authenticate(client_id, client_secret)
def _authenticate(self, client_id, client_secret):
resp = requests.post(f"{self.base_url}/signin", json={
"client_id": client_id, "client_secret": client_secret,
}, timeout=30)
resp.raise_for_status()
return resp.json()["token"]
def _get(self, endpoint):
resp = requests.get(f"{self.base_url}/mgmtconfig/v1/admin/customers/{self.customer_id}/{endpoint}",
headers={"Authorization": f"Bearer {self.token}"}, timeout=30)
resp.raise_for_status()
return resp.json()
def list_app_segments(self):
return self._get("application")
def list_server_groups(self):
return self._get("serverGroup")
def list_app_connectors(self):
return self._get("connector")
def list_access_policies(self):
return self._get("policySet/rules")
def list_segment_groups(self):
return self._get("segmentGroup")
def audit_zpa_config(client):
"""Audit ZPA configuration for security posture."""
findings = []
apps = client.list_app_segments()
for app in apps.get("list", []):
if not app.get("enabled"):
findings.append({
"type": "disabled_app_segment",
"name": app.get("name", ""),
"severity": "LOW",
})
if app.get("bypassType") == "ALWAYS":
findings.append({
"type": "bypass_enabled",
"name": app.get("name", ""),
"severity": "HIGH",
"recommendation": "Remove bypass to enforce ZPA inspection",
})
connectors = client.list_app_connectors()
for conn in connectors.get("list", []):
if conn.get("runtimeStatus") != "running":
findings.append({
"type": "connector_down",
"name": conn.get("name", ""),
"status": conn.get("runtimeStatus", ""),
"severity": "CRITICAL",
})
return findings
def run_audit(client_id, client_secret, customer_id):
"""Execute ZPA ZTNA audit."""
client = ZPAClient(client_id, client_secret, customer_id)
print(f"\n{'='*60}")
print(f" ZSCALER PRIVATE ACCESS ZTNA AUDIT")
print(f" Generated: {datetime.utcnow().isoformat()} UTC")
print(f"{'='*60}\n")
apps = client.list_app_segments()
app_list = apps.get("list", [])
print(f"--- APPLICATION SEGMENTS ({len(app_list)}) ---")
for a in app_list[:10]:
print(f" {a.get('name', '')}: enabled={a.get('enabled', '')} bypass={a.get('bypassType', '')}")
connectors = client.list_app_connectors()
conn_list = connectors.get("list", [])
print(f"\n--- APP CONNECTORS ({len(conn_list)}) ---")
for c in conn_list[:10]:
print(f" {c.get('name', '')}: {c.get('runtimeStatus', '')}")
findings = audit_zpa_config(client)
print(f"\n--- AUDIT FINDINGS ({len(findings)}) ---")
for f in findings:
print(f" [{f['severity']}] {f['type']}: {f.get('name', '')}")
return {"apps": len(app_list), "connectors": len(conn_list), "findings": findings}
def main():
parser = argparse.ArgumentParser(description="ZPA ZTNA Audit Agent")
parser.add_argument("--client-id", required=True, help="ZPA API client ID")
parser.add_argument("--client-secret", required=True, help="ZPA API client secret")
parser.add_argument("--customer-id", required=True, help="ZPA customer ID")
parser.add_argument("--output", help="Save report to JSON file")
args = parser.parse_args()
report = run_audit(args.client_id, args.client_secret, args.customer_id)
if args.output:
with open(args.output, "w") as f:
json.dump(report, f, indent=2, default=str)
print(f"\n[+] Report saved to {args.output}")
if __name__ == "__main__":
main()