mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-25 13:50:59 +03:00
Complete folder anatomy for all 649 cybersecurity skills + update LICENSE to Mahipal
- 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
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Anthropic Agent Skills Contributors
|
||||
Copyright (c) 2025 Mahipal
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# Software-Defined Perimeter — API Reference
|
||||
|
||||
## Core SDP Concepts
|
||||
|
||||
| Component | Description |
|
||||
|-----------|-------------|
|
||||
| SDP Controller | Central policy engine managing authentication and authorization |
|
||||
| SDP Gateway | Enforces access policies, terminates encrypted tunnels |
|
||||
| SDP Client | End-user agent performing Single Packet Authorization (SPA) |
|
||||
| SPA (Single Packet Authorization) | Cryptographic knock before TCP connection allowed |
|
||||
|
||||
## Appgate SDP Admin API
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|--------|----------|-------------|
|
||||
| POST | `/admin/login` | Authenticate and get Bearer token |
|
||||
| GET | `/admin/sites` | List configured sites |
|
||||
| GET | `/admin/policies` | List access policies |
|
||||
| GET | `/admin/entitlements` | List entitlements (resource access rules) |
|
||||
| GET | `/admin/appliances` | List SDP gateways and controllers |
|
||||
| GET | `/admin/identity-providers` | List identity providers |
|
||||
| POST | `/admin/entitlements` | Create new entitlement |
|
||||
|
||||
## Dark Port Scanning
|
||||
|
||||
```python
|
||||
import socket
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.settimeout(5)
|
||||
result = sock.connect_ex((host, port)) # Non-zero = port dark (SDP enforced)
|
||||
```
|
||||
|
||||
## Mutual TLS Verification
|
||||
|
||||
```python
|
||||
import ssl
|
||||
ctx = ssl.create_default_context()
|
||||
ctx.load_cert_chain("client.crt", "client.key")
|
||||
with ctx.wrap_socket(socket.socket(), server_hostname=host) as s:
|
||||
s.connect((host, 443))
|
||||
```
|
||||
|
||||
## SPA Packet Structure
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| Random Data | 16 bytes of random padding |
|
||||
| Username | SDP client identity |
|
||||
| Timestamp | Prevents replay attacks |
|
||||
| HMAC | SHA-256 authentication code |
|
||||
|
||||
## External References
|
||||
|
||||
- [Appgate SDP API Docs](https://sdphelp.appgate.com/adminguide/rest-api-guide.html)
|
||||
- [CSA SDP Specification](https://cloudsecurityalliance.org/research/sdp/)
|
||||
- [fwknop SPA Tool](https://www.cipherdyne.org/fwknop/)
|
||||
@@ -0,0 +1,176 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Software-Defined Perimeter (SDP) deployment audit agent."""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import argparse
|
||||
import socket
|
||||
import ssl
|
||||
from datetime import datetime
|
||||
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
print("Install: pip install requests")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def check_spa_port(host, port, timeout=5):
|
||||
"""Check if a port responds to standard TCP connect (should be dark in SDP)."""
|
||||
try:
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.settimeout(timeout)
|
||||
result = sock.connect_ex((host, port))
|
||||
sock.close()
|
||||
return {"host": host, "port": port, "open": result == 0}
|
||||
except socket.error as e:
|
||||
return {"host": host, "port": port, "open": False, "error": str(e)}
|
||||
|
||||
|
||||
def audit_dark_ports(host, ports):
|
||||
"""Verify SDP ports are invisible to unauthorized scanners."""
|
||||
results = []
|
||||
for port in ports:
|
||||
scan = check_spa_port(host, port)
|
||||
if scan.get("open"):
|
||||
scan["finding"] = "Port visible without SPA — SDP not enforced"
|
||||
scan["severity"] = "HIGH"
|
||||
else:
|
||||
scan["finding"] = "Port dark — SDP enforced"
|
||||
scan["severity"] = "INFO"
|
||||
results.append(scan)
|
||||
return results
|
||||
|
||||
|
||||
def check_tls_mutual_auth(host, port, client_cert=None, client_key=None):
|
||||
"""Verify mutual TLS authentication on SDP controller."""
|
||||
result = {"host": host, "port": port}
|
||||
try:
|
||||
ctx = ssl.create_default_context()
|
||||
if client_cert and client_key:
|
||||
ctx.load_cert_chain(client_cert, client_key)
|
||||
with ctx.wrap_socket(socket.socket(), server_hostname=host) as s:
|
||||
s.settimeout(10)
|
||||
s.connect((host, port))
|
||||
cert = s.getpeercert()
|
||||
result["tls_version"] = s.version()
|
||||
result["cipher"] = s.cipher()[0]
|
||||
result["server_cn"] = dict(x[0] for x in cert.get("subject", ()))
|
||||
result["mtls_enforced"] = client_cert is not None
|
||||
except ssl.SSLError as e:
|
||||
result["error"] = str(e)
|
||||
if "CERTIFICATE_REQUIRED" in str(e):
|
||||
result["mtls_enforced"] = True
|
||||
result["finding"] = "Server requires client certificate — mTLS enforced"
|
||||
except Exception as e:
|
||||
result["error"] = str(e)
|
||||
return result
|
||||
|
||||
|
||||
class SDPControllerClient:
|
||||
"""Client for SDP controller REST API (e.g., Appgate SDP)."""
|
||||
|
||||
def __init__(self, controller_url, username, password):
|
||||
self.base_url = controller_url.rstrip("/")
|
||||
self.session = requests.Session()
|
||||
self._authenticate(username, password)
|
||||
|
||||
def _authenticate(self, username, password):
|
||||
resp = self.session.post(f"{self.base_url}/admin/login", json={
|
||||
"providerName": "local",
|
||||
"username": username,
|
||||
"password": password,
|
||||
}, timeout=15, verify=True)
|
||||
resp.raise_for_status()
|
||||
token = resp.json().get("token", "")
|
||||
self.session.headers.update({"Authorization": f"Bearer {token}"})
|
||||
|
||||
def list_sites(self):
|
||||
resp = self.session.get(f"{self.base_url}/admin/sites", timeout=15)
|
||||
resp.raise_for_status()
|
||||
return resp.json().get("data", [])
|
||||
|
||||
def list_policies(self):
|
||||
resp = self.session.get(f"{self.base_url}/admin/policies", timeout=15)
|
||||
resp.raise_for_status()
|
||||
return resp.json().get("data", [])
|
||||
|
||||
def list_entitlements(self):
|
||||
resp = self.session.get(f"{self.base_url}/admin/entitlements", timeout=15)
|
||||
resp.raise_for_status()
|
||||
return resp.json().get("data", [])
|
||||
|
||||
def list_appliances(self):
|
||||
resp = self.session.get(f"{self.base_url}/admin/appliances", timeout=15)
|
||||
resp.raise_for_status()
|
||||
return resp.json().get("data", [])
|
||||
|
||||
|
||||
def run_audit(args):
|
||||
"""Execute SDP deployment audit."""
|
||||
print(f"\n{'='*60}")
|
||||
print(f" SOFTWARE-DEFINED PERIMETER AUDIT")
|
||||
print(f" Generated: {datetime.utcnow().isoformat()} UTC")
|
||||
print(f"{'='*60}\n")
|
||||
|
||||
report = {}
|
||||
|
||||
if args.scan_host:
|
||||
ports = [int(p) for p in args.ports.split(",")] if args.ports else [22, 443, 8443, 3389]
|
||||
dark_results = audit_dark_ports(args.scan_host, ports)
|
||||
report["dark_port_scan"] = dark_results
|
||||
print(f"--- DARK PORT SCAN ({args.scan_host}) ---")
|
||||
for r in dark_results:
|
||||
status = "OPEN" if r["open"] else "DARK"
|
||||
print(f" Port {r['port']}: {status} — {r['finding']}")
|
||||
|
||||
if args.mtls_host:
|
||||
mtls = check_tls_mutual_auth(args.mtls_host, args.mtls_port or 443,
|
||||
args.client_cert, args.client_key)
|
||||
report["mtls_check"] = mtls
|
||||
print(f"\n--- MUTUAL TLS CHECK ---")
|
||||
print(f" Host: {mtls['host']}:{mtls['port']}")
|
||||
print(f" mTLS Enforced: {mtls.get('mtls_enforced', 'unknown')}")
|
||||
if mtls.get("tls_version"):
|
||||
print(f" TLS Version: {mtls['tls_version']}")
|
||||
|
||||
if args.controller_url and args.username and args.password:
|
||||
client = SDPControllerClient(args.controller_url, args.username, args.password)
|
||||
appliances = client.list_appliances()
|
||||
report["appliances"] = len(appliances)
|
||||
print(f"\n--- SDP APPLIANCES ({len(appliances)}) ---")
|
||||
for a in appliances[:10]:
|
||||
print(f" {a.get('name', '')}: {a.get('function', '')} ({a.get('state', '')})")
|
||||
|
||||
entitlements = client.list_entitlements()
|
||||
report["entitlements"] = len(entitlements)
|
||||
print(f"\n--- ENTITLEMENTS ({len(entitlements)}) ---")
|
||||
for e in entitlements[:10]:
|
||||
print(f" {e.get('name', '')}: {e.get('site', '')} -> {e.get('actions', [])}")
|
||||
|
||||
return report
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="SDP Deployment Audit")
|
||||
parser.add_argument("--scan-host", help="Host to scan for dark ports")
|
||||
parser.add_argument("--ports", help="Comma-separated ports to scan (default: 22,443,8443,3389)")
|
||||
parser.add_argument("--mtls-host", help="Host to check mutual TLS")
|
||||
parser.add_argument("--mtls-port", type=int, default=443, help="mTLS port")
|
||||
parser.add_argument("--client-cert", help="Client certificate for mTLS test")
|
||||
parser.add_argument("--client-key", help="Client key for mTLS test")
|
||||
parser.add_argument("--controller-url", help="SDP controller URL (Appgate)")
|
||||
parser.add_argument("--username", help="Controller admin username")
|
||||
parser.add_argument("--password", help="Controller admin password")
|
||||
parser.add_argument("--output", help="Save report to JSON file")
|
||||
args = parser.parse_args()
|
||||
|
||||
report = run_audit(args)
|
||||
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()
|
||||
Reference in New Issue
Block a user