mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-11 21:54:56 +03:00
c47eed6a64
- 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
134 lines
5.5 KiB
Python
134 lines
5.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Agent for auditing Zscaler Private Access (ZPA) zero trust configuration via API."""
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
import requests
|
|
from datetime import datetime, timezone
|
|
|
|
ZPA_BASE = os.environ.get("ZPA_BASE_URL", "https://config.private.zscaler.com")
|
|
|
|
|
|
def authenticate(client_id, client_secret, customer_id):
|
|
"""Authenticate to Zscaler ZPA API."""
|
|
url = f"{ZPA_BASE}/signin"
|
|
payload = {"client_id": client_id, "client_secret": client_secret}
|
|
headers = {"Content-Type": "application/x-www-form-urlencoded"}
|
|
resp = requests.post(url, data=payload, headers=headers, timeout=30)
|
|
resp.raise_for_status()
|
|
token = resp.json()["access_token"]
|
|
print("[*] Authenticated to ZPA API")
|
|
return {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
|
|
|
|
|
|
def list_app_segments(headers, customer_id):
|
|
"""List ZPA application segments."""
|
|
url = f"{ZPA_BASE}/mgmtconfig/v1/admin/customers/{customer_id}/application"
|
|
resp = requests.get(url, headers=headers, timeout=30)
|
|
resp.raise_for_status()
|
|
apps = resp.json().get("list", [])
|
|
print(f"\n[*] Application Segments: {len(apps)}")
|
|
findings = []
|
|
for app in apps:
|
|
bypass = app.get("bypassType", "NEVER")
|
|
if bypass != "NEVER":
|
|
findings.append({"name": app["name"], "bypass": bypass, "severity": "HIGH"})
|
|
print(f" {app['name']} - bypass={bypass}, enabled={app.get('enabled', False)}")
|
|
return apps, findings
|
|
|
|
|
|
def list_server_groups(headers, customer_id):
|
|
"""List server groups and their connectors."""
|
|
url = f"{ZPA_BASE}/mgmtconfig/v1/admin/customers/{customer_id}/serverGroup"
|
|
resp = requests.get(url, headers=headers, timeout=30)
|
|
resp.raise_for_status()
|
|
groups = resp.json().get("list", [])
|
|
print(f"\n[*] Server Groups: {len(groups)}")
|
|
for g in groups:
|
|
connectors = g.get("connectors", [])
|
|
print(f" {g['name']} - {len(connectors)} connectors, enabled={g.get('enabled')}")
|
|
return groups
|
|
|
|
|
|
def list_access_policies(headers, customer_id):
|
|
"""List ZPA access policies to verify least-privilege enforcement."""
|
|
url = f"{ZPA_BASE}/mgmtconfig/v1/admin/customers/{customer_id}/policySet/rules"
|
|
resp = requests.get(url, headers=headers, timeout=30)
|
|
resp.raise_for_status()
|
|
rules = resp.json().get("list", [])
|
|
findings = []
|
|
print(f"\n[*] Access Policy Rules: {len(rules)}")
|
|
for r in rules:
|
|
action = r.get("action", "")
|
|
conditions = r.get("conditions", [])
|
|
if action == "ALLOW" and not conditions:
|
|
findings.append({"rule": r.get("name"), "issue": "ALLOW with no conditions",
|
|
"severity": "CRITICAL"})
|
|
print(f" [!] {r.get('name')}: ALLOW without conditions")
|
|
else:
|
|
print(f" {r.get('name')}: action={action}, conditions={len(conditions)}")
|
|
return rules, findings
|
|
|
|
|
|
def check_connector_health(headers, customer_id):
|
|
"""Check connector enrollment and health status."""
|
|
url = f"{ZPA_BASE}/mgmtconfig/v1/admin/customers/{customer_id}/connector"
|
|
resp = requests.get(url, headers=headers, timeout=30)
|
|
resp.raise_for_status()
|
|
connectors = resp.json().get("list", [])
|
|
issues = []
|
|
for c in connectors:
|
|
status = c.get("currentVersion", "unknown")
|
|
enabled = c.get("enabled", False)
|
|
if not enabled:
|
|
issues.append({"connector": c.get("name"), "issue": "disabled", "severity": "MEDIUM"})
|
|
print(f" {c.get('name')}: enabled={enabled}, version={status}")
|
|
print(f"[*] Connectors: {len(connectors)} total, {len(issues)} disabled")
|
|
return connectors, issues
|
|
|
|
|
|
def generate_report(apps, app_findings, policy_findings, connector_issues, output_path):
|
|
"""Generate ZPA audit report."""
|
|
report = {
|
|
"audit_date": datetime.now(timezone.utc).isoformat(),
|
|
"summary": {"app_segments": len(apps), "bypass_findings": len(app_findings),
|
|
"policy_findings": len(policy_findings),
|
|
"connector_issues": len(connector_issues)},
|
|
"bypass_findings": app_findings, "policy_findings": policy_findings,
|
|
"connector_issues": connector_issues,
|
|
}
|
|
with open(output_path, "w") as f:
|
|
json.dump(report, f, indent=2, default=str)
|
|
print(f"\n[*] Report saved to {output_path}")
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Zscaler ZPA Zero Trust Audit Agent")
|
|
parser.add_argument("action", choices=["apps", "servers", "policies", "connectors", "full-audit"])
|
|
parser.add_argument("--client-id", required=True)
|
|
parser.add_argument("--client-secret", required=True)
|
|
parser.add_argument("--customer-id", required=True)
|
|
parser.add_argument("-o", "--output", default="zpa_audit.json")
|
|
args = parser.parse_args()
|
|
|
|
headers = authenticate(args.client_id, args.client_secret, args.customer_id)
|
|
if args.action == "apps":
|
|
list_app_segments(headers, args.customer_id)
|
|
elif args.action == "servers":
|
|
list_server_groups(headers, args.customer_id)
|
|
elif args.action == "policies":
|
|
list_access_policies(headers, args.customer_id)
|
|
elif args.action == "connectors":
|
|
check_connector_health(headers, args.customer_id)
|
|
elif args.action == "full-audit":
|
|
apps, af = list_app_segments(headers, args.customer_id)
|
|
list_server_groups(headers, args.customer_id)
|
|
_, pf = list_access_policies(headers, args.customer_id)
|
|
_, ci = check_connector_health(headers, args.customer_id)
|
|
generate_report(apps, af, pf, ci, args.output)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|