mcpField
I
implementing-opa-gatekeeper-for-policy-enforcement

implementing-opa-gatekeeper-for-policy-enforcement

github.com/mukul975セキュリティ35.2k50 回インストール8 週間前に更新
リポジトリ

implementing-opa-gatekeeper-for-policy-enforcement について

KubernetesでOPA Gatekeeperを導入し、Regoポリシーをリソース要求の受付時に適用する方法を説明するスキルです。クラスターやセキュリティの担当者向けに、制約の設定、監査、ポリシー監視を扱います。

主な機能

  1. 01Regoによるポリシー記述
  2. 02テンプレートと制約によるポリシー定義
  3. 03受付時の要求の検証または拒否
  4. 04dryrun、deny、warnモード
  5. 05監査違反とメトリクスの確認

活用シーン

  1. 01Kubernetesリソースへのラベル必須化
  2. 02特権コンテナのデプロイ防止
  3. 03コンテナイメージレジストリの制限
  4. 04リソース制限や読み取り専用ルートファイルシステムの監査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill implementing-opa-gatekeeper-for-policy-enforcement

インストール後、Claude Code で/implementing-opa-gatekeeper-for-policy-enforcementを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

LICENSE
assets/
template.md
references/
api-reference.md
standards.md
workflows.md
scripts/
agent.py
process.py

詳細

ポリシー適用のための OPA Gatekeeper の実装

概要

OPA Gatekeeper は、Rego で記述されたポリシーを適用する Kubernetes アドミッションコントローラーです。ConstraintTemplate(Rego ロジックを含むポリシーのひな形)と Constraint(パラメーターを指定してインスタンス化したポリシー)を使用し、アドミッション時に Kubernetes リソースのリクエストを検証、変更、または拒否します。

使用するタイミング

  • 環境で opa gatekeeper for policy enforcement の機能をデプロイまたは設定するとき
  • コンプライアンス要件に沿ったセキュリティ統制を確立するとき
  • この分野のセキュリティアーキテクチャを構築または改善するとき
  • この実装が必要なセキュリティ評価を実施するとき

前提条件

  • Kubernetes クラスター v1.24 以降
  • Helm 3
  • cluster-admin 権限を持つ kubectl
  • Rego ポリシー言語の基本的な理解

Gatekeeper のインストール

# Install via Helm
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm repo update

helm install gatekeeper gatekeeper/gatekeeper \
  --namespace gatekeeper-system --create-namespace \
  --set replicas=3 \
  --set audit.replicas=1 \
  --set audit.logLevel=INFO

# Verify
kubectl get pods -n gatekeeper-system
kubectl get crd | grep gatekeeper
インストールの確認
# Check webhook
kubectl get validatingwebhookconfigurations gatekeeper-validating-webhook-configuration

# Check CRDs
kubectl get crd constrainttemplates.templates.gatekeeper.sh
kubectl get crd configs.config.gatekeeper.sh

ConstraintTemplate の例

1. リソースへのラベル必須化
# template-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, "details": {"missing_labels": missing}}] {
          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])
        }
# constraint-require-team-label.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: require-team-label
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Namespace"]
      - apiGroups: ["apps"]
        kinds: ["Deployment"]
  parameters:
    labels:
      - "team"
      - "environment"
2. 特権コンテナーのブロック
# template-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])
        }
# constraint-block-privileged.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sBlockPrivileged
metadata:
  name: block-privileged-containers
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaces:
      - "production"
      - "staging"
3. コンテナーイメージレジストリの制限
# template-allowed-repos.yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8sallowedrepos
spec:
  crd:
    spec:
      names:
        kind: K8sAllowedRepos
      validation:
        openAPIV3Schema:
          type: object
          properties:
            repos:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sallowedrepos

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not image_matches(container.image)
          msg := sprintf("Container image %v is not from an allowed registry. Allowed: %v", [container.image, input.parameters.repos])
        }

        violation[{"msg": msg}] {
          container := input.review.object.spec.initContainers[_]
          not image_matches(container.image)
          msg := sprintf("Init container image %v is not from an allowed registry. Allowed: %v", [container.image, input.parameters.repos])
        }

        image_matches(image) {
          repo := input.parameters.repos[_]
          startswith(image, repo)
        }
# constraint-allowed-repos.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedRepos
metadata:
  name: restrict-image-repos
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
  parameters:
    repos:
      - "gcr.io/my-project/"
      - "ghcr.io/my-org/"
      - "registry.k8s.io/"
4. リソース制限の適用
# template-require-limits.yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8srequirelimits
spec:
  crd:
    spec:
      names:
        kind: K8sRequireLimits
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequirelimits

        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])
        }
5. latest イメージタグのブロック
# template-block-latest-tag.yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8sblocklatesttag
spec:
  crd:
    spec:
      names:
        kind: K8sBlockLatestTag
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sblocklatesttag

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          endswith(container.image, ":latest")
          msg := sprintf("Container %v uses ':latest' tag. Use specific version tags.", [container.name])
        }

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not contains(container.image, ":")
          msg := sprintf("Container %v has no tag (defaults to latest). Use specific version tags.", [container.name])
        }
6. ルートファイルシステムの読み取り専用化
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8sreadonlyroot
spec:
  crd:
    spec:
      names:
        kind: K8sReadOnlyRoot
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sreadonlyroot

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not container.securityContext.readOnlyRootFilesystem
          msg := sprintf("Container %v must have readOnlyRootFilesystem set to true", [container.name])
        }

監査モードと適用モード

# Dry-run mode (audit only, don't block)
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sBlockPrivileged
metadata:
  name: block-privileged-dryrun
spec:
  enforcementAction: dryrun   # dryrun | deny | warn
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
監査違反の確認
# List all constraint violations
kubectl get k8sblockprivileged block-privileged-containers -o yaml | grep -A 20 violations

# Check all constraints audit status
kubectl get constraints -o json | jq '.items[] | {name: .metadata.name, violations: (.status.violations // [] | length)}'

Gatekeeper の設定(除外する名前空間)

apiVersion: config.gatekeeper.sh/v1alpha1
kind: Config
metadata:
  name: config
  namespace: gatekeeper-system
spec:
  match:
    - excludedNamespaces:
        - kube-system
        - gatekeeper-system
        - calico-system
      processes:
        - "*"

モニタリング

# Check Gatekeeper metrics
kubectl port-forward -n gatekeeper-system svc/gatekeeper-webhook-service 8443:443

# Prometheus metrics
kubectl get --raw /metrics | grep gatekeeper

ベストプラクティス

  1. dryrun から開始する - まず dryrun モードで Constraint をデプロイして違反を確認し、その後 deny に切り替えます
  2. ポリシーライブラリを利用する - 既製のテンプレートには https://github.com/open-policy-agent/gatekeeper-library を活用します
  3. システム名前空間を除外する - kube-system と gatekeeper-system は必ず除外します
  4. ポリシーをバージョン管理する - ConstraintTemplate と Constraint を Git に保存します
  5. 監査結果を監視する - Constraint の .status.violations を定期的に確認します
  6. Rego ポリシーをテストする - デプロイ前に opa test または Rego Playground を使用します
  7. アドミッション Webhook と組み合わせる - 多層防御のため、Gatekeeper を Pod Security Admission と組み合わせます

コメント