Amazon Web Services ブログ
Amazon EKS での Kyverno によるワンツースリーのように簡単なポリシー管理
本記事は、Easy as one-two-three policy management with Kyverno on Amazon EKS を翻訳したものです。
この投稿は、Raj Seshadri と Jimmy Ray によって寄稿されました。
クラウドネイティブな本番環境でコンテナが使用されるようになると、DevOps やセキュリティチームは、コンテナのアクティビティをリアルタイムで可視化し、ホストやネットワークリソースへのコンテナアクセスを制限し、実行中のコンテナに対する脆弱性の悪用に代表されるような攻撃を検出して防止する必要があります。
Kyverno は、ユーザーがプログラミング言語を習得する必要のない Kubernetes 用のポリシーエンジンです。Kyverno は、Kubernetes クラスターにポリシー対応のガバナンスとコンプライアンスを適用するための、直感的で Kubernetes ネイティブな手段を提供します。
ユースケース
今日まで、リアルタイムのコンテナランタイムセキュリティは、そのベストプラクティスを実装するオープンソースツールが限られているために、敷居が高いものでした。Kyverno は、API オブジェクトが変更されたときに Webhook イベントを受信するアドミッションコントローラーとしてインストールされます。この記事では、Kubernetes クラスターの管理者が構成を検証および変更する方法を紹介します。これらはすべて、Rego や他の言語を知らなくても可能です。Kyverno は、EKS クラスター上でポリシー管理をシンプルかつ簡単にしてくれます。
前提条件
すでに EKS または類似の Kubernetes クラスターが稼働していることを前提とします。例えば、このリンクをたどって Amazon EKS の使用を開始することができます。注意: k8s クラスターのバージョンは v1.14 以上である必要があります。このバージョンには Webhook のタイムアウトが追加されています。kubectl version
を実行して確認してください。
ステップ 1: かんたんインストール
Kyverno のインストールは簡単です。インストールプロセスの出力は以下のようになります。
kubectl create -f https://raw.githubusercontent.com/kyverno/kyverno/master/definitions/release/install.yaml
namespace/kyverno created
customresourcedefinition.apiextensions.k8s.io/clusterpolicies.kyverno.io created
customresourcedefinition.apiextensions.k8s.io/clusterpolicyviolations.kyverno.io created
customresourcedefinition.apiextensions.k8s.io/generaterequests.kyverno.io created
customresourcedefinition.apiextensions.k8s.io/policies.kyverno.io created
customresourcedefinition.apiextensions.k8s.io/policyviolations.kyverno.io created
serviceaccount/kyverno-service-account created
clusterrole.rbac.authorization.k8s.io/kyverno:customresources created
clusterrole.rbac.authorization.k8s.io/kyverno:generatecontroller created
clusterrole.rbac.authorization.k8s.io/kyverno:policycontroller created
clusterrole.rbac.authorization.k8s.io/kyverno:userinfo created
clusterrole.rbac.authorization.k8s.io/kyverno:webhook created
clusterrole.rbac.authorization.k8s.io/kyverno:admin-policies created
clusterrole.rbac.authorization.k8s.io/kyverno:edit-policies-policyviolations created
clusterrole.rbac.authorization.k8s.io/kyverno:policyviolations created
clusterrole.rbac.authorization.k8s.io/kyverno:view-clusterpolicyviolations created
clusterrole.rbac.authorization.k8s.io/kyverno:view-policies-policyviolations created
clusterrolebinding.rbac.authorization.k8s.io/kyverno:customresources created
clusterrolebinding.rbac.authorization.k8s.io/kyverno:generatecontroller created
clusterrolebinding.rbac.authorization.k8s.io/kyverno:policycontroller created
clusterrolebinding.rbac.authorization.k8s.io/kyverno:userinfo created
clusterrolebinding.rbac.authorization.k8s.io/kyverno:webhook created
configmap/init-config created
service/kyverno-svc created
deployment.apps/kyverno created
ステップ 2: 設定の検証のデモ
特権 (Privileged) コンテナの使用は、理想的なセキュリティの実践ではありません。これは、コンテナにホストが実行できるすべての機能を許可することになります。例えば、侵入されたコンテナが特権を持っていると、不正なコンテナを生成したり、ホスト上で実行されている他のコンテナを詮索したりすることができます。このデモでは、特権を要求する Pod を許可しないポリシーを追加する方法を紹介します。最初のステップは、以下に示すようなポリシーを作成して適用することです。Kyverno は、EKS クラスター内でダイナミックアドミッションコントローラーとして動作します。この場合、Kyverno は、API サーバーから Validating Admission Webhook 呼び出しを受け取り、一致するポリシーを適用してアドミッションポリシーを強制したり、リクエストを拒否したりします。また、Kyverno は既存の Kubernetes リソースのポリシー違反も報告します。
まず、ポリシーを作成しましょう。 以下に示すような disallow_privileged.yaml という YAML ファイルを作成します。 このポリシーでは、特権モードでのプロセスの実行を許可しません。
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-privileged
annotations:
policies.kyverno.io/category: Security
policies.kyverno.io/description: Privileged containers are defined as any
container where the container uid 0 is mapped to the host’s uid 0.
A process within a privileged container can get unrestricted host access.
With `securityContext.allowPrivilegeEscalation` enabled, a process can
gain privileges from its parent.
spec:
validationFailureAction: enforce
rules:
- name: validate-privileged
match:
resources:
kinds:
- Pod
validate:
message: "Privileged mode is not allowed. Set privileged to false"
pattern:
spec:
containers:
- =(securityContext):
=(privileged): false
- name: validate-allowPrivilegeEscalation
match:
resources:
kinds:
- Pod
validate:
message: "Privileged mode is not allowed. Set allowPrivilegeEscalation to false"
pattern:
spec:
containers:
- securityContext:
allowPrivilegeEscalation: false
注: 上記のポリシーは “Pod” に適用されますが、Pod コントローラーに対する Kyverno の “自動生成” ルールによって Deployment のポリシーも作成されます。Kyverno はデフォルトでアノテーション pod-policies.kyverno.io/autogen-controllers=DaemonSet,Deployment,Job,StatefulSet,CrobJob
を追加します。
➜ kubectl create -f disallow_privileged.yaml
clusterpolicy.kyverno.io/disallow-privileged create
以下のコマンドを実行すると、disallow-privileged
ポリシーが作成されていることがわかります (訳注: Kyverno のバージョンによって出力結果が異ります) 。 cpol
は、ClusterPolicy の Custom Resource Definition (CRD) で設定されているショートネームです。
➜ kubectl get cpol
NAME AGE
disallow-privileged 62s
それでは、以下の YAML ブロックに示すような、特権アクセスを持つ NGINX の Pod を作成してみましょう。
➜ cat nginx-privileged.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-privileged
labels:
app: nginx-privileged
spec:
containers:
- name: nginx
image: nginx
securityContext:
allowPrivilegeEscalation: true
➜ kubectl create -f nginx-privileged.yaml
Error from server: error when creating "nginx-privileged.yaml": admission webhook "nirmata.kyverno.resource.validating-webhook" denied the request:
resource Pod/default/nginx-privileged was blocked due to the following policies
disallow-privileged:
validate-allowPrivilegeEscalation: 'Validation error: Privileged mode is not allowed. Set allowPrivilegeEscalation to false; Validation rule validate-allowPrivilegeEscalation failed at path /spec/containers/0/securityContext/allowPrivilegeEscalation/'
上に示されたように、YAML ファイルに allowPrivilegeEscalation: true
が含まれているため、Pod の作成は失敗します。YAML を allowPrivilegeEscalation: false
に変更すると、Pod の作成は成功します。これは、Pod 上での特権昇格を許可すべきではないというセキュリティベストプラクティスの一つです。
ステップ 3: 不明なイメージレジストリを許可しないデモ
アドミッションコントローラーを使用して、Kyverno のルールで不明なイメージレジストリからのイメージをブロックすることができます。このサンプルポリシーでは、すべてのイメージが k8s.gcr.io
または gallery.ecr.aws
のいずれかからのものであることを要求します。このポリシーをカスタマイズして、信頼できる他の異なるイメージレジストリを許可できます。
以下のポリシーを unknown-image-registry.yaml
という名前で作成しましょう。
➜ cat unknown-image-registry.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: deployment-pod-valid-registry
labels:
app: kyverno
annotations:
policies.kyverno.io/category: Compliance
policies.kyverno.io/description: Rules to enforce correct image source registry
spec:
validationFailureAction: enforce
rules:
- name: validate-registries
match:
resources:
kinds:
- Pod
validate:
message: "Unknown image registry"
pattern:
spec:
containers:
- image: "k8s.gcr.io/* | gallery.ecr.aws/*"
上記のポリシーをテストするために、以下のような mongo:latest
の Pod を作成しましょう。Docker Hub からイメージを Pull していますが、承認されたレジストリではないため、イメージの Pull が失敗するはずです。
➜ cat mongo.yaml
apiVersion: v1
kind: Pod
metadata:
name: mongo
labels:
app: mongo
spec:
containers:
- name: mongo
image: mongo:latest
上記の YAML は、以下のように不明なイメージレジストリのエラーにより失敗します。
Error from server: error when creating "mongo.yaml": admission webhook "nirmata.kyverno.resource.validating-webhook" denied the request:
resource Pod/default/mongo was blocked due to the following policies
deployment-pod-valid-registry:
validate-registries: 'Validation error: Unknown image registry; Validation rule validate-registries failed at path /spec/containers/0/image/'
ArgoCD を使用したポリシーの自動化
DevOps の世界では、常に自動化を念頭に置く必要があります。ご使用の環境でこれらのポリシーを管理および維持するための最良の方法は、GitOps ツールを使用することです。GitOps パターンを適用する CD ツール である ArgoCD を使って、上記の Kyverno のポリシーのすべてを自動化する必要があります。このセクションでは、ArgoCD を使用してコンテナセキュリティのコアとなるベストプラクティスのいくつかを実装する方法を紹介します。EKS クラスターに ArgoCD をインストールするには、このリンクを参照してください (訳注: ArgoCD のインストールの前に、kubectl delete cpol --all
を実行し、ここまでに作成した ポリシーを削除してください) 。ArgoCD をインストールしたら、UI にログインして、以下に示すように “New App” をクリックします。
以下に示すように Kyverno アプリの詳細を入力します。サンプル YAML ファイルは https://github.com/texanraj/kyverno/tree/master/samples/core_best_practices
にあります。
このステップの後、以下に示すように “Sync” と “Synchronize” をクリックします。これにより、画像の右側に表示されているすべての Kyverno ポリシーが実装されます (訳注: “自動生成” ルールによってマニフェストに変更が加えられるため、ステータスは OutOfSync となりますが、このウォークスルーに影響はないため先に進んでください) 。
これは、以下のように ClusterPolicy (cpol
) を照会することで確認できます。
➜ kubectl get cpol
NAME AGE
disallow-bind-mounts 37s
disallow-docker-sock-mount 37s
disallow-helm-tiller 37s
disallow-host-network-port 37s
disallow-new-capabilities 37s
disallow-privileged 37s
disallow-root-user 37s
disallow-sysctls 37s
require-ro-rootfs 37s
EKS クラスター内の即時のポリシー違反を把握するには、以下のように PolicyViolation を照会して、問題のあるリソースをレポートします。例えば、私の EKS クラスターでは以下の Deployment で PolicyViolation (polv
) がありました (訳注: Kyverno 1.3.0+ では、PolicyViolation ではなくPolicyReport を使用します。詳細は PolicyReport に関する Kyverno のドキュメントを参照してください) 。
➜ kubectl get polv
NAME POLICY RESOURCEKIND RESOURCENAME AGE
disallow-privileged-9bzrp disallow-privileged Deployment octank-fintech-dev 5m43s
disallow-privileged-jqdq7 disallow-privileged Deployment jenkins 5m45s
disallow-root-user-lbzvw disallow-root-user Deployment octank-fintech-dev 7m20s
require-ro-rootfs-8k27x require-ro-rootfs Deployment octank-fintech-dev 6m45s
require-ro-rootfs-pmcmn require-ro-rootfs Deployment jenkins 6m46s
シフトレフトによるオペレーションとユーザーエクスペリエンスの改善
ポリシー対応の Kubernetes では、ミューテーション (変更) とバリデーションのアドミッションコントロールを使用することで、Kubernetes オペレーションの周囲にガードレールを設置することができます。ガードレールは、クラスター内での不要や不正な動作を減らします。また、クラスター運用に関して、考えるべきことを減らしてくれるという副次的な効果も得られます。Kubernetes クラスターと対話してデプロイを行うすべてのユーザーが、Kubernetes の専門家 (SME) ではありません。Pod が期待通りに起動しない場合、ユーザーはしばしば問題のトラブルシューティングの支援のために、クラスターオペレーター/管理者/SME の助けを借ります。Pod 起動の失敗をトラブルシューティングする際に、Pod Security Policy (PSP) のような単純なものが SME のサイクルを消費する可能性があります。
ポリシー対応の Kubernetes は、クラスターの状態が変更される前に判断を行うことで、この負担を軽減します。SME の介入を必要とした PSP の問題は、すべての Pod とコンテナの Spec に正しい SecurityContext の構成が含まれていることを要求することで、なくならないかもしれませんが、減らすことができます。Kubernetes API のリクエストサイクルでこれらの動作を強制するポリシーは、望ましくない状態変更が etcd に適用されるのを防ぎます。クラスターの API サーバーと対話しているエンドユーザーには、リクエストが無効であり、出力メッセージで定義されている理由で失敗したことがすぐに通知されます。このシンプルなプロセスは、ユーザーを教育し、クラスターオペレーター/管理者のサポートの負担を軽減する大きな可能性を秘めています。このモデルでは、ポリシー対応の Kubernetes はセキュリティ制御を強化し、API サーバーへのリクエストのレスポンスとして判断をシフトレフトさせることで、クラスターユーザーのユーザーエクスペリエンスを向上させます。
クリーンアップ
以下のように ArgoCD のデプロイメントを削除します。
kubectl delete -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
以下のように Kyverno を削除します。
kubectl delete -f https://raw.githubusercontent.com/kyverno/kyverno/master/definitions/release/install.yaml
結論
Kyverno プロジェクトは、Kubernetes クラスターに適切な DevSecOps ポリシーを作成するプロセスを合理化します。この記事では、Kyverno を使ってポリシーを作成し、ArgoCD を使って実装することがいかに簡単であるかを説明しました。Custom Resource Definition (CRD) のような Kubernetes ネイティブのコンポーネントを使用することで、新しい構文や新しいポリシー言語を学ぶ必要性が少なくなります。EKS 環境に Kubernetes ネイティブの方法でポリシーを実装および管理することを選択する場合、Kyverno は優れたオプションです。
リファレンス
https://github.com/nirmata/kyverno
https://kyverno.io/docs/
翻訳はプロフェッショナルサービスの杉田が担当しました。