Files
Anthropic-Cybersecurity-Skills/skills/implementing-cloud-waf-rules/scripts/agent.py
T
mukul975 27c6414ca5 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
2026-03-10 21:02:12 +01:00

211 lines
8.2 KiB
Python

#!/usr/bin/env python3
"""Cloud WAF rules management agent using AWS WAFv2 boto3 client."""
import json
import sys
import argparse
from datetime import datetime
try:
import boto3
from botocore.exceptions import ClientError
except ImportError:
print("Install boto3: pip install boto3")
sys.exit(1)
MANAGED_RULE_GROUPS = [
{"vendor": "AWS", "name": "AWSManagedRulesCommonRuleSet",
"description": "OWASP Top 10 core protection"},
{"vendor": "AWS", "name": "AWSManagedRulesSQLiRuleSet",
"description": "SQL injection protection"},
{"vendor": "AWS", "name": "AWSManagedRulesKnownBadInputsRuleSet",
"description": "Known malicious input patterns"},
{"vendor": "AWS", "name": "AWSManagedRulesLinuxRuleSet",
"description": "Linux-specific LFI protection"},
{"vendor": "AWS", "name": "AWSManagedRulesBotControlRuleSet",
"description": "Bot management and detection"},
{"vendor": "AWS", "name": "AWSManagedRulesATPRuleSet",
"description": "Account takeover prevention"},
]
def get_waf_client(region="us-east-1", scope="REGIONAL"):
"""Create WAFv2 client."""
return boto3.client("wafv2", region_name=region)
def create_web_acl(client, name, scope="REGIONAL", description=""):
"""Create a new Web ACL with default block action."""
try:
resp = client.create_web_acl(
Name=name, Scope=scope,
DefaultAction={"Allow": {}},
Description=description or f"WAF ACL managed by agent - {name}",
VisibilityConfig={
"SampledRequestsEnabled": True, "CloudWatchMetricsEnabled": True,
"MetricName": name.replace("-", "")},
Rules=[])
return {"arn": resp["Summary"]["ARN"], "id": resp["Summary"]["Id"],
"status": "created"}
except ClientError as e:
return {"error": str(e)}
def add_managed_rule_group(client, acl_name, acl_id, lock_token, scope,
vendor, rule_group_name, priority):
"""Add a managed rule group to an existing Web ACL."""
try:
acl = client.get_web_acl(Name=acl_name, Scope=scope, Id=acl_id)
rules = acl["WebACL"]["Rules"]
lock_token = acl["LockToken"]
rules.append({
"Name": rule_group_name,
"Priority": priority,
"Statement": {
"ManagedRuleGroupStatement": {"VendorName": vendor, "Name": rule_group_name}},
"OverrideAction": {"None": {}},
"VisibilityConfig": {
"SampledRequestsEnabled": True, "CloudWatchMetricsEnabled": True,
"MetricName": rule_group_name}})
client.update_web_acl(
Name=acl_name, Scope=scope, Id=acl_id, LockToken=lock_token,
DefaultAction={"Allow": {}}, Rules=rules,
VisibilityConfig=acl["WebACL"]["VisibilityConfig"])
return {"rule_group": rule_group_name, "status": "added", "priority": priority}
except ClientError as e:
return {"rule_group": rule_group_name, "error": str(e)}
def create_rate_limit_rule(client, acl_name, acl_id, scope, limit=2000, priority=1):
"""Create a rate-limiting rule for DDoS/brute-force protection."""
try:
acl = client.get_web_acl(Name=acl_name, Scope=scope, Id=acl_id)
rules = acl["WebACL"]["Rules"]
lock_token = acl["LockToken"]
rules.append({
"Name": "RateLimitRule",
"Priority": priority,
"Statement": {"RateBasedStatement": {"Limit": limit, "AggregateKeyType": "IP"}},
"Action": {"Block": {}},
"VisibilityConfig": {
"SampledRequestsEnabled": True, "CloudWatchMetricsEnabled": True,
"MetricName": "RateLimitRule"}})
client.update_web_acl(
Name=acl_name, Scope=scope, Id=acl_id, LockToken=lock_token,
DefaultAction={"Allow": {}}, Rules=rules,
VisibilityConfig=acl["WebACL"]["VisibilityConfig"])
return {"rule": "RateLimitRule", "limit": limit, "status": "created"}
except ClientError as e:
return {"error": str(e)}
def create_geo_block_rule(client, acl_name, acl_id, scope, country_codes, priority=2):
"""Create a geo-blocking rule for specified country codes."""
try:
acl = client.get_web_acl(Name=acl_name, Scope=scope, Id=acl_id)
rules = acl["WebACL"]["Rules"]
lock_token = acl["LockToken"]
rules.append({
"Name": "GeoBlockRule",
"Priority": priority,
"Statement": {"GeoMatchStatement": {"CountryCodes": country_codes}},
"Action": {"Block": {}},
"VisibilityConfig": {
"SampledRequestsEnabled": True, "CloudWatchMetricsEnabled": True,
"MetricName": "GeoBlockRule"}})
client.update_web_acl(
Name=acl_name, Scope=scope, Id=acl_id, LockToken=lock_token,
DefaultAction={"Allow": {}}, Rules=rules,
VisibilityConfig=acl["WebACL"]["VisibilityConfig"])
return {"rule": "GeoBlockRule", "countries": country_codes, "status": "created"}
except ClientError as e:
return {"error": str(e)}
def list_web_acls(client, scope="REGIONAL"):
"""List all Web ACLs."""
try:
resp = client.list_web_acls(Scope=scope)
return [{"name": acl["Name"], "id": acl["Id"], "arn": acl["ARN"]}
for acl in resp.get("WebACLs", [])]
except ClientError as e:
return [{"error": str(e)}]
def get_sampled_requests(client, acl_arn, rule_metric, scope="REGIONAL", max_items=100):
"""Get sampled requests for WAF rule analysis."""
try:
resp = client.get_sampled_requests(
WebAclArn=acl_arn, RuleMetricName=rule_metric, Scope=scope,
TimeWindow={"StartTime": datetime.utcnow().replace(hour=0, minute=0),
"EndTime": datetime.utcnow()},
MaxItems=max_items)
return [{"action": r["Action"], "uri": r["Request"]["URI"],
"method": r["Request"]["Method"],
"country": r["Request"].get("Country", ""),
"source_ip": r["Request"]["ClientIP"]}
for r in resp.get("SampledRequests", [])]
except ClientError as e:
return [{"error": str(e)}]
def run_waf_audit(region="us-east-1", scope="REGIONAL"):
"""Run WAF configuration audit."""
client = get_waf_client(region, scope)
print(f"\n{'='*60}")
print(f" AWS WAF CONFIGURATION AUDIT")
print(f" Region: {region} | Scope: {scope}")
print(f" Generated: {datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')} UTC")
print(f"{'='*60}\n")
acls = list_web_acls(client, scope)
print(f"--- WEB ACLs ({len(acls)}) ---")
for acl in acls:
if "error" in acl:
print(f" Error: {acl['error']}")
continue
print(f" {acl['name']} ({acl['id']})")
try:
detail = client.get_web_acl(Name=acl["name"], Scope=scope, Id=acl["id"])
rules = detail["WebACL"]["Rules"]
print(f" Rules: {len(rules)}")
for r in rules:
print(f" [{r['Priority']}] {r['Name']}")
except ClientError:
pass
print(f"\n--- AVAILABLE MANAGED RULE GROUPS ---")
for mrg in MANAGED_RULE_GROUPS:
print(f" {mrg['name']}: {mrg['description']}")
print(f"\n{'='*60}\n")
return {"acls": acls}
def main():
parser = argparse.ArgumentParser(description="Cloud WAF Rules Agent")
parser.add_argument("--region", default="us-east-1")
parser.add_argument("--scope", default="REGIONAL", choices=["REGIONAL", "CLOUDFRONT"])
parser.add_argument("--audit", action="store_true", help="Audit WAF configuration")
parser.add_argument("--create-acl", help="Create new Web ACL with given name")
parser.add_argument("--output", help="Save report to JSON")
args = parser.parse_args()
if args.audit:
report = run_waf_audit(args.region, args.scope)
if args.output:
with open(args.output, "w") as f:
json.dump(report, f, indent=2, default=str)
elif args.create_acl:
client = get_waf_client(args.region, args.scope)
result = create_web_acl(client, args.create_acl, args.scope)
print(json.dumps(result, indent=2))
else:
parser.print_help()
if __name__ == "__main__":
main()