Blog post image for Policy-as-Code Governance with OPA/Rego - 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.

Policy-as-Code Governance with OPA/Rego

03 Mins read

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

Terminal window
# 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

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)

Terminal window
# Install conftest
brew install conftest
# Validate Terraform plan
terraform plan -json | conftest test -

Policy Example: Enforce Tags

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

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

Kubernetes ConstraintTemplate

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

.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.

# 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:

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

Terminal window
# 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:

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

Real-World Implementation Timeline

PhaseFocusTimeline
Phase 1Basic security policies (public access, required tags)Week 1-2
Phase 2Terraform integration in CI/CDWeek 3-4
Phase 3Kubernetes Gatekeeper deploymentWeek 5-6
Phase 4Comprehensive auditing and monitoringWeek 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

Related Posts

You might also enjoy

Check out some of our other posts on similar topics

Container Image Vulnerability Scanning in CI/CD with Trivy

Container Image Vulnerability Scanning in CI/CD with Trivy

Why Container Security Matters The Vulnerability Problem Container images are a critical attack surface in modern deployments. Every time you build a container image, it includes the bas

7 Reasons Learning the Linux Terminal is Worth It (Even for Beginners)

7 Reasons Learning the Linux Terminal is Worth It (Even for Beginners)

Why Learn the Linux Terminal? The Terminal's Enduring Value Is the Linux terminal still relevant in 2026? You bet it is. Even with all the fancy graphical interfaces and AI assistants ou

Managing Terraform at Scale with Terragrunt

Managing Terraform at Scale with Terragrunt

The Problem with Terraform at Scale Code Duplication Across Environments Tired of copying Terraform code across every environment? If you're managing infrastructure with Terraform across

Securing CI/CD with IAM Roles

Securing CI/CD with IAM Roles

Why Secure Your CI/CD Pipeline? The Importance of Pipeline Security Hey, want to keep your CI/CD pipeline safe? If you’re working on software, locking down your pipeline is a must. Using

Understanding Kubernetes Services: ClusterIP vs NodePort vs LoadBalancer

Understanding Kubernetes Services: ClusterIP vs NodePort vs LoadBalancer

Hey, trying to figure out how to expose your Kubernetes apps? If you're working with Kubernetes, you've probably noticed that Pods come and go, and their IP addresses keep changing. That's where

HashiCorp Pulls the Plug on CDKTF

HashiCorp Pulls the Plug on CDKTF

CDKTF is Officially Deprecated The Deprecation Announcement Well, it finally happened. HashiCorp (now owned by IBM) officially deprecated the Cloud Development Kit for Terraform (CDKTF)

6 related posts