DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Cloud Automation Excellence: Terraform, Ansible, and Nomad for Enterprise Architecture
  • Codify Your Cloud and Kubernetes With Crossplane and IaC
  • Securing Your Kubernetes Cluster: Terraform Secrets Management
  • Auto-Scaling a Spring Boot Native App With Nomad

Trending

  • Feature Flag Debt: Performance Impact in Enterprise Applications
  • When Perfect Data Breaks: The Journey from Data Quality to Data Observability
  • Ujorm3: A New Lightweight ORM for JavaBeans and Records
  • Edge Computing in Utility IoT: Two Architecture Patterns That Actually Work
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. DevOps and CI/CD
  4. Write Once, Enforce Everywhere: Reusing Rego Policies Across Build and Runtime

Write Once, Enforce Everywhere: Reusing Rego Policies Across Build and Runtime

Stop writing the same policy twice. With the use of Rego, you can enforce the same exact rules, both in CI/CD and in production.

By 
Akshay Pratinav user avatar
Akshay Pratinav
·
Oct. 13, 25 · Analysis
Likes (2)
Comment
Save
Tweet
Share
2.0K Views

Join the DZone community and get the full member experience.

Join For Free

In most organizations, security and compliance are enforced twice — once during build-time checks and again at runtime through admission controllers and monitoring systems. Often, the policies written at build-time are not reused at runtime, leading to drift, redundancy, and gaps in enforcement. With the rise of Open Policy Agent (OPA) and Rego, teams now have the opportunity to unify policy logic and reuse it seamlessly across both phases. 

This article discusses the principles, design patterns, and practical techniques for reusing Rego policies at build-time and runtime, helping teams reduce duplication, improve compliance confidence, and accelerate software delivery.

The Policy Fragmentation Problem

Organizations have traditionally split policy enforcement into two silos:

  • Build-time policies: Applied during CI/CD pipelines to validate container images, infrastructure-as-code templates, or dependency versions. Example: “No container image may run as root.”
  • Runtime policies: Enforced when applications are deployed and running — often through Kubernetes admission controllers. Example: “Pods cannot be scheduled on production nodes unless labeled.”

These two worlds often use different languages, frameworks, and enforcement mechanisms, resulting in:

  • Duplication of the same policy logic across multiple systems.
  • Leads to drift where build-time and runtime checks diverge.
  • Creates blind spots where a policy is only partially enforced.

This results in an inconsistent compliance posture and wasted engineering effort.

Writing a Reusable Policy

Here’s a simple Rego policy that blocks containers from running as root:

Shell
 
package policies.security

deny[msg] {

  input.spec.containers[_].securityContext.runAsUser == 0

  msg := "Containers must not run as root user"

}


  • Build-time: Use conftest in the CI/CD pipeline to validate Kubernetes manifests or Helm charts before deployment.
  • Runtime: Deploy the same policy using OPA Gatekeeper to enforce rules on live clusters.

This makes it possible to express a rule once and reuse it across the software lifecycle with zero drift.

Case Study: Kubernetes + Terraform

Consider an enterprise adopting Kubernetes and multi-cloud infrastructure. They face two common challenges:

  1. Kubernetes Pods must not run with privileged escalation.
  2. Terraform-managed AWS S3 buckets must enforce encryption.

Traditionally, these were checked separately — Kubernetes admission controllers for pods and static analysis tools for Terraform. With Rego, the organization defined policies once and reused them everywhere.

Kubernetes Policy (Privileged Escalation)

Shell
 
package policies.k8s

deny[msg] {

  input.kind == "Pod"

  input.spec.containers[_].securityContext.allowPrivilegeEscalation == true

  msg := "Privilege escalation not allowed in Pods"

}


  • CI/CD: Run conftest test pod.yaml to block bad manifests before merge.
  • Runtime: Enforce via Gatekeeper so developers can’t sneak in privileged pods.

Terraform Policy (S3 Encryption)

Shell
 
package policies.terraform

deny[msg] {

  input.resource_type == "aws_s3_bucket"

  not input.encryption.enabled

  msg := sprintf("S3 bucket %v must enable encryption", [input.name])

}


  • CI/CD: Run OPA eval against Terraform plan JSON.
  • Runtime: Hook into cloud policy engines that leverage OPA bundles.

Results

  • One Git repo for all policies
  • Same rules applied across dev, CI, and production
  • Developers got faster feedback, and security got consistent enforcement

Best Practices for Policy Reuse

1. Policy as Code Repository

Store all Rego policies in a central Git repository. Reference them both in CI/CD and runtime controllers. Version control ensures auditability.

2. Abstract Inputs, Normalize Data

Build-time inputs (YAML manifests, Terraform templates) and runtime inputs (Kubernetes AdmissionReview objects) often differ. Define a normalization layer to convert inputs into a consistent schema.

Shell
package normalize.kubernetes

pod(cont) = {

  "name": cont.name,

  "user": cont.securityContext.runAsUser,

} {

  cont := input.spec.containers[_]

}

 

3. Bundle Policies

Package policies into OPA bundles that can be distributed and reused across build and runtime. CI/CD pipelines can fetch the same bundle that Gatekeeper enforces in production.

4. Test Once, Deploy Everywhere

Write unit tests for Rego policies and run them in CI. This guarantees correctness before promoting policies to runtime enforcement.

Challenges and How to Address Them

Reusing policies across build-time and runtime introduces practical challenges. While the vision is straightforward — write once, enforce everywhere — the reality requires careful engineering.

1. Different Data Shapes

  • Problem: At build-time, policies evaluate static manifests (e.g., YAML, Terraform plan files). At runtime, inputs are dynamic objects (e.g., Kubernetes AdmissionReview requests). Their schemas differ significantly. Without harmonization, the same Rego rule cannot be directly reused.
  • Solution: Introduce a normalization layer. Write helper Rego modules that translate input data into a consistent schema before applying policies. Example: Map both Pod specs in YAML and AdmissionReview payloads into a normalized pod object with fields like user, privileged, and image. Policies remain environment-agnostic and easier to reuse.

2. Performance at Scale

  • Problem: Build-time checks are relatively cheap (they run once per pipeline), but runtime enforcement may need to handle thousands of admission requests per second in Kubernetes or API gateway decisions. Evaluating raw Rego on every request can create latency. Runtime bottlenecks can degrade cluster performance or increase request latency.
  • Solution: Using data filtering minimizes the input passed into OPA (e.g., only the relevant fields instead of the full AdmissionReview payload). Splitting heavy, complex rules into smaller, focused policies reduces evaluation cost.

3. Change Management and Policy Drift

  • Problem: Policies evolve over time. A rule that is acceptable today may become too restrictive tomorrow (or vice versa). Updating policies across environments (build vs. runtime) introduces the risk of breaking developer workflows or blocking production deployments. Developers lose trust in the policy system if changes cause friction.
  • Solution: Implement a progressive rollout strategy by introducing new rules in “warn” or “audit” mode first, capturing violations without blocking. Once confidence is built, move to enforce.

4. Debugging and Observability

  • Problem: When policies block a deployment at runtime, developers often see a generic “denied” message. Without context, debugging is frustrating. Teams may bypass policy enforcement altogether to “unblock themselves.”
  • Solution: Always return human-readable reasons from Rego (msg := "Containers must not run as root"). Enable OPA decision logging and integrate with logging platforms (e.g., ELK, Datadog).

5. Policy Testing and Regression Risks

  • Problem: A single Rego change can inadvertently block valid workloads across multiple pipelines and clusters. It can lead to high regression risk — especially when policies are reused across environments.
  • Solution: Write Rego unit tests (OPA test) to validate expected outcomes. Run automated tests in CI before publishing a new policy bundle.

Conclusion

Reusing policies across build-time and runtime is not just a best practice — it’s becoming essential for modern DevSecOps. By embracing OPA and Rego, organizations can unify policy enforcement, reduce redundancy, and ensure compliance without slowing down developers. The key lies in treating policies as code, centralizing them, and reusing them seamlessly across the software lifecycle.

In the world of cloud-native security, shift-left doesn’t mean abandoning runtime — it means reuse.

Kubernetes Opa (programming language) Terraform (software)

Opinions expressed by DZone contributors are their own.

Related

  • Cloud Automation Excellence: Terraform, Ansible, and Nomad for Enterprise Architecture
  • Codify Your Cloud and Kubernetes With Crossplane and IaC
  • Securing Your Kubernetes Cluster: Terraform Secrets Management
  • Auto-Scaling a Spring Boot Native App With Nomad

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook