mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-05 23:38:57 +03:00
Add folder anatomy (scripts/agent.py + references/api-reference.md) for 648 cybersecurity skills
Complete skill folder anatomy across all cybersecurity skills: - scripts/agent.py: 80-150 line Python agents using real libraries (impacket, boto3, azure-mgmt-*, kubernetes, pefile, yara, scapy, shodan, stix2, etc.) - references/api-reference.md: real API documentation with method signatures - LICENSE: MIT license for all skill folders
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for implementing and testing API rate limiting and throttling."""
|
||||
|
||||
import json
|
||||
import argparse
|
||||
import time
|
||||
from datetime import datetime
|
||||
from collections import defaultdict, Counter
|
||||
|
||||
|
||||
class TokenBucket:
|
||||
"""In-memory token bucket rate limiter."""
|
||||
def __init__(self, max_tokens=100, refill_rate=10.0):
|
||||
self.max_tokens = max_tokens
|
||||
self.refill_rate = refill_rate
|
||||
self.buckets = {}
|
||||
|
||||
def allow(self, client_id):
|
||||
now = time.time()
|
||||
if client_id not in self.buckets:
|
||||
self.buckets[client_id] = {"tokens": self.max_tokens, "last": now}
|
||||
bucket = self.buckets[client_id]
|
||||
elapsed = now - bucket["last"]
|
||||
bucket["tokens"] = min(self.max_tokens, bucket["tokens"] + elapsed * self.refill_rate)
|
||||
bucket["last"] = now
|
||||
if bucket["tokens"] >= 1:
|
||||
bucket["tokens"] -= 1
|
||||
return True, {"remaining": int(bucket["tokens"]), "limit": self.max_tokens}
|
||||
return False, {"remaining": 0, "retry_after": round((1 - bucket["tokens"]) / self.refill_rate, 2)}
|
||||
|
||||
|
||||
class SlidingWindow:
|
||||
"""In-memory sliding window rate limiter."""
|
||||
def __init__(self, window_seconds=60, max_requests=100):
|
||||
self.window = window_seconds
|
||||
self.max_requests = max_requests
|
||||
self.requests = defaultdict(list)
|
||||
|
||||
def allow(self, client_id):
|
||||
now = time.time()
|
||||
cutoff = now - self.window
|
||||
self.requests[client_id] = [t for t in self.requests[client_id] if t > cutoff]
|
||||
current = len(self.requests[client_id])
|
||||
if current < self.max_requests:
|
||||
self.requests[client_id].append(now)
|
||||
return True, {"remaining": self.max_requests - current - 1, "window": self.window}
|
||||
return False, {"remaining": 0, "retry_after": round(self.requests[client_id][0] - cutoff, 2)}
|
||||
|
||||
|
||||
def analyze_rate_limit_effectiveness(log_path):
|
||||
"""Analyze API logs to assess rate limiting effectiveness."""
|
||||
ip_requests = Counter()
|
||||
ip_429s = Counter()
|
||||
endpoint_load = Counter()
|
||||
with open(log_path) as f:
|
||||
for line in f:
|
||||
try:
|
||||
entry = json.loads(line)
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
ip = entry.get("client_ip", entry.get("ip", ""))
|
||||
status = int(entry.get("status_code", entry.get("status", 0)))
|
||||
endpoint = entry.get("path", entry.get("endpoint", ""))
|
||||
ip_requests[ip] += 1
|
||||
if status == 429:
|
||||
ip_429s[ip] += 1
|
||||
endpoint_load[endpoint] += 1
|
||||
findings = []
|
||||
for ip, total in ip_requests.most_common(20):
|
||||
rate_limited = ip_429s.get(ip, 0)
|
||||
if total > 1000 and rate_limited == 0:
|
||||
findings.append({
|
||||
"ip": ip, "total_requests": total, "rate_limited": 0,
|
||||
"issue": "high_volume_not_rate_limited", "severity": "HIGH",
|
||||
})
|
||||
elif rate_limited > 0 and rate_limited < total * 0.1:
|
||||
findings.append({
|
||||
"ip": ip, "total_requests": total, "rate_limited": rate_limited,
|
||||
"issue": "rate_limit_too_permissive", "severity": "MEDIUM",
|
||||
})
|
||||
return findings
|
||||
|
||||
|
||||
def simulate_rate_limit_test(algorithm="token_bucket", requests_count=200, rate=10):
|
||||
"""Simulate rate limiting to test configuration."""
|
||||
if algorithm == "token_bucket":
|
||||
limiter = TokenBucket(max_tokens=rate, refill_rate=rate / 60.0)
|
||||
else:
|
||||
limiter = SlidingWindow(window_seconds=60, max_requests=rate)
|
||||
allowed = 0
|
||||
denied = 0
|
||||
for i in range(requests_count):
|
||||
ok, _ = limiter.allow("test_client")
|
||||
if ok:
|
||||
allowed += 1
|
||||
else:
|
||||
denied += 1
|
||||
return {
|
||||
"algorithm": algorithm, "total_requests": requests_count,
|
||||
"allowed": allowed, "denied": denied,
|
||||
"effective_rate": round(allowed / requests_count * 100, 1),
|
||||
}
|
||||
|
||||
|
||||
def generate_rate_limit_recommendations(log_path):
|
||||
"""Generate rate limit recommendations from traffic patterns."""
|
||||
ip_rpm = defaultdict(int)
|
||||
endpoint_rpm = defaultdict(int)
|
||||
with open(log_path) as f:
|
||||
for line in f:
|
||||
try:
|
||||
entry = json.loads(line)
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
ip = entry.get("client_ip", "")
|
||||
endpoint = entry.get("path", "")
|
||||
ip_rpm[ip] += 1
|
||||
endpoint_rpm[endpoint] += 1
|
||||
ip_values = sorted(ip_rpm.values())
|
||||
p95 = ip_values[int(len(ip_values) * 0.95)] if ip_values else 100
|
||||
p99 = ip_values[int(len(ip_values) * 0.99)] if ip_values else 200
|
||||
return {
|
||||
"global_rate_limit": p99 * 2,
|
||||
"per_ip_limit": p95 * 2,
|
||||
"auth_endpoint_limit": max(10, p95 // 10),
|
||||
"p95_requests_per_ip": p95,
|
||||
"p99_requests_per_ip": p99,
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="API Rate Limiting Agent")
|
||||
parser.add_argument("--action", choices=[
|
||||
"analyze", "simulate", "recommend", "full"
|
||||
], default="full")
|
||||
parser.add_argument("--log", help="API access log (JSON lines)")
|
||||
parser.add_argument("--algorithm", choices=["token_bucket", "sliding_window"],
|
||||
default="token_bucket")
|
||||
parser.add_argument("--output", default="rate_limiting_report.json")
|
||||
args = parser.parse_args()
|
||||
|
||||
report = {"generated_at": datetime.utcnow().isoformat(), "findings": {}}
|
||||
|
||||
if args.action in ("analyze", "full") and args.log:
|
||||
f = analyze_rate_limit_effectiveness(args.log)
|
||||
report["findings"]["effectiveness"] = f
|
||||
print(f"[+] Rate limit issues: {len(f)}")
|
||||
|
||||
if args.action in ("simulate", "full"):
|
||||
result = simulate_rate_limit_test(args.algorithm)
|
||||
report["findings"]["simulation"] = result
|
||||
print(f"[+] Simulation: {result['allowed']}/{result['total_requests']} allowed")
|
||||
|
||||
if args.action in ("recommend", "full") and args.log:
|
||||
recs = generate_rate_limit_recommendations(args.log)
|
||||
report["findings"]["recommendations"] = recs
|
||||
print(f"[+] Recommended per-IP limit: {recs['per_ip_limit']}")
|
||||
|
||||
with open(args.output, "w") as fout:
|
||||
json.dump(report, fout, indent=2, default=str)
|
||||
print(f"[+] Report saved to {args.output}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user