mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-25 13:50:59 +03:00
Production hardening: security fixes, code quality, 724 skills complete
- Fix 25 shell=True subprocess calls with list-based commands - Fix 49 verify=False in defensive skills (env-var override) - Add timeout to 231 HTTP/subprocess/socket calls - Fix 6 SQL injection patterns with whitelist validation - Replace 8 __import__() with standard imports - Remove 701 unused imports across 442 files - Add authorized-testing disclaimers to all offensive skills - Complete 11 incomplete skill directories - Expand 10 stub SKILL.md files with full content - Fix 2 YAML parse errors in frontmatter - Fix 5 pre-existing syntax errors - Convert 22 hardcoded paths/ports to environment variables - Back up 21 redundant skill pairs to .bak - Fix 2 global declaration errors - 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE) - 0 compile errors across all 724 agent.py files
This commit is contained in:
+170
-14
@@ -1,27 +1,183 @@
|
||||
# API Reference: OPA policy-as-code implementation audit
|
||||
# API Reference: Open Policy Agent (OPA) Policy-as-Code
|
||||
|
||||
## API Endpoints
|
||||
OPA: POST /v1/data/{package}, PUT /v1/policies/{id}, GET /v1/data, Rego policy language
|
||||
## Libraries Used
|
||||
|
||||
| Library | Purpose |
|
||||
|---------|---------|
|
||||
| `requests` | HTTP client for OPA REST API |
|
||||
| `json` | Parse OPA decision responses |
|
||||
| `subprocess` | Run `opa eval` and `opa test` CLI commands |
|
||||
| `yaml` | Parse Kubernetes admission review objects |
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install requests
|
||||
# OPA binary
|
||||
curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_linux_amd64_static
|
||||
chmod 755 opa && sudo mv opa /usr/local/bin/
|
||||
|
||||
# Python dependencies
|
||||
pip install requests pyyaml
|
||||
```
|
||||
|
||||
## Libraries
|
||||
## OPA REST API Endpoints
|
||||
|
||||
| Library | Use |
|
||||
|---------|-----|
|
||||
| `requests` | requests SDK/client |
|
||||
| Method | Endpoint | Description |
|
||||
|--------|----------|-------------|
|
||||
| PUT | `/v1/policies/{id}` | Create or update a policy module |
|
||||
| GET | `/v1/policies/{id}` | Retrieve a policy module |
|
||||
| DELETE | `/v1/policies/{id}` | Delete a policy module |
|
||||
| GET | `/v1/policies` | List all policy modules |
|
||||
| PUT | `/v1/data/{path}` | Create or overwrite a document |
|
||||
| GET | `/v1/data/{path}` | Evaluate a rule or retrieve data |
|
||||
| POST | `/v1/data/{path}` | Evaluate a rule with input |
|
||||
| PATCH | `/v1/data/{path}` | Patch a data document |
|
||||
| POST | `/v1/query` | Execute ad-hoc Rego query |
|
||||
| POST | `/v1/compile` | Partially evaluate a query |
|
||||
| GET | `/health` | Health check (liveness) |
|
||||
| GET | `/health?bundles` | Health check including bundle status |
|
||||
|
||||
## Authentication
|
||||
## Core Operations
|
||||
|
||||
| Method | Header |
|
||||
|--------|--------|
|
||||
| Bearer Token | `Authorization: Bearer <token>` |
|
||||
| API Key | `X-API-Key: <key>` |
|
||||
### Upload a Rego Policy
|
||||
```python
|
||||
import requests
|
||||
import os
|
||||
|
||||
OPA_URL = os.environ.get("OPA_URL", "http://localhost:8181")
|
||||
|
||||
policy_rego = """
|
||||
package authz
|
||||
|
||||
default allow := false
|
||||
|
||||
allow if {
|
||||
input.user.role == "admin"
|
||||
}
|
||||
|
||||
allow if {
|
||||
input.user.role == "editor"
|
||||
input.action == "read"
|
||||
}
|
||||
"""
|
||||
|
||||
resp = requests.put(
|
||||
f"{OPA_URL}/v1/policies/authz",
|
||||
data=policy_rego,
|
||||
headers={"Content-Type": "text/plain"},
|
||||
timeout=10,
|
||||
)
|
||||
resp.raise_for_status()
|
||||
```
|
||||
|
||||
### Evaluate a Policy Decision
|
||||
```python
|
||||
decision_input = {
|
||||
"input": {
|
||||
"user": {"role": "editor", "name": "alice"},
|
||||
"action": "read",
|
||||
"resource": "/api/reports",
|
||||
}
|
||||
}
|
||||
|
||||
resp = requests.post(
|
||||
f"{OPA_URL}/v1/data/authz/allow",
|
||||
json=decision_input,
|
||||
timeout=10,
|
||||
)
|
||||
result = resp.json()
|
||||
allowed = result.get("result", False) # True
|
||||
```
|
||||
|
||||
### Upload Data Documents
|
||||
```python
|
||||
role_permissions = {
|
||||
"admin": ["read", "write", "delete", "admin"],
|
||||
"editor": ["read", "write"],
|
||||
"viewer": ["read"],
|
||||
}
|
||||
|
||||
resp = requests.put(
|
||||
f"{OPA_URL}/v1/data/roles",
|
||||
json=role_permissions,
|
||||
timeout=10,
|
||||
)
|
||||
```
|
||||
|
||||
### List All Policies
|
||||
```python
|
||||
resp = requests.get(f"{OPA_URL}/v1/policies", timeout=10)
|
||||
policies = resp.json().get("result", [])
|
||||
for p in policies:
|
||||
print(f" {p['id']} — {len(p.get('raw', ''))} bytes")
|
||||
```
|
||||
|
||||
## OPA CLI Reference
|
||||
|
||||
```bash
|
||||
# Evaluate a policy locally
|
||||
opa eval -i input.json -d policy.rego "data.authz.allow"
|
||||
|
||||
# Run Rego unit tests
|
||||
opa test ./policies/ -v
|
||||
|
||||
# Check policy syntax
|
||||
opa check policy.rego
|
||||
|
||||
# Format Rego files
|
||||
opa fmt -w policy.rego
|
||||
|
||||
# Start OPA as a server
|
||||
opa run --server --addr :8181 ./policies/ ./data/
|
||||
|
||||
# Build an OPA bundle
|
||||
opa build -b ./policies/ -o bundle.tar.gz
|
||||
```
|
||||
|
||||
## Kubernetes Gatekeeper Integration
|
||||
|
||||
```yaml
|
||||
apiVersion: templates.gatekeeper.sh/v1
|
||||
kind: ConstraintTemplate
|
||||
metadata:
|
||||
name: k8srequiredlabels
|
||||
spec:
|
||||
crd:
|
||||
spec:
|
||||
names:
|
||||
kind: K8sRequiredLabels
|
||||
validation:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
labels:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
targets:
|
||||
- target: admission.k8s.gatekeeper.sh
|
||||
rego: |
|
||||
package k8srequiredlabels
|
||||
violation[{"msg": msg}] {
|
||||
provided := {l | input.review.object.metadata.labels[l]}
|
||||
required := {l | l := input.parameters.labels[_]}
|
||||
missing := required - provided
|
||||
count(missing) > 0
|
||||
msg := sprintf("Missing required labels: %v", [missing])
|
||||
}
|
||||
```
|
||||
|
||||
## Output Format
|
||||
|
||||
```json
|
||||
{"timestamp": "ISO-8601", "findings": [], "risk_level": "HIGH"}
|
||||
{
|
||||
"decision_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
||||
"result": true,
|
||||
"policy": "data.authz.allow",
|
||||
"input": {
|
||||
"user": {"role": "admin"},
|
||||
"action": "delete",
|
||||
"resource": "/api/users/42"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,61 +1,273 @@
|
||||
#!/usr/bin/env python3
|
||||
"""OPA policy-as-code implementation audit."""
|
||||
import argparse, json, sys
|
||||
"""Open Policy Agent (OPA) policy-as-code agent.
|
||||
|
||||
Evaluates security policies against infrastructure configurations using
|
||||
the OPA REST API or CLI. Supports evaluating Rego policies for Kubernetes
|
||||
admission control, Terraform plans, IAM policies, and custom security rules.
|
||||
"""
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
requests = None
|
||||
|
||||
def audit_config(target, token):
|
||||
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)})
|
||||
return findings
|
||||
|
||||
def check_compliance(target, token):
|
||||
findings = []
|
||||
if not requests: return []
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
def find_opa_binary():
|
||||
"""Locate the OPA binary on the system."""
|
||||
custom_path = os.environ.get("OPA_PATH")
|
||||
if custom_path and os.path.isfile(custom_path):
|
||||
return custom_path
|
||||
for name in ["opa", "opa.exe"]:
|
||||
for directory in os.environ.get("PATH", "").split(os.pathsep):
|
||||
full_path = os.path.join(directory, name)
|
||||
if os.path.isfile(full_path):
|
||||
return full_path
|
||||
return None
|
||||
|
||||
|
||||
def eval_policy_cli(opa_bin, policy_path, input_path, data_path=None, query="data"):
|
||||
"""Evaluate a Rego policy using OPA CLI."""
|
||||
cmd = [opa_bin, "eval", "--format", "json"]
|
||||
cmd.extend(["--bundle", policy_path])
|
||||
if input_path:
|
||||
cmd.extend(["--input", input_path])
|
||||
if data_path:
|
||||
cmd.extend(["--data", data_path])
|
||||
cmd.append(query)
|
||||
|
||||
print(f"[*] Running: {' '.join(cmd)}")
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=120,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
print(f"[!] OPA error: {result.stderr}", file=sys.stderr)
|
||||
return None
|
||||
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
|
||||
return json.loads(result.stdout)
|
||||
except json.JSONDecodeError:
|
||||
print(f"[!] Failed to parse OPA output", file=sys.stderr)
|
||||
return None
|
||||
|
||||
|
||||
def eval_policy_api(opa_url, policy_path, input_data):
|
||||
"""Evaluate a policy via OPA REST API."""
|
||||
if not requests:
|
||||
print("[!] 'requests' library required for API mode", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
url = f"{opa_url}/v1/data/{policy_path.replace('.', '/')}"
|
||||
print(f"[*] Querying OPA API: {url}")
|
||||
resp = requests.post(
|
||||
url,
|
||||
json={"input": input_data},
|
||||
timeout=30,
|
||||
)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
|
||||
def test_policies(opa_bin, policy_dir):
|
||||
"""Run OPA test suite against policy directory."""
|
||||
cmd = [opa_bin, "test", "--format", "json", policy_dir, "-v"]
|
||||
print(f"[*] Running policy tests: {' '.join(cmd)}")
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=120,
|
||||
)
|
||||
try:
|
||||
test_results = json.loads(result.stdout)
|
||||
except json.JSONDecodeError:
|
||||
test_results = []
|
||||
return test_results, result.returncode
|
||||
|
||||
|
||||
def check_policy_syntax(opa_bin, policy_path):
|
||||
"""Check Rego policy syntax."""
|
||||
cmd = [opa_bin, "check", "--format", "json", policy_path]
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=30,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
print(f"[+] Policy syntax valid: {policy_path}")
|
||||
return True, []
|
||||
try:
|
||||
errors = json.loads(result.stdout)
|
||||
except json.JSONDecodeError:
|
||||
errors = [{"message": result.stderr}]
|
||||
print(f"[!] Syntax errors in {policy_path}")
|
||||
return False, errors
|
||||
|
||||
|
||||
def extract_violations(eval_result, violation_key="violations"):
|
||||
"""Extract policy violations from OPA evaluation result."""
|
||||
violations = []
|
||||
if not eval_result:
|
||||
return violations
|
||||
|
||||
results = eval_result.get("result", [])
|
||||
if isinstance(results, list):
|
||||
for entry in results:
|
||||
bindings = entry.get("bindings", {})
|
||||
expressions = entry.get("expressions", [])
|
||||
for expr in expressions:
|
||||
value = expr.get("value", {})
|
||||
if isinstance(value, dict):
|
||||
for key, val in value.items():
|
||||
if key == violation_key and isinstance(val, list):
|
||||
violations.extend(val)
|
||||
elif isinstance(val, dict):
|
||||
nested_violations = val.get(violation_key, [])
|
||||
if isinstance(nested_violations, list):
|
||||
violations.extend(nested_violations)
|
||||
elif isinstance(results, dict):
|
||||
violations = results.get(violation_key, [])
|
||||
|
||||
return violations
|
||||
|
||||
|
||||
def format_summary(violations, test_results, policy_path, input_path):
|
||||
"""Print evaluation summary."""
|
||||
print(f"\n{'='*60}")
|
||||
print(f" OPA Policy Evaluation Report")
|
||||
print(f"{'='*60}")
|
||||
print(f" Policy : {policy_path}")
|
||||
print(f" Input : {input_path or 'N/A'}")
|
||||
print(f" Violations: {len(violations)}")
|
||||
|
||||
if test_results:
|
||||
passed = sum(1 for t in test_results if t.get("pass", t.get("result") == "pass"))
|
||||
failed = len(test_results) - passed
|
||||
print(f" Tests : {passed} passed, {failed} failed")
|
||||
|
||||
if violations:
|
||||
severity_counts = {}
|
||||
for v in violations:
|
||||
sev = "HIGH"
|
||||
if isinstance(v, dict):
|
||||
sev = v.get("severity", v.get("level", "HIGH"))
|
||||
severity_counts[sev] = severity_counts.get(sev, 0) + 1
|
||||
|
||||
print(f"\n Violations by Severity:")
|
||||
for sev, count in sorted(severity_counts.items()):
|
||||
print(f" {sev:10s}: {count}")
|
||||
|
||||
print(f"\n Violation Details:")
|
||||
for v in violations[:20]:
|
||||
if isinstance(v, dict):
|
||||
msg = v.get("msg", v.get("message", str(v)))
|
||||
resource = v.get("resource", v.get("name", ""))
|
||||
sev = v.get("severity", "HIGH")
|
||||
print(f" [{sev:6s}] {resource:30s} | {msg[:60]}")
|
||||
else:
|
||||
print(f" {str(v)[:80]}")
|
||||
|
||||
return len(violations)
|
||||
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser(description="OPA policy-as-code implementation 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("[*] OPA policy-as-code implementation 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="Open Policy Agent policy-as-code evaluation agent"
|
||||
)
|
||||
sub = parser.add_subparsers(dest="command", help="Action")
|
||||
|
||||
p_eval = sub.add_parser("eval", help="Evaluate policy against input")
|
||||
p_eval.add_argument("--policy", required=True, help="Path to Rego policy or bundle dir")
|
||||
p_eval.add_argument("--input", dest="input_file", help="Path to input JSON")
|
||||
p_eval.add_argument("--data", help="Path to external data JSON")
|
||||
p_eval.add_argument("--query", default="data", help="OPA query (default: data)")
|
||||
p_eval.add_argument("--violation-key", default="violations",
|
||||
help="Key in result containing violations")
|
||||
|
||||
p_api = sub.add_parser("api", help="Evaluate via OPA REST API")
|
||||
p_api.add_argument("--url", default="http://localhost:8181", help="OPA server URL")
|
||||
p_api.add_argument("--policy-path", required=True, help="OPA document path (e.g., authz.allow)")
|
||||
p_api.add_argument("--input", dest="input_file", required=True, help="Input JSON file")
|
||||
|
||||
p_test = sub.add_parser("test", help="Run OPA test suite")
|
||||
p_test.add_argument("--policy-dir", required=True, help="Directory containing policies and tests")
|
||||
|
||||
p_check = sub.add_parser("check", help="Check Rego syntax")
|
||||
p_check.add_argument("--policy", required=True, help="Policy file or directory")
|
||||
|
||||
parser.add_argument("--output", "-o", help="Output JSON report path")
|
||||
parser.add_argument("--verbose", "-v", action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.command:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
opa_bin = find_opa_binary()
|
||||
violations = []
|
||||
test_results = []
|
||||
|
||||
if args.command == "eval":
|
||||
if not opa_bin:
|
||||
print("[!] OPA binary not found", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
eval_result = eval_policy_cli(
|
||||
opa_bin, args.policy, args.input_file, args.data, args.query
|
||||
)
|
||||
violations = extract_violations(eval_result, args.violation_key)
|
||||
format_summary(violations, [], args.policy, args.input_file)
|
||||
|
||||
elif args.command == "api":
|
||||
with open(args.input_file, "r") as f:
|
||||
input_data = json.load(f)
|
||||
eval_result = eval_policy_api(args.url, args.policy_path, input_data)
|
||||
violations = extract_violations(eval_result)
|
||||
format_summary(violations, [], args.policy_path, args.input_file)
|
||||
|
||||
elif args.command == "test":
|
||||
if not opa_bin:
|
||||
print("[!] OPA binary not found", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
test_results, returncode = test_policies(opa_bin, args.policy_dir)
|
||||
format_summary([], test_results, args.policy_dir, None)
|
||||
|
||||
elif args.command == "check":
|
||||
if not opa_bin:
|
||||
print("[!] OPA binary not found", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
valid, errors = check_policy_syntax(opa_bin, args.policy)
|
||||
if not valid:
|
||||
for e in errors:
|
||||
print(f" Error: {e}")
|
||||
|
||||
report = {
|
||||
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||
"tool": "Open Policy Agent",
|
||||
"command": args.command,
|
||||
"violations_count": len(violations),
|
||||
"violations": violations,
|
||||
"test_results": test_results,
|
||||
"risk_level": (
|
||||
"CRITICAL" if len(violations) > 10
|
||||
else "HIGH" if len(violations) > 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()
|
||||
|
||||
Reference in New Issue
Block a user