---
title: "Policy-as-Code Governance with OPA/Rego"
description: "Learn how to enforce infrastructure standards across your DevOps pipeline using Open Policy Agent (OPA). This guide covers policy writing in Rego, integration with Terraform and Kubernetes, and automating compliance checks in CI/CD pipelines."
author: "Mohammad Abu Mattar"
canonical: https://mkabumattar.com/devtips/post/policy-as-code-opa-rego
---

# Policy-as-Code Governance with OPA/Rego

## Why Policy-as-Code Matters

### The Governance Challenge

**Managing infrastructure at scale gets complicated fast.**

As your infrastructure grows, ensuring consistency and compliance becomes increasingly difficult. Manual reviews don't scale, and configuration drift is inevitable. You need automation that enforces standards without becoming a bottleneck.

### Common Infrastructure Issues

- Developers accidentally making resources publicly accessible
- Missing required tags on cloud resources
- Non-compliant security group configurations
- Kubernetes deployments without resource limits
- Terraform modules bypassing organizational standards

## The Problem: Manual Governance

### Why Manual Reviews Fail

Relying on manual code reviews and post-deployment checks is inefficient and error-prone. Standards get ignored, security policies get bypassed, and by the time issues are caught, they're already in production. You need guardrails that prevent problems before deployment.

### Real-World Impact

When policies aren't enforced, organizations face:

- **Security breaches** from misconfigured resources
- **Compliance violations** leading to audits and fines
- **Cost overruns** from unoptimized infrastructure
- **Operational chaos** from inconsistent deployments

## The Solution: Open Policy Agent (OPA)

### What is OPA?

Open Policy Agent is a unified policy engine that decouples policy logic from application logic. It evaluates policies written in Rego (a declarative language) against any kind of data Terraform plans, Kubernetes manifests, CI/CD configurations, and more.

### Key Benefits

- **Unified enforcement** across Terraform, Kubernetes, and custom tools
- **Declarative policies** that are easy to understand and maintain
- **Pre-deployment validation** to catch issues before they reach production
- **Audit trails** for compliance and governance requirements
- **Organization-wide standards** enforced consistently

## Getting Started with OPA and Rego

### Installation

```bash
# macOS
brew install opa

# Linux
curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_linux_x86_64
chmod +x opa
sudo mv opa /usr/local/bin/
```

### Basic Rego Policy

```rego title="restrict-public-buckets.rego"
# Deny public S3 buckets
package s3

deny[msg] {
    input.resource_type == "aws_s3_bucket"
    input.acl == "public-read"
    msg := sprintf("S3 bucket %s cannot be public", [input.name])
}

deny[msg] {
    input.resource_type == "aws_s3_bucket"
    input.acl == "public-read-write"
    msg := sprintf("S3 bucket %s cannot be public", [input.name])
}
```

## Integrating OPA with Terraform

### Using Conftest (OPA CLI for Terraform)

```bash
# Install conftest
brew install conftest

# Validate Terraform plan
terraform plan -json | conftest test -
```

### Policy Example: Enforce Tags

```rego title="require-tags.rego"
package terraform

deny[msg] {
    resource := input.resource_changes[_]
    resource.type in ["aws_instance", "aws_rds_cluster"]
    not resource.change.after.tags.Environment
    msg := sprintf("Resource %s must have Environment tag", [resource.address])
}

deny[msg] {
    resource := input.resource_changes[_]
    resource.type in ["aws_instance", "aws_rds_cluster"]
    not resource.change.after.tags.CostCenter
    msg := sprintf("Resource %s must have CostCenter tag", [resource.address])
}
```

## Enforcing Policies in Kubernetes

### OPA Gatekeeper Installation

```bash
# Deploy Gatekeeper to your cluster
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/release-3.14/deploy/gatekeeper.yaml
```

### Kubernetes ConstraintTemplate

```yaml title="require-resource-limits.yaml"
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredResources
metadata:
  name: require-resource-limits
spec:
  match:
    kinds:
      - apiGroups: ['']
        kinds: ['Pod']
    excludedNamespaces: ['kube-system', 'gatekeeper-system']
---
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8srequiredresources
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredResources
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredresources

        violation[{"msg": msg}] {
            container := input.review.object.spec.containers[_]
            not container.resources.limits.cpu
            msg := sprintf("Container %s must have CPU limit", [container.name])
        }

        violation[{"msg": msg}] {
            container := input.review.object.spec.containers[_]
            not container.resources.limits.memory
            msg := sprintf("Container %s must have memory limit", [container.name])
        }
```

## CI/CD Pipeline Integration

### GitHub Actions Example

```yaml title=".github/workflows/policy-check.yml"
name: Policy Validation

on: [pull_request]

jobs:
  policy-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Install OPA
        run: |
          curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_linux_x86_64
          chmod +x opa
          sudo mv opa /usr/local/bin/

      - name: Run Policy Tests
        run: |
          opa test policies/ -v

      - name: Validate Terraform
        if: hashFiles('*.tf') != ''
        run: |
          terraform init
          terraform plan -json | opa eval -d policies/ 'data.terraform.deny' -f pretty
```

## Best Practices

### 1. Organization-First Approach

Define policies at the organization level, not project level. Make them discoverable and documented.

```rego
# Start with clear policy namespaces
package org_policies.infrastructure.aws.security
package org_policies.kubernetes.workload
```

### 2. Fail Safely

Distinguish between hard denials and warnings:

```rego
package my_policies

deny[msg] {
    # Hard deny: completely block this
    input.security_critical_violation == true
    msg := "This violates critical security policy"
}

warn[msg] {
    # Warning: recommend but allow with approval
    input.non_standard_naming == true
    msg := "Consider following naming standards"
}
```

### 3. Test Your Policies

```bash
# Test policy logic before deployment
opa test policies/ -v
```

### 4. Version Control Policies

Keep policies in the same repo as infrastructure code, with proper code review processes.

## Monitoring and Auditing

### Log Policy Violations

Capture and log every policy decision for audit trails:

```rego
package audit

log_decision[decision] {
    decision := {
        "action": "denied",
        "reason": input.violation_reason,
        "timestamp": input.timestamp,
        "resource": input.resource_id
    }
}
```

## Real-World Implementation Timeline

| Phase       | Focus                                                  | Timeline |
| ----------- | ------------------------------------------------------ | -------- |
| **Phase 1** | Basic security policies (public access, required tags) | Week 1-2 |
| **Phase 2** | Terraform integration in CI/CD                         | Week 3-4 |
| **Phase 3** | Kubernetes Gatekeeper deployment                       | Week 5-6 |
| **Phase 4** | Comprehensive auditing and monitoring                  | Week 7-8 |

## Conclusion

**Policy-as-Code transforms governance from reactive to proactive.**

Using OPA and Rego, you can enforce organizational standards consistently across Terraform, Kubernetes, and custom systems. Start with critical security policies, gradually expand coverage, and build a culture where compliance is automatic, not manual.

## Resources

- [OPA Official Documentation](https://www.openpolicyagent.org)
- [Rego Playground](https://play.openpolicyagent.org)
- [Gatekeeper Documentation](https://open-policy-agent.github.io/gatekeeper)
- [Conftest: Testing Framework](https://www.conftest.dev)
