# Implementing Policy As Code With Open Policy Agent

> 本技能涵盖在 Kubernetes 和 CI/CD 管道中实施 Open Policy Agent（OPA）和 Gatekeeper 进行策略即代码执行。 内容包括编写 Rego 策略、将 OPA Gatekeeper 部署为 Kubernetes 准入控制器、在开发中测试策略， 以及将策略评估集成到部署管道中。

- Skill: `killvxk/implementing-policy-as-code-with-open-policy-agent` (Agent Skill, multi-file: 8 files)
- Install (CLI): `npx skillmds@latest add killvxk/implementing-policy-as-code-with-open-policy-agent`
- Raw SKILL.md: https://api.skillmd.com/api/skills/killvxk/implementing-policy-as-code-with-open-policy-agent/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- License: Apache-2.0
- Author: killvxk (https://skillmd.com/u/killvxk)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/killvxk/implementing-policy-as-code-with-open-policy-agent

---


# 使用 Open Policy Agent 实施策略即代码

## 使用场景

- 以编程方式跨 Kubernetes 集群强制执行组织安全策略时
- 需要准入控制以阻止创建不合规资源时
- 实施可进行版本控制、测试和审计的策略治理时
- 跨多个集群和环境标准化安全规则时
- 需要可扩展到 Kubernetes 之外（API 和 CI/CD）的灵活策略引擎时

**不适用于**漏洞扫描（使用 Trivy/Checkov）、运行时威胁检测（使用 Falco）或网络策略执行（使用 Kubernetes NetworkPolicy 或 Calico）。

## 前置条件

- 具有管理员访问权限的 Kubernetes 集群（用于 Gatekeeper 安装）
- 用于 Gatekeeper 部署的 Helm
- 用于本地策略测试的 OPA CLI 或 conftest
- 用于策略编写的 Rego 知识

## 操作流程

### 步骤 1：安装 OPA Gatekeeper

```bash
# 通过 Helm 安装 Gatekeeper
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm install gatekeeper gatekeeper/gatekeeper \
  --namespace gatekeeper-system --create-namespace \
  --set replicas=3 \
  --set audit.replicas=1 \
  --set audit.writeToRAMDisk=true
```

### 步骤 2：创建约束模板

```yaml
# templates/k8s-required-labels.yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8srequiredlabels
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredLabels
      validation:
        openAPIV3Schema:
          type: object
          properties:
            labels:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredlabels
        violation[{"msg": msg}] {
          provided := {label | input.review.object.metadata.labels[label]}
          required := {label | label := input.parameters.labels[_]}
          missing := required - provided
          count(missing) > 0
          msg := sprintf("Missing required labels: %v", [missing])
        }

---
# templates/k8s-container-limits.yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8scontainerlimits
spec:
  crd:
    spec:
      names:
        kind: K8sContainerLimits
      validation:
        openAPIV3Schema:
          type: object
          properties:
            cpu:
              type: string
            memory:
              type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8scontainerlimits
        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not container.resources.limits.cpu
          msg := sprintf("Container %v has no CPU limit", [container.name])
        }
        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not container.resources.limits.memory
          msg := sprintf("Container %v has no memory limit", [container.name])
        }

---
# templates/k8s-block-privileged.yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8sblockprivileged
spec:
  crd:
    spec:
      names:
        kind: K8sBlockPrivileged
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sblockprivileged
        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          container.securityContext.privileged == true
          msg := sprintf("Privileged container not allowed: %v", [container.name])
        }
        violation[{"msg": msg}] {
          container := input.review.object.spec.initContainers[_]
          container.securityContext.privileged == true
          msg := sprintf("Privileged init container not allowed: %v", [container.name])
        }
```

### 步骤 3：应用约束

```yaml
# constraints/require-labels.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: require-team-labels
spec:
  enforcementAction: deny
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Namespace"]
      - apiGroups: ["apps"]
        kinds: ["Deployment", "StatefulSet"]
    excludedNamespaces:
      - kube-system
      - gatekeeper-system
  parameters:
    labels:
      - "team"
      - "environment"
      - "cost-center"

---
# constraints/block-privileged.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sBlockPrivileged
metadata:
  name: block-privileged-containers
spec:
  enforcementAction: deny
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
      - apiGroups: ["apps"]
        kinds: ["Deployment", "DaemonSet", "StatefulSet"]
    excludedNamespaces:
      - kube-system
```

### 步骤 4：使用 conftest 测试策略

```bash
# 安装 conftest
brew install conftest

# 在本地针对 OPA 策略测试 Kubernetes 清单
conftest test deployment.yaml --policy policies/ --output json

# 针对 OPA 策略测试 Terraform
conftest test terraform/main.tf --policy policies/terraform/ --parser hcl2

# 测试 Dockerfile
conftest test Dockerfile --policy policies/docker/
```

```rego
# policies/kubernetes/deny_latest_tag.rego
package kubernetes

deny[msg] {
  input.kind == "Deployment"
  container := input.spec.template.spec.containers[_]
  endswith(container.image, ":latest")
  msg := sprintf("Container %v uses :latest tag. Pin to specific version.", [container.name])
}

deny[msg] {
  input.kind == "Deployment"
  container := input.spec.template.spec.containers[_]
  not contains(container.image, ":")
  msg := sprintf("Container %v has no tag. Pin to specific version.", [container.name])
}
```

### 步骤 5：在 CI/CD 中集成策略测试

```yaml
# .github/workflows/policy-test.yml
name: Policy Validation

on:
  pull_request:
    paths: ['k8s/**', 'terraform/**', 'policies/**']

jobs:
  conftest:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install conftest
        run: |
          wget -q https://github.com/open-policy-agent/conftest/releases/download/v0.50.0/conftest_0.50.0_Linux_x86_64.tar.gz
          tar xzf conftest_0.50.0_Linux_x86_64.tar.gz
          sudo mv conftest /usr/local/bin/
      - name: Test K8s manifests
        run: conftest test k8s/**/*.yaml --policy policies/kubernetes/ --output json
      - name: Test Terraform
        run: conftest test terraform/*.tf --policy policies/terraform/ --parser hcl2
```

## 关键概念

| 术语 | 定义 |
|------|------|
| OPA | Open Policy Agent — 使用 Rego 语言进行策略决策的通用策略引擎 |
| Rego | OPA 用于编写策略规则的声明性查询语言 |
| Gatekeeper | 实现通过 ConstraintTemplates 进行准入控制的 Kubernetes 原生 OPA 集成 |
| ConstraintTemplate | 定义 Rego 策略逻辑和约束类参数模式的 CRD |
| Constraint | ConstraintTemplate 的实例，包含特定参数和范围（检查哪些资源） |
| 准入控制器 | 在持久化之前拦截 API 请求并可允许或拒绝的 Kubernetes 组件 |
| conftest | 用于针对 OPA 策略测试结构化数据（YAML、JSON、HCL）的 CLI 工具 |

## 工具与系统

- **Open Policy Agent（OPA）**：用于统一策略执行的通用策略引擎
- **Gatekeeper**：基于 OPA 构建的 Kubernetes 准入控制器，使用基于 CRD 的配置
- **conftest**：针对配置文件测试 OPA 策略的测试框架
- **Kyverno**：使用基于 YAML 策略的替代 Kubernetes 策略引擎（无需 Rego）
- **Styra DAS**：具有策略编写、测试和分发功能的商业 OPA 管理平台

## 常见场景

### 场景：跨集群强制执行容器安全标准

**背景**：多个开发团队部署到共享的 Kubernetes 集群。部分团队运行特权容器和没有资源限制的镜像，导致安全和稳定性问题。

**方法**：
1. 通过 GitOps（FluxCD 仓库中的 Helm chart）在所有集群上部署 Gatekeeper
2. 创建 ConstraintTemplates：禁止特权容器、必须资源限制、必须标签、禁用 latest 标签
3. 从 `enforcementAction: warn` 开始，识别违规而不阻止部署
4. 通知团队违规情况，并提供 2 周的修复窗口
5. 修复期后切换到 `enforcementAction: deny`
6. 为 kube-system 和监控命名空间添加 `excludedNamespaces`

**注意事项**：立即以 deny 模式部署 Gatekeeper 可能会破坏现有工作负载。始终从 warn 模式开始。过于严格且没有系统命名空间豁免的策略可能阻止集群组件正常运行。

## 输出格式

```
OPA 策略评估报告
==============================
集群：production-east
日期：2026-02-23
Gatekeeper 版本：3.16.0

约束摘要：
  K8sRequiredLabels:        12 个违规（warn）
  K8sBlockPrivileged:        0 个违规（deny）
  K8sContainerLimits:        8 个违规（deny）
  K8sBlockLatestTag:         3 个违规（deny）

已拦截部署（deny）：
  [K8sContainerLimits] deployment/api-server in ns/payments
    - 容器 'api' 没有内存限制
  [K8sBlockLatestTag] deployment/frontend in ns/web
    - 容器 'nginx' 使用 :latest 标签

审计违规（warn）：
  [K8sRequiredLabels] namespace/staging
    - 缺少标签：{cost-center}
```

