Table of Contents

Policy as code is the practice of expressing a security or governance rule as machine-readable code that automated tooling can evaluate and, where configured, enforce. Instead of relying only on someone reading a document and checking by hand, the tooling checks requests, infrastructure plans or existing resources at configured points and produces a result. Teams commonly keep the rules under version control so changes can be reviewed and traced. A person still writes the rule and owns its scope and enforcement setting. What changes is who does the checking, and when.

The shift is in repeatability and rigor, and it cuts both ways. A written policy waits for a person or a process to apply it. The same rule as code runs on a proposed change, an admission request or an existing resource, wherever the engine sits, which makes it useful both for stopping unwanted changes and for producing records of the checks. That speed is the point, and it is also the risk. A rule wired into admission fires on every request that crosses it, and a steady stream of passing checks is easy to read as proof that the control held. It is not. A check records a decision about one input at one moment. Whether the control held across the whole population, for the whole period, in a form an assessor would accept, is a different question, and it is the one a regulated program is graded on. Connecting those checks to that question is what compliance as code is for.

How policy as code works

No standards body owns the definition of policy as code, and the engines that implement it do not all work the same way. Break the practice down, though, and the same four moves show up every time: you define a rule, store it, evaluate it, and enforce the result.

Define the rule

A rule begins as a plain statement of intent: no storage bucket may be publicly readable, say, or every container image must come from an approved registry. Policy as code turns that statement into something an engine can read and act on. Open Policy Agent expresses rules in a declarative language it calls Rego. Kyverno manages policies as declarative Kubernetes resources, authored in YAML and CEL. HashiCorp Sentinel uses a policy language of its own. The syntax differs from tool to tool; the move is the same. You declare the condition you want to hold true, and you hand the checking to the machine. This is the same move behind infrastructure as code and security as code: something that used to live in a document becomes a versioned artifact a tool acts on.

Store it under version control

Once a rule is code, it lives where the rest of your code lives, in a repository with a history of who changed what. That history is the point, not a formality: a policy change can go through review, roll back cleanly, and ship on the same path as the software it governs. HCP Terraform, for one, connects to a version-control repository that holds a policy set and picks up the updated set automatically when you push to it. Version control is one supported path rather than a law of the practice; the same policies can also be managed through a UI or an API. With Kyverno, the policy is itself a Kubernetes resource, so it sits in the same manifests as the workloads it checks.

Evaluate it automatically

The engine runs the rule where you place the check. OPA can read a Terraform plan as JSON and evaluate a proposed change before it is applied. Kyverno can check Kubernetes resources at admission and can also evaluate existing resources. The timing and available input differ: a plan can contain values that will not be known until apply, while a runtime check observes an existing state. Choose the point that can actually answer the rule's question. Running checks in the delivery pipeline is one use covered by DevOps compliance automation tools.

Enforce the result

Enforcement decides what happens after the check. A failed rule can produce a warning, require a decision or block the change; the configured behavior matters as much as the rule. Sentinel defines three enforcement levels: advisory, where failure produces a warning; soft mandatory, where an authorized override can allow the run to continue; and hard mandatory, where the failure cannot be overridden. A hard failure calls for fixing the violation or changing the applicable policy through the controlled process. Other engines and integrations have their own enforcement settings, so check the environment in which the rule runs. Kyverno, for example, can report a violation in Audit mode without blocking the resource.

Kyverno publishes a ready policy called Restrict Image Registries that flags an image from a registry you have not approved, with the message "Unknown image registry." In the published example the action is set to audit, so a pod running a disallowed image is recorded as a violation and still runs. In a blocking configuration, the same rule keeps that pod out entirely. One rule, two enforcement settings, and the distance between them is the whole of what automatic enforcement can mean for your pipeline. But set both settings beside a different question. Audit mode records a violation and lets the pod run; a blocking configuration keeps it out. Each one decides whether a single pod is allowed. Neither one, on its own, tells you whether every image in the cluster came from an approved registry, or whether the rule was even in force all quarter. That is a question about evidence, not about admission, and it is where policy as code and compliance as code part ways.

Policy as code vs. compliance as code

A policy decision and a compliance assessment answer related questions. The decision says what a particular rule concluded about its input. The assessment asks how the relevant control is implemented and operating within a defined scope and period. Policy as code can contribute evidence to that assessment; it does not have to stop at an allow-or-deny result.

OPA decision logs can record inputs, results, timestamps and policy-bundle revisions. Those records help a reviewer reconstruct a decision. Logging must be configured and retained appropriately, and a record of a decision does not establish coverage of requests the engine never saw.

Kyverno has a different limit on evidence history. Its policy reports summarize matching resources and can be updated through admission checks and background scans. The reports describe current cluster state; they are not a historical archive. A program that needs a period of evidence must design for that history rather than assuming the current report contains it.

Compliance as code connects executable checks and their results to framework-oriented control definitions and assessment records. NIST's OSCAL illustrates how control and assessment information can be represented in machine-readable form. OSCAL is a set of formats, not a policy-enforcement engine or a requirement to adopt one particular workflow.

QuestionPolicy as codeCompliance as code
Primary purposeExpress a rule so tooling can evaluate it and apply a configured responseConnect controls, requirements, tests and assessment evidence in a repeatable process
Typical unitA policy and its input: a request, plan, resource or collected stateA control or requirement with implementation, scope and assessment records
When it runsAt a configured decision point or during a scan of existing resourcesWhen evidence or assessments are updated, and when results are assembled for review
Records it can produceDecisions, logs, violations and reports, depending on the engine and configurationRelationships between requirements and evidence, with the context of the assessment
What needs separate attentionInput coverage, policy version, exceptions, logging and retentionWhether the evidence is sufficient for the control, scope and period being assessed

The distinction is purpose, not an absolute boundary between tools that can and cannot produce evidence. A well-designed program can use the same check to enforce a rule and contribute a record to assessment. It still has to explain what was checked, what was excluded and what the result supports. The broader evidence-collection process supplies records alongside policy decisions, rather than turning one green check into proof of an entire quarter.

This is the distinction we care about most. Automation is indifferent to the unit it repeats. Point it at a decision and you get decisions faster; you do not get assurance. Take the approved-registry rule again. A blocking rule that turns away every unapproved image is a real control action, and a report that shows it passing hour after hour looks like proof. What it holds is a record of many admissions, each judged one at a time. It still does not show that every workload in the cluster pulled from an approved registry over the quarter, that the rule covered every cluster, or that no one moved it to audit for a week. A program that reads the green as proof has not closed the gap between passing and being secure. It has automated the gap, and automation on the wrong unit of proof spreads the error at the speed of the pipeline. The answer is not to trust the checks less. It is to keep what each check ran on: the population it evaluated, the time it ran, the scope it covered and the version of the rule in force, so the record answers a reviewer directly instead of asking them to take the green light on faith.

Where it fits in GRC engineering

GRC engineering connects the way a control is defined and changed with the evidence of how it operates. Policy as code implements the executable rules; compliance as code organizes their results for assessment. Read as one system, they let a reviewer trace an assessment back to the rule, its input and the version that ran, which is what turns a run of checks into something a program can stand on. The useful question, then, is not whether to adopt policy as code. It is how to run it so it feeds that system instead of sitting to the side of it.

From one rule to a reviewable assessment

The continuous compliance cycle places that result in an operating process: collect the relevant records, review exceptions, verify corrective action, and reassess when the environment or rule changes.

Take the approved-image-registry rule from the earlier example. The policy checks the image's registry. Its enforcement setting decides whether a violation is reported or blocked. Keep that setting with the result: the same failure means something different when the workload was allowed to run.

  1. Version the rule. Keep the approved policy and the change history that explains what was in force.
  2. Record the evaluation. Retain the relevant input, outcome, time and policy version using the engine's supported records.
  3. Account for coverage and exceptions. Identify where the rule ran, where it did not and which exceptions or overrides applied.
  4. Relate the record to the requirement. Explain which control objective it supports and what additional evidence is needed. Our guide to requirement-level control mapping covers that distinction.
  5. Review the conclusion. A person checks that the retained records support the claim for the scope and period being assessed.

To use this sequence, check which records the policy engine supplies and assign the remaining evidence and review work to an owner. In an enterprise program the same registry rule usually answers to more than one framework and more than one entity, so its record has to roll up cleanly across all of them, not only satisfy the pipeline it ran in. A single decision, a series of decisions and repeated observations cover different periods. Describe the result in those terms; claim uninterrupted coverage only when the evidence supports it.

This is the practice behind managing GRC like infrastructure and the GRC Engineering 101 guide: definitions and changes remain inspectable, while evidence is collected and reviewed on a repeatable basis. The wider GRC automation workflow carries findings and decisions to their owners.

Anecdotes' evidence collection and control testing support that evidence side of the program. Policy Guardian addresses a narrower connection: it reads a written policy, extracts statements that need enforcing and checks which statements have a matching analysis rule. That is useful policy-to-rule visibility; it is not a claim that Policy Guardian is an admission controller or a replacement for OPA, Kyverno or Sentinel.

Frequently asked questions

What does policy as code mean?

It means expressing security or governance rules as code that tooling can evaluate repeatedly. Teams commonly keep those rules under version control and run them against requests, planned changes or existing resources. People decide the rule, its scope and its enforcement setting; the tooling performs the configured check.

Can you give me an example of policy as code?

A common one is a rule that every container image must come from an approved registry. Kyverno publishes exactly this as a ready policy, Restrict Image Registries, which flags a disallowed image with the message "Unknown image registry." What happens next depends on the enforcement level: in the published example the mode is audit, so the violation is recorded and the workload still runs, while a blocking configuration would keep it out. The rule is the same; the enforcement setting decides the outcome.

What are some policy as code tools?

Three come up most often, each documented by the project behind it. Open Policy Agent (OPA) is a general-purpose, CNCF-graduated engine that decides policy for anything expressible as structured data, using its Rego language. Kyverno, also CNCF-graduated, is built for Kubernetes and manages policy as native cluster resources. HashiCorp Sentinel is HashiCorp's own policy as code tool for controlling what users of its products are allowed to do. There is no single best one; the fit depends on where you are enforcing.

How can I use policy as code in Terraform?

An engine such as OPA can evaluate a Terraform plan before it is applied. Check that the plan contains the information the rule needs, because some values are not known until apply. The surrounding workflow decides what to do with a failed result. Terraform describes the proposed infrastructure; the policy evaluates it against the rules you configured.

How is compliance as code different from policy as code?

Policy as code focuses on executable rules and their evaluation or enforcement. Compliance as code connects controls, requirements and assessment evidence in a repeatable process. They overlap: retained policy decisions can support a compliance assessment, provided the reviewer understands their coverage, version, exceptions and scope.

Key takeaways

  • Policy as code makes a rule repeatable: define it, version it, evaluate it and apply the configured result.
  • Checks can run before a change or against existing resources. The engine, input and integration determine what the result can establish.
  • Enforcement does not always mean blocking. Advisory, overridable and mandatory outcomes need to be read in their actual configuration.
  • Policy engines can produce useful evidence. Logging, retention, coverage and exceptions determine whether a reviewer can rely on it later.
  • Compliance as code connects that evidence to control and requirement assessments. A passing check is one record in that assessment, not proof of the whole program, so adopt the checks for what they do well and keep the evidence they ran on: the population, the timing, the scope and the rule version a reviewer will ask for.

Anecdotes team
The Better Way to GRC