<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Conftest on Backend Engineering Strategy Tools</title><link>https://backend-engineering-strategy-tools.github.io/site/tags/conftest/</link><description>Recent content in Conftest on Backend Engineering Strategy Tools</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Tue, 09 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://backend-engineering-strategy-tools.github.io/site/tags/conftest/index.xml" rel="self" type="application/rss+xml"/><item><title>Policy as Code — Overview</title><link>https://backend-engineering-strategy-tools.github.io/site/public-notes/policy-as-code/overview/</link><pubDate>Tue, 09 Jun 2026 00:00:00 +0000</pubDate><guid>https://backend-engineering-strategy-tools.github.io/site/public-notes/policy-as-code/overview/</guid><description>&lt;p&gt;Encoding compliance, security, and operational rules as version-controlled, testable code — evaluated at the point where things are created or changed rather than audited after the fact.&lt;/p&gt;
&lt;p&gt;The alternative is manual review and reactive alerts. Policy as code shifts that left: rules are explicit, reviewable, and enforced automatically.&lt;/p&gt;
&lt;h2 id="enforcement-points"&gt;Enforcement points
&lt;/h2&gt;&lt;p&gt;The same policy intent can be applied at three different points in the lifecycle:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CI/CD gate&lt;/strong&gt; — evaluate before anything reaches the cluster. Fail the pipeline on violations. Tools: Conftest, Checkov, Trivy IaC. Lowest blast radius, fastest feedback loop.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cluster admission&lt;/strong&gt; — intercept every &lt;code&gt;kubectl apply&lt;/code&gt; at the API server. No non-compliant resource can be created or updated. Tools: Kyverno, Gatekeeper (OPA), K8s-native ValidatingAdmissionPolicy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Runtime / drift detection&lt;/strong&gt; — continuously evaluate live state against policy and surface violations. Catches things that predate the policy, or that arrived outside normal pipelines. Tools: OPA, AWS Config, Kyverno audit mode.&lt;/p&gt;
&lt;p&gt;Most teams layer these: CI catches the obvious mistakes early and cheap, admission control enforces hard requirements at the cluster boundary, audit mode gives visibility into what is already out of compliance.&lt;/p&gt;
&lt;h2 id="how-the-tools-relate"&gt;How the tools relate
&lt;/h2&gt;&lt;p&gt;OPA is the common engine underneath Gatekeeper and Conftest. Rego is its policy language — learn it once and it applies across both. Kyverno is a separate engine that replaces Rego with Kubernetes-native YAML; lower barrier to entry, but the policy language does not transfer outside K8s. The K8s-native ValidatingAdmissionPolicy uses CEL, a simpler expression language built into the API server — no extra install, but limited to validation and basic mutation.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Policy intent
 ├── CI/CD gate → Conftest (Rego) / Checkov / Trivy IaC
 ├── K8s admission → Kyverno (YAML) / Gatekeeper (Rego) / VAP (CEL)
 └── Runtime → OPA server / Kyverno audit / AWS Config
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="to-explore"&gt;To explore
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Rego standalone&lt;/strong&gt; — eval policies against arbitrary JSON input using &lt;code&gt;opa eval&lt;/code&gt; and the REPL, without Kubernetes. Good way to learn the language in isolation before wiring it into a pipeline or cluster. See the &lt;a class="link" href="https://backend-engineering-strategy-tools.github.io/site/public-notes/policy-as-code/opa/" &gt;OPA &amp;amp; Rego&lt;/a&gt; note.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Conftest</title><link>https://backend-engineering-strategy-tools.github.io/site/public-notes/policy-as-code/conftest/</link><pubDate>Mon, 08 Jun 2026 00:00:00 +0000</pubDate><guid>https://backend-engineering-strategy-tools.github.io/site/public-notes/policy-as-code/conftest/</guid><description>&lt;p&gt;Conftest is a CLI tool that runs OPA policies against structured config files — Kubernetes manifests, Terraform plans, Helm output, Dockerfiles, GitHub Actions workflows, anything that can be parsed. It is the CI/CD enforcement layer on top of Rego.&lt;/p&gt;
&lt;p&gt;Write a policy once in Rego, run &lt;code&gt;conftest test&lt;/code&gt; in your pipeline, fail the build if violations are found.&lt;/p&gt;
&lt;h2 id="install"&gt;Install
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;brew install conftest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="basic-usage"&gt;Basic usage
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Test a Kubernetes manifest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;conftest test deployment.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Test all YAML in a directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;conftest test k8s/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Test a Terraform plan (JSON output)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;terraform show -json tfplan &amp;gt; tfplan.json
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;conftest test tfplan.json --parser json
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Test Helm-rendered output&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm template my-app ./chart | conftest test -
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;By default Conftest looks for policies in &lt;code&gt;./policy/&lt;/code&gt;. Change with &lt;code&gt;--policy&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="policy-structure"&gt;Policy structure
&lt;/h2&gt;&lt;p&gt;Policies are Rego files in the &lt;code&gt;policy/&lt;/code&gt; directory. Conftest checks for &lt;code&gt;deny&lt;/code&gt;, &lt;code&gt;warn&lt;/code&gt;, and &lt;code&gt;violation&lt;/code&gt; rules.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rego" data-lang="rego"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# policy/k8s.rego&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# deny blocks the pipeline&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;deny &lt;span style="color:#66d9ef"&gt;contains&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;input&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;kind&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Deployment&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;not&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;input&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;spec&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;template&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;spec&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;securityContext&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;runAsNonRoot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;sprintf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Deployment %v must set runAsNonRoot&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;,&lt;/span&gt; [&lt;span style="color:#a6e22e"&gt;input&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;metadata&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# warn prints a warning but does not fail&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;warn &lt;span style="color:#66d9ef"&gt;contains&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;input&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;kind&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Deployment&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;not&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;input&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;metadata&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;labels&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#34;app.kubernetes.io/version&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;sprintf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Deployment %v is missing version label&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;,&lt;/span&gt; [&lt;span style="color:#a6e22e"&gt;input&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;metadata&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;$ conftest test deployment.yaml
FAIL - deployment.yaml - main - Deployment nginx must set runAsNonRoot
WARN - deployment.yaml - main - Deployment nginx is missing version label

2 tests, 0 passed, 1 warning, 1 failure
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="namespaces"&gt;Namespaces
&lt;/h2&gt;&lt;p&gt;Use &lt;code&gt;--namespace&lt;/code&gt; to scope which Rego package Conftest evaluates. Useful when you have per-resource-type policies in separate packages.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;conftest test deployment.yaml --namespace kubernetes.deployments
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="multiple-parsers"&gt;Multiple parsers
&lt;/h2&gt;&lt;p&gt;Conftest supports many input formats. Common ones:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Flag&lt;/th&gt;
 &lt;th&gt;Parses&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--parser yaml&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;YAML (default for &lt;code&gt;.yaml&lt;/code&gt;/&lt;code&gt;.yml&lt;/code&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--parser json&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;JSON, Terraform plan&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--parser hcl2&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Terraform HCL&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--parser dockerfile&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Dockerfiles&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;--parser toml&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;TOML&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="sharing-policies"&gt;Sharing policies
&lt;/h2&gt;&lt;p&gt;Policies can be distributed as OCI artifacts and pulled with &lt;code&gt;conftest pull&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;conftest pull ghcr.io/myorg/policies:latest
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;conftest test deployment.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;a class="link" href="https://www.conftest.dev/sharing/" target="_blank" rel="noopener"
 &gt;Conftest policy hub&lt;/a&gt; documents the format. Useful for sharing a common policy library across repos without copy-pasting Rego.&lt;/p&gt;
&lt;h2 id="in-ci"&gt;In CI
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# GitHub Actions example&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Policy check&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;run&lt;/span&gt;: |&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; conftest test k8s/ --policy policy/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Exits non-zero on &lt;code&gt;deny&lt;/code&gt; violations. &lt;code&gt;warn&lt;/code&gt; violations print but do not fail the build — useful for phased enforcement (warn first, deny later).&lt;/p&gt;
&lt;h2 id="resources"&gt;Resources
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.conftest.dev/" target="_blank" rel="noopener"
 &gt;Conftest documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/open-policy-agent/conftest" target="_blank" rel="noopener"
 &gt;Conftest GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/open-policy-agent/conftest/tree/master/examples" target="_blank" rel="noopener"
 &gt;Example policies&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>