mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-12 22:24:56 +03:00
27c6414ca5
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
192 lines
6.9 KiB
Python
192 lines
6.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Agent for auditing Kubernetes cluster RBAC configurations."""
|
|
|
|
import os
|
|
import json
|
|
import argparse
|
|
from datetime import datetime
|
|
|
|
from kubernetes import client, config
|
|
|
|
|
|
def load_kube_config(kubeconfig=None, context=None):
|
|
"""Load Kubernetes configuration."""
|
|
if kubeconfig:
|
|
config.load_kube_config(config_file=kubeconfig, context=context)
|
|
else:
|
|
try:
|
|
config.load_incluster_config()
|
|
except config.ConfigException:
|
|
config.load_kube_config(context=context)
|
|
|
|
|
|
def list_cluster_roles_with_wildcards():
|
|
"""Find ClusterRoles with wildcard verb or resource permissions."""
|
|
rbac = client.RbacAuthorizationV1Api()
|
|
roles = rbac.list_cluster_role()
|
|
risky = []
|
|
for role in roles.items:
|
|
for rule in role.rules or []:
|
|
verbs = rule.verbs or []
|
|
resources = rule.resources or []
|
|
if "*" in verbs or "*" in resources:
|
|
risky.append({
|
|
"name": role.metadata.name,
|
|
"verbs": verbs,
|
|
"resources": resources,
|
|
"api_groups": rule.api_groups or [],
|
|
})
|
|
return risky
|
|
|
|
|
|
def list_secret_access_roles():
|
|
"""Find ClusterRoles that can read secrets."""
|
|
rbac = client.RbacAuthorizationV1Api()
|
|
roles = rbac.list_cluster_role()
|
|
results = []
|
|
for role in roles.items:
|
|
for rule in role.rules or []:
|
|
resources = rule.resources or []
|
|
verbs = rule.verbs or []
|
|
if ("secrets" in resources or "*" in resources) and \
|
|
("get" in verbs or "list" in verbs or "*" in verbs):
|
|
if not role.metadata.name.startswith("system:"):
|
|
results.append({
|
|
"role": role.metadata.name,
|
|
"verbs": verbs,
|
|
"resources": resources,
|
|
})
|
|
return results
|
|
|
|
|
|
def list_cluster_admin_bindings():
|
|
"""Find all ClusterRoleBindings that grant cluster-admin."""
|
|
rbac = client.RbacAuthorizationV1Api()
|
|
bindings = rbac.list_cluster_role_binding()
|
|
results = []
|
|
for binding in bindings.items:
|
|
if binding.role_ref.name == "cluster-admin":
|
|
subjects = []
|
|
for s in binding.subjects or []:
|
|
subjects.append({
|
|
"kind": s.kind,
|
|
"name": s.name,
|
|
"namespace": s.namespace or "cluster-wide",
|
|
})
|
|
results.append({
|
|
"binding": binding.metadata.name,
|
|
"subjects": subjects,
|
|
})
|
|
return results
|
|
|
|
|
|
def find_dangerous_bindings():
|
|
"""Find bindings granting access to system:authenticated or system:unauthenticated."""
|
|
rbac = client.RbacAuthorizationV1Api()
|
|
bindings = rbac.list_cluster_role_binding()
|
|
dangerous = []
|
|
for binding in bindings.items:
|
|
for s in binding.subjects or []:
|
|
if s.name in ("system:authenticated", "system:unauthenticated"):
|
|
dangerous.append({
|
|
"binding": binding.metadata.name,
|
|
"role": binding.role_ref.name,
|
|
"subject": s.name,
|
|
})
|
|
return dangerous
|
|
|
|
|
|
def audit_service_account_tokens():
|
|
"""Find pods with automounted service account tokens."""
|
|
v1 = client.CoreV1Api()
|
|
pods = v1.list_pod_for_all_namespaces()
|
|
risky_pods = []
|
|
for pod in pods.items:
|
|
spec = pod.spec
|
|
sa = spec.service_account_name or "default"
|
|
automount = spec.automount_service_account_token
|
|
if automount is not False and sa != "default":
|
|
risky_pods.append({
|
|
"namespace": pod.metadata.namespace,
|
|
"pod": pod.metadata.name,
|
|
"service_account": sa,
|
|
"automount": True,
|
|
})
|
|
return risky_pods
|
|
|
|
|
|
def find_privileged_containers():
|
|
"""Find containers running as privileged or root."""
|
|
v1 = client.CoreV1Api()
|
|
pods = v1.list_pod_for_all_namespaces()
|
|
privileged = []
|
|
for pod in pods.items:
|
|
for container in pod.spec.containers or []:
|
|
sc = container.security_context
|
|
if sc:
|
|
is_privileged = getattr(sc, "privileged", False)
|
|
run_as_root = getattr(sc, "run_as_user", None) == 0
|
|
if is_privileged or run_as_root:
|
|
privileged.append({
|
|
"namespace": pod.metadata.namespace,
|
|
"pod": pod.metadata.name,
|
|
"container": container.name,
|
|
"privileged": is_privileged,
|
|
"run_as_root": run_as_root,
|
|
})
|
|
return privileged
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Kubernetes RBAC Audit Agent")
|
|
parser.add_argument("--kubeconfig", default=os.getenv("KUBECONFIG"))
|
|
parser.add_argument("--context", help="Kubernetes context to use")
|
|
parser.add_argument("--output", default="k8s_rbac_audit.json")
|
|
parser.add_argument("--action", choices=[
|
|
"wildcards", "secrets", "cluster_admin", "dangerous",
|
|
"tokens", "privileged", "full_audit"
|
|
], default="full_audit")
|
|
args = parser.parse_args()
|
|
|
|
load_kube_config(args.kubeconfig, args.context)
|
|
report = {"audit_date": datetime.utcnow().isoformat(), "findings": {}}
|
|
|
|
if args.action in ("wildcards", "full_audit"):
|
|
wildcards = list_cluster_roles_with_wildcards()
|
|
report["findings"]["wildcard_roles"] = wildcards
|
|
print(f"[+] Wildcard ClusterRoles: {len(wildcards)}")
|
|
|
|
if args.action in ("secrets", "full_audit"):
|
|
secret_roles = list_secret_access_roles()
|
|
report["findings"]["secret_access_roles"] = secret_roles
|
|
print(f"[+] Roles with secret access: {len(secret_roles)}")
|
|
|
|
if args.action in ("cluster_admin", "full_audit"):
|
|
admins = list_cluster_admin_bindings()
|
|
report["findings"]["cluster_admin_bindings"] = admins
|
|
total_subjects = sum(len(a["subjects"]) for a in admins)
|
|
print(f"[+] cluster-admin bindings: {len(admins)} ({total_subjects} subjects)")
|
|
|
|
if args.action in ("dangerous", "full_audit"):
|
|
danger = find_dangerous_bindings()
|
|
report["findings"]["dangerous_bindings"] = danger
|
|
print(f"[+] Dangerous bindings: {len(danger)}")
|
|
|
|
if args.action in ("tokens", "full_audit"):
|
|
tokens = audit_service_account_tokens()
|
|
report["findings"]["automounted_tokens"] = tokens
|
|
print(f"[+] Pods with automounted tokens: {len(tokens)}")
|
|
|
|
if args.action in ("privileged", "full_audit"):
|
|
priv = find_privileged_containers()
|
|
report["findings"]["privileged_containers"] = priv
|
|
print(f"[+] Privileged containers: {len(priv)}")
|
|
|
|
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()
|