TT Lab
はじめる
学ぶ 学習パス コース

ポリシーをコードで

テナントのオンボーディングを自動化する生成ポリシー

TT Labで続きを見る

目標

新しいテナントのネームスペースが作られた瞬間に、デフォルトのセキュリティ・リソースのリソースが一緒に生まれるようにする生成ポリシーを書き、そのポリシーが実際のクラスターで動作するために、ほかに何が必要かまで備えます。

なぜ重要なのか

新しいチームにネームスペースを1つ渡す作業は、普通、チェックリストで回っています。NetworkPolicyをかけ、ResourceQuotaをかぶせ、LimitRangeを入れ、レジストリのSecretをコピーします。人がやると、いつかどこかの手順を抜かし、抜かしたのがよりによってデフォルトの遮断ポリシーだった場合、そのネームスペースだけが何か月も開いたままになります。生成ルールは、このチェックリストを、ネームスペースの作成イベントに結び付けてしまいます。ここで、3つのことを学びます。1つ目は、トリガーの範囲をラベルで絞らないと、システムのネームスペースまで対象になることです。2つ目は、Secretのように、内容をポリシーファイルに書いてはいけないものは、cloneで元のものだけを指すことです。ポリシーはgitに入るからです。3つ目は、バックグラウンドコントローラーは最小権限でインストールされるため、作るリソースの種類の権限を別に付ける必要があり、権限がないと、リクエストは成功するのに、リソースだけが黙って作られないことです。この環境では、コントローラーが動いていないため、実際のリソースは作られず、kyverno CLIでローカルに評価した結果と、ポリシーのYAMLの構造で採点します。

ステップ

  1. /root/policy/generate/add-networkpolicy.yamlにkind: ClusterPolicyを作成してください。spec.rules[0].generateに、apiVersion: networking.k8s.io/v1、kind: NetworkPolicy、name: default-denyを書き、generate.data.specに、podSelector: {}とpolicyTypesを置きますが、Ingressを必ず含めてください。
  2. 同じルールのmatch.any[0].resources.kindsをNamespaceにして、selector.matchLabelsにlabhub.io/tenant: "true"を書いて、テナントのネームスペースにだけ反応するようにしてください。
  3. generate.synchronizeをtrueにしてください。そして、/root/policy/generate/out/sync-note.txtに、オンにしたときの動作(誰かが手で直すと元に戻す)と、オフにしたときの違い(作るときに一度だけ関与する)の両方を書いてください。
  4. /root/policy/generate/clone-registry-secret.yamlを作成してください。generate.kindはSecret、generate.clone.namespaceはpol-lab、generate.clone.nameはregistry-credsです。generate.dataは書いてはいけず、ポリシーファイルの中にSecretの内容が入っていてもいけません。
  5. add-networkpolicy.yamlのgenerate.namespaceを"{{ request.object.metadata.name }}"に、generate.nameを明示してください。そして、/root/policy/generate/out/vars-note.txtに、ポリシーで使える変数を整理しますが、request.objectと、リクエスト元の情報を持つ変数(request.operationまたはrequest.userInfo)を必ず含めてください。
  6. /root/policy/generate/background-rbac.yamlにkind: ClusterRoleを作成してください。rulesにnetworkpoliciesを含め、verbsにcreateとupdateを入れてください(同期をオンにしたので、更新も必要です)。metadata.labelsに、rbac.kyverno.io/aggregate-to-background-controller: "true"のような集約ラベルを付けてください。
  7. kyverno apply /root/policy/generate/add-networkpolicy.yaml --resource /opt/lab/fixtures/policy/resources/target-ns.yamlを実行して、生成されたNetworkPolicyのマニフェストだけを/root/policy/generate/out/generated.txtに保存してください。実行の要約行(pass: ..., error: 0 ...)は入れないでください。
  8. /root/policy/generate/tenant-onboarding.yamlに、ルール3つのポリシーを作成してください。各ルールがそれぞれNetworkPolicy・ResourceQuota・LimitRangeを生成し、ルール名は互いに異なる必要があり、3つのルールすべてがgenerate.synchronize: trueである必要があります。そして、/root/policy/generate/out/onboarding-report.jsonに、trigger_namespaceをtenant-alphaとして、generated配列に、生成されるリソースを3件以上、kindキーを含めて入れてください(ResourceQuotaが必ず入っている必要があります)。

参考

デフォルトのNetworkPolicyを作るルールを書く

/root/policy/generate/add-networkpolicy.yamlにkind: ClusterPolicyを作成してください。spec.rules[0].generateに、apiVersion: networking.k8s.io/v1、kind: NetworkPolicy、name: default-denyを書き、generate.data.specに、podSelector: {}とpolicyTypesを置きますが、Ingressを必ず含めてください。

生成ルールは、作るリソースのapiVersion・kind・name・namespaceを最初に書きます。内容をポリシーに直接書くキーが、別にあります。

トリガーと対象セレクターを絞る

同じルールのmatch.any[0].resources.kindsをNamespaceにして、selector.matchLabelsにlabhub.io/tenant: "true"を書いて、テナントのネームスペースにだけ反応するようにしてください。

何が作られたときに反応するかを、matchに書きます。すべてのネームスペースに作ると、システムのネームスペースまで対象になるので、ラベルで絞ってください。

同期をオンにして、その意味を整理する

generate.synchronizeをtrueにしてください。そして、/root/policy/generate/out/sync-note.txtに、オンにしたときの動作(誰かが手で直すと元に戻す)と、オフにしたときの違い(作るときに一度だけ関与する)の両方を書いてください。

オンにすると、作った後も見守り続けます。オフにしたときと何が変わるかを、ファイルに書いて、はじめて通過します。

元のものをコピーするcloneルールを書く

/root/policy/generate/clone-registry-secret.yamlを作成してください。generate.kindはSecret、generate.clone.namespaceはpol-lab、generate.clone.nameはregistry-credsです。generate.dataは書いてはいけず、ポリシーファイルの中にSecretの内容が入っていてもいけません。

Secretの内容をポリシーファイルに書くと、ポリシーがそのまま流出経路になります。元のものがどこにあるかだけを伝える方式があり、内容を直接書くキーとは、一緒に使えません。

リクエストコンテキストの変数で対象を決める

add-networkpolicy.yamlのgenerate.namespaceを"{{ request.object.metadata.name }}"に、generate.nameを明示してください。そして、/root/policy/generate/out/vars-note.txtに、ポリシーで使える変数を整理しますが、request.objectと、リクエスト元の情報を持つ変数(request.operationまたはrequest.userInfo)を必ず含めてください。

作られたネームスペースの名前は、リクエストのオブジェクトから取り出します。ポリシーで使える変数を3つ整理して、はじめて通過します。

生成権限のためのClusterRoleを書く

/root/policy/generate/background-rbac.yamlにkind: ClusterRoleを作成してください。rulesにnetworkpoliciesを含め、verbsにcreateとupdateを入れてください(同期をオンにしたので、更新も必要です)。metadata.labelsに、rbac.kyverno.io/aggregate-to-background-controller: "true"のような集約ラベルを付けてください。

バックグラウンドコントローラーは、もともと何の権限も持っていません。同期をオンにしたなら、作ることだけでなく、更新も必要です。権限を集めていく集約ラベルも、忘れないでください。

トリガーのリソースで実行して、生成結果を保存する

kyverno apply /root/policy/generate/add-networkpolicy.yaml --resource /opt/lab/fixtures/policy/resources/target-ns.yamlを実行して、生成されたNetworkPolicyのマニフェストだけを/root/policy/generate/out/generated.txtに保存してください。実行の要約行(pass: ..., error: 0 ...)は入れないでください。

保存するのは、生成されたリソースのマニフェストです。実行の要約行は入れないでください。採点がエラーの文字列を探します。

オンボーディングのポリシーのセットと、結果レポートを作る

/root/policy/generate/tenant-onboarding.yamlに、ルール3つのポリシーを作成してください。各ルールがそれぞれNetworkPolicy・ResourceQuota・LimitRangeを生成し、ルール名は互いに異なる必要があり、3つのルールすべてがgenerate.synchronize: trueである必要があります。そして、/root/policy/generate/out/onboarding-report.jsonに、trigger_namespaceをtenant-alphaとして、generated配列に、生成されるリソースを3件以上、kindキーを含めて入れてください(ResourceQuotaが必ず入っている必要があります)。

ネットワーク・クォータ・デフォルトのリソースの3つを、1つのポリシーの中の別々のルールとして作ります。ルール名が重複してはならず、すべてで同期がオンになっている必要があります。