---
title: "Implementing Compliance as Code"
description: "Operational sequence for implementing compliance as code — policy frameworks (OPA/Gatekeeper, Kyverno, Checkov), CIS benchmark automation, SOC2/PCI-DSS/HIPAA control mapping, audit trail generation, and continuous compliance monitoring."
url: https://agent-zone.ai/knowledge/security/compliance-as-code/
section: knowledge
date: 2026-02-22
categories: ["security"]
tags: ["compliance-as-code","opa","gatekeeper","kyverno","checkov","cis-benchmark","soc2","pci-dss","hipaa","audit","policy-as-code"]
skills: ["policy-engine-deployment","compliance-automation","audit-trail-generation","control-mapping"]
tools: ["opa","gatekeeper","kyverno","checkov","terraform","kubernetes","conftest"]
levels: ["intermediate"]
word_count: 1248
formats:
  json: https://agent-zone.ai/knowledge/security/compliance-as-code/index.json
  html: https://agent-zone.ai/knowledge/security/compliance-as-code/?format=html
  api: https://api.agent-zone.ai/api/v1/knowledge/search?q=Implementing+Compliance+as+Code
---


# Implementing Compliance as Code

Compliance as code encodes compliance requirements as machine-readable policies evaluated automatically, continuously, and with every change. Instead of quarterly spreadsheet audits, a policy like "all S3 buckets must have encryption enabled" becomes a check that runs in CI, blocks non-compliant Terraform plans, and scans running infrastructure hourly. Evidence generation is automatic. Drift is detected immediately.

## Step 1: Map Compliance Controls to Technical Policies

Translate your compliance framework's controls into specific, testable technical requirements. This mapping bridges auditor language and infrastructure code.

### SOC2 Trust Service Criteria

| SOC2 Control | Technical Requirement | Enforcement Point |
|---|---|---|
| CC6.1 Logical Access | RBAC with least privilege, no cluster-admin for workloads | Kubernetes admission, IAM policy |
| CC6.3 Role-Based Access | Service accounts per workload, no shared credentials | Kubernetes admission |
| CC6.6 System Boundaries | Default-deny network policies in all namespaces | Kubernetes admission |
| CC6.8 Prevent Unauthorized Software | Only signed images from approved registries | Kubernetes admission |
| CC7.1 Monitoring | Audit logging enabled, logs shipped to central SIEM | Infrastructure as code, runtime check |
| CC7.2 Anomaly Detection | Alerting on privilege escalation, unusual API access | Runtime monitoring |
| CC8.1 Change Management | All changes via GitOps, no manual kubectl apply | Kubernetes admission, CI gate |

### PCI-DSS v4.0

| PCI-DSS Requirement | Technical Requirement | Enforcement Point |
|---|---|---|
| 1.2.1 Network segmentation | Network policies isolating cardholder data environment | Kubernetes admission |
| 2.2.1 Secure configurations | CIS benchmark pass on all nodes and containers | Infrastructure scan, admission |
| 6.3.2 Vulnerability management | No critical/high CVEs in deployed images | CI gate, admission |
| 7.2.1 Access control | RBAC policies, no default service account usage | Kubernetes admission |
| 8.3.1 MFA | OIDC with MFA for cluster access | Identity provider configuration |
| 10.2.1 Audit trails | API server audit logs with 90-day retention | Infrastructure as code |
| 11.3.1 Vulnerability scanning | Weekly automated scanning of running workloads | Scheduled job |

### HIPAA Security Rule

| HIPAA Standard | Technical Requirement | Enforcement Point |
|---|---|---|
| 164.312(a)(1) Access Control | RBAC, namespace isolation for PHI workloads | Kubernetes admission |
| 164.312(a)(2)(iv) Encryption | Encryption at rest and in transit (mTLS) | Infrastructure as code, admission |
| 164.312(b) Audit Controls | Complete audit trail of PHI access | API audit logs, application logs |
| 164.312(e)(1) Transmission Security | TLS 1.2+ on all endpoints, mTLS between services | Admission, network policy |

## Step 2: Select and Deploy a Policy Engine

Three tools cover most use cases. They are not mutually exclusive -- use Checkov in CI and Kyverno or Gatekeeper at admission.

### Checkov: Static Infrastructure Scanning

Checkov scans Terraform, Kubernetes manifests, Helm charts, and Dockerfiles before they are applied:

```bash
# Scan Terraform files
checkov -d ./terraform/ --framework terraform

# Scan Kubernetes manifests
checkov -d ./k8s-manifests/ --framework kubernetes

# Scan Helm charts (renders templates first)
checkov -d ./helm-chart/ --framework helm

# Output in JUnit format for CI integration
checkov -d ./terraform/ -o junitxml > checkov-results.xml
```

Checkov includes over 2,500 built-in policies mapped to CIS benchmarks, SOC2, PCI-DSS, and HIPAA. Run only the policies relevant to your compliance scope:

```bash
# Run by compliance framework
checkov -d ./terraform/ --compliance-framework soc2

# Run specific checks
checkov -d ./terraform/ --check CKV_AWS_18,CKV_AWS_19,CKV_AWS_21
```

### OPA Gatekeeper: Kubernetes Admission Control

Gatekeeper evaluates policies at the Kubernetes API admission point. Non-compliant resources are rejected before they are created.

Install with Helm (`helm install gatekeeper gatekeeper/gatekeeper -n gatekeeper-system --create-namespace`). Define constraint templates (policy logic in Rego) and apply constraints using them:

```yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: require-compliance-labels
spec:
  enforcementAction: deny
  match:
    kinds:
      - apiGroups: ["apps"]
        kinds: ["Deployment"]
  parameters:
    labels:
      - "app.kubernetes.io/name"
      - "compliance/data-classification"
      - "compliance/owner"
```

### Kyverno: Kubernetes-Native Policies

Kyverno uses Kubernetes YAML natively -- no Rego required. For teams that already manage Kubernetes resources in YAML, the learning curve is lower.

Install with Helm (`helm install kyverno kyverno/kyverno -n kyverno --create-namespace`). Enforce that containers must not run as root:

```yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-non-root
  annotations:
    policies.kyverno.io/category: Pod Security
    policies.kyverno.io/severity: high
    policies.kyverno.io/subject: Pod
    policies.kyverno.io/description: >-
      Containers must run as non-root. Maps to SOC2 CC6.1,
      PCI-DSS 2.2.1, HIPAA 164.312(a)(1).
spec:
  validationFailureAction: Enforce
  background: true
  rules:
    - name: check-containers
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "Containers must not run as root (runAsNonRoot must be true)"
        pattern:
          spec:
            containers:
              - securityContext:
                  runAsNonRoot: true
```

Kyverno can also mutate resources (inject labels, set defaults) and generate resources (create network policies when a namespace is created).

### Conftest: Pre-Deployment Policy Testing

Conftest uses OPA/Rego to test structured data files (YAML, JSON, HCL, Dockerfile) in CI before admission. Useful when you want OPA's policy language for pre-deployment checks:

```bash
conftest test deployment.yaml -p ./policies/
terraform show -json plan.tfplan | conftest test - -p ./policies/terraform/
```

## Step 3: Integrate Policies into CI/CD

Policies must run automatically. Manual compliance checks are compliance theater.

```yaml
# GitHub Actions: compliance gates
name: Compliance Checks
on:
  pull_request:
    branches: [main]

jobs:
  checkov-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: bridgecrewio/checkov-action@v12
        with:
          directory: ./terraform
          framework: terraform
          soft_fail: false

  kyverno-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Test policies against manifests
        run: kyverno apply ./policies/ --resource ./k8s-manifests/

  conftest-terraform:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: |
          terraform -chdir=terraform init -backend=false
          terraform -chdir=terraform plan -out=plan.tfplan
          terraform -chdir=terraform show -json plan.tfplan > plan.json
          conftest test plan.json -p ./policies/terraform/
```

Block merges if any compliance check fails.

## Step 4: Generate Audit Trails

Auditors need evidence. Compliance as code generates evidence automatically, but you must collect and retain it.

### Policy Decision Logs

Gatekeeper logs every admission decision (allow/deny) including the resource, the policy evaluated, and the result. Configure audit logging:

```yaml
# Gatekeeper audit configuration
helm upgrade gatekeeper gatekeeper/gatekeeper \
  --namespace gatekeeper-system \
  --set audit.logLevel=INFO \
  --set audit.constraintViolationsLimit=100
```

Kyverno generates Policy Reports as Kubernetes resources (`kubectl get policyreport -n production`). These list every resource evaluated, pass/fail status, and which policy was applied. Export them to your log aggregation system for long-term retention.

### CI Pipeline Records and State Snapshots

Every CI run that executes compliance checks is an audit artifact. Retain CI logs, test results (JUnit XML), and the specific policy versions evaluated. Store in tamper-evident storage (S3 with object lock or write-once retention policies).

Periodically capture the compliance state of running infrastructure:

```bash
#!/bin/bash
DATE=$(date +%Y-%m-%d)
kubescape scan framework cis-v1.23-t1.0.1 -f json -o "audit/k8s-cis-$DATE.json"
kube-bench run --json > "audit/kube-bench-$DATE.json"
kubectl get clusterpolicyreport -o json > "audit/policy-report-$DATE.json"
checkov -d ./terraform/ --framework terraform -o json > "audit/checkov-$DATE.json"
aws s3 cp audit/ s3://compliance-audit-bucket/$DATE/ --recursive
```

## Step 5: Establish Continuous Compliance Monitoring

Compliance at deployment is necessary but not sufficient. Configuration drifts, new CVEs emerge, and certificates expire. Continuous monitoring catches what CI cannot.

### Scheduled Compliance Scans

Run full compliance scans on a schedule against live infrastructure using Kubernetes CronJobs. Schedule kube-bench, kubescape, and Checkov scans daily and store results as audit evidence.

### Gatekeeper Audit and Drift Detection

Gatekeeper's audit controller periodically evaluates all existing resources against constraints, catching resources created before a policy existed:

```bash
kubectl get constraints -o json | jq '.items[].status.totalViolations'
```

For infrastructure drift, run `terraform plan -detailed-exitcode` on a schedule (exit code 2 means drift). Alert when actual state diverges from declared state.

### Alerting on Compliance Violations

Route violations to your alerting system with severity-based response: **Critical** (privilege escalation, encryption disabled) -- page on-call immediately. **High** (missing network policies, RBAC drift) -- alert within 1 hour, create incident ticket. **Medium** (missing labels, benchmark failures) -- daily alert, backlog ticket with SLA.

Organize policies by framework (`policies/soc2/`, `policies/pci-dss/`, `policies/hipaa/`, `policies/cis/`) with annotations mapping each to its compliance control.

## Common Mistakes

1. **Writing policies without mapping to controls first.** You end up with gaps where requirements have no policy.
2. **Enforcing everything immediately.** Start in audit/warn mode. Switch to enforce after confirming no false positives.
3. **Not retaining audit evidence.** Compliance checks whose results are not stored provide no audit value.
4. **Relying solely on admission control.** Admission only applies to new resources. Pre-existing non-compliant resources require audit-mode scanning.
5. **Treating compliance as code as one-time setup.** Review and update policies quarterly, aligned with your audit cycle.

