implementing-policy-as-code-with-open-policy-agent について
Open Policy Agent と Gatekeeper を使い、Kubernetes のアドミッション制御や設定チェックを行うためのセキュリティスキルです。Rego の作成、ローカルテスト、CI/CD 検証、段階的な適用を扱います。
主な機能
- 01Gatekeeper による Kubernetes アドミッション制御
- 02Rego の制約とテンプレート作成
- 03conftest によるローカルテスト
- 04CI/CD へのポリシーチェック追加
- 05違反の監査と段階的な適用
活用シーン
- 01準拠しない Kubernetes リソースの作成防止
- 02複数クラスターでのラベルとコンテナ規則の統一
- 03提出前の Terraform や YAML の検査
- 04警告モードで評価してから違反を拒否
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill implementing-policy-as-code-with-open-policy-agentインストール後、Claude Code で/implementing-policy-as-code-with-open-policy-agentを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSEassets/template.mdreferences/api-reference.mdstandards.mdworkflows.mdscripts/agent.pyprocess.py詳細
Open Policy Agent によるポリシー・アズ・コードの実装
使用するタイミング
- Kubernetes クラスター全体で組織のセキュリティポリシーをプログラムによって適用する場合
- 非準拠のリソースが作成されないようにブロックするアドミッション制御が必要な場合
- バージョン管理、テスト、監査が可能なポリシーガバナンスを実装する場合
- 複数のクラスターや環境にわたってセキュリティルールを標準化する場合
- Kubernetes を超えて API や CI/CD にも適用できる柔軟なポリシーエンジンが必要な場合
使用しないでください: 脆弱性スキャンには(Trivy/Checkov を使用)、ランタイムの脅威検知には(Falco を使用)、ネットワークポリシーの適用には(Kubernetes NetworkPolicy または Calico を使用)。
前提条件
- Gatekeeper をインストールするための管理者権限を持つ Kubernetes クラスター
- Gatekeeper のデプロイ用の Helm
- ローカルでのポリシーテスト用の OPA CLI または conftest
- ポリシー作成のための Rego の知識
ワークフロー
ステップ 1: OPA Gatekeeper をインストールする
# Install Gatekeeper via Helm
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: Constraint Template を作成する
# 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: Constraint を適用する
# 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 でポリシーをテストする
# Install conftest
brew install conftest
# Test Kubernetes manifests against OPA policies locally
conftest test deployment.yaml --policy policies/ --output json
# Test Terraform against OPA policies
conftest test terraform/main.tf --policy policies/terraform/ --parser hcl2
# Test Dockerfiles
conftest test Dockerfile --policy policies/docker/
# 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 にポリシーテストを統合する
# .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 | ConstraintTemplate を介してアドミッション制御を実装する Kubernetes ネイティブの OPA 統合 |
| ConstraintTemplate | 一群の Constraint に対する Rego ポリシーロジックとパラメーススキーマを定義する CRD |
| Constraint | 特定のパラメーターとスコープ(チェック対象のリソース)を持つ ConstraintTemplate のインスタンス |
| Admission Controller | 永続化の前に API リクエストを傍受し、それを許可または拒否できる Kubernetes コンポーネント |
| conftest | OPA ポリシーに対して構造化データ(YAML、JSON、HCL)をテストするための CLI ツール |
ツールとシステム
- Open Policy Agent (OPA): 統一されたポリシー適用のための汎用ポリシーエンジン
- Gatekeeper: CRD ベースの設定を備えた、OPA 上に構築された Kubernetes アドミッションコントローラー
- conftest: 設定ファイルに対して OPA ポリシーをテストするためのテストフレームワーク
- Kyverno: YAML ベースのポリシーを使用する代替の Kubernetes ポリシーエンジン(Rego は不要)
- Styra DAS: ポリシーの作成、テスト、配布機能を備えた商用の OPA 管理プラットフォーム
よくあるシナリオ
シナリオ: クラスター全体でコンテナーのセキュリティ標準を適用する
背景: 複数の開発チームが共有の Kubernetes クラスターにデプロイしています。一部のチームは特権コンテナーやリソース制限のないイメージを実行しており、セキュリティと安定性の問題を引き起こしています。
アプローチ:
- GitOps(FluxCD リポジトリ内の Helm チャート)を介して、すべてのクラスターに Gatekeeper をデプロイする
- 次の項目について Constraint Template を作成する: 特権コンテナーの禁止、リソース制限の必須化、ラベルの必須化、latest タグの禁止
- デプロイをブロックせずに違反を特定するため、
enforcementAction: warnから開始する - 違反をチームに通知し、2 週間の是正期間を設ける
- 是正期間の後に
enforcementAction: denyに切り替える - kube-system と monitoring の名前空間を
excludedNamespacesに追加する
落とし穴: Gatekeeper を直ちに deny モードでデプロイすると、既存のワークロードが壊れる可能性があります。必ず warn モードから開始してください。システム名前空間の例外を設けない過度に制限的なポリシーは、クラスターのコンポーネントが機能しなくなる原因になります。
出力形式
OPA Policy Evaluation Report
==============================
Cluster: production-east
Date: 2026-02-23
Gatekeeper Version: 3.16.0
CONSTRAINT SUMMARY:
K8sRequiredLabels: 12 violations (warn)
K8sBlockPrivileged: 0 violations (deny)
K8sContainerLimits: 8 violations (deny)
K8sBlockLatestTag: 3 violations (deny)
BLOCKED DEPLOYMENTS (deny):
[K8sContainerLimits] deployment/api-server in ns/payments
- Container 'api' has no memory limit
[K8sBlockLatestTag] deployment/frontend in ns/web
- Container 'nginx' uses :latest tag
AUDIT VIOLATIONS (warn):
[K8sRequiredLabels] namespace/staging
- Missing labels: {cost-center}
コメント
Markdown 対応