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

Kubernetes運用実務

最小権限でロールを設計する

TT Labで続きを見る

目標

ロールとバインディングを自分で作成して最小権限を設計し、kubectl auth can-iで権限の境界を検証する習慣を身に付けます。

なぜ重要なのか

RBACで最も多くの人が混同するのは、スコープを決めるのはロールではなくバインディングだという点です。同じClusterRoleでも、ClusterRoleBindingで紐づければクラスター全体、RoleBindingで紐づければそのネームスペースでのみ有効です。この性質のおかげで、共通の権限のまとまりをClusterRoleとして一度だけ定義し、チームごとに自分のネームスペースで再利用できます。2つ目の落とし穴はサブリソースです。podsとpods/log、pods/execは別々のリソース名なので、権限が自動的についてくることはありません。ログだけを読むボットに、シェルへの接続権限までついていかないようにするには、この区別が必要です。最後に、権限は書くものではなく判定されるものなので、マニフェストを目で読む代わりに、impersonationで問い合わせてください。yesだけを確認せず、noも一緒に確認して初めて、権限が必要以上に広くないかがわかります。

ステップ

  1. ネームスペースrbac-labを作成し、その中にサービスアカウントapp-reader、inspector、log-botの3つを作成してください。
  2. rbac-labにRolepod-readerを作成してください。ルールは1つで、apiGroupsはコアグループ(空文字列)、resourcesはpods、verbsはget、list、watchの3つです。ワイルドカード*は、どこにも使ってはいけません。
  3. rbac-labにRoleBindingread-podsを作成してください。roleRefはkindRole、namepod-readerで、サブジェクトはkindServiceAccount、nameapp-reader、namespacerbac-labです。
  4. app-readerにimpersonationして権限を確認し、結果を/root/ops/rbac/out/can-i.txtに保存してください。このファイルには、yesの応答とnoの応答の両方が含まれている必要があります。確認する項目は、最低でも次の3つです。rbac-labでのPod一覧の取得(yes)、rbac-labでのPodの削除(no)、defaultネームスペースでのPod一覧の取得(no)です。
  5. ClusterRolenode-viewerを作成してください。resourcesにnodesが含まれ、すべてのルールのverbsはget、list、watchだけである必要があります。続けてClusterRoleBindingnode-viewer-bindingで、このロールをrbac-labのapp-readerに与えてください。結果として、app-readerはノードを取得できて、削除はできない状態になっている必要があります。
  6. ClusterRolens-inspectorを作成してください(ConfigMapを読み取れる必要があります)。そしてrbac-labにRoleBindinginspect-hereを作成し、roleRef.kindをClusterRole、nameをns-inspectorとし、サブジェクトはrbac-labのinspectorにしてください。結果として、inspectorはrbac-labではConfigMapを読み取れますが、defaultでは読み取れない状態になっている必要があります。
  7. rbac-labにRolelog-readerを作成してください。resourcesにはpods/logだけを入れ、podsは入れないでください。このロールをlog-botにRoleBindingで紐づけてください。結果として、log-botはpods/logを読み取れて、pods自体は読み取れず、pods/execも使えない状態になっている必要があります。
  8. /root/ops/rbac/out/rbac-audit.jsonを作成してください。フィールドは4つです。cluster_admin_bindingsは、roleRef.nameがcluster-adminであるClusterRoleBindingの名前の配列で、実際のクラスターの数と正確に一致している必要があり、デフォルトのバインディングであるcluster-adminが含まれている必要があります。wildcard_rolesは*を使うロール名の配列(1つ以上)、secret_readersはsecretsを扱うロール名の配列(1つ以上)、least_privilege_violationsは最小権限の違反と判断した項目の配列です。

参考

ネームスペースとサービスアカウントを準備する

ネームスペースrbac-labを作成し、その中にサービスアカウントapp-reader、inspector、log-botの3つを作成してください。

サブジェクトがなければ、権限を与えられません。サービスアカウントはネームスペースに属し、名前だけで作成できます。

読み取り専用のRoleを作成する

rbac-labにRolepod-readerを作成してください。ルールは1つで、apiGroupsはコアグループ(空文字列)、resourcesはpods、verbsはget、list、watchの3つです。ワイルドカード*は、どこにも使ってはいけません。

コアリソースのAPIグループの名前が何かを確認してください。読み取り系の動詞は3つで、ワイルドカードは使いません。

Roleをサービスアカウントにバインドする

rbac-labにRoleBindingread-podsを作成してください。roleRefはkindRole、namepod-readerで、サブジェクトはkindServiceAccount、nameapp-reader、namespacerbac-labです。

サブジェクトがサービスアカウントの場合は、名前だけでは足りません。どのネームスペースのアカウントなのかまで書く必要があります。

impersonationで権限の境界を確認する

app-readerにimpersonationして権限を確認し、結果を/root/ops/rbac/out/can-i.txtに保存してください。このファイルには、yesの応答とnoの応答の両方が含まれている必要があります。確認する項目は、最低でも次の3つです。rbac-labでのPod一覧の取得(yes)、rbac-labでのPodの削除(no)、defaultネームスペースでのPod一覧の取得(no)です。

サービスアカウントの正式な名前の形式を思い出してください。できることとできないことの両方を確認して初めて、境界が見えてきます。

クラスタースコープのリソース用のClusterRoleを作成する

ClusterRolenode-viewerを作成してください。resourcesにnodesが含まれ、すべてのルールのverbsはget、list、watchだけである必要があります。続けてClusterRoleBindingnode-viewer-bindingで、このロールをrbac-labのapp-readerに与えてください。結果として、app-readerはノードを取得できて、削除はできない状態になっている必要があります。

ノードはネームスペースのないリソースなので、Roleでは扱えません。クラスター全体に適用するには、バインディングもクラスタースコープである必要があります。

ClusterRoleをRoleBindingで紐づけてみる

ClusterRolens-inspectorを作成してください(ConfigMapを読み取れる必要があります)。そしてrbac-labにRoleBindinginspect-hereを作成し、roleRef.kindをClusterRole、nameをns-inspectorとし、サブジェクトはrbac-labのinspectorにしてください。結果として、inspectorはrbac-labではConfigMapを読み取れますが、defaultでは読み取れない状態になっている必要があります。

スコープを決めるのは、ロールの種類ではなくバインディングの種類です。同じロールがどのネームスペースでだけ有効になるのかを確認してください。

サブリソースだけを開くロールを作成する

rbac-labにRolelog-readerを作成してください。resourcesにはpods/logだけを入れ、podsは入れないでください。このロールをlog-botにRoleBindingで紐づけてください。結果として、log-botはpods/logを読み取れて、pods自体は読み取れず、pods/execも使えない状態になっている必要があります。

ログは、Podとは別のリソース名を持ちます。上位のリソースまで一緒に開けてしまうと、このステップの意味がなくなります。

権限の監査レポートを作成する

/root/ops/rbac/out/rbac-audit.jsonを作成してください。フィールドは4つです。cluster_admin_bindingsは、roleRef.nameがcluster-adminであるClusterRoleBindingの名前の配列で、実際のクラスターの数と正確に一致している必要があり、デフォルトのバインディングであるcluster-adminが含まれている必要があります。wildcard_rolesは*を使うロール名の配列(1つ以上)、secret_readersはsecretsを扱うロール名の配列(1つ以上)、least_privilege_violationsは最小権限の違反と判断した項目の配列です。

手で数えず、クラスターから抽出してください。cluster-adminのバインディングの数は、実際の値と正確に一致している必要があります。