Agent skill
policy-as-code
Policy as Code with OPA, Kyverno, and Checkov. Use when implementing governance, compliance automation, or security policies for infrastructure and Kubernetes.
Stars
163
Forks
31
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/policy-as-code
SKILL.md
Policy as Code
Automated policy enforcement for infrastructure, Kubernetes, and CI/CD pipelines.
When to Use
- Enforcing security policies in Kubernetes
- Validating Terraform configurations
- Implementing compliance requirements
- Pre-commit infrastructure validation
- Admission control in clusters
Tools Overview
| Tool | Target | Language | Use Case |
|---|---|---|---|
| OPA/Gatekeeper | K8s, General | Rego | Complex policies |
| Kyverno | Kubernetes | YAML | K8s-native policies |
| Checkov | IaC | Python | Terraform, CloudFormation |
| Sentinel | Terraform | Sentinel | Terraform Enterprise |
| Conftest | Config files | Rego | CI/CD validation |
OPA Gatekeeper (Kubernetes)
Installation
bash
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/deploy/gatekeeper.yaml
Constraint Template
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])
}
Constraint
yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: require-team-label
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Namespace"]
- apiGroups: ["apps"]
kinds: ["Deployment"]
parameters:
labels:
- "team"
- "environment"
Common Policies
yaml
# Require resource limits
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8scontainerlimits
spec:
crd:
spec:
names:
kind: K8sContainerLimits
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])
}
---
# Block privileged containers
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8spsprivilegedcontainer
spec:
crd:
spec:
names:
kind: K8sPSPPrivilegedContainer
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8spsprivilegedcontainer
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
container.securityContext.privileged
msg := sprintf("Privileged container not allowed: %v", [container.name])
}
Kyverno (Kubernetes)
Installation
bash
kubectl create -f https://github.com/kyverno/kyverno/releases/latest/download/install.yaml
Policies
yaml
# Require labels
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-labels
spec:
validationFailureAction: Enforce
rules:
- name: check-team-label
match:
any:
- resources:
kinds:
- Deployment
- StatefulSet
validate:
message: "Label 'team' is required"
pattern:
metadata:
labels:
team: "?*"
---
# Add default labels (mutating)
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: add-default-labels
spec:
rules:
- name: add-managed-by
match:
any:
- resources:
kinds:
- Deployment
mutate:
patchStrategicMerge:
metadata:
labels:
managed-by: kyverno
---
# Block latest tag
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-latest-tag
spec:
validationFailureAction: Enforce
rules:
- name: validate-image-tag
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Using 'latest' tag is not allowed"
pattern:
spec:
containers:
- image: "!*:latest"
---
# Require resource limits
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-resources
spec:
validationFailureAction: Enforce
rules:
- name: validate-resources
match:
any:
- resources:
kinds:
- Pod
validate:
message: "CPU and memory limits are required"
pattern:
spec:
containers:
- resources:
limits:
memory: "?*"
cpu: "?*"
requests:
memory: "?*"
cpu: "?*"
Checkov (Terraform/IaC)
Installation
bash
pip install checkov
# or
brew install checkov
Usage
bash
# Scan Terraform directory
checkov -d ./terraform
# Scan specific file
checkov -f main.tf
# Output formats
checkov -d . -o json
checkov -d . -o sarif
# Skip checks
checkov -d . --skip-check CKV_AWS_1,CKV_AWS_2
# Custom policies
checkov -d . --external-checks-dir ./custom-policies
Custom Policy
python
# custom-policies/check_s3_versioning.py
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck
from checkov.common.models.enums import CheckResult, CheckCategories
class S3Versioning(BaseResourceCheck):
def __init__(self):
name = "Ensure S3 bucket has versioning enabled"
id = "CKV_CUSTOM_1"
supported_resources = ["aws_s3_bucket"]
categories = [CheckCategories.BACKUP_AND_RECOVERY]
super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)
def scan_resource_conf(self, conf):
versioning = conf.get("versioning", [{}])
if versioning and versioning[0].get("enabled", [False])[0]:
return CheckResult.PASSED
return CheckResult.FAILED
check = S3Versioning()
.checkov.yaml
yaml
# .checkov.yaml
soft-fail: false
compact: true
framework:
- terraform
- kubernetes
skip-check:
- CKV_AWS_1 # S3 access logging
- CKV_K8S_1 # Pod security
check:
- CKV_AWS_*
- CKV_K8S_*
Conftest (CI/CD)
Installation
bash
brew install conftest
# or
go install github.com/open-policy-agent/conftest@latest
Terraform Policy
rego
# policy/terraform.rego
package main
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket"
resource.change.after.versioning[0].enabled != true
msg := sprintf("S3 bucket %v must have versioning enabled", [resource.address])
}
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_security_group_rule"
resource.change.after.cidr_blocks[_] == "0.0.0.0/0"
resource.change.after.from_port == 22
msg := sprintf("Security group rule %v allows SSH from 0.0.0.0/0", [resource.address])
}
CI/CD Integration
yaml
# .github/workflows/policy.yml
name: Policy Check
on: [pull_request]
jobs:
terraform-policy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
- name: Terraform Init
run: terraform init
- name: Terraform Plan
run: terraform plan -out=tfplan
- name: Convert to JSON
run: terraform show -json tfplan > tfplan.json
- name: Run Conftest
uses: instrumenta/conftest-action@master
with:
files: tfplan.json
policy: policy/
kubernetes-policy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Checkov
uses: bridgecrewio/checkov-action@master
with:
directory: ./kubernetes
framework: kubernetes
Pre-commit Hooks
yaml
# .pre-commit-config.yaml
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.86.0
hooks:
- id: terraform_fmt
- id: terraform_validate
- id: terraform_tflint
- id: terraform_checkov
args:
- --args=--skip-check CKV_AWS_1
- repo: https://github.com/open-policy-agent/conftest
rev: v0.46.0
hooks:
- id: conftest
args: [--policy, policy/]
Best Practices
- Start with audit mode before enforcing
- Document exceptions with rationale
- Version policies in Git
- Test policies before deployment
- Monitor policy violations for trends
- Regular policy reviews for relevance
Integration
Works with:
/k8s- Kubernetes policies/terraform- IaC validation/security- Security policies/devops- CI/CD integration
Didn't find tool you were looking for?