Expand 38 agent.py stubs, standardize 347 SKILL.md sections, fix 4 verify=False

This commit is contained in:
mukul975
2026-03-19 13:55:45 +01:00
parent 79287253fb
commit 051e7e72ed
11 changed files with 1931 additions and 386 deletions
@@ -1,61 +1,210 @@
#!/usr/bin/env python3
"""Proofpoint email security gateway audit."""
import argparse, json
from datetime import datetime, timezone
"""Proofpoint email security gateway audit agent.
Audits Proofpoint TAP (Targeted Attack Protection) via the SIEM API
to retrieve blocked threats, clicked URLs, delivered messages, and
campaign attribution data for email security monitoring.
"""
import argparse
import json
import os
import sys
from datetime import datetime, timezone, timedelta
try:
import requests
from requests.auth import HTTPBasicAuth
except ImportError:
requests = None
print("[!] 'requests' required: pip install requests", file=sys.stderr)
sys.exit(1)
def audit_config(target, token):
PROOFPOINT_BASE = "https://tap-api-v2.proofpoint.com"
def get_pp_config():
"""Return Proofpoint TAP API credentials."""
principal = os.environ.get("PROOFPOINT_PRINCIPAL", "")
secret = os.environ.get("PROOFPOINT_SECRET", "")
if not principal or not secret:
print("[!] Set PROOFPOINT_PRINCIPAL and PROOFPOINT_SECRET env vars", file=sys.stderr)
sys.exit(1)
return principal, secret
def pp_api(endpoint, principal, secret, params=None):
"""Make authenticated Proofpoint TAP API call."""
url = f"{PROOFPOINT_BASE}{endpoint}"
resp = requests.get(url, auth=HTTPBasicAuth(principal, secret),
params=params, timeout=30)
resp.raise_for_status()
return resp.json()
def get_blocked_clicks(principal, secret, hours=24):
"""Get URLs that were blocked when clicked."""
print(f"[*] Fetching blocked clicks (last {hours}h)...")
since = (datetime.now(timezone.utc) - timedelta(hours=hours)).strftime("%Y-%m-%dT%H:%M:%SZ")
data = pp_api("/v2/siem/clicks/blocked", principal, secret,
params={"sinceTime": since, "format": "json"})
clicks = data.get("clicksBlocked", [])
print(f"[+] {len(clicks)} blocked clicks")
return clicks
def get_blocked_messages(principal, secret, hours=24):
"""Get messages that were blocked."""
print(f"[*] Fetching blocked messages (last {hours}h)...")
since = (datetime.now(timezone.utc) - timedelta(hours=hours)).strftime("%Y-%m-%dT%H:%M:%SZ")
data = pp_api("/v2/siem/messages/blocked", principal, secret,
params={"sinceTime": since, "format": "json"})
messages = data.get("messagesBlocked", [])
print(f"[+] {len(messages)} blocked messages")
return messages
def get_delivered_threats(principal, secret, hours=24):
"""Get threats that were delivered (missed by filters)."""
print(f"[*] Fetching delivered threats (last {hours}h)...")
since = (datetime.now(timezone.utc) - timedelta(hours=hours)).strftime("%Y-%m-%dT%H:%M:%SZ")
data = pp_api("/v2/siem/messages/delivered", principal, secret,
params={"sinceTime": since, "format": "json"})
messages = data.get("messagesDelivered", [])
threats = [m for m in messages if m.get("threatsInfoMap")]
print(f"[+] {len(messages)} delivered, {len(threats)} with threats")
return threats
def get_permitted_clicks(principal, secret, hours=24):
"""Get URLs that were permitted when clicked (potential misses)."""
print(f"[*] Fetching permitted clicks (last {hours}h)...")
since = (datetime.now(timezone.utc) - timedelta(hours=hours)).strftime("%Y-%m-%dT%H:%M:%SZ")
data = pp_api("/v2/siem/clicks/permitted", principal, secret,
params={"sinceTime": since, "format": "json"})
clicks = data.get("clicksPermitted", [])
print(f"[+] {len(clicks)} permitted clicks")
return clicks
def analyze_threats(blocked_msgs, delivered_threats, blocked_clicks, permitted_clicks):
"""Analyze threat data for security insights."""
findings = []
if not requests: return [{"error": "requests required"}]
headers = {"Authorization": f"Bearer {token}"}
try:
resp = requests.get(f"{target}/api/v1/status", headers=headers, timeout=10)
if resp.status_code == 200:
data = resp.json()
if not data.get("enabled", True):
findings.append({"check": "Service Status", "status": "DISABLED", "severity": "CRITICAL"})
elif resp.status_code == 401:
findings.append({"check": "Authentication", "status": "UNAUTHORIZED", "severity": "HIGH"})
except requests.RequestException as e:
findings.append({"error": str(e)})
# Delivered threats are highest priority
for msg in delivered_threats:
for threat_info in msg.get("threatsInfoMap", []):
findings.append({
"type": "delivered_threat",
"severity": "CRITICAL",
"threat_type": threat_info.get("threatType", ""),
"classification": threat_info.get("classification", ""),
"threat_url": threat_info.get("threat", "")[:100],
"recipient": msg.get("recipient", [""])[0] if msg.get("recipient") else "",
"sender": msg.get("sender", ""),
"subject": msg.get("subject", "")[:80],
"timestamp": msg.get("messageTime", ""),
})
# Summarize blocked activity
threat_types = {}
for msg in blocked_msgs:
for t in msg.get("threatsInfoMap", []):
tt = t.get("threatType", "unknown")
threat_types[tt] = threat_types.get(tt, 0) + 1
if threat_types:
findings.append({
"type": "blocked_summary",
"severity": "INFO",
"detail": f"Blocked threats by type: {json.dumps(threat_types)}",
"total_blocked": len(blocked_msgs),
})
# Permitted clicks on potentially malicious URLs
for click in permitted_clicks:
if click.get("threatStatus") == "active":
findings.append({
"type": "permitted_malicious_click",
"severity": "HIGH",
"url": click.get("url", "")[:100],
"user": click.get("recipient", [""])[0] if click.get("recipient") else "",
"click_time": click.get("clickTime", ""),
})
return findings
def check_compliance(target, token):
findings = []
if not requests: return []
headers = {"Authorization": f"Bearer {token}"}
try:
resp = requests.get(f"{target}/api/v1/compliance", headers=headers, timeout=10)
if resp.status_code == 200:
for item in resp.json().get("checks", []):
if item.get("status") != "PASS":
findings.append({"check": item.get("name"), "status": item.get("status"),
"severity": item.get("severity", "MEDIUM")})
except requests.RequestException:
pass
return findings
def format_summary(findings, blocked_msgs, delivered, blocked_clicks, permitted_clicks):
"""Print email security summary."""
print(f"\n{'='*60}")
print(f" Proofpoint Email Security Report")
print(f"{'='*60}")
print(f" Blocked Messages : {len(blocked_msgs)}")
print(f" Delivered Threats : {len(delivered)}")
print(f" Blocked Clicks : {len(blocked_clicks)}")
print(f" Permitted Clicks : {len(permitted_clicks)}")
print(f" Security Findings : {len(findings)}")
critical = [f for f in findings if f["severity"] == "CRITICAL"]
if critical:
print(f"\n CRITICAL - Threats That Bypassed Filters ({len(critical)}):")
for f in critical[:10]:
print(f" {f.get('threat_type', 'N/A'):15s} | "
f"To: {f.get('recipient', 'N/A'):30s} | "
f"{f.get('subject', '')[:40]}")
severity_counts = {}
for f in findings:
sev = f.get("severity", "INFO")
severity_counts[sev] = severity_counts.get(sev, 0) + 1
return severity_counts
def main():
p = argparse.ArgumentParser(description="Proofpoint email security gateway audit")
p.add_argument("--target", required=True, help="Target URL")
p.add_argument("--token", required=True, help="API token")
p.add_argument("--output", "-o", help="Output JSON report")
p.add_argument("--verbose", "-v", action="store_true")
a = p.parse_args()
print("[*] Proofpoint email security gateway audit")
report = {"timestamp": datetime.now(timezone.utc).isoformat(), "findings": []}
report["findings"].extend(audit_config(a.target, a.token))
report["findings"].extend(check_compliance(a.target, a.token))
high = sum(1 for f in report["findings"] if f.get("severity") in ("HIGH", "CRITICAL"))
report["risk_level"] = "HIGH" if high else "MEDIUM" if report["findings"] else "LOW"
print(f"[*] {len(report['findings'])} findings, risk: {report['risk_level']}")
if a.output:
with open(a.output, "w") as f: json.dump(report, f, indent=2)
else:
parser = argparse.ArgumentParser(description="Proofpoint email security audit agent")
parser.add_argument("--principal", help="TAP API principal (or PROOFPOINT_PRINCIPAL env)")
parser.add_argument("--secret", help="TAP API secret (or PROOFPOINT_SECRET env)")
parser.add_argument("--hours", type=int, default=24, help="Hours to look back (default: 24)")
parser.add_argument("--output", "-o", help="Output JSON report")
parser.add_argument("--verbose", "-v", action="store_true")
args = parser.parse_args()
if args.principal:
os.environ["PROOFPOINT_PRINCIPAL"] = args.principal
if args.secret:
os.environ["PROOFPOINT_SECRET"] = args.secret
principal, secret = get_pp_config()
blocked_msgs = get_blocked_messages(principal, secret, args.hours)
delivered = get_delivered_threats(principal, secret, args.hours)
blocked_clicks = get_blocked_clicks(principal, secret, args.hours)
permitted_clicks = get_permitted_clicks(principal, secret, args.hours)
findings = analyze_threats(blocked_msgs, delivered, blocked_clicks, permitted_clicks)
severity_counts = format_summary(findings, blocked_msgs, delivered, blocked_clicks, permitted_clicks)
report = {
"timestamp": datetime.now(timezone.utc).isoformat(),
"tool": "Proofpoint TAP",
"period_hours": args.hours,
"blocked_messages": len(blocked_msgs),
"delivered_threats": len(delivered),
"findings": findings,
"severity_counts": severity_counts,
"risk_level": (
"CRITICAL" if severity_counts.get("CRITICAL", 0) > 0
else "HIGH" if severity_counts.get("HIGH", 0) > 0
else "LOW"
),
}
if args.output:
with open(args.output, "w") as f:
json.dump(report, f, indent=2)
print(f"\n[+] Report saved to {args.output}")
elif args.verbose:
print(json.dumps(report, indent=2))
if __name__ == "__main__":
main()