GKE RBAC のベスト プラクティス

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

このページでは、ロールベースのアクセス制御(RBAC)ポリシーを計画する際のベスト プラクティスについて説明します。Google Kubernetes Engine(GKE)で RBAC を実装する方法については、ロールベースのアクセス制御の構成をご覧ください。

RBAC は Kubernetes のコア セキュリティ機能であり、きめ細かい権限を作成して、クラスタ内のリソースに対してユーザーとワークロードが実行できるアクションを管理できます。プラットフォーム管理者として、RBAC ロールを作成し、それらのロールをサブジェクト(サービス アカウントやグループなどの認証済みユーザー)にバインドします。

始める前に

次のコンセプトについて理解していることを確認してください。

このガイダンスのチェックリストについては、チェックリストの概要をご覧ください。

RBAC の仕組み

RBAC では、次の種類のロールとバインディングがサポートされます。

  • ClusterRole: 任意の名前空間またはクラスタ全体に適用できる一連の権限。
  • ロール: 名前空間が 1 つに制限されている一連の権限。
  • ClusterRoleBinding: クラスタ内のすべての名前空間のユーザーまたはグループに ClusterRole をバインドします。
  • RoleBinding: 特定の名前空間内のユーザーまたはグループに Role または ClusterRole をバインドします。

権限は、Role または ClusterRolerules として定義します。ロール内の各 rules フィールドは、API グループ、その API グループ内の API リソース、およびそれらのリソースに対して許可される動詞(アクション)で構成されます。必要に応じて、resourceNames フィールドを使用して、動詞を API リソースの名前付きインスタンスにスコープできます。例については、特定のリソース インスタンスへのアクセスを制限するをご覧ください。

ロールを定義したら、RoleBinding または ClusterRoleBinding を使用して、ロールをサブジェクトにバインドします。権限を 1 つの名前空間に付与するか、複数の名前空間に付与するかに基づいて、バインディングの種類を選択します。

RBAC ロールの設計

最小権限の原則を使用する

RBAC ロールで権限を割り当てるときは、最小権限の原則に従い、タスクを実行するために必要な最小限の権限を付与します。最小権限の原則を使用すると、クラスタが侵害された場合に権限昇格の可能性が低減され、過剰なアクセスによってセキュリティ インシデントが発生する可能性が低くなります。

ロールを設計する際は、escalate または bind 動詞、PersistentVolume への create アクセス、証明書署名リクエストへの create アクセスなどの権限昇格の一般的なリスクを慎重に検討してください。リスクの一覧については、Kubernetes RBAC - 権限昇格のリスクをご覧ください。

デフォルトのロールとグループを避ける

Kubernetes によって一連の ClusterRole オブジェクトと ClusterRoleBinding オブジェクトが自動的に作成されます。これらのオブジェクトを使用して、API ディスカバリやマネージド コンポーネント機能を有効にできます。これらのデフォルトのロールで付与される権限は、広範囲に及ぶ場合があります。たとえば、cluster-admin ClusterRole は、任意のリソースに対して何かを行うサブジェクト権限を付与します。ClusterRoleBinding を使用して cluster-admin ClusterRole をユーザーまたはサービス アカウントにバインドした場合、そのサブジェクトはクラスタ内で無限の権限を持つことになります。

デフォルトのロールをサブジェクトにバインドする前に、そのロールによって付与される権限をユースケースに照らして評価します。リスクを認識しておいてください。Kubernetes が作成するデフォルトのロールとバインディングの完全なリストについては、デフォルトのロールとロール バインディングをご覧ください。

Kubernetes は、デフォルトのロールにバインドされたデフォルト グループも作成します。たとえば、cluster-admin ClusterRole は、system:masters グループにバインドされ、マネージド コンポーネントに API サーバーへの完全アクセス権を付与します。独自のサブジェクトを system:masters に追加しないでください。

可能であれば、次のガイドラインを参考にしてください。

  • 独自のサブジェクトを system:masters グループに追加しないでください。
  • system:unauthenticated グループを RBAC ロールにバインドしないでください。
  • cluster-admin ClusterRole を独自のサブジェクトにバインドしないでください。
  • サブジェクトをバインドする前に、他のデフォルトのロールによって付与される権限を評価します。
  • グループのメンバーを変更する前に、デフォルトのグループにバインドされたロールを評価します。

名前空間レベルで権限にスコープを設定する

ワークロードやユーザーのニーズに応じて、次のバインディングとロールを使用します。

  • 1 つの名前空間内のリソースへのアクセス権を付与するには、RoleBinding を持つ Role を使用します。
  • 複数の名前空間内のリソースへのアクセス権を付与するには、各名前空間に RoleBinding を持つ ClusterRole を使用します。
  • すべての名前空間内のリソースへのアクセス権を付与するには、ClusterRoleBinding を持つ ClusterRole を使用します。

権限を付与する名前空間はできるだけ少なくしてください。

ワイルドカードを使用しない

* 文字は、すべてに適用されるワイルドカードです。ルールでワイルドカードは使用しないでください。RBAC ルールで API グループ、リソース、動詞を明示的に指定します。たとえば、verbs フィールドに * を指定すると、リソースに対する getlistwatchpatchupdatedeletecollection、および delete の権限が付与されます。次の表に、ルールでワイルドカードを使用しない例を示します。

推奨 非推奨

- rules:
    apiGroups: ["apps","extensions"]
    resources: ["deployments"]
    verbs: ["get","list","watch"]

getlistwatch 動詞を apps API および extensions API グループに付与します。


- rules:
    apiGroups: ["*"]
    resources: ["deployments"]
    verbs: ["get","list","watch"]

任意の API グループの deployments に動詞を付与します。


- rules:
    apiGroups: ["apps", "extensions"]
    resources: ["deployments"]
    verbs: ["get", "list", "watch"]

getlistwatch 動詞のみを、apps API および extensions API グループ内のデプロイメントに付与します。


- rules:
    apiGroups: ["apps", "extensions"]
    resources: ["deployments"]
    verbs: ["*"]

patchdelete を含むすべての動詞を付与します。

個別のルールを使用して特定のリソースに対する最小権限アクセスを付与する

ルールを計画する際は、次に示す各ロールで最小権限ルールをより効率的に設計するための大まかな手順をお試しください。

  1. サブジェクトがアクセスする必要がある各リソースの動詞ごとに個別の RBAC ルールを作成します。
  2. ルールの下書きを作成したら、ルールを分析して、複数のルールに同じ verbs リストがあるかどうかを確認します。これらのルールを 1 つのルールにまとめます。
  3. 残りのルールはそれぞれ分割します。

このアプローチでは、複数のリソースに同じ動詞を付与するルールと、リソースに異なる動詞を付与するルールを組み合わせた、より整理されたルール設計になります。

たとえば、ワークロードで deployments リソースに対する権限を取得する必要があるが、daemonsets リソースでは listwatch が必要な場合、ロールの作成時に別のルールを使用する必要があります。RBAC ロールをワークロードにバインドすると、deploymentswatch を使用できなくなります。

別の例として、ワークロードが pods リソースと daemonsets リソースの両方で getwatch を必要とする場合、ワークロードは両方のリソースで同じ動詞を必要とするため、これらを 1 つのルールに結合することができます。

次の表では、両方のルール設計が機能しますが、分割ルールはニーズに応じてリソースへのアクセスをきめ細かく制限します。

推奨 非推奨

- rules:
    apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get"]
- rules:
    apiGroups: ["apps"]
    resources: ["daemonsets"]
    verbs: ["list", "watch"]

Deployment に get アクセス権を付与し、DaemonSet に watch アクセス権と list アクセス権を付与します。 サブジェクトは Deployment を一覧表示できません。


- rules:
    apiGroups: ["apps"]
    resources: ["deployments", "daemonsets"]
    verbs: ["get","list","watch"]

Deployment と DaemonSets の両方に動詞を付与します。deployments オブジェクトで list アクセスを必要としないサブジェクトにも、そのアクセス権が付与されます。


- rules:
    apiGroups: ["apps"]
    resources: ["daemonsets", "deployments"]
    verbs: ["list", "watch"]

サブジェクトが daemonsets リソースと deployments リソースの両方について同じ動詞を必要とするため、2 つのルールを結合します。


- rules:
    apiGroups: ["apps"]
    resources: ["daemonsets"]
    verbs: ["list", "watch"]
- rules:
    apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["list", "watch"]

これらの分割ルールは、結合されたルールと同じ結果になりますが、ロールのマニフェストに不要な混乱が生じます。

特定のリソース インスタンスへのアクセスを制限する

RBAC では、ルール内の resourceNames フィールドを使用して、リソースの特定の名前付きインスタンスへのアクセスを制限できます。たとえば、seccomp-high ConfigMap を update にする必要がある RBAC ロールを作成する場合、resourceNames を使用してその ConfigMap のみを指定できます。可能な限り resourceNames を使用してください。

推奨 非推奨

- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["seccomp-high"]
    verbs: ["update"]

サブジェクトが seccomp-high ConfigMap のみを更新するように制限します。サブジェクトは、名前空間内の他の ConfigMap を更新できません。


- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["update"]

サブジェクトは、seccomp-high ConfigMap と名前空間内の他の ConfigMap を更新できます。


- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["list"]
- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["seccomp-high"]
    verbs: ["update"]

seccomp-high を含む、名前空間内のすべての ConfigMap に対する list アクセス権を付与します。update アクセス権を seccomp-high ConfigMap のみに制限します。名前付きリソースに list を付与できないため、ルールは分割されます。


- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["update", "list"]

すべての ConfigMap に対する update アクセス権と、list アクセス権を付与します。

サービス アカウントに RBAC リソースの変更を許可しない

rbac.authorization.k8s.io API グループに対する bindescalatecreateupdate、または patch の権限を持つ Role または ClusterRole リソースを、任意の名前空間内のサービス アカウントにバインドしないでください。特に escalatebind を使用すると、攻撃者がRBAC に組み込まれているエスカレーション防止メカニズムをバイパスできます。

Kubernetes サービス アカウント

ワークロードごとに Kubernetes サービス アカウントを作成する

ワークロードごとに個別の Kubernetes サービス アカウントを作成します。そのサービス アカウントに最小権限の Role または ClusterRole をバインドします。

デフォルトのサービス アカウントを使用しない

Kubernetes は、すべての名前空間に default という名前のサービス アカウントを作成します。default サービス アカウントは、マニフェストでサービス アカウントを明示的に指定しない Pod に自動的に割り当てられます。RoleClusterRoledefault サービス アカウントにバインドしないでください。Kubernetes は、これらのロールで付与されるアクセス権を必要としない Pod に default サービス アカウントを割り当てます。

サービス アカウント トークンを自動的にマウントしない

Pod 仕様の automountServiceAccountToken フィールドは、Kubernetes サービス アカウントの認証情報トークンを Pod に挿入するよう Kubernetes に指示します。Pod はこのトークンを使用して、Kubernetes API サーバーに対して認証済みのリクエストを行うことができます。このフィールドのデフォルト値は true です。

すべての GKE バージョンで、Pod が API サーバーと通信する必要がない場合は、Pod 仕様に automountServiceAccountToken=false を設定します。

シークレット ベースのトークンよりもエフェメラル トークンを優先する

サービス アカウント トークンを作成して使用する場合は、Kubernetes Secret を使用してトークンを保存しないでください。シークレット ベースのサービス アカウント トークンは、以前の認証情報で、自動的にはローテーションされず、期限切れになりません。サービス アカウントの認証情報が必要な場合は、TokenRequest API を使用して、自動的にローテーションされる有効期間の短いトークンを取得します。

RBAC 権限を継続的に確認する

RBAC ロールを確認し、定期的にアクセスして、潜在的なエスカレーション パスと冗長ルールを特定します。たとえば、特別な権限を持つ Role を削除されたユーザーにバインドする RoleBinding を削除しない状況を考えてみましょう。攻撃者が、削除されたユーザーと同じ名前でその名前空間にユーザー アカウントを作成すると、攻撃者はその Role にバインドされ、同じアクセス権を継承します。このリスクは、定期的なレビューにより最小限に抑えられます。

チェックリストの概要

次のステップ