<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Policy-as-Code on Tarragon</title><link>https://tarrragon.github.io/blog/tags/policy-as-code/</link><description>Recent content in Policy-as-Code on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Mon, 18 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/policy-as-code/index.xml" rel="self" type="application/rss+xml"/><item><title>Open Policy Agent (OPA)</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/opa/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/opa/</guid><description>&lt;p>Open Policy Agent (OPA) 是 CNCF graduated 的 &lt;em>general-purpose policy engine&lt;/em>、設計目的是把「誰能做什麼、什麼 config 才合法」從 application code 抽到外部 policy decision layer。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &amp;#43; Constraint 兩層、Rego policy &amp;#43; Audit &amp;#43; Mutation">Gatekeeper&lt;/a> 的差別是：後兩者鎖在 K8s admission controller 領域、OPA 是 &lt;em>跨 enforcement point&lt;/em> 的 unified policy framework — 同一份 policy 可以同時管 K8s admission、API authz、Terraform plan、SQL row-level filter。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &amp;#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest&lt;/a> 的差別是：Conftest 是 OPA 的 &lt;em>CLI wrapper for static config&lt;/em>（在 CI 跑 Terraform / Dockerfile / K8s YAML 檢查）、OPA 本體是 &lt;em>runtime evaluation engine&lt;/em>（線上服務查詢決策）。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>OPA 的核心抽象是 &lt;em>decoupled decision + enforcement&lt;/em> — OPA 只負責 &lt;em>decide&lt;/em>（&lt;code>input&lt;/code> 進來、&lt;code>allow&lt;/code> / &lt;code>deny&lt;/code> + decision metadata 出去）、application 負責 &lt;em>enforce&lt;/em>（拿到 decision 後實際 reject request / block deploy / mask data）。這個解耦讓同一份 policy 跨 K8s admission（透過 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &amp;#43; Constraint 兩層、Rego policy &amp;#43; Audit &amp;#43; Mutation">Gatekeeper&lt;/a> 或 kube-mgmt sidecar）、Envoy authz filter、API gateway、Terraform pre-plan、SQL row-level filter、Kafka topic ACL 都能重用。&lt;/p>
&lt;p>OPA 的查詢語言是 &lt;em>Rego&lt;/em>、Datalog-like declarative language、設計上適合表達「給定一組 fact，這個動作合法嗎」。Rego 跟一般 imperative programming（Python / Go / YAML rules）差距大、team 要投入 1-2 週才能寫出 production-grade policy；換回的是 &lt;em>表達力 + 跨情境一致性&lt;/em> — Kyverno 的 YAML policy 易上手、但跨 K8s 邊界後沒辦法用。&lt;/p></description><content:encoded><![CDATA[<p>Open Policy Agent (OPA) 是 CNCF graduated 的 <em>general-purpose policy engine</em>、設計目的是把「誰能做什麼、什麼 config 才合法」從 application code 抽到外部 policy decision layer。它跟 <a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a> / <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> 的差別是：後兩者鎖在 K8s admission controller 領域、OPA 是 <em>跨 enforcement point</em> 的 unified policy framework — 同一份 policy 可以同時管 K8s admission、API authz、Terraform plan、SQL row-level filter。跟 <a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a> 的差別是：Conftest 是 OPA 的 <em>CLI wrapper for static config</em>（在 CI 跑 Terraform / Dockerfile / K8s YAML 檢查）、OPA 本體是 <em>runtime evaluation engine</em>（線上服務查詢決策）。</p>
<h2 id="服務定位">服務定位</h2>
<p>OPA 的核心抽象是 <em>decoupled decision + enforcement</em> — OPA 只負責 <em>decide</em>（<code>input</code> 進來、<code>allow</code> / <code>deny</code> + decision metadata 出去）、application 負責 <em>enforce</em>（拿到 decision 後實際 reject request / block deploy / mask data）。這個解耦讓同一份 policy 跨 K8s admission（透過 <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> 或 kube-mgmt sidecar）、Envoy authz filter、API gateway、Terraform pre-plan、SQL row-level filter、Kafka topic ACL 都能重用。</p>
<p>OPA 的查詢語言是 <em>Rego</em>、Datalog-like declarative language、設計上適合表達「給定一組 fact，這個動作合法嗎」。Rego 跟一般 imperative programming（Python / Go / YAML rules）差距大、team 要投入 1-2 週才能寫出 production-grade policy；換回的是 <em>表達力 + 跨情境一致性</em> — Kyverno 的 YAML policy 易上手、但跨 K8s 邊界後沒辦法用。</p>
<p>關鍵張力：<em>Rego 學習曲線</em> ↔ <em>unified policy 的長期價值</em>。只跑 K8s 的團隊用 Kyverno YAML 更直覺；只跑 CI policy 的用 Conftest 更輕；要在 K8s + API + Terraform + DB 跨層統一 policy、或要 audit-grade decision log、或預期 policy 會長期累積成資產的、才值得投資 OPA + Rego。</p>
<p>商業模型：核心 OPA 是 Apache 2.0 OSS、免費。Styra DAS（OPA 創辦人公司）是 enterprise SKU、提供 policy library + impact analysis + multi-cluster management + audit dashboard、適合大型團隊。OPAL（Permit.io 維護的 OSS）是 GitOps-style policy distribution layer、補 OSS OPA 缺的 bundle server。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>OPA 在 policy stack 中承擔哪一段（decision engine） vs enforcement point 各自的 ownership</li>
<li>Rego 投資門檻是否值得（K8s-only vs 跨 enforcement point）</li>
<li>Policy bundle / Decision log / Partial evaluation 三個 first-class concept 在 production 的設計形狀</li>
<li>何時用 OPA、何時走 <a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a> / <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> / <a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a> 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 OPA deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Policy ownership</strong>：誰能寫 / 改 Rego policy（platform team / security team / SRE）、policy 是否進 Git、change 是否經 PR review + staging tenant 跑 24-48hr 觀察</li>
<li><strong>Bundle distribution</strong>：policy 是否 build 成 bundle（tar.gz）、是否簽章、OPA agent 是否定期 pull、bundle server 在哪（自管 nginx / S3 / OPAL / Styra DAS）</li>
<li><strong>Decision log governance</strong>：每個 decision 是否進 audit log（input + output + policy version + timestamp）、log 是否進 SIEM（<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / Elastic）、retention 多久</li>
<li><strong>Enforcement coverage</strong>：哪些 enforcement point 接 OPA（K8s admission / API / Envoy / Terraform）、policy 是否 share 還是各 point 各寫一份、跨 point 的一致性怎麼驗</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/security-as-risk-routing-system/" data-link-title="7.15 資安作為風險路由系統" data-link-desc="建立資安作為風險路由系統的導讀大綱，串接問題節點、控制面與跨模組交接">Policy as Code Foundations</a> 的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Rego policy 形狀</strong>：Rego 是 Datalog-like declarative language、policy 寫成 <code>allow { ... }</code> rule、所有條件成立才 evaluate 為 true。實務 idiom：底層寫 <em>base policy</em>（如 <code>policies/k8s/required_labels.rego</code>）、上層寫 <em>policy library</em>（共用 helper 如 <code>policies/lib/registry.rego</code>）、application 端傳 <code>input</code>（K8s admission request / API request / Terraform plan JSON）查詢。Rego 鼓勵 <em>small composable rule</em>、不寫長 imperative function。</p>
<p><strong>Policy bundle</strong>：OPA 不從 Git 直接讀 policy、而是讀 <em>bundle</em>（tar.gz、含 <code>.rego</code> + data JSON、optional 簽章）。Bundle 從 <em>bundle server</em> pull（自管 nginx / S3 / OPAL / Styra DAS）、OPA agent 定期 polling（預設 60s）。Bundle 的核心價值是 <em>versioned + signed + atomically swap</em> — policy 更新不會 partial apply、簽章確保中間沒被改、版本 metadata 讓 decision log 可追到當時用哪版 policy。</p>
<p><strong>Decision log</strong>：每個 OPA query 都可開 decision logging、log entry 含 <code>input</code> + <code>result</code> + <code>policy_version</code> + <code>timestamp</code> + <code>decision_id</code>。意義是 <em>audit-grade reconstruction</em> — 事後可以重跑 <code>opa eval --bundle &lt;version&gt; --input &lt;log_input&gt;</code> 驗證當時 decision 是否正確。Decision log 進 SIEM 後可做 <em>over-permission analysis</em>（哪些 user 拿到 allow 但實際從不該被 allow）跟 <em>policy coverage check</em>（哪些 rule 從沒被觸發過、可能是 dead code）。</p>
<p><strong>Integration pattern</strong>：production OPA 主要四種 enforcement integration — <em>K8s admission</em>（走 <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> 是 OPA 官方 K8s integration、或 kube-mgmt 把 OPA 當 sidecar 跑、admission webhook 把 request 送進 OPA decide）；<em>API authz</em>（application 在 request handler 開頭 query OPA、拿 allow/deny 後 enforce）；<em>Envoy / service mesh</em>（Envoy 的 ext_authz filter 接 OPA、L7 authz decision）；<em>Infrastructure as Code</em>（CI 跑 <a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a> 對 Terraform plan / K8s YAML 做 OPA 評估）。</p>
<p><strong>Partial evaluation</strong>：OPA 進階 feature、把一份 policy 對某個 <em>partial input</em>（如 <code>user=&quot;alice&quot;</code>）pre-evaluate、產出 <em>殘餘 query</em>（如 SQL <code>WHERE tenant_id IN (...)</code> 或 regex），下發給 enforcement point 直接用。意義是 <em>把 policy decision 推到 enforcement point 內部</em>、減少每次 query 都要過 OPA 的 latency；常用於 row-level data filter（policy 寫一次、partial eval 出 SQL WHERE clause、application 直接拼進 query）。</p>
<p><strong>OPAL（GitOps for OPA）</strong>：OSS、Permit.io 維護、解決「policy 從 Git push 到所有 OPA agent」的 distribution 問題。Git → OPAL Server → OPA Agent 的 push model、policy commit 到 main branch 後幾秒內所有 OPA 更新。對應 OSS-only 的 production setup；Styra DAS 提供同等功能 + 管理 UI。</p>
<p><strong>Styra DAS（商業 management）</strong>：Styra 是 OPA 創辦人公司、DAS 是 enterprise SKU。核心價值：<em>policy library</em>（pre-built policy for K8s / Terraform / Kafka）、<em>impact analysis</em>（policy 上 production 前 dry-run 看會 deny 多少現有 resource）、<em>multi-cluster policy distribution</em>、<em>audit dashboard</em>。OSS-only 自己拼 OPAL + decision log + SIEM 也能做、但團隊 &gt; 50 個 cluster / 多 BU 時 DAS 划算。</p>
<p><strong>Constraint Framework</strong>：<a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> 在 OPA 之上加的 K8s-specific 抽象、用 <code>ConstraintTemplate</code>（Rego policy 模板）+ <code>Constraint</code>（K8s CRD instance、實際 enforce）。對純 K8s 場景比直接寫 Rego 更 K8s-native；但這個抽象只在 K8s 領域有意義、不會跨到 API / Terraform。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>OPA</th>
          <th>Kyverno</th>
          <th>Gatekeeper</th>
          <th>Conftest</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>定位</td>
          <td>General-purpose policy engine</td>
          <td>K8s-native admission controller</td>
          <td>OPA 的 K8s admission integration（官方）</td>
          <td>OPA 的 CLI wrapper for static config</td>
      </tr>
      <tr>
          <td>語言</td>
          <td>Rego（Datalog-like declarative）</td>
          <td>YAML（K8s-native）</td>
          <td>Rego（透過 ConstraintTemplate）</td>
          <td>Rego</td>
      </tr>
      <tr>
          <td>Enforcement</td>
          <td>K8s / API / Envoy / Terraform / SQL / Kafka 跨層</td>
          <td>K8s admission only</td>
          <td>K8s admission only</td>
          <td>CI / pre-commit（不在 runtime）</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>陡 — Rego 1-2 週</td>
          <td>緩 — YAML 1-2 天</td>
          <td>中 — ConstraintTemplate 抽象 + Rego</td>
          <td>中 — Rego 1-2 週、但 scope 小</td>
      </tr>
      <tr>
          <td>部署模型</td>
          <td>OPA agent（sidecar / daemon / library embed）</td>
          <td>K8s controller + webhook</td>
          <td>K8s controller + webhook</td>
          <td>CLI（CI / 本地）</td>
      </tr>
      <tr>
          <td>Mutation</td>
          <td>透過 Gatekeeper Mutation 或 application enforce 補上</td>
          <td>原生 mutate webhook（強項）</td>
          <td>Mutation 是 v3.10+ beta、功能不及 Kyverno</td>
          <td>無（static check only）</td>
      </tr>
      <tr>
          <td>Bundle / 分發</td>
          <td>Bundle server + sign + OPA agent pull / OPAL push</td>
          <td>K8s CRD apply（kubectl）</td>
          <td>K8s CRD apply</td>
          <td>Git repo（CI 直接 clone）</td>
      </tr>
      <tr>
          <td>Decision log</td>
          <td>First-class、audit-grade</td>
          <td>K8s event + audit log</td>
          <td>K8s event + audit log</td>
          <td>CI build log</td>
      </tr>
      <tr>
          <td>商業 SKU</td>
          <td>Styra DAS（management + impact analysis）</td>
          <td>Nirmata Kyverno Enterprise</td>
          <td>無（純 OSS）</td>
          <td>無（純 OSS）</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>跨 enforcement point + long-term policy investment</td>
          <td>K8s-only + 快速上手 + YAML-friendly team</td>
          <td>K8s-only + 已用 OPA / Rego、要 OPA 官方整合</td>
          <td>CI pre-deploy check + Terraform / K8s YAML / Dockerfile</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — Rego policy 可移到其他 OPA-compatible engine</td>
          <td>高 — YAML policy 僅 Kyverno 認</td>
          <td>中 — Rego 可重用、Constraint 抽象要重寫</td>
          <td>低 — CLI tool、policy 可移到 OPA runtime</td>
      </tr>
  </tbody>
</table>
<p>選 OPA 的核心訴求：<em>跨 enforcement point 的 unified policy</em> + <em>long-term policy 資產化</em> + <em>audit-grade decision log</em> + 團隊願意投資 Rego。純 K8s + 想快速上手用 <a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a>；K8s + 已決定走 OPA 生態用 <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a>；只跑 CI 不跑 runtime 用 <a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a>。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Rego idioms（policy library + base policy）</strong>：production Rego 走分層結構 — <code>lib/</code>（utility function、registry whitelist、CIDR check）、<code>base/</code>（concrete policy、引用 lib）、<code>tests/</code>（用 <code>opa test</code> 跑 unit test）。Policy 也是 code、走 PR review + CI test + staging tenant、不是 console 直改。</p>
<p><strong>Partial evaluation for SQL row-level filter</strong>：把 policy 寫成「user 能看哪些 row」、用 <code>opa eval --partial</code> 把 <code>user=&quot;alice&quot;</code> 部分 pre-evaluate、output 殘餘 query 變 SQL <code>WHERE tenant_id IN ('a', 'b', 'c')</code>、application 拼進 query。意義是 <em>policy 不在 query path latency 上</em>、policy 規則仍是 SSoT。對應 RLS（row-level security）的工程化作法。</p>
<p><strong>跟 <a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a> workload identity 整合 authz</strong>：service-to-service authz 場景、SPIRE 簽 SVID（SPIFFE ID + mTLS cert）證明 caller 身份、OPA 拿到 SPIFFE ID 後 decide「這個 service 能呼叫這個 API 嗎」。SPIRE 解 <em>who</em>、OPA 解 <em>can they do this</em>、職責清楚分離。</p>
<p><strong>跟 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> 整合 dynamic credential policy</strong>：Vault 簽 dynamic credential（DB password / cloud STS token）的 issue 決定可以走 OPA — Vault 收到 issue request、轉 OPA decide「這個 caller 在這個 context 能不能拿這個 scope 的 token」。對應 <a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a> 的 lesson：scope 判斷不分散在應用層、集中到 policy engine。</p>
<p><strong>Decision log 進 SIEM</strong>：OPA decision log 設成 push 到 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> HEC / Elastic / Datadog、進 SIEM 後可做三件事 — over-permission analysis（哪些 allow 從沒被合法理由觸發）、dead policy detection（哪些 rule 從沒被 evaluate）、anomalous decision pattern（某 service 突然大量 allow 不在 baseline）。</p>
<p><strong>跟 K8s admission 的兩條路</strong>：純 K8s admission 場景、走 <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a>（OPA 官方 K8s integration、有 Constraint Framework 抽象、社群活躍）比直接跑 OPA + kube-mgmt sidecar 更 production-ready。kube-mgmt 路線適合 already-running OPA 想加 K8s admission 而不引入 Gatekeeper 抽象。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Rego policy review 卡 SRE</strong>：policy 都得 SRE 寫、security team 看不懂 — 拆 <code>lib/</code> 給 SRE 維護、<code>base/</code> 給 security review、用 <code>opa test</code> unit test 保持迭代速度</li>
<li><strong>Bundle distribution 慢 / policy 不一致</strong>：自管 nginx bundle server 沒高可用、agent pull 失敗 fallback 用舊版 — 換 OPAL push model 或 S3 + CloudFront、bundle pull 失敗時 OPA <code>--set status.console=true</code> 直接 alert</li>
<li><strong>Decision log 沒進 SIEM</strong>：OPA 開了 decision log 但只進本地 file、沒人看 — 設 decision log plugin push 到 <a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> HEC / Kafka、不是寫本地 disk</li>
<li><strong>Policy 改完 production 大量 deny</strong>：新 policy 沒在 staging dry-run、上 production 後合法 traffic 被擋 — Styra DAS 的 impact analysis 或自己跑 <code>opa eval --partial</code> 對歷史 decision log replay、看 deny 數量再 promote</li>
<li><strong>OPA latency 高 / API 卡</strong>：每個 request 都 round-trip OPA、policy 複雜 evaluation 慢 — embed OPA as library（Go SDK / WASM）跑 in-process、或用 partial evaluation 把 policy compile 進 SQL / regex</li>
<li><strong>Rego policy bug 線上才發現</strong>：沒 unit test、staging 沒 cover edge case — 強制 PR 要含 <code>opa test</code> case、staging 跑 shadow mode（log only 不 enforce）24hr 再切 enforce</li>
<li><strong>跨 cluster policy drift</strong>：多 cluster 各自 apply、版本不同步 — OPAL 或 Styra DAS multi-cluster sync、不靠 kubectl apply 人工同步</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>K8s admission only + YAML-friendly</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a></td>
      </tr>
      <tr>
          <td>K8s admission + 已選 OPA 生態</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a></td>
      </tr>
      <tr>
          <td>CI pre-deploy check（Terraform / K8s YAML / Dockerfile）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a></td>
      </tr>
      <tr>
          <td>Runtime container behavior（不是 admission）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/" data-link-title="資安與資料保護 Vendor 清單" data-link-desc="規劃身份、秘密、金鑰、入口防護、供應鏈與偵測工具的服務頁撰寫順序與教學大綱">Falco</a></td>
      </tr>
      <tr>
          <td>Image scan + vulnerability policy</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>（scan）+ OPA（gate）</td>
      </tr>
      <tr>
          <td>Workload identity / mTLS</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a> + OPA（identity → authz 分工）</td>
      </tr>
      <tr>
          <td>Cloud IAM policy（AWS / GCP / Azure 本體）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-iam/" data-link-title="AWS IAM" data-link-desc="AWS cloud resource permission engine、Role / Policy / STS、跨帳號信任邊界與 OIDC federation 的核心">AWS IAM</a> / <a href="/blog/backend/07-security-data-protection/vendors/google-cloud-iam/" data-link-title="Google Cloud IAM" data-link-desc="GCP cloud resource permission engine、Role Binding / Service Account / Workload Identity Federation、resource hierarchy 為核心的權限治理">Google Cloud IAM</a></td>
      </tr>
      <tr>
          <td>Decision log → SIEM</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> / <a href="/blog/backend/07-security-data-protection/vendors/elastic-security/" data-link-title="Elastic Security" data-link-desc="Elastic Stack 上的 SIEM &#43; EDR &#43; Cloud Security 套件、OSS 起源、KQL/EQL/Lucene/ES|QL 多查詢語言、resource-based pricing">Elastic Security</a></td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Rego 完整語法 reference（rule / function / built-in / <code>with</code> / <code>some</code>）</li>
<li>Gatekeeper Constraint Framework 的 ConstraintTemplate / Constraint CRD 設計細節（屬 Gatekeeper 頁）</li>
<li>Conftest CLI 用法跟 <code>conftest test</code> / <code>conftest verify</code> 流程（屬 Conftest 頁）</li>
<li>Kyverno YAML policy 語法跟 mutate / generate / verifyImages（屬 Kyverno 頁）</li>
<li>Styra DAS 商業 license / SKU 對照、Nirmata Enterprise 對照</li>
<li>WASM-compiled Rego policy 的 edge deployment 細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 OPA 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>OPA admission policy 在 K8s 擋住未簽章 image deploy、配合 cosign signature verify 補 supply chain 信任鏈、policy 集中不分散到各 deployment</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>OPA admission 配合 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> scan result 擋住已知 vulnerable image deploy、policy 走「critical CVE = deny」</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">Failure: Credential Rotation Without Scope</a></td>
          <td>OPA 控制 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> dynamic credential issuance policy、scope 判斷集中不分散到應用層各自 if-else</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性 (section)</a></td>
          <td>OPA 是 admission gate 的核心工具、跟 SLSA provenance / cosign signature 組合做 policy enforcement、不是看一兩個欄位放行</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/security-as-risk-routing-system/" data-link-title="7.15 資安作為風險路由系統" data-link-desc="建立資安作為風險路由系統的導讀大綱，串接問題節點、控制面與跨模組交接">Policy as Code Foundations (section)</a></td>
          <td>OPA 對應 policy-as-code 的 <em>decoupled decision + enforcement</em>、跨 enforcement point 共用 policy 是設計核心、不是「再寫一份 K8s policy」</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/security-as-risk-routing-system/" data-link-title="7.15 資安作為風險路由系統" data-link-desc="建立資安作為風險路由系統的導讀大綱，串接問題節點、控制面與跨模組交接">7 章 policy-as-code foundations</a>、<a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性</a></li>
<li>平行（Policy-as-Code 批次）：<a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a>（CI static check）、<a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a>（K8s YAML-native）、<a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a>（OPA K8s integration）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a>（workload identity → OPA authz）、<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a>（dynamic credential policy）、<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>（scan → OPA gate）、<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a>（decision log → SIEM）</li>
<li>跨模組：<a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">6 reliability</a>（CI pre-deploy gate 接 Conftest）、<a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">8 incident response</a>（policy violation alert → IR routing）</li>
<li>官方：<a href="https://www.openpolicyagent.org/">Open Policy Agent</a>、<a href="https://www.openpolicyagent.org/docs/latest/policy-language/">Rego Policy Language</a>、<a href="https://www.styra.com/">Styra DAS</a>、<a href="https://github.com/permitio/opal">OPAL</a></li>
</ul>
]]></content:encoded></item><item><title>Kyverno</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/kyverno/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/kyverno/</guid><description>&lt;p>Kyverno 是 K8s-native 的 policy engine、CNCF Incubating（2024 升級）、設計 mindset 把 &lt;em>policy 寫成 YAML&lt;/em> 而不是引入新語言（vs &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &amp;#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA&lt;/a> 的 Rego、&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &amp;#43; Constraint 兩層、Rego policy &amp;#43; Audit &amp;#43; Mutation">Gatekeeper&lt;/a> 也用 Rego）。它的核心不是「更輕量的 OPA」、而是 &lt;em>K8s 專用 policy engine&lt;/em> — 把 Validate / Mutate / Generate / Verify Images / Cleanup 五類動作做成 first-class rule type、跟 K8s admission webhook + GitOps + cosign / Sigstore ecosystem 深度整合。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Kyverno 的定位是 &lt;em>K8s admission controller-shaped policy engine、policy 用 YAML 表達&lt;/em>。底層是 dynamic admission webhook + background controller、頂層 CRD 包含 &lt;em>ClusterPolicy&lt;/em>（cluster 範圍）/ &lt;em>Policy&lt;/em>（namespace 範圍）/ &lt;em>PolicyException&lt;/em>（明確例外）/ &lt;em>ClusterCleanupPolicy&lt;/em>（過期 resource 清理）/ &lt;em>PolicyReport&lt;/em>（CIS / NIST 等審計輸出）。Nirmata 是 Kyverno 商業版、補 policy library / multi-cluster management / audit dashboard / 24x7 support。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &amp;#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA&lt;/a> 比、Kyverno 走 &lt;em>narrow + opinionated&lt;/em> — OPA 是 general-purpose policy engine（K8s / API gateway / Terraform / 自家服務都能用、語言是 Rego）、Kyverno &lt;em>K8s-only + YAML&lt;/em>、學習成本對 K8s admin 接近零。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &amp;#43; Constraint 兩層、Rego policy &amp;#43; Audit &amp;#43; Mutation">Gatekeeper&lt;/a> 比、Gatekeeper 也是 K8s admission controller 但底層用 OPA + Rego、ConstraintTemplate / Constraint 兩層 CRD；Kyverno 不用 Rego、policy 就是 YAML rule list。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &amp;#43; Secret &amp;#43; License &amp;#43; SBOM、Apache 2.0、CI 友善">Trivy&lt;/a> 的 misconfig scan 比、Trivy 是 &lt;em>scan static manifest&lt;/em>、Kyverno 是 &lt;em>admission gate + background scan&lt;/em>、定位互補不衝突。&lt;/p></description><content:encoded><![CDATA[<p>Kyverno 是 K8s-native 的 policy engine、CNCF Incubating（2024 升級）、設計 mindset 把 <em>policy 寫成 YAML</em> 而不是引入新語言（vs <a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a> 的 Rego、<a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> 也用 Rego）。它的核心不是「更輕量的 OPA」、而是 <em>K8s 專用 policy engine</em> — 把 Validate / Mutate / Generate / Verify Images / Cleanup 五類動作做成 first-class rule type、跟 K8s admission webhook + GitOps + cosign / Sigstore ecosystem 深度整合。</p>
<h2 id="服務定位">服務定位</h2>
<p>Kyverno 的定位是 <em>K8s admission controller-shaped policy engine、policy 用 YAML 表達</em>。底層是 dynamic admission webhook + background controller、頂層 CRD 包含 <em>ClusterPolicy</em>（cluster 範圍）/ <em>Policy</em>（namespace 範圍）/ <em>PolicyException</em>（明確例外）/ <em>ClusterCleanupPolicy</em>（過期 resource 清理）/ <em>PolicyReport</em>（CIS / NIST 等審計輸出）。Nirmata 是 Kyverno 商業版、補 policy library / multi-cluster management / audit dashboard / 24x7 support。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a> 比、Kyverno 走 <em>narrow + opinionated</em> — OPA 是 general-purpose policy engine（K8s / API gateway / Terraform / 自家服務都能用、語言是 Rego）、Kyverno <em>K8s-only + YAML</em>、學習成本對 K8s admin 接近零。跟 <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> 比、Gatekeeper 也是 K8s admission controller 但底層用 OPA + Rego、ConstraintTemplate / Constraint 兩層 CRD；Kyverno 不用 Rego、policy 就是 YAML rule list。跟 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> 的 misconfig scan 比、Trivy 是 <em>scan static manifest</em>、Kyverno 是 <em>admission gate + background scan</em>、定位互補不衝突。</p>
<p>關鍵張力：<em>YAML policy 的表達力上限</em> ↔ <em>跨平台統一 policy 的訴求</em>。Kyverno YAML rule 對 90% K8s 場景夠用、但需要跨 K8s / API gateway / Terraform 統一 policy decision 時、Rego 的表達力跟可移植性勝出。要看清楚 policy <em>邊界是否就在 K8s 內</em>。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Kyverno 在 K8s 治理 stack 中承擔哪一段（admission gate / mutation / generation / image verify / cleanup）、跟 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> scan / <a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">SBOM Tools</a> / Sigstore cosign 怎麼分工</li>
<li>ClusterPolicy / Policy 的 ownership 設計（platform team 還是 app team 寫、誰 review、PolicyException 怎麼治理）</li>
<li>Validate / Mutate / Generate / Verify Images / Cleanup 五類 rule 的使用邊界跟陷阱</li>
<li>何時用 Kyverno、何時走 OPA / Gatekeeper / K8s native ValidatingAdmissionPolicy 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Kyverno deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>Policy 是否走 GitOps</strong>：ClusterPolicy / Policy 是否在 Git 版控、走 ArgoCD / Flux sync、policy change 是否經 PR review、staging cluster 跑過 audit mode 才 promote 到 enforce</li>
<li><strong>Mode 配置</strong>：每條 policy 是 <em>Audit</em>（只記、不擋）還是 <em>Enforce</em>（擋 admission）、新規則是否先 audit 觀察 24-48hr 再 enforce、Background scan 是否開（補 admission 不到的 historical drift）</li>
<li><strong>Verify Images 啟用度</strong>：production cluster 是否要求 image 必須通過 cosign signature verify、SBOM attestation 是否驗、policy 是否包含 keyless verify（Fulcio + Rekor）</li>
<li><strong>PolicyException 治理</strong>：例外是否走 PR 申請 + 到期日 + owner、跟 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a> 的 exception governance 對齊</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>ClusterPolicy / Policy 結構</strong>：Kyverno policy 是 K8s CRD、結構 <code>spec.rules[]</code> 一條條 rule、每條 rule 有 <code>match</code>（套用對象、kind / namespace / label / name）+ <code>exclude</code>（明確排除）+ rule body（<code>validate</code> / <code>mutate</code> / <code>generate</code> / <code>verifyImages</code> / <code>cleanup</code> 五選一）。ClusterPolicy 套整個 cluster、Policy 套單一 namespace、app team 通常只能改自家 namespace 的 Policy、平台 team 控 ClusterPolicy。</p>
<p><strong>Validate rule</strong>：admission 階段檢查 manifest 是否符合條件、不符合就拒絕。最常見場景 — 禁止 <code>latest</code> tag、要求所有 pod 有 resource limit、禁止 privileged container、要求 specific label。寫法是 <code>validate.pattern</code> 或 <code>validate.deny</code>（後者支援更複雜的 boolean expression）、output 是 admission webhook reject。Validate 是 <em>K8s policy as code</em> 的入門場景、80% 的 ClusterPolicy 都是 Validate rule。</p>
<p><strong>Mutate rule</strong>：admission 階段修改 manifest、把缺的欄位補上或改成符合的值。常見場景 — 自動注入 sidecar（service mesh proxy / log forwarder）、自動加 resource limit default、自動加 label（cost center / owner）、自動把 imagePullPolicy 改成 <code>Always</code>。Mutate 是 OPA / Gatekeeper 做不到的（兩者都偏 Validate-only）、是 Kyverno 的 <em>K8s-specific 強項</em>。陷阱是 mutate 變更後 GitOps diff 會永遠不一致、要在 ArgoCD ignoreDifferences 上對齊。</p>
<p><strong>Generate rule</strong>：cluster event（namespace 建立、resource 變動）觸發、自動建立 <em>關聯 resource</em>。最常見場景 — 新 namespace 自動建 default NetworkPolicy（deny-all egress 起手）、自動建 ResourceQuota / LimitRange、自動 copy ConfigMap / Secret 到新 namespace。Generate 是把 <em>security default</em> 從文件層落到 runtime layer、避免 app team 忘記設 NetworkPolicy 就把整個 cluster 暴露。Generate 也是 OPA / Gatekeeper 做不到、Kyverno 獨有。</p>
<p><strong>Verify Images rule</strong>：admission 階段驗證 container image 的簽章 / SBOM attestation / in-toto provenance。實作底層 <a href="https://docs.sigstore.dev/">Sigstore</a> cosign — keyless 簽章驗 Fulcio CA + Rekor transparency log、key-based 驗 public key、attestation 驗 SLSA provenance / SBOM。production 場景 — internal registry image 必須 cosign 簽 + 來自 trusted CI runner、external image 必須在 allowlist。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a> 的 supply chain attack 防禦邊界。</p>
<p><strong>Cleanup policy</strong>：ClusterCleanupPolicy / CleanupPolicy 是 K8s 1.27+ 引入、Kyverno 1.10+ 支援、按 cron 跑、清掉符合條件的 resource。常見場景 — 過 30 天的 completed Job、過 7 天的 failed Pod、ephemeral namespace（PR preview env）超過 TTL 自動刪。Cleanup 補的是 K8s 沒有 <em>resource lifecycle policy</em> 的洞、TTL controller 只覆蓋 Job / Pod 子集。</p>
<p><strong>Background scan</strong>：除了 admission 攔截 <em>新 resource</em>、Kyverno 定期掃描 <em>已存在 resource</em> 是否違反 policy、結果寫入 PolicyReport CRD。意義是補 <em>歷史 drift</em> — policy 是後來加的、已 deploy 的 resource 不會被 admission 攔到、background scan 才會找出來。production 一定要開、不開等於 policy 只防新犯不抓舊案。</p>
<p><strong>ValidatingAdmissionPolicy (VAP) 整合</strong>：K8s 1.30+ 內建 CEL-based admission policy、不需要 admission webhook（VAP 由 kube-apiserver 直接 enforce、延遲低、不會因為 Kyverno pod 掛掉就讓 admission 失敗）。Kyverno 1.11+ 可以從 ClusterPolicy <em>生成</em> VAP、把簡單 Validate rule 卸載給 K8s native engine、複雜 rule（Mutate / Generate / Verify Images）留在 Kyverno。長期趨勢 — K8s native VAP 會吃掉 Kyverno <em>Validate-only</em> 的場景、Mutate / Generate / Verify Images 仍是 Kyverno 護城河。</p>
<p><strong>GitOps 整合</strong>：ClusterPolicy / Policy 是普通 K8s CRD、走 ArgoCD / Flux sync 沒任何特殊性。staging cluster 跑 Audit mode 24-48hr 看 PolicyReport 有多少違規 → tune rule 或加 PolicyException → 確認沒誤殺再 promote 到 production cluster 的 Enforce mode。對應 <a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle</a> 的 propose → staging → promote pattern。</p>
<p><strong>Policy Reporter</strong>：OSS dashboard（不是 Kyverno 內建、是社群專案）、把 PolicyReport CRD 視覺化、給 platform team / app team 看 cluster 違規概況。Nirmata 商業版有更完整的 multi-cluster dashboard + 歷史 trend + compliance mapping（CIS / NIST / PCI）。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Kyverno</th>
          <th>OPA + Gatekeeper</th>
          <th>OPA standalone</th>
          <th>Conftest</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Policy 語言</td>
          <td>YAML（patterns / deny / preconditions）</td>
          <td>Rego（DSL、表達力強）</td>
          <td>Rego</td>
          <td>Rego</td>
      </tr>
      <tr>
          <td>覆蓋範圍</td>
          <td>K8s only</td>
          <td>K8s only</td>
          <td>K8s / API / Terraform / 任意 JSON 輸入</td>
          <td>CI-time static file（Terraform / Docker）</td>
      </tr>
      <tr>
          <td>Rule 類型</td>
          <td>Validate / Mutate / Generate / Verify Images / Cleanup</td>
          <td>Validate-only（Mutate 是 experimental）</td>
          <td>由 host application 決定</td>
          <td>Validate（CI-time）</td>
      </tr>
      <tr>
          <td>部署形態</td>
          <td>K8s admission webhook + controller</td>
          <td>K8s admission webhook（Gatekeeper 是 OPA 包）</td>
          <td>sidecar / library / standalone server</td>
          <td>CLI（CI pipeline）</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>緩 — K8s admin 已熟 YAML</td>
          <td>陡 — 要學 Rego</td>
          <td>陡 — 要學 Rego + host integration</td>
          <td>中 — Rego 但範圍小</td>
      </tr>
      <tr>
          <td>Image signature</td>
          <td>內建 Verify Images（cosign + Sigstore）</td>
          <td>需自己接 cosign CLI</td>
          <td>需自己接</td>
          <td>不適用</td>
      </tr>
      <tr>
          <td>Background scan</td>
          <td>內建</td>
          <td>gator audit（弱）</td>
          <td>不適用</td>
          <td>不適用</td>
      </tr>
      <tr>
          <td>跨 platform 一致</td>
          <td>弱 — K8s only</td>
          <td>弱 — K8s only</td>
          <td>強 — 同份 Rego 跑 K8s / API / Terraform</td>
          <td>強 — CI 跑同份 Rego</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>K8s-heavy + 想用 YAML + 需 Mutate / Generate / Image</td>
          <td>K8s + 已有 Rego 投資 + Validate-only</td>
          <td>跨 K8s / API / Terraform 統一 policy</td>
          <td>CI-time pre-merge 檢查</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>中 — YAML rule 跟 K8s CRD 綁</td>
          <td>中 — Rego 可移植到 OPA standalone</td>
          <td>低 — Rego 跨平台</td>
          <td>低</td>
      </tr>
  </tbody>
</table>
<p>選 Kyverno 的核心訴求：<em>K8s-only 場景 + 不想學 Rego + 需要 Mutate / Generate / Verify Images 的 K8s-specific 能力</em>。團隊已投資 Rego ecosystem、或 policy 邊界跨 K8s + Terraform + API gateway、走 OPA / Gatekeeper 更合適。CI-time pre-merge 檢查走 Conftest 補位。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Verify Images 進階 — cosign keyless + SBOM attestation</strong>：production-grade image trust 不只驗 signature、要驗 <em>who signed it from where with what build process</em>。keyless 模式驗 Fulcio CA-issued 短期憑證 + Rekor transparency log entry、確認簽章來自 trusted CI runner 的 OIDC identity（例如 <code>https://github.com/myorg/myrepo/.github/workflows/release.yaml@refs/tags/v*</code>）。SBOM attestation 用 <code>verifyImages.attestations</code> 驗 in-toto envelope、確認 image 帶 SLSA provenance + SBOM（<a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">CycloneDX / SPDX</a>）。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/xz-backdoor-2024-open-source-supply-chain/" data-link-title="7.R7.2.4 XZ Backdoor 2024：開源供應鏈長期滲透" data-link-desc="開源維護鏈遭滲透後，為何會直接影響廣泛 Linux 發行流程">XZ Backdoor 2024</a> 的 lesson：maintainer takeover 也能簽 image、要靠 build provenance attestation 看出 build process 跟過去不一致。</p>
<p><strong>Mutate policy 跟 GitOps 的張力</strong>：Mutate 自動補欄位、ArgoCD / Flux 會永遠看到 live state 跟 Git state diff。處理方式有三 — <em>ignoreDifferences</em> on specific fields（ArgoCD <code>spec.ignoreDifferences</code>、Flux <code>spec.patches</code>）、<em>把 mutate 改成 validate + 在 PR template 補預設</em>（成本高但 GitOps diff 乾淨）、<em>Mutate at create only</em>（用 <code>mutate.mutateExistingOnPolicyUpdate: false</code>、只在 admission 動、不重複 mutate existing resource）。</p>
<p><strong>Generate policy 跟 multi-tenant security default</strong>：新 namespace 一建立、Generate rule 自動建 default-deny NetworkPolicy + ResourceQuota + LimitRange + 必要 RoleBinding。意義是 <em>security default 從 README 落到 runtime</em>、app team 開新 namespace 不會忘記設安全邊界。陷阱是 generated resource 的 ownership — 預設 Kyverno owns、app team 修改會被 reconcile 回去；要讓 app team 改、用 <code>synchronize: false</code>。</p>
<p><strong>Nirmata Enterprise</strong>：商業版補三件事 — <em>Policy Library</em>（CIS / NIST / PCI / SOC 2 預製 policy pack）、<em>Multi-cluster Management</em>（中央 console 推 policy 到多 cluster + audit dashboard + drift detection）、<em>Policy Reporter Plus</em>（trend + compliance mapping + JIRA / Slack integration）。對大企業多 cluster + 合規驅動的場景值得評估、中小 deployment OSS Kyverno + 社群 Policy Reporter 夠用。</p>
<p><strong>PolicyException 治理</strong>：Kyverno 1.9+ 引入 PolicyException CRD、讓特定 resource 明確繞過特定 policy、避免「app team 為了 deploy 直接把 policy 改寬」。Exception 走 PR + 到期日 + owner、跟 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a> 的 exception lifecycle 對齊 — 例外不是黑箱、是 <em>暫時性、有 owner、有 review 日期</em>。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Policy 改了沒生效</strong>：admission webhook 沒 ready、或 policy 寫在錯的 namespace（Policy CRD 是 namespace-scoped、放錯 namespace 不會作用）— <code>kubectl get clusterpolicies</code> 看 ready 狀態、<code>kubectl describe</code> 看 events</li>
<li><strong>Admission 卡住 / Pod 起不來</strong>：Kyverno webhook 掛掉、failurePolicy 設 <code>Fail</code> 結果整個 cluster 不能 deploy — production 對 critical workload 設 <code>failurePolicy: Ignore</code> + 監控 Kyverno controller availability、不要讓 policy engine 變成 cluster-wide SPOF</li>
<li><strong>Mutate 後 ArgoCD 永遠 OutOfSync</strong>：mutate 改的欄位沒在 ArgoCD <code>ignoreDifferences</code> 排除 — 對應加 <code>spec.ignoreDifferences[*].jsonPointers</code> 或 <code>.jqPathExpressions</code>、不然每次 sync 都跳 diff</li>
<li><strong>Verify Images 全部失敗</strong>：cluster 沒對外網路、Fulcio / Rekor 拉不到、或 image 真的沒簽 — 先 audit mode 跑 + 看 PolicyReport 統計 unsigned image 比例、確認預期路徑（內部 image 簽 / 外部 image allowlist）後才 enforce</li>
<li><strong>Background scan 跑爆 controller</strong>：cluster 太大、scan interval 太短 — 調整 <code>backgroundScan: false</code> for 高頻變動 policy、或拉長 scan interval、或 Nirmata 用分散式 scan</li>
<li><strong>PolicyException 變成漏洞</strong>：例外沒到期日、owner 離職、規則永久繞過 — Exception CRD 補 metadata（owner / expiry / ticket）+ 定期 audit 過期 Exception</li>
<li><strong>VAP migration 不一致</strong>：Kyverno 生成的 VAP 跟原 ClusterPolicy 行為有差（CEL 不支援部分 Kyverno feature）— 對 critical rule 保留 Kyverno 不 migrate、只把簡單 Validate 卸載</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>跨 K8s + API gateway + Terraform 統一 policy</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA standalone</a></td>
      </tr>
      <tr>
          <td>K8s only 但團隊已投資 Rego</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a></td>
      </tr>
      <tr>
          <td>CI-time pre-merge 檢查 Terraform / Dockerfile</td>
          <td>Conftest（OPA 系列、CLI-based）</td>
      </tr>
      <tr>
          <td>Image 漏洞 / misconfig scan（scan, not gate）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> / <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a></td>
      </tr>
      <tr>
          <td>SBOM 生成 / 管理</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">SBOM Tools</a></td>
      </tr>
      <tr>
          <td>Image signing pipeline</td>
          <td>Sigstore cosign（CI 簽、Kyverno 驗）</td>
      </tr>
      <tr>
          <td>K8s 1.30+ 簡單 Validate-only 場景</td>
          <td>K8s native ValidatingAdmissionPolicy（CEL、kube-apiserver 內建）</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Kyverno policy 完整 YAML reference、JMESPath 進階用法</li>
<li>Sigstore cosign CLI 操作、Fulcio / Rekor 部署</li>
<li>Nirmata Enterprise 詳細功能跟 pricing</li>
<li>K8s ValidatingAdmissionPolicy CEL 語法 reference</li>
<li>跟 service mesh（Istio / Linkerd）整合的 sidecar injection 細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Kyverno 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>Kyverno Verify Images policy 強制 production cluster 只 deploy 已 cosign 簽章 + Rekor transparency log entry 的 image、未簽 / 來源異常 image 在 admission 階段擋掉</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>Kyverno admission policy 配 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> scan 結果 — image 帶 vulnerability label 超過閾值就擋 deploy、補 CI scan 沒攔到的舊 image</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/xz-backdoor-2024-open-source-supply-chain/" data-link-title="7.R7.2.4 XZ Backdoor 2024：開源供應鏈長期滲透" data-link-desc="開源維護鏈遭滲透後，為何會直接影響廣泛 Linux 發行流程">XZ Backdoor 2024</a></td>
          <td>Kyverno Verify Images + SBOM attestation 補位 — maintainer takeover 也能簽 image、但缺乏 SLSA build provenance attestation 會被 Kyverno admission 擋住</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性 (section)</a></td>
          <td>Kyverno 是 <em>K8s admission gate</em> 的 K8s-specific 落實工具、跟 CI-time SBOM 生成 + cosign 簽章 + Rekor transparency log 組成 supply chain trust chain 的 runtime enforcement 段</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/blue-team/detection-engineering-lifecycle/" data-link-title="7.B5 Detection Engineering Lifecycle" data-link-desc="把偵測規則視為可維護資產，建立從來源、測試、調校到退場的完整生命週期">Detection Engineering Lifecycle (section)</a></td>
          <td>ClusterPolicy / Policy 走 propose → staging audit mode → tune → promote enforce mode 的工程 lifecycle、PolicyException 是 lifecycle 一部分、不是黑箱繞過</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性</a>、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a>、<a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>（scan + label）、<a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a>（vuln 資訊源）、<a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">SBOM Tools</a>（attestation 來源）</li>
<li>跨類：Sigstore cosign（CI 簽、Kyverno 驗）、ArgoCD / Flux（GitOps sync policy 本身）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（policy violation → IR routing）</li>
<li>官方：<a href="https://kyverno.io/docs/">Kyverno Documentation</a>、<a href="https://docs.sigstore.dev/">Sigstore Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>OPA Gatekeeper</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gatekeeper/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gatekeeper/</guid><description>&lt;p>OPA Gatekeeper 是 OPA 官方在 Kubernetes admission 層的落實、把 OPA 的 general-purpose policy engine 適配成 K8s-native admission controller。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &amp;#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &amp;#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest&lt;/a> 的差異不在「policy 能不能寫」、而在 &lt;em>對接面 + 抽象層次 + 工具鏈定位&lt;/em> — Gatekeeper 是 OPA 在 K8s admission 的 first-class 落實、ConstraintTemplate + Constraint 兩層抽象把 Rego policy 變成 K8s CRD、Audit 補位 background scan、Mutation 2024 起進 stable。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Gatekeeper 的核心定位是 &lt;em>Rego policy 在 K8s admission 層的 K8s-native 包裝&lt;/em>、不是另一個 policy engine。底層仍是 OPA、Rego 是同一套語言；上層加了兩個 K8s-specific 抽象 — &lt;em>ConstraintTemplate&lt;/em>（Rego policy + parameter schema 的 CRD 定義）跟 &lt;em>Constraint&lt;/em>（Template 的 instance、指定 match scope 與 parameter）。意義是同一份 Rego policy 寫一次、在不同 cluster / 不同 namespace 給不同 Constraint instance、不用改 Rego 本體。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &amp;#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA&lt;/a>（純 sidecar）比、Gatekeeper 走 &lt;em>K8s-native + 兩層抽象&lt;/em>、犧牲 OPA 純 sidecar 的跨平台彈性（OPA 可同時管 K8s admission + API gateway + Terraform plan）、換來 K8s 內部 CRD + RBAC + GitOps 的一致體驗。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno&lt;/a> 比、Gatekeeper 走 &lt;em>Rego DSL&lt;/em>、Kyverno 走 &lt;em>YAML pattern matching&lt;/em> — team 已投資 OPA / Rego（API gateway / Terraform 已用 Rego）就走 Gatekeeper、純 K8s shop + 沒 Rego 包袱直接用 Kyverno 較省學習成本。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &amp;#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest&lt;/a> 比、Conftest 是 &lt;em>CI-time static config check&lt;/em>、Gatekeeper 是 &lt;em>runtime admission + audit&lt;/em>、兩者互補不互斥（CI 用 Conftest 擋 PR、admission 用 Gatekeeper 擋 deploy）。&lt;/p></description><content:encoded><![CDATA[<p>OPA Gatekeeper 是 OPA 官方在 Kubernetes admission 層的落實、把 OPA 的 general-purpose policy engine 適配成 K8s-native admission controller。它跟 <a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a> / <a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a> / <a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a> 的差異不在「policy 能不能寫」、而在 <em>對接面 + 抽象層次 + 工具鏈定位</em> — Gatekeeper 是 OPA 在 K8s admission 的 first-class 落實、ConstraintTemplate + Constraint 兩層抽象把 Rego policy 變成 K8s CRD、Audit 補位 background scan、Mutation 2024 起進 stable。</p>
<h2 id="服務定位">服務定位</h2>
<p>Gatekeeper 的核心定位是 <em>Rego policy 在 K8s admission 層的 K8s-native 包裝</em>、不是另一個 policy engine。底層仍是 OPA、Rego 是同一套語言；上層加了兩個 K8s-specific 抽象 — <em>ConstraintTemplate</em>（Rego policy + parameter schema 的 CRD 定義）跟 <em>Constraint</em>（Template 的 instance、指定 match scope 與 parameter）。意義是同一份 Rego policy 寫一次、在不同 cluster / 不同 namespace 給不同 Constraint instance、不用改 Rego 本體。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a>（純 sidecar）比、Gatekeeper 走 <em>K8s-native + 兩層抽象</em>、犧牲 OPA 純 sidecar 的跨平台彈性（OPA 可同時管 K8s admission + API gateway + Terraform plan）、換來 K8s 內部 CRD + RBAC + GitOps 的一致體驗。跟 <a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a> 比、Gatekeeper 走 <em>Rego DSL</em>、Kyverno 走 <em>YAML pattern matching</em> — team 已投資 OPA / Rego（API gateway / Terraform 已用 Rego）就走 Gatekeeper、純 K8s shop + 沒 Rego 包袱直接用 Kyverno 較省學習成本。跟 <a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a> 比、Conftest 是 <em>CI-time static config check</em>、Gatekeeper 是 <em>runtime admission + audit</em>、兩者互補不互斥（CI 用 Conftest 擋 PR、admission 用 Gatekeeper 擋 deploy）。</p>
<p>關鍵張力：<em>Rego 學習曲線</em> ↔ <em>跨平台 policy 一致性</em> 是 Gatekeeper 跟 Kyverno 最大的選擇分水嶺。純 K8s 場景 Kyverno YAML 寫起來快、但同樣的 image signature 規則若要在 Terraform plan / CI / admission 三處 enforce、Rego 寫一次跨三處比 YAML / Cue / Sentinel 多種語言混用乾淨。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Gatekeeper 在 cluster policy stack 中承擔哪一段（admission validation / audit / mutation）、哪些要外接（<a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a> 純 sidecar 管非 K8s 對象、<a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a> 補 CI-time）</li>
<li>ConstraintTemplate 跟 Constraint 兩層怎麼切（Template 由 platform team 維護、Constraint 給 app team 在 namespace 內 instantiate）</li>
<li>Audit / Mutation / External Data Provider 何時開、開了之後 cost 與 failure mode</li>
<li>何時用 Gatekeeper、何時改 Kyverno 或退回純 OPA 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Gatekeeper deployment 是否健康、最少看四件事：</p>
<ul>
<li><strong>ConstraintTemplate 的 ownership</strong>：誰寫 Rego、誰 review、Template 是否走 Git（PR review + Gator CLI unit test）、是否有共用 library 避免每個 Template 重寫 K8s helper</li>
<li><strong>Audit coverage</strong>：除了 admission 攔截、Audit 是否定期 scan 已存在 resource（pre-Gatekeeper 部署的 legacy resource 違規）、<code>auditFromCache</code> 是否開、audit interval 是否合理（預設 60s、production 通常拉到 5-10min 避 API server 壓力）</li>
<li><strong>Failure mode 治理</strong>：Constraint <code>enforcementAction</code> 是 <code>deny</code> / <code>warn</code> / <code>dryrun</code>、Webhook failurePolicy 是 <code>Fail</code> / <code>Ignore</code>、<code>Fail</code> + Gatekeeper pod down 會擋全 cluster deploy</li>
<li><strong>跟 GitOps 的對接</strong>：ConstraintTemplate / Constraint 是否走 ArgoCD / Flux 部署、policy change 是否經 staging cluster 驗證、emergency exception 流程是否定義</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">Detection Coverage and Signal Governance</a> 在 admission 層的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>ConstraintTemplate（CT）— Rego policy + CRD 定義</strong>：CT 是 Gatekeeper 的核心抽象、由 Rego policy + parameter schema（OpenAPI v3）兩段組成。Template 寫好 apply 到 cluster 後、Gatekeeper 會生成同名 CRD（例 <code>K8sRequiredLabels</code>）、app team 就能用該 CRD 寫 Constraint。Template 由 platform team 維護、不該每個 app team 自己寫 Rego — 集中維護才能保證 helper / convention / unit test 一致。</p>
<p><strong>Constraint — Template 的 instance + match scope</strong>：Constraint 指定三件事 — <em>該套用哪個 Template</em>（kind）、<em>套用範圍</em>（match：kinds / namespaces / labelSelector / excludedNamespaces）、<em>parameter 值</em>（spec.parameters、對應 Template 的 schema）。同一個 Template 可以有多個 Constraint instance（production / staging 不同 threshold、不同 namespace 不同 required label set）。這層抽象的意義是 <em>policy logic 跟 environment-specific configuration 分開</em>。</p>
<p><strong>Audit — background scan 已存在 resource</strong>：除了 admission webhook 在 create / update 時攔、Audit controller 定期（預設 60s）掃整個 cluster 找違規 resource、結果寫到 Constraint status 的 <code>violations</code> 欄位。意義是 <em>legacy resource 在你 install Gatekeeper 之前就在那、admission 不會觸發、Audit 才會抓到</em>。<code>auditFromCache: true</code> 用 Gatekeeper 自己的 informer cache 不打 API server、適合大 cluster。</p>
<p><strong>Mutation — 2024+ stable</strong>：早期 Gatekeeper 只有 Validation、Mutation 在 v3.10+ 進 beta、2024 隨 v3.14+ 進 stable。Mutation 走獨立 CRD（<code>Assign</code> / <code>AssignMetadata</code> / <code>ModifySet</code>）、不走 ConstraintTemplate。常見用法：注入 <code>securityContext.runAsNonRoot: true</code>、補 default resource limit、加 organization label。Mutation 跟 Validation 都開的話、Mutation 先跑、Validation 看 mutated 後的結果。</p>
<p><strong>Sync Resources — cross-resource lookup</strong>：Rego policy 若要查 <em>別的 resource</em>（例：擋 Service 用了不存在的 Namespace）、要先 declare <code>Config</code> CRD 把該 resource type 加進 Gatekeeper 的 sync list、Gatekeeper 才會在 cache 裡有那個 resource 供 Rego 查。沒 sync 的 resource 不能跨 reference、是常見踩雷點。</p>
<p><strong>External Data Provider — query 外部 API 做 decision</strong>：Gatekeeper v3.10+ 引入 External Data Provider、Rego 可以 call 外部 HTTPS endpoint 取 runtime data 做 policy decision。典型用法：query image scan service（例 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> server）確認 image 沒 CVE、query SBOM attestation service 確認 supply chain 完整、query custom IAM 確認 namespace owner 有權建立該 resource。要設 timeout + cache、外部 service down 不能擋全 cluster admission。</p>
<p><strong>Gator CLI — policy unit test</strong>：Gator 是 Gatekeeper 官方 CLI、本機跑 Template + Constraint 對 mock K8s manifest、不需 cluster。CI pipeline 跑 <code>gator test</code> 對每個 Template 跑 fixture、policy change 出 PR 時自動驗證 — 避免 production deploy 才發現 Template Rego bug 擋全 cluster。</p>
<p><strong>跟 GitOps 整合</strong>：ConstraintTemplate / Constraint / Mutation / Config CRD 都是純 YAML、走 ArgoCD / Flux 部署是標準作法。實務 layout：<code>gatekeeper-system</code> namespace 裝 Gatekeeper、<code>gatekeeper-policies</code> repo 放 Template 跟 baseline Constraint（platform team owned）、各 app namespace 的 Constraint instance 可以由 app team 在自己 repo 管理（透過 ArgoCD AppProject 限制 Constraint kind）。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>OPA Gatekeeper</th>
          <th>Kyverno</th>
          <th>OPA 純 sidecar</th>
          <th>Conftest</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>對接面</td>
          <td>K8s admission + Audit（K8s-only）</td>
          <td>K8s admission + Audit（K8s-only）</td>
          <td>任意 — API gateway / Terraform / K8s</td>
          <td>CI-time（static config check）</td>
      </tr>
      <tr>
          <td>Policy 語言</td>
          <td>Rego（OPA 同一套）</td>
          <td>YAML pattern matching（K8s-native）</td>
          <td>Rego</td>
          <td>Rego（OPA 同一套）</td>
      </tr>
      <tr>
          <td>抽象層次</td>
          <td>ConstraintTemplate + Constraint 兩層</td>
          <td>ClusterPolicy / Policy（單層）</td>
          <td>OPA policy bundle（無 K8s-specific 抽象）</td>
          <td>conftest test file（無 cluster 概念）</td>
      </tr>
      <tr>
          <td>Mutation</td>
          <td>支援（v3.14+ stable）</td>
          <td>支援（first-class、Kyverno 強項）</td>
          <td>不支援（需自寫 admission webhook）</td>
          <td>不適用</td>
      </tr>
      <tr>
          <td>Cross-resource</td>
          <td>Sync Resources（要 declare）</td>
          <td>Context API（內建）</td>
          <td>看自己 sidecar 怎麼寫</td>
          <td>看 CI 怎麼 load</td>
      </tr>
      <tr>
          <td>外部 data</td>
          <td>External Data Provider（v3.10+）</td>
          <td>Context API（image registry / ConfigMap）</td>
          <td>看自己 sidecar 怎麼寫</td>
          <td>不適用（純 static）</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>Rego 陡 + 兩層抽象多概念</td>
          <td>YAML 直觀、K8s-native idiom</td>
          <td>Rego 陡 + 自管 deployment</td>
          <td>Rego 陡 + CI integration</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>team 已投資 Rego / OPA、跨 K8s + 其他平台一致</td>
          <td>純 K8s shop、無 Rego 包袱、Mutation 是重點</td>
          <td>跨 K8s + API + Terraform 一致 policy 管理面</td>
          <td>PR 階段擋 manifest / IaC config</td>
      </tr>
      <tr>
          <td>退場成本</td>
          <td>高 — Template / Constraint / Rego 量多</td>
          <td>中 — YAML 較可移植</td>
          <td>中 — Rego 可搬到 Gatekeeper</td>
          <td>低</td>
      </tr>
  </tbody>
</table>
<p>選 Gatekeeper 的核心訴求：<em>team 已用 Rego（API gateway / Terraform plan / CI 已 OPA）+ 想把 same policy 延伸到 K8s admission + 看重 OPA ecosystem 一致性</em>。純 K8s shop 沒 Rego 包袱、又特別需要 Mutation 場景密集（PSP 廢除後重建、跨 namespace 統一 sidecar 注入）直接走 Kyverno 更省學習成本。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Rego idioms for K8s admission</strong>：K8s admission review 物件結構是 <code>input.review.object</code>、Template 的 <code>violation</code> rule 走 <code>violation[{&quot;msg&quot;: msg}] { ... }</code> 形式。常見 idiom：<code>match.kinds</code> 跟 <code>match.namespaceSelector</code> 在 Constraint 層處理 scope、Rego 內只寫 <em>policy logic</em>；K8s helper（label 取值、container loop、init container 排除）抽到 shared library Template；錯誤訊息要帶 <code>input.review.object.metadata.name</code> 幫 app team 定位是哪個 resource 被擋。</p>
<p><strong>External Data Provider 的 production 治理</strong>：Provider 是獨立 service、Gatekeeper webhook 透過 HTTPS call、cache 在 Gatekeeper 內。要設 timeout（預設 3s、過時 ConstraintTemplate <code>failurePolicy</code> 決定 fail-open / fail-closed）、cache TTL、Provider 自身的 readiness / liveness。Provider down 不該擋全 cluster — 用 <code>failurePolicy: Ignore</code> 對 External Data Provider 例外、但記錄 metric alert。對應 <a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/xz-backdoor-2024-open-source-supply-chain/" data-link-title="7.R7.2.4 XZ Backdoor 2024：開源供應鏈長期滲透" data-link-desc="開源維護鏈遭滲透後，為何會直接影響廣泛 Linux 發行流程">XZ Backdoor 2024</a> 的 SBOM attestation 查詢場景。</p>
<p><strong>Gator CLI 在 CI 的 pipeline 設計</strong>：<code>gator test</code> 對 fixture 跑、<code>gator verify</code> 跑 Template 自帶 test suite、<code>gator expand</code> 預覽 Mutation 結果。PR 流程：Template change → <code>gator verify</code> 跑 unit test → kind cluster 起 Gatekeeper apply Template + sample violation manifest → confirm 擋下來才 merge。</p>
<p><strong>跟 Styra DAS / Nirmata 整合</strong>：Gatekeeper OSS 本身沒 central management UI、多 cluster deployment 看 violation status 要自己拼。Styra DAS 是 OPA 商業 control plane、可以 push Template / Constraint 到多 cluster Gatekeeper、彙整 audit violation、做 policy impact analysis。Nirmata 走類似路線。OSS-only deployment 通常用 ArgoCD ApplicationSet + Prometheus exporter（gatekeeper-policy-manager / Open Policy Agent metrics）拼。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Gatekeeper webhook timeout / 擋全 cluster admission</strong>：Rego policy 寫了 expensive operation（大量 cross-resource lookup、External Data Provider call without cache）— webhook timeout 預設 3s、超過就走 failurePolicy；改寫 Rego 用 indexed lookup、External Data Provider 加 cache、<code>failurePolicy: Ignore</code> for non-critical Template</li>
<li><strong>新 Template apply 後 admission 整個壞</strong>：Rego syntax / logic bug、production 才發現 — PR 必跑 <code>gator verify</code> + staging cluster 24-48hr soak、Constraint 先用 <code>enforcementAction: dryrun</code> 觀察 violation count 才切 <code>deny</code></li>
<li><strong>Audit 跑很慢 / API server 壓力大</strong>：cluster resource 量大、Audit interval 預設 60s 太頻繁 — 拉長到 5-10min、<code>auditFromCache: true</code> 用 informer 不打 API server、大 cluster 開 <code>auditChunkSize</code> 分批處理</li>
<li><strong>legacy resource 不擋</strong>：admission webhook 只攔 create / update、<code>kubectl apply</code> 沒改動 spec 不觸發 — 用 Audit 抓 violation、配合手動 migration plan、不要期待 admission 自動修</li>
<li><strong>Mutation 跟 Validation 衝突</strong>：Mutation 加了 label、Validation 又擋說 label 不該存在 — Mutation 先跑、Validation 看 mutated 結果；設計 policy 時要對齊兩端、不能各自寫</li>
<li><strong>Sync 沒 declare、cross-resource policy 看不到對象</strong>：Rego <code>data.inventory.namespace[&quot;foo&quot;].v1.Pod</code> 回 undefined — <code>Config</code> CRD 加 sync targets、確認 Gatekeeper pod restart 後 cache 載入</li>
<li><strong>External Data Provider down 擋全 cluster</strong>：Provider service 自己掛、<code>failurePolicy: Fail</code> 整個 admission 壞 — Provider 走 <code>failurePolicy: Ignore</code> + metric alert、Provider 自身 HA 部署、cache TTL 拉長</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>純 K8s + 無 Rego 包袱 + Mutation 重點</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a></td>
      </tr>
      <tr>
          <td>跨 K8s + API gateway + Terraform</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a>（純 sidecar）</td>
      </tr>
      <tr>
          <td>CI-time / PR 階段擋 manifest</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a></td>
      </tr>
      <tr>
          <td>Image scan 結果作為 policy 來源</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>（feed External Data Provider）</td>
      </tr>
      <tr>
          <td>Runtime threat detection（syscall）</td>
          <td>Falco / Cilium Tetragon（屬 runtime detection、不在 admission 層）</td>
      </tr>
      <tr>
          <td>Multi-cluster policy 集中管理</td>
          <td>Styra DAS / Nirmata（OPA / Gatekeeper 商業 control plane）</td>
      </tr>
      <tr>
          <td>偵測 / SIEM</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a> 或同類 SIEM</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Rego 完整語法 reference（unification、comprehension、partial evaluation）</li>
<li>Gatekeeper helm chart / installation 細節（看官方 docs）</li>
<li>Open Policy Agent 在 service mesh / API gateway 的 sidecar 部署模式（看 <a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a> 頁）</li>
<li>Pod Security Admission（K8s 內建、跟 Gatekeeper 互補但不是 Gatekeeper 一部分）</li>
<li>Multi-cluster policy bundle 的 OCI registry 分發（屬 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性</a> 邊界）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Gatekeeper 在 07 案例庫沒有直接 vendor-level 事件、但 supply chain 跟 admission policy 相關 case 都是 Gatekeeper 落實位置的對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Gatekeeper 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>ConstraintTemplate 配 cosign image signature verify、擋未簽 / 簽章不符 image 進 cluster；Audit 補位掃既有 deployment 找未簽 image</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>Gatekeeper External Data Provider 接 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> server、admission 階段查 image 是否有 critical CVE 直接擋</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/xz-backdoor-2024-open-source-supply-chain/" data-link-title="7.R7.2.4 XZ Backdoor 2024：開源供應鏈長期滲透" data-link-desc="開源維護鏈遭滲透後，為何會直接影響廣泛 Linux 發行流程">XZ Backdoor 2024</a></td>
          <td>External Data Provider 可 query SBOM attestation 服務做 policy decision、不只看 image hash 而看 component provenance 鏈</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性 (section)</a></td>
          <td>Gatekeeper 是 OPA ecosystem 在 K8s admission 的官方落實、artifact trust gate 從 CI（Conftest）延伸到 runtime（Gatekeeper）的閉環</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性與 Artifact Trust</a>、<a href="/blog/backend/07-security-data-protection/detection-coverage-and-signal-governance/" data-link-title="7.13 偵測覆蓋率與訊號治理" data-link-desc="定義偵測覆蓋、訊號品質與誤報成本的治理問題">7.13 偵測覆蓋率與訊號治理</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a>、<a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a>、<a href="/blog/backend/07-security-data-protection/vendors/conftest/" data-link-title="Conftest" data-link-desc="OPA CLI wrapper for static config policy check、Rego policy &#43; 多 parser（Terraform / K8s / Dockerfile / JSON）、CI-time gate">Conftest</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>（image scan 結果 feed External Data Provider）、<a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a>（workload identity 跟 admission policy 互補）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/splunk/" data-link-title="Splunk" data-link-desc="業界 SIEM 標準、forwarder &#43; indexer &#43; search head 架構、SPL 為核心查詢語言、ingestion-based 計費跟偵測覆蓋率的 trade-off">Splunk</a>（admission violation event 進 SIEM correlation）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（policy violation → IR routing）</li>
<li>官方：<a href="https://open-policy-agent.github.io/gatekeeper/">OPA Gatekeeper Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Conftest</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/conftest/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/conftest/</guid><description>&lt;p>Conftest 是 &lt;em>OPA CLI wrapper for static config policy check&lt;/em>、Open Policy Agent project 旗下的 CLI 工具、Apache 2.0 OSS、無商業版。它的核心定位是 &lt;em>CI-time policy gate&lt;/em>、有別於 admission runtime：在 git commit / PR / merge 階段、用 Rego policy 對 config file（Terraform HCL / K8s YAML / Dockerfile / JSON / TOML / INI / serverless.yml）做 static check、把 misconfiguration 攔在 deploy 之前。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &amp;#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &amp;#43; Constraint 兩層、Rego policy &amp;#43; Audit &amp;#43; Mutation">Gatekeeper&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &amp;#43; Secret &amp;#43; License &amp;#43; SBOM、Apache 2.0、CI 友善">Trivy&lt;/a> Config 的差異在 &lt;em>執行時機 + 客製化方式&lt;/em>、規則表達力反而相近。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Conftest 是 OPA 生態中 &lt;em>最輕量的 CI-time tool&lt;/em> — 拿一份 Rego policy + 一份 config file、跑 &lt;code>conftest test&lt;/code> 就出 violation report。它不需要 cluster、不需要 daemon、不接 admission webhook、只是個 binary。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &amp;#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA&lt;/a> 比、OPA 是 &lt;em>runtime decision engine&lt;/em>（HTTP server / library / sidecar 提供 policy decision）、Conftest 只是 &lt;em>CLI 跑 once、結束即關&lt;/em>。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &amp;#43; Constraint 兩層、Rego policy &amp;#43; Audit &amp;#43; Mutation">Gatekeeper&lt;/a> 比、Gatekeeper 是 &lt;em>K8s admission controller runtime&lt;/em>、會在 kubectl apply 時攔下違規；Conftest 是在 PR 階段就攔下、deploy 前就 fail CI。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno&lt;/a> 比、Kyverno 是 K8s-only 的 admission policy（YAML 語法）、Conftest 跨多 config format（不只 K8s）且用 Rego。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &amp;#43; Secret &amp;#43; License &amp;#43; SBOM、Apache 2.0、CI 友善">Trivy&lt;/a> Config 比、Trivy Config 是 &lt;em>built-in misconfig rule&lt;/em>（開箱即用、預定義常見 anti-pattern）、Conftest 是 &lt;em>自己寫 Rego policy&lt;/em>（客製化彈性大但要寫 rule）。&lt;/p></description><content:encoded><![CDATA[<p>Conftest 是 <em>OPA CLI wrapper for static config policy check</em>、Open Policy Agent project 旗下的 CLI 工具、Apache 2.0 OSS、無商業版。它的核心定位是 <em>CI-time policy gate</em>、有別於 admission runtime：在 git commit / PR / merge 階段、用 Rego policy 對 config file（Terraform HCL / K8s YAML / Dockerfile / JSON / TOML / INI / serverless.yml）做 static check、把 misconfiguration 攔在 deploy 之前。跟 <a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a> / <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> / <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> Config 的差異在 <em>執行時機 + 客製化方式</em>、規則表達力反而相近。</p>
<h2 id="服務定位">服務定位</h2>
<p>Conftest 是 OPA 生態中 <em>最輕量的 CI-time tool</em> — 拿一份 Rego policy + 一份 config file、跑 <code>conftest test</code> 就出 violation report。它不需要 cluster、不需要 daemon、不接 admission webhook、只是個 binary。跟 <a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a> 比、OPA 是 <em>runtime decision engine</em>（HTTP server / library / sidecar 提供 policy decision）、Conftest 只是 <em>CLI 跑 once、結束即關</em>。跟 <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> 比、Gatekeeper 是 <em>K8s admission controller runtime</em>、會在 kubectl apply 時攔下違規；Conftest 是在 PR 階段就攔下、deploy 前就 fail CI。跟 <a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a> 比、Kyverno 是 K8s-only 的 admission policy（YAML 語法）、Conftest 跨多 config format（不只 K8s）且用 Rego。跟 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> Config 比、Trivy Config 是 <em>built-in misconfig rule</em>（開箱即用、預定義常見 anti-pattern）、Conftest 是 <em>自己寫 Rego policy</em>（客製化彈性大但要寫 rule）。</p>
<p>關鍵張力：<em>CI-time static check</em> ↔ <em>runtime admission enforcement</em> 是兩種互補機制、不是替代。CI 抓在 deploy 之前、但 manifest 不一定都走 PR（kubectl apply 直接打 cluster 就漏接）；admission 抓 runtime 寫入、但 deploy 後才 fail 已經慢。production 通常 CI（Conftest / Trivy Config）+ admission（Gatekeeper / Kyverno）雙層覆蓋。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Conftest 在 policy-as-code stack 中承擔哪一段（CI gate）、跟 admission runtime 怎麼分工</li>
<li>Rego policy directory / <code>conftest test</code> / <code>conftest verify</code> / Bundle / Combine flag 的 ownership 跟工程化做法</li>
<li>Conftest vs Trivy Config vs Checkov vs OPA + custom CI wrapper 的取捨</li>
<li>何時用 Conftest、何時走 Trivy Config（不想學 Rego）或 Gatekeeper（runtime enforcement）</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Conftest 導入是否健康、最少看四件事：</p>
<ul>
<li><strong>Policy directory 走版控</strong>：Rego files（<code>policy/*.rego</code>）跟 application code 同 repo、或抽到中央 policy repo + Bundle 拉取、PR review 才能改 policy</li>
<li><strong><code>conftest verify</code> 是否跑</strong>：Rego policy 本身有單元測試（<code>*_test.rego</code>）、policy 改動有 test coverage、不是寫完就上 production CI</li>
<li><strong>CI integration 點</strong>：跑在 PR check / merge gate、fail 阻斷 merge、不是只跑 warning 沒人看</li>
<li><strong>跟 admission 是否雙層</strong>：CI fail 之外、cluster 也裝 <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> / <a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a> 接 runtime；否則 kubectl apply 繞過 CI 就破口</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">Supply Chain Integrity</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Policy directory（Rego files）</strong>：Conftest 預設讀 <code>./policy/</code> 目錄下所有 <code>*.rego</code> 檔。Policy 用 <code>deny[msg]</code> / <code>warn[msg]</code> / <code>violation[msg]</code> rule 表達 — <code>deny</code> 失敗整個 test、<code>warn</code> 只 print 不 fail、<code>violation</code> 給結構化輸出（含 metadata 給後續 SOAR 處理）。慣例是一個 policy 檔對一個 anti-pattern（<code>policy/k8s_privileged.rego</code> / <code>policy/terraform_public_s3.rego</code>）、不混寫。</p>
<p><strong><code>conftest test</code> command</strong>：<code>conftest test deployment.yaml</code> / <code>conftest test --policy ./custom-policy terraform.plan.json</code> 是日常入口。支援 <code>--all-namespaces</code>（K8s 多 manifest）、<code>--input</code>（強制 parser 類型）、<code>--combine</code>（跨檔 check）、<code>--output json|tap|table</code>（CI 報表格式）。CI integration 通常 <code>conftest test infra/**/*.yaml --output github</code> 直接 emit GitHub Actions annotation。</p>
<p><strong>Parser（多 format 支援）</strong>：Conftest 原生支援 HCL（Terraform）/ YAML / JSON / TOML / INI / Dockerfile / CUE / Jsonnet / EDN / XML / VCL（Fastly）/ Cyclonedx SBOM 等。同一份 Rego 可跑多 format — parser 把不同 format normalize 成 Rego input JSON、policy 寫 <code>input.spec.containers[_].securityContext.privileged == true</code> 不管原本是 YAML 還是 JSON。這是 Conftest 比 Checkov / Trivy Config 客製化彈性更大的關鍵：同一個 policy 引擎處理跨 format misconfig。</p>
<p><strong>Combine flag（跨檔 check）</strong>：<code>conftest test --combine *.yaml</code> 把多檔合併成單一 input array、policy 可跨檔 reference。實務場景：K8s deployment 必須有對應 service + configmap + networkpolicy、缺一就 fail；Terraform module 跨檔 reference（VPC + subnet + security group）必須一致。沒有 Combine 就只能單檔檢查、跨檔 invariant 抓不到。</p>
<p><strong><code>conftest verify</code>（policy unit test）</strong>：Policy 本身要有測試 — <code>policy/k8s_privileged_test.rego</code> 寫 <code>test_privileged_denied</code> / <code>test_non_privileged_allowed</code>、<code>conftest verify</code> 跑這些測試。Policy 改動先跑 verify、再 merge policy 到 production CI。沒做 verify 的 policy 是「policy 自己 broken 沒人發現」的常見破口。</p>
<p><strong>Bundle（OPA bundle 拉 policy）</strong>：<code>conftest pull</code> 從 OCI registry / HTTP / git / S3 拉 policy bundle、policy 集中在 central repo、各 service repo 不重複維護。Bundle 包含 Rego files + data files + manifest、可簽章驗證（配 <a href="https://docs.sigstore.dev/">Sigstore cosign</a>）。大組織通常 platform team 維護 policy bundle、application team 在 CI 拉最新版本跑。</p>
<p><strong>CI integration</strong>：GitHub Actions（<code>open-policy-agent/conftest-action</code>）/ GitLab CI / Jenkins / CircleCI 都有現成 step。跑點通常在 PR check 階段（review 前 fail fast）+ merge gate（防止繞過）。失敗訊息含 file / line / policy name、SOC / SRE 看 annotation 就知道哪行違規。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Conftest</th>
          <th>Trivy Config</th>
          <th>Checkov</th>
          <th>OPA + custom CI wrapper</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>規則來源</td>
          <td>自己寫 Rego（彈性大、要學 Rego）</td>
          <td>內建 misconfig rule（開箱即用）</td>
          <td>內建 + 自訂 Python rule</td>
          <td>自己寫 Rego + 自己包 CI</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>中 — Rego 語法 + Conftest CLI</td>
          <td>緩 — <code>trivy config</code> 一個指令</td>
          <td>緩 — 內建 rule、自訂 Python 稍重</td>
          <td>陡 — Rego + 自己組 CI 跑點</td>
      </tr>
      <tr>
          <td>Format 支援</td>
          <td>廣 — Terraform / K8s / Dockerfile 等</td>
          <td>中 — Terraform / K8s / CloudFormation</td>
          <td>中 — Terraform / K8s / Serverless</td>
          <td>看自己包</td>
      </tr>
      <tr>
          <td>客製彈性</td>
          <td>高 — 任意 Rego policy</td>
          <td>低 — 內建 rule、客製要寫 plugin</td>
          <td>中 — Python custom rule</td>
          <td>高</td>
      </tr>
      <tr>
          <td>跨檔 check</td>
          <td>強 — <code>--combine</code> flag</td>
          <td>弱 — 主要單檔</td>
          <td>中</td>
          <td>看自己寫</td>
      </tr>
      <tr>
          <td>Policy 共享</td>
          <td>OPA Bundle（OCI / git / HTTP）</td>
          <td>Trivy DB（中央更新）</td>
          <td>Checkov rule pack</td>
          <td>自己管</td>
      </tr>
      <tr>
          <td>計費</td>
          <td>OSS Apache 2.0</td>
          <td>OSS（Aqua 商業版有加值）</td>
          <td>OSS（Bridgecrew 商業版）</td>
          <td>OSS（OPA）</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>客製化 policy、Rego 已用、跨 format</td>
          <td>開箱即用、團隊不想學 Rego</td>
          <td>Terraform-heavy、Python team 熟</td>
          <td>OPA 已是 runtime、CI 想複用 policy</td>
      </tr>
  </tbody>
</table>
<p>選 Conftest 的核心訴求：<em>組織有 custom policy 需求</em> + <em>已用 OPA / Rego（admission 走 Gatekeeper、CI 走 Conftest 統一語言）</em> + <em>跨多 config format 需要同一個 policy 引擎</em>。如果只是要 K8s privileged container / Terraform public S3 這類常見 anti-pattern 攔截、直接 Trivy Config 開箱即用更划算。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong><code>conftest verify</code>（policy unit test lifecycle）</strong>：Policy 是 code、code 要有測試。<code>policy/k8s_privileged_test.rego</code> 寫 <code>test_privileged_denied { count(deny) &gt; 0 with input as {...} }</code>、CI 跑 <code>conftest verify ./policy</code> 把 policy test 當 unit test。Policy change 走 PR → verify pass → 部署到 central bundle → application CI 拉新版本。沒 verify 的 policy 是「沒人知道 policy 自己壞掉、所有 application CI 都 silently pass」的 systemic 風險。</p>
<p><strong>Bundle 從 OCI registry pull + 簽章驗證</strong>：<code>conftest pull oci://registry.example.com/policy-bundle:v1.2.3</code> 從 OCI registry 拉 policy bundle、policy distribution 走 container image 同一套 supply chain。配 <a href="https://docs.sigstore.dev/">Sigstore cosign</a> 簽章驗證、policy bundle 也走 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性</a> 的 release gate 邏輯 — policy 本身就是 artifact、需要 signing + verification。</p>
<p><strong>跟 <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a> Config 混用</strong>：實務上 <em>Trivy Config 跑預設 rule</em>（CIS / NSA / OWASP baseline、開箱即用）+ <em>Conftest 跑客製 rule</em>（organization-specific：必須有特定 label、必須走特定 namespace、必須引用特定 ConfigMap）。兩者 CI 階段都跑、報表合併。不是二選一、是 baseline + custom 的分工。</p>
<p><strong>跟 admission 雙層</strong>：CI 階段 Conftest fail 之外、cluster 也裝 <a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> 接 admission。Gatekeeper 用 ConstraintTemplate（也是 Rego）、同一份 Rego policy 理論上 CI / runtime 共用 — 但實務上 admission 場景跟 static check 場景的 input shape 不同（admission 拿 AdmissionReview object、static 拿 raw manifest）、policy 通常分兩份維護或寫 abstraction layer 共用。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Policy pass 但 production 還是 misconfig</strong>：CI 沒卡在 merge gate、或有 <code>kubectl apply</code> 繞過 PR — 加 admission controller（<a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> / <a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a>）做 runtime 雙層</li>
<li><strong>Rego policy 自己 broken / silently pass</strong>：沒寫 <code>*_test.rego</code> + <code>conftest verify</code> — 補 policy unit test、CI 跑 verify 才 promote</li>
<li><strong><code>conftest test</code> 跑出 0 violations 但 manifest 有問題</strong>：policy directory 沒讀對、或 parser 自動偵測選錯 — 顯式 <code>--policy ./policy --input yaml</code></li>
<li><strong>跨檔 invariant 抓不到</strong>（deployment 沒對應 service）：忘記用 <code>--combine</code> flag — 改 <code>conftest test --combine *.yaml</code></li>
<li><strong>Bundle 拉到舊版本 / policy drift</strong>：沒固定 bundle tag、用 <code>latest</code> 漂移 — bundle reference 用 digest（<code>sha256:...</code>）或 immutable tag</li>
<li><strong>False positive 多 / team 開始 ignore CI</strong>：policy 寫得太寬、沒考慮合理例外 — Rego 加 exception list（<code>data.exceptions</code>）、走 <a href="/blog/backend/07-security-data-protection/blue-team/" data-link-title="7.B 防守者視角（藍隊）與控制面驗證" data-link-desc="從防守者角度整理控制面、偵測路由、驗證策略與演練回寫">Exception Workflow</a> lifecycle</li>
<li><strong>Policy 散落各 application repo / 維護不一致</strong>：沒走 central bundle — 抽 policy 到中央 repo、各 application 拉 bundle</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>開箱即用、不想學 Rego</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy Config</a></td>
      </tr>
      <tr>
          <td>K8s admission runtime</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a> / <a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a></td>
      </tr>
      <tr>
          <td>Runtime application policy</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a></td>
      </tr>
      <tr>
          <td>Terraform-heavy + Python team</td>
          <td>Checkov / tfsec</td>
      </tr>
      <tr>
          <td>Cloud-native CNAPP</td>
          <td>Wiz / Prisma Cloud</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Rego 完整語法 reference、<code>every</code> / <code>walk</code> / built-in function 進階用法</li>
<li>OPA Bundle 的 server-side 實作（policy publish pipeline）</li>
<li>Conftest 跟 Open Policy Agent runtime 的內部架構差異</li>
<li>Sigstore cosign 的 keyless signing flow 細節</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Conftest 在 07 案例庫沒有直接 vendor-level 事件、但所有 supply chain case 都是 CI-time policy gate 的對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Conftest 的關係（對照啟示）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/solarwinds-2020-sunburst/" data-link-title="7.R7.2.1 SolarWinds 2020：更新鏈被濫用" data-link-desc="合法更新流程遭植入後，攻擊者如何長期潛伏與橫向擴散">SolarWinds 2020 Sunburst</a></td>
          <td>Conftest 在 CI 階段檢查 Terraform / K8s manifest 是否符合 image signing policy（image 必須來自 signed registry、必須有 cosign attestation）</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>Conftest 配 SBOM 檔案做 CI-time vulnerable component check、補 admission 之前的 gate（image 含 log4j-core &lt;2.17 直接 PR fail）</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性 (section)</a></td>
          <td>Conftest 是 release gate 在 CI 階段的 policy enforcement 工具、跟 admission 雙層覆蓋、policy bundle 本身也走 cosign 簽章 supply chain</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性與 artifact 信任</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/opa/" data-link-title="Open Policy Agent (OPA)" data-link-desc="CNCF general-purpose policy engine、Rego Datalog-like 語言、decoupled decision &#43; enforcement、跨 K8s / API / Terraform / SQL 統一 policy">OPA</a>、<a href="/blog/backend/07-security-data-protection/vendors/gatekeeper/" data-link-title="OPA Gatekeeper" data-link-desc="OPA 官方 K8s admission controller、ConstraintTemplate &#43; Constraint 兩層、Rego policy &#43; Audit &#43; Mutation">Gatekeeper</a>、<a href="/blog/backend/07-security-data-protection/vendors/kyverno/" data-link-title="Kyverno" data-link-desc="K8s-native policy engine、YAML policy（非 Rego）、五類 rule（Validate / Mutate / Generate / Verify Images / Cleanup）、CNCF Incubating">Kyverno</a>、<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a></li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a>（CI security check pipeline 共用）</li>
<li>官方：<a href="https://www.conftest.dev/">Conftest Documentation</a></li>
</ul>
]]></content:encoded></item></channel></rss>