mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-11 05:34:55 +03:00
c21af3347e
- Add scripts/agent.py and references/api-reference.md to all remaining skills - Update all 648 LICENSE files: copyright now reads 'Mahipal' - Add implementing-security-monitoring-with-datadog (new skill with full anatomy) - All 649 skills now have: SKILL.md, LICENSE, scripts/agent.py, references/api-reference.md
223 lines
8.6 KiB
Python
223 lines
8.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Agent for assessing identity verification controls in zero trust architecture."""
|
|
|
|
import json
|
|
import argparse
|
|
from datetime import datetime
|
|
from collections import Counter
|
|
|
|
|
|
CISA_ZT_IDENTITY_LEVELS = {
|
|
"traditional": {
|
|
"description": "Password-based auth, static policies",
|
|
"score": 1,
|
|
},
|
|
"initial": {
|
|
"description": "MFA deployed, basic conditional access",
|
|
"score": 2,
|
|
},
|
|
"advanced": {
|
|
"description": "Phishing-resistant MFA, risk-based access",
|
|
"score": 3,
|
|
},
|
|
"optimal": {
|
|
"description": "Continuous verification, passwordless, behavioral analytics",
|
|
"score": 4,
|
|
},
|
|
}
|
|
|
|
|
|
def assess_authentication_methods(auth_config):
|
|
"""Assess authentication method strength against zero trust requirements."""
|
|
findings = []
|
|
methods = auth_config.get("methods", auth_config.get("authentication", {}))
|
|
|
|
if isinstance(methods, dict):
|
|
mfa_enabled = methods.get("mfa_enabled", False)
|
|
phishing_resistant = methods.get("phishing_resistant_mfa", False)
|
|
passwordless = methods.get("passwordless", False)
|
|
fido2 = methods.get("fido2_enabled", False)
|
|
sso = methods.get("sso_enabled", False)
|
|
|
|
if not mfa_enabled:
|
|
findings.append({"control": "MFA", "status": "MISSING",
|
|
"severity": "CRITICAL"})
|
|
elif not phishing_resistant:
|
|
findings.append({"control": "Phishing-resistant MFA", "status": "MISSING",
|
|
"severity": "HIGH",
|
|
"recommendation": "Deploy FIDO2 or certificate-based auth"})
|
|
|
|
if not fido2:
|
|
findings.append({"control": "FIDO2/WebAuthn", "status": "NOT_DEPLOYED",
|
|
"severity": "MEDIUM"})
|
|
if not passwordless:
|
|
findings.append({"control": "Passwordless authentication",
|
|
"status": "NOT_DEPLOYED", "severity": "MEDIUM"})
|
|
if not sso:
|
|
findings.append({"control": "SSO", "status": "NOT_DEPLOYED",
|
|
"severity": "HIGH"})
|
|
return findings
|
|
|
|
|
|
def assess_conditional_access(policies_path):
|
|
"""Assess conditional access policies for zero trust alignment."""
|
|
with open(policies_path) as f:
|
|
policies = json.load(f)
|
|
items = policies if isinstance(policies, list) else policies.get("policies", [])
|
|
findings = []
|
|
required_signals = ["device_compliance", "location", "risk_level",
|
|
"application", "user_group"]
|
|
covered_signals = set()
|
|
|
|
for policy in items:
|
|
conditions = policy.get("conditions", {})
|
|
for signal in required_signals:
|
|
if conditions.get(signal) or signal in str(conditions):
|
|
covered_signals.add(signal)
|
|
if policy.get("grant_controls", {}).get("operator") == "OR":
|
|
findings.append({
|
|
"policy": policy.get("name", ""),
|
|
"issue": "Grant controls use OR (should be AND)",
|
|
"severity": "HIGH",
|
|
})
|
|
if not policy.get("state", "").lower() in ("enabled", "on"):
|
|
findings.append({
|
|
"policy": policy.get("name", ""),
|
|
"issue": "Policy not enabled",
|
|
"severity": "MEDIUM",
|
|
})
|
|
|
|
missing = set(required_signals) - covered_signals
|
|
for signal in missing:
|
|
findings.append({
|
|
"control": f"Conditional access signal: {signal}",
|
|
"status": "NOT_COVERED",
|
|
"severity": "HIGH",
|
|
})
|
|
return {"findings": findings, "covered_signals": list(covered_signals),
|
|
"missing_signals": list(missing)}
|
|
|
|
|
|
def assess_identity_maturity(config):
|
|
"""Assess identity pillar maturity against CISA Zero Trust Maturity Model."""
|
|
scores = {}
|
|
categories = {
|
|
"authentication": {
|
|
"checks": ["mfa_enforced", "phishing_resistant_mfa", "passwordless",
|
|
"continuous_auth"],
|
|
},
|
|
"identity_stores": {
|
|
"checks": ["centralized_idp", "cloud_identity", "directory_sync",
|
|
"identity_federation"],
|
|
},
|
|
"risk_assessment": {
|
|
"checks": ["risk_based_access", "behavioral_analytics",
|
|
"impossible_travel_detection", "session_risk_scoring"],
|
|
},
|
|
"visibility": {
|
|
"checks": ["identity_audit_logging", "real_time_monitoring",
|
|
"identity_analytics_dashboard", "automated_anomaly_detection"],
|
|
},
|
|
}
|
|
|
|
for category, info in categories.items():
|
|
implemented = sum(1 for check in info["checks"]
|
|
if config.get(category, {}).get(check, False))
|
|
total = len(info["checks"])
|
|
ratio = implemented / total if total else 0
|
|
if ratio >= 0.9:
|
|
level = "optimal"
|
|
elif ratio >= 0.6:
|
|
level = "advanced"
|
|
elif ratio >= 0.3:
|
|
level = "initial"
|
|
else:
|
|
level = "traditional"
|
|
scores[category] = {
|
|
"implemented": implemented,
|
|
"total": total,
|
|
"ratio": round(ratio, 2),
|
|
"maturity_level": level,
|
|
"score": CISA_ZT_IDENTITY_LEVELS[level]["score"],
|
|
}
|
|
|
|
avg_score = sum(s["score"] for s in scores.values()) / len(scores) if scores else 0
|
|
for level_name, level_info in CISA_ZT_IDENTITY_LEVELS.items():
|
|
if level_info["score"] >= avg_score:
|
|
overall_level = level_name
|
|
break
|
|
else:
|
|
overall_level = "traditional"
|
|
|
|
return {"categories": scores, "overall_score": round(avg_score, 1),
|
|
"overall_level": overall_level}
|
|
|
|
|
|
def analyze_auth_events(events_path):
|
|
"""Analyze authentication events for zero trust insights."""
|
|
with open(events_path) as f:
|
|
events = json.load(f)
|
|
items = events if isinstance(events, list) else events.get("events", [])
|
|
|
|
by_method = Counter(e.get("auth_method", "unknown") for e in items)
|
|
by_result = Counter(e.get("result", "unknown") for e in items)
|
|
risky = [e for e in items if e.get("risk_level", "").lower() in ("high", "critical")]
|
|
mfa_bypassed = [e for e in items if e.get("mfa_bypassed", False)]
|
|
|
|
return {
|
|
"total_events": len(items),
|
|
"by_method": dict(by_method),
|
|
"by_result": dict(by_result),
|
|
"high_risk_events": len(risky),
|
|
"mfa_bypass_events": len(mfa_bypassed),
|
|
"password_only_rate": round(
|
|
by_method.get("password", 0) / len(items) * 100, 1) if items else 0,
|
|
}
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Zero Trust Identity Verification Agent")
|
|
parser.add_argument("--auth-config", help="Authentication config JSON")
|
|
parser.add_argument("--policies", help="Conditional access policies JSON")
|
|
parser.add_argument("--maturity-config", help="Identity maturity assessment config JSON")
|
|
parser.add_argument("--auth-events", help="Authentication events log JSON")
|
|
parser.add_argument("--action", choices=["auth", "policies", "maturity", "events", "full"],
|
|
default="full")
|
|
parser.add_argument("--output", default="zt_identity_report.json")
|
|
args = parser.parse_args()
|
|
|
|
report = {"generated_at": datetime.utcnow().isoformat(), "results": {}}
|
|
|
|
if args.action in ("auth", "full") and args.auth_config:
|
|
with open(args.auth_config) as f:
|
|
config = json.load(f)
|
|
findings = assess_authentication_methods(config)
|
|
report["results"]["auth_assessment"] = findings
|
|
critical = sum(1 for f in findings if f.get("severity") == "CRITICAL")
|
|
print(f"[+] Auth findings: {len(findings)}, {critical} critical")
|
|
|
|
if args.action in ("policies", "full") and args.policies:
|
|
result = assess_conditional_access(args.policies)
|
|
report["results"]["conditional_access"] = result
|
|
print(f"[+] Missing signals: {result['missing_signals']}")
|
|
|
|
if args.action in ("maturity", "full") and args.maturity_config:
|
|
with open(args.maturity_config) as f:
|
|
config = json.load(f)
|
|
result = assess_identity_maturity(config)
|
|
report["results"]["maturity"] = result
|
|
print(f"[+] Identity maturity: {result['overall_level']} (score: {result['overall_score']})")
|
|
|
|
if args.action in ("events", "full") and args.auth_events:
|
|
result = analyze_auth_events(args.auth_events)
|
|
report["results"]["events"] = result
|
|
print(f"[+] Auth events: {result['total_events']}, password-only: {result['password_only_rate']}%")
|
|
|
|
with open(args.output, "w") as f:
|
|
json.dump(report, f, indent=2, default=str)
|
|
print(f"[+] Report saved to {args.output}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|