mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-16 20:55:17 +03:00
Initial commit - 611 cybersecurity skills across all subdomains
This commit is contained in:
@@ -0,0 +1,307 @@
|
||||
---
|
||||
name: implementing-policy-as-code-with-open-policy-agent
|
||||
description: >
|
||||
This skill covers implementing Open Policy Agent (OPA) and Gatekeeper for policy-as-code
|
||||
enforcement in Kubernetes and CI/CD pipelines. It addresses writing Rego policies, deploying
|
||||
OPA Gatekeeper as a Kubernetes admission controller, testing policies in development, and
|
||||
integrating policy evaluation into deployment pipelines.
|
||||
domain: cybersecurity
|
||||
subdomain: devsecops
|
||||
tags: [devsecops, cicd, opa, gatekeeper, policy-as-code, kubernetes, secure-sdlc]
|
||||
version: 1.0.0
|
||||
author: mahipal
|
||||
license: MIT
|
||||
---
|
||||
|
||||
# Implementing Policy as Code with Open Policy Agent
|
||||
|
||||
## When to Use
|
||||
|
||||
- When enforcing organizational security policies across Kubernetes clusters programmatically
|
||||
- When requiring admission control that blocks non-compliant resources from being created
|
||||
- When implementing policy governance that can be version-controlled, tested, and audited
|
||||
- When standardizing security rules across multiple clusters and environments
|
||||
- When needing a flexible policy engine that extends beyond Kubernetes to APIs and CI/CD
|
||||
|
||||
**Do not use** for vulnerability scanning (use Trivy/Checkov), for runtime threat detection (use Falco), or for network policy enforcement (use Kubernetes NetworkPolicy or Calico).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Kubernetes cluster with admin access for Gatekeeper installation
|
||||
- Helm for Gatekeeper deployment
|
||||
- OPA CLI or conftest for local policy testing
|
||||
- Rego knowledge for policy authoring
|
||||
|
||||
## Workflow
|
||||
|
||||
### Step 1: Install OPA Gatekeeper
|
||||
|
||||
```bash
|
||||
# Install Gatekeeper via Helm
|
||||
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
|
||||
helm install gatekeeper gatekeeper/gatekeeper \
|
||||
--namespace gatekeeper-system --create-namespace \
|
||||
--set replicas=3 \
|
||||
--set audit.replicas=1 \
|
||||
--set audit.writeToRAMDisk=true
|
||||
```
|
||||
|
||||
### Step 2: Create Constraint Templates
|
||||
|
||||
```yaml
|
||||
# templates/k8s-required-labels.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 := {label | input.review.object.metadata.labels[label]}
|
||||
required := {label | label := input.parameters.labels[_]}
|
||||
missing := required - provided
|
||||
count(missing) > 0
|
||||
msg := sprintf("Missing required labels: %v", [missing])
|
||||
}
|
||||
|
||||
---
|
||||
# templates/k8s-container-limits.yaml
|
||||
apiVersion: templates.gatekeeper.sh/v1
|
||||
kind: ConstraintTemplate
|
||||
metadata:
|
||||
name: k8scontainerlimits
|
||||
spec:
|
||||
crd:
|
||||
spec:
|
||||
names:
|
||||
kind: K8sContainerLimits
|
||||
validation:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
cpu:
|
||||
type: string
|
||||
memory:
|
||||
type: string
|
||||
targets:
|
||||
- target: admission.k8s.gatekeeper.sh
|
||||
rego: |
|
||||
package k8scontainerlimits
|
||||
violation[{"msg": msg}] {
|
||||
container := input.review.object.spec.containers[_]
|
||||
not container.resources.limits.cpu
|
||||
msg := sprintf("Container %v has no CPU limit", [container.name])
|
||||
}
|
||||
violation[{"msg": msg}] {
|
||||
container := input.review.object.spec.containers[_]
|
||||
not container.resources.limits.memory
|
||||
msg := sprintf("Container %v has no memory limit", [container.name])
|
||||
}
|
||||
|
||||
---
|
||||
# templates/k8s-block-privileged.yaml
|
||||
apiVersion: templates.gatekeeper.sh/v1
|
||||
kind: ConstraintTemplate
|
||||
metadata:
|
||||
name: k8sblockprivileged
|
||||
spec:
|
||||
crd:
|
||||
spec:
|
||||
names:
|
||||
kind: K8sBlockPrivileged
|
||||
targets:
|
||||
- target: admission.k8s.gatekeeper.sh
|
||||
rego: |
|
||||
package k8sblockprivileged
|
||||
violation[{"msg": msg}] {
|
||||
container := input.review.object.spec.containers[_]
|
||||
container.securityContext.privileged == true
|
||||
msg := sprintf("Privileged container not allowed: %v", [container.name])
|
||||
}
|
||||
violation[{"msg": msg}] {
|
||||
container := input.review.object.spec.initContainers[_]
|
||||
container.securityContext.privileged == true
|
||||
msg := sprintf("Privileged init container not allowed: %v", [container.name])
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: Apply Constraints
|
||||
|
||||
```yaml
|
||||
# constraints/require-labels.yaml
|
||||
apiVersion: constraints.gatekeeper.sh/v1beta1
|
||||
kind: K8sRequiredLabels
|
||||
metadata:
|
||||
name: require-team-labels
|
||||
spec:
|
||||
enforcementAction: deny
|
||||
match:
|
||||
kinds:
|
||||
- apiGroups: [""]
|
||||
kinds: ["Namespace"]
|
||||
- apiGroups: ["apps"]
|
||||
kinds: ["Deployment", "StatefulSet"]
|
||||
excludedNamespaces:
|
||||
- kube-system
|
||||
- gatekeeper-system
|
||||
parameters:
|
||||
labels:
|
||||
- "team"
|
||||
- "environment"
|
||||
- "cost-center"
|
||||
|
||||
---
|
||||
# constraints/block-privileged.yaml
|
||||
apiVersion: constraints.gatekeeper.sh/v1beta1
|
||||
kind: K8sBlockPrivileged
|
||||
metadata:
|
||||
name: block-privileged-containers
|
||||
spec:
|
||||
enforcementAction: deny
|
||||
match:
|
||||
kinds:
|
||||
- apiGroups: [""]
|
||||
kinds: ["Pod"]
|
||||
- apiGroups: ["apps"]
|
||||
kinds: ["Deployment", "DaemonSet", "StatefulSet"]
|
||||
excludedNamespaces:
|
||||
- kube-system
|
||||
```
|
||||
|
||||
### Step 4: Test Policies with conftest
|
||||
|
||||
```bash
|
||||
# Install conftest
|
||||
brew install conftest
|
||||
|
||||
# Test Kubernetes manifests against OPA policies locally
|
||||
conftest test deployment.yaml --policy policies/ --output json
|
||||
|
||||
# Test Terraform against OPA policies
|
||||
conftest test terraform/main.tf --policy policies/terraform/ --parser hcl2
|
||||
|
||||
# Test Dockerfiles
|
||||
conftest test Dockerfile --policy policies/docker/
|
||||
```
|
||||
|
||||
```rego
|
||||
# policies/kubernetes/deny_latest_tag.rego
|
||||
package kubernetes
|
||||
|
||||
deny[msg] {
|
||||
input.kind == "Deployment"
|
||||
container := input.spec.template.spec.containers[_]
|
||||
endswith(container.image, ":latest")
|
||||
msg := sprintf("Container %v uses :latest tag. Pin to specific version.", [container.name])
|
||||
}
|
||||
|
||||
deny[msg] {
|
||||
input.kind == "Deployment"
|
||||
container := input.spec.template.spec.containers[_]
|
||||
not contains(container.image, ":")
|
||||
msg := sprintf("Container %v has no tag. Pin to specific version.", [container.name])
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5: Integrate Policy Testing in CI/CD
|
||||
|
||||
```yaml
|
||||
# .github/workflows/policy-test.yml
|
||||
name: Policy Validation
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths: ['k8s/**', 'terraform/**', 'policies/**']
|
||||
|
||||
jobs:
|
||||
conftest:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install conftest
|
||||
run: |
|
||||
wget -q https://github.com/open-policy-agent/conftest/releases/download/v0.50.0/conftest_0.50.0_Linux_x86_64.tar.gz
|
||||
tar xzf conftest_0.50.0_Linux_x86_64.tar.gz
|
||||
sudo mv conftest /usr/local/bin/
|
||||
- name: Test K8s manifests
|
||||
run: conftest test k8s/**/*.yaml --policy policies/kubernetes/ --output json
|
||||
- name: Test Terraform
|
||||
run: conftest test terraform/*.tf --policy policies/terraform/ --parser hcl2
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
| Term | Definition |
|
||||
|------|------------|
|
||||
| OPA | Open Policy Agent — general-purpose policy engine using Rego language for policy decisions |
|
||||
| Rego | OPA's declarative query language for writing policy rules |
|
||||
| Gatekeeper | Kubernetes-native OPA integration implementing admission control via ConstraintTemplates |
|
||||
| ConstraintTemplate | CRD defining the Rego policy logic and parameters schema for a class of constraints |
|
||||
| Constraint | Instance of a ConstraintTemplate with specific parameters and scope (which resources to check) |
|
||||
| Admission Controller | Kubernetes component that intercepts API requests before persistence and can allow or deny them |
|
||||
| conftest | CLI tool for testing structured data (YAML, JSON, HCL) against OPA policies |
|
||||
|
||||
## Tools & Systems
|
||||
|
||||
- **Open Policy Agent (OPA)**: General-purpose policy engine for unified policy enforcement
|
||||
- **Gatekeeper**: Kubernetes admission controller built on OPA with CRD-based configuration
|
||||
- **conftest**: Testing framework for OPA policies against configuration files
|
||||
- **Kyverno**: Alternative Kubernetes policy engine using YAML-based policies (no Rego required)
|
||||
- **Styra DAS**: Commercial OPA management platform with policy authoring, testing, and distribution
|
||||
|
||||
## Common Scenarios
|
||||
|
||||
### Scenario: Enforcing Container Security Standards Across Clusters
|
||||
|
||||
**Context**: Multiple development teams deploy to shared Kubernetes clusters. Some teams run privileged containers and images without resource limits, causing security and stability issues.
|
||||
|
||||
**Approach**:
|
||||
1. Deploy Gatekeeper on all clusters via GitOps (Helm chart in a FluxCD repository)
|
||||
2. Create ConstraintTemplates for: no privileged containers, required resource limits, required labels, no latest tag
|
||||
3. Start with `enforcementAction: warn` to identify violations without blocking deployments
|
||||
4. Notify teams of violations and provide a 2-week remediation window
|
||||
5. Switch to `enforcementAction: deny` after the remediation period
|
||||
6. Add `excludedNamespaces` for kube-system and monitoring namespaces
|
||||
|
||||
**Pitfalls**: Deploying Gatekeeper with deny mode immediately can break existing workloads. Always start with warn mode. Overly restrictive policies without exemptions for system namespaces can prevent cluster components from functioning.
|
||||
|
||||
## Output Format
|
||||
|
||||
```
|
||||
OPA Policy Evaluation Report
|
||||
==============================
|
||||
Cluster: production-east
|
||||
Date: 2026-02-23
|
||||
Gatekeeper Version: 3.16.0
|
||||
|
||||
CONSTRAINT SUMMARY:
|
||||
K8sRequiredLabels: 12 violations (warn)
|
||||
K8sBlockPrivileged: 0 violations (deny)
|
||||
K8sContainerLimits: 8 violations (deny)
|
||||
K8sBlockLatestTag: 3 violations (deny)
|
||||
|
||||
BLOCKED DEPLOYMENTS (deny):
|
||||
[K8sContainerLimits] deployment/api-server in ns/payments
|
||||
- Container 'api' has no memory limit
|
||||
[K8sBlockLatestTag] deployment/frontend in ns/web
|
||||
- Container 'nginx' uses :latest tag
|
||||
|
||||
AUDIT VIOLATIONS (warn):
|
||||
[K8sRequiredLabels] namespace/staging
|
||||
- Missing labels: {cost-center}
|
||||
```
|
||||
@@ -0,0 +1,75 @@
|
||||
# OPA Policy as Code Templates
|
||||
|
||||
## Gatekeeper ConstraintTemplate Library
|
||||
|
||||
```yaml
|
||||
# Block containers running as root
|
||||
apiVersion: templates.gatekeeper.sh/v1
|
||||
kind: ConstraintTemplate
|
||||
metadata:
|
||||
name: k8sblockrootuser
|
||||
spec:
|
||||
crd:
|
||||
spec:
|
||||
names:
|
||||
kind: K8sBlockRootUser
|
||||
targets:
|
||||
- target: admission.k8s.gatekeeper.sh
|
||||
rego: |
|
||||
package k8sblockrootuser
|
||||
violation[{"msg": msg}] {
|
||||
container := input.review.object.spec.containers[_]
|
||||
container.securityContext.runAsUser == 0
|
||||
msg := sprintf("Container %v runs as root (UID 0)", [container.name])
|
||||
}
|
||||
violation[{"msg": msg}] {
|
||||
input.review.object.spec.securityContext.runAsUser == 0
|
||||
msg := "Pod runs as root (UID 0)"
|
||||
}
|
||||
```
|
||||
|
||||
## conftest Policy for CI/CD
|
||||
|
||||
```rego
|
||||
# policies/kubernetes/security.rego
|
||||
package kubernetes
|
||||
|
||||
deny[msg] {
|
||||
input.kind == "Deployment"
|
||||
container := input.spec.template.spec.containers[_]
|
||||
container.securityContext.privileged == true
|
||||
msg := sprintf("Privileged container '%v' not allowed", [container.name])
|
||||
}
|
||||
|
||||
deny[msg] {
|
||||
input.kind == "Deployment"
|
||||
container := input.spec.template.spec.containers[_]
|
||||
not container.resources.limits
|
||||
msg := sprintf("Container '%v' missing resource limits", [container.name])
|
||||
}
|
||||
|
||||
deny[msg] {
|
||||
input.kind == "Deployment"
|
||||
container := input.spec.template.spec.containers[_]
|
||||
endswith(container.image, ":latest")
|
||||
msg := sprintf("Container '%v' uses :latest tag", [container.name])
|
||||
}
|
||||
```
|
||||
|
||||
## GitHub Actions Integration
|
||||
|
||||
```yaml
|
||||
name: Policy Check
|
||||
on:
|
||||
pull_request:
|
||||
paths: ['k8s/**']
|
||||
jobs:
|
||||
conftest:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: open-policy-agent/conftest-action@v1
|
||||
with:
|
||||
files: k8s/
|
||||
policy: policies/kubernetes/
|
||||
```
|
||||
@@ -0,0 +1,26 @@
|
||||
# Standards Reference: Policy as Code with OPA
|
||||
|
||||
## NIST SP 800-53 - Security and Privacy Controls
|
||||
|
||||
| Control | OPA Policy | Description |
|
||||
|---------|-----------|-------------|
|
||||
| AC-3 | Block unauthorized access | Enforce RBAC and namespace isolation |
|
||||
| AC-6 | Least privilege | Block privileged containers and host access |
|
||||
| CM-2 | Baseline configuration | Require resource limits and labels |
|
||||
| CM-6 | Configuration settings | Enforce approved image registries |
|
||||
| SI-7 | Software integrity | Require image signatures and digests |
|
||||
|
||||
## CIS Kubernetes Benchmark Mapping
|
||||
|
||||
- 5.1.1: Ensure RBAC is enabled → OPA can enforce RBAC policies
|
||||
- 5.2.1: Minimize privileged containers → K8sBlockPrivileged constraint
|
||||
- 5.2.2: Minimize host namespace sharing → Block hostNetwork/hostPID
|
||||
- 5.2.5: Ensure allowPrivilegeEscalation is false → OPA constraint
|
||||
- 5.7.1: Create administrative boundaries between resources → Namespace policies
|
||||
|
||||
## OWASP Kubernetes Security Cheat Sheet
|
||||
|
||||
- Enforce Pod Security Standards via admission control
|
||||
- Restrict container capabilities using OPA policies
|
||||
- Enforce network policies and resource quotas
|
||||
- Validate image provenance and signatures
|
||||
@@ -0,0 +1,55 @@
|
||||
# Workflow Reference: Policy as Code with OPA
|
||||
|
||||
## Policy Lifecycle
|
||||
|
||||
```
|
||||
Author Rego Policy
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ Unit Test with │
|
||||
│ OPA test │
|
||||
└──────┬───────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ Integration Test │
|
||||
│ with conftest │
|
||||
└──────┬───────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ Deploy to Cluster│
|
||||
│ (warn mode) │
|
||||
└──────┬───────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ Monitor + Triage │
|
||||
│ Violations │
|
||||
└──────┬───────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ Switch to deny │
|
||||
│ mode │
|
||||
└──────────────────┘
|
||||
```
|
||||
|
||||
## OPA/Gatekeeper Architecture
|
||||
|
||||
```
|
||||
API Request → Kubernetes API Server → Gatekeeper Webhook
|
||||
│
|
||||
┌──────┴──────┐
|
||||
│ OPA Engine │
|
||||
│ (Rego eval) │
|
||||
└──────┬──────┘
|
||||
│
|
||||
┌──────┴──────┐
|
||||
│ Constraint │
|
||||
│ Templates │
|
||||
└──────┬──────┘
|
||||
│
|
||||
Allow / Deny
|
||||
```
|
||||
@@ -0,0 +1,167 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
OPA Policy Evaluation Pipeline Script
|
||||
|
||||
Runs conftest against Kubernetes manifests and Terraform files,
|
||||
evaluates policy compliance, and generates reports.
|
||||
|
||||
Usage:
|
||||
python process.py --manifests-dir ./k8s --policies-dir ./policies
|
||||
python process.py --manifests-dir ./terraform --policies-dir ./policies --parser hcl2
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@dataclass
|
||||
class PolicyViolation:
|
||||
file: str
|
||||
rule: str
|
||||
message: str
|
||||
severity: str = "HIGH"
|
||||
|
||||
|
||||
def run_conftest(manifests_dir: str, policies_dir: str,
|
||||
parser: str = "yaml") -> dict:
|
||||
"""Run conftest and return JSON results."""
|
||||
files = []
|
||||
extensions = {"yaml": [".yaml", ".yml"], "hcl2": [".tf"], "dockerfile": ["Dockerfile"]}
|
||||
for ext in extensions.get(parser, [".yaml", ".yml"]):
|
||||
files.extend(str(p) for p in Path(manifests_dir).rglob(f"*{ext}"))
|
||||
|
||||
if not files:
|
||||
return {"results": [], "error": f"No {parser} files found in {manifests_dir}"}
|
||||
|
||||
cmd = [
|
||||
"conftest", "test",
|
||||
"--policy", policies_dir,
|
||||
"--output", "json",
|
||||
"--parser", parser
|
||||
] + files
|
||||
|
||||
try:
|
||||
proc = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
|
||||
if proc.stdout:
|
||||
return {"results": json.loads(proc.stdout), "error": ""}
|
||||
return {"results": [], "error": proc.stderr[:300]}
|
||||
except subprocess.TimeoutExpired:
|
||||
return {"results": [], "error": "conftest timed out"}
|
||||
except FileNotFoundError:
|
||||
return {"results": [], "error": "conftest not found"}
|
||||
except json.JSONDecodeError:
|
||||
return {"results": [], "error": "Failed to parse conftest output"}
|
||||
|
||||
|
||||
def parse_conftest_results(results: list) -> list:
|
||||
"""Parse conftest JSON results into violations."""
|
||||
violations = []
|
||||
for result in results:
|
||||
filename = result.get("filename", "unknown")
|
||||
for failure in result.get("failures", []):
|
||||
violations.append(PolicyViolation(
|
||||
file=filename,
|
||||
rule=failure.get("metadata", {}).get("rule", "unknown"),
|
||||
message=failure.get("msg", ""),
|
||||
severity="HIGH"
|
||||
))
|
||||
for warning in result.get("warnings", []):
|
||||
violations.append(PolicyViolation(
|
||||
file=filename,
|
||||
rule=warning.get("metadata", {}).get("rule", "unknown"),
|
||||
message=warning.get("msg", ""),
|
||||
severity="MEDIUM"
|
||||
))
|
||||
return violations
|
||||
|
||||
|
||||
def check_gatekeeper_violations(namespace: str = "") -> list:
|
||||
"""Query Gatekeeper audit violations from the cluster."""
|
||||
cmd = ["kubectl", "get", "constraints", "-o", "json"]
|
||||
if namespace:
|
||||
cmd.extend(["-n", namespace])
|
||||
|
||||
try:
|
||||
proc = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
|
||||
if proc.returncode != 0:
|
||||
return []
|
||||
|
||||
data = json.loads(proc.stdout)
|
||||
violations = []
|
||||
for item in data.get("items", []):
|
||||
status = item.get("status", {})
|
||||
for v in status.get("violations", []):
|
||||
violations.append(PolicyViolation(
|
||||
file=f"{v.get('kind', '')}/{v.get('name', '')}",
|
||||
rule=item.get("kind", ""),
|
||||
message=v.get("message", ""),
|
||||
severity="HIGH" if item.get("spec", {}).get("enforcementAction") == "deny" else "MEDIUM"
|
||||
))
|
||||
return violations
|
||||
except (subprocess.TimeoutExpired, FileNotFoundError, json.JSONDecodeError):
|
||||
return []
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="OPA Policy Evaluation Pipeline")
|
||||
parser.add_argument("--manifests-dir", required=True)
|
||||
parser.add_argument("--policies-dir", required=True)
|
||||
parser.add_argument("--parser", default="yaml", choices=["yaml", "hcl2", "dockerfile"])
|
||||
parser.add_argument("--output", default="policy-report.json")
|
||||
parser.add_argument("--fail-on-violations", action="store_true")
|
||||
parser.add_argument("--check-cluster", action="store_true",
|
||||
help="Also check Gatekeeper violations in cluster")
|
||||
args = parser.parse_args()
|
||||
|
||||
violations = []
|
||||
|
||||
print(f"[*] Evaluating policies from {args.policies_dir} against {args.manifests_dir}")
|
||||
result = run_conftest(os.path.abspath(args.manifests_dir),
|
||||
os.path.abspath(args.policies_dir), args.parser)
|
||||
|
||||
if result.get("error"):
|
||||
print(f"[WARN] {result['error']}")
|
||||
else:
|
||||
violations.extend(parse_conftest_results(result["results"]))
|
||||
print(f" conftest: {len(violations)} violations")
|
||||
|
||||
if args.check_cluster:
|
||||
cluster_violations = check_gatekeeper_violations()
|
||||
violations.extend(cluster_violations)
|
||||
print(f" cluster: {len(cluster_violations)} audit violations")
|
||||
|
||||
report = {
|
||||
"metadata": {"date": datetime.now(timezone.utc).isoformat()},
|
||||
"summary": {
|
||||
"total_violations": len(violations),
|
||||
"high": sum(1 for v in violations if v.severity == "HIGH"),
|
||||
"medium": sum(1 for v in violations if v.severity == "MEDIUM")
|
||||
},
|
||||
"violations": [
|
||||
{"file": v.file, "rule": v.rule, "message": v.message, "severity": v.severity}
|
||||
for v in violations
|
||||
]
|
||||
}
|
||||
|
||||
output_path = os.path.abspath(args.output)
|
||||
with open(output_path, "w") as f:
|
||||
json.dump(report, f, indent=2)
|
||||
print(f"[*] Report: {output_path}")
|
||||
|
||||
passed = len(violations) == 0
|
||||
print(f"\n[{'PASS' if passed else 'FAIL'}] {len(violations)} policy violations found")
|
||||
for v in violations[:10]:
|
||||
print(f" [{v.severity}] {v.file}: {v.message[:100]}")
|
||||
|
||||
if args.fail_on_violations and not passed:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user