Kubernetesクラスターを保護するためのRBACのベストプラクティス
Kubernetes RBACのベストプラクティス、最小権限のRole例、サービスアカウントのスコープ設定、より安全なクラスターのための監査チェックについて学びます。
Kubernetesクラスターを保護するための必須RBACベストプラクティス
Kubernetes RBACは、クラスター内で誰が何をできるかを決定します。単一の広範なバインディングにより、侵害されたアカウントがシークレットを読み取り、ワークロードを変更し、クラスターリソースを乗っ取る可能性があります。
このガイドでは、RBACオブジェクトの基本を説明し、実用的な例を示し、アクセスが時間とともに逸脱するのを防ぐためのレビューの習慣を提供します。
Kubernetes RBACの基礎を理解する
KubernetesのRBACは、個々のユーザーまたはサービスアカウントの役割に基づいてKubernetesリソースへのアクセスを規制する認可メカニズムです。これは防御の重要な層であり、許可されたエンティティのみが特定のリソースに対して特定のアクションを実行できるようにします。
RBACは、主に4種類のKubernetesオブジェクトに依存しています。
Role:Roleは、特定の名前空間内で適用される一連の権限です。これは、どのリソース(pods、deployments、services、secretsなど)に対してどのアクション(get、list、create、update、deleteなどの動詞)を実行できるかを定義します。たとえば、Roleはdevelopment名前空間内のpodsとdeploymentsを読み取る権限を付与する場合があります。ClusterRole:Roleと似ていますが、ClusterRoleはクラスター全体または名前空間のないリソース(例:nodes、persistentvolumes)に適用される権限を定義します。ClusterRoleは、すべての名前空間にわたる名前空間付きリソースの権限を定義することもできます。たとえば、ClusterRoleはクラスター内のすべてのnodesを一覧表示することを許可する場合があります。RoleBinding:RoleBindingは、Role(または名前空間付きで適用されるClusterRole)で定義された権限をユーザー、グループ、またはサービスアカウントに付与します。これは常に特定の名前空間内で動作します。ClusterRoleBinding:ClusterRoleBindingは、ClusterRoleで定義された権限をユーザー、グループ、またはサービスアカウントに付与し、それらの権限をクラスター全体に適用します。
これらのオブジェクトは連携して、管理者が堅牢で詳細なアクセス制御システムを構築できるようにします。ユーザーまたはアプリケーション(サービスアカウントで表される)がアクションを実行しようとすると、Kubernetesは既存のRoleBindingsとClusterRoleBindingsを評価して、要求されたアクションが許可されているかどうかを判断します。
RBACで最小権限の原則を実装する
情報セキュリティの中心的な教義は最小権限の原則です。ユーザー、プログラム、またはプロセスは、そのジョブを実行するために必要な権限のみを受け取る必要があります。Kubernetesでは、過度に寛大なロールは、小さな侵害がクラスター全体の問題に発展する一般的な方法です。
詳細な権限の定義
RBACポリシーを作成する際は、必要な正確なアクションとリソースを検討します。
- 動詞:
*(すべての動詞)を付与する代わりに、必要なアクションを正確に指定します(get、list、watch、create、update、delete、patch、exec)。 - リソース: リソース(
pods、deployments、secrets、configmaps)を具体的に指定します。絶対に必要で、十分に正当化された管理ロールでない限り、リソースに*へのアクセスを付与しないでください。 - リソース名:
secretsなどの非常に機密性の高いリソースの場合、リソースタイプ内の特定のresourceNamesに対してgetなどの一部の動詞を制限できます。listおよびwatchは同じ方法で単一の名前付きオブジェクトにスコープされないため、リスト形式のアクセスにはresourceNamesに依存しないでください。 - APIグループ: ほとんどのKubernetesリソースはAPIグループ(例:
apps、rbac.authorization.k8s.io、コアリソースの場合は"")に属します。正しいAPIグループを指定して、スコープをさらに絞り込みます。
名前空間スコープ
ほとんどのアプリケーションと開発チームでは、権限を特定の名前空間に限定する必要があります。この分離により、1つのアプリケーションまたはチームの環境での侵害が自動的にクラスター全体のアクセスにつながらないようにします。可能な場合は常に、ClusterRoleとClusterRoleBindingよりもRoleとRoleBindingを優先します。
実用的なRBAC実装:例
RBACポリシーを作成およびバインドするための実用的な例をいくつか見てみましょう。
例1:特定の名前空間への開発者アクセス
開発者が専用の名前空間dev-team-aでデプロイメントを管理し、ログを表示する必要があるとします。他の名前空間やクラスター全体のリソースにアクセスできないようにする必要があります。
まず、dev-team-a名前空間に開発者用のRoleを定義します。
# dev-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: dev-team-a
name: dev-deployer
rules:
- apiGroups: ["apps"] # For Deployments
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "watch", "create", "update", "delete", "patch"]
- apiGroups: [""] # Core API group for Pods and Pod logs
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
このロールを適用します。
kubectl apply -f dev-role.yaml
次に、このRoleを特定のユーザー(例:外部IDプロバイダー経由の[email protected])またはdev-team-a名前空間内のサービスアカウントにバインドします。
# dev-role-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: dev-team-a
name: john-dev-deployer-binding
subjects:
- kind: User
name: [email protected] # Name is case sensitive
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: dev-deployer
apiGroup: rbac.authorization.k8s.io
このバインディングを適用します。
kubectl apply -f dev-role-binding.yaml
これで、[email protected]はdev-team-a名前空間内でのみデプロイメントを管理し、ログを表示できます。たとえば、kube-systemでシークレットを作成したり、すべてのノードを一覧表示したりすることはできません。
例2:シークレットにアクセスするアプリケーションサービスアカウント
ServiceAccountとして実行されるアプリケーションは、自身の名前空間内の特定のシークレットを読み取る必要があります。
まず、サービスアカウントが存在することを確認するか、作成します。
# app-sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: my-app-namespace
name: my-app-service-account
このサービスアカウントを適用します。
kubectl apply -f app-sa.yaml
次に、特定のシークレットの読み取りを許可するRoleを定義します。
# secret-reader-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: my-app-namespace
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["my-app-db-credentials"]
verbs: ["get"]
このロールを適用します。
kubectl apply -f secret-reader-role.yaml
最後に、このRoleをmy-app-service-accountにバインドします。
# app-secret-reader-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: my-app-namespace
name: my-app-secret-reader-binding
subjects:
- kind: ServiceAccount
name: my-app-service-account
namespace: my-app-namespace
roleRef:
kind: Role
name: secret-reader
apiGroup: rbac.authorization.k8s.io
このバインディングを適用します。
kubectl apply -f app-secret-reader-binding.yaml
アプリケーションは、指定されたシークレットのみを読み取ることができ、それ以外は何もできなくなります。
例3:クラスター管理者ロール(注意して使用)
クラスター全体の管理ロールは、非常に控えめに付与する必要があります。以下は、すべてのノードを一覧表示するためのClusterRoleの例です。これは監視ツールに必要になる場合があります。
# node-viewer-clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: node-viewer
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
このClusterRoleを適用します。
kubectl apply -f node-viewer-clusterrole.yaml
次に、ClusterRoleBindingを使用して監視サービスアカウントにバインドします。
# monitoring-node-viewer-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: monitoring-node-viewer-binding
subjects:
- kind: ServiceAccount
name: monitoring-sa
namespace: monitoring
roleRef:
kind: ClusterRole
name: node-viewer
apiGroup: rbac.authorization.k8s.io
このバインディングを適用します。
kubectl apply -f monitoring-node-viewer-binding.yaml
警告: 人間のユーザーに対してClusterRoleとClusterRoleBindingを使用する場合は、細心の注意を払ってください。使用は真のクラスター管理者と特定のインフラストラクチャサービスアカウントに限定してください。
必須のRBACベストプラクティス
これらのベストプラクティスを遵守することで、クラスターのセキュリティ体制が大幅に向上します。
最小権限の原則(PoLP)を適用する:
- 必要な最小限の権限のみを付与します。すべての権限を注意深く確認します。
- 可能な場合は、
resourcesとverbsにワイルドカード(*)を使用しないでください。使用する場合は、正当化し、可能な限り狭くスコープするようにしてください。 - ロールで
resourceNamesを使用して、機密リソース(secretsなど)へのアクセスを制限します。
分離に名前空間を使用する:
- アプリケーションとチームを個別の名前空間に整理します。
- デフォルトでは、これらの名前空間内で権限を付与するために
RoleとRoleBindingを使用します。
ClusterRoleよりもRoleを優先する:
- 権限が本当にクラスター全体に必要な場合(例:ノード管理、カスタムリソース定義、特定の監視エージェント)にのみ
ClusterRoleとClusterRoleBindingを使用します。 - ほとんどのアプリケーション固有の権限は名前空間スコープにする必要があります。
- 権限が本当にクラスター全体に必要な場合(例:ノード管理、カスタムリソース定義、特定の監視エージェント)にのみ
RBACポリシーを定期的に監査およびレビューする:
- RBACポリシーは時間の経過とともに逸脱する可能性があります。誰がどのようなアクセス権を持っているかを定期的に確認します。
kubectl auth can-iなどのツールを使用して、特定のユーザー/サービスアカウントの権限をテストします。
# '[email protected]'が'dev-team-a'でポッドを取得できるか確認する kubectl auth can-i get pods --namespace=dev-team-a [email protected] # 'monitoring-sa'がノードを一覧表示できるか確認する(クラスター全体) kubectl auth can-i list nodes --as=system:serviceaccount:monitoring:monitoring-sa- 包括的なRBAC監査のために、サードパーティのツールやカスタムスクリプトを検討します。
管理ロールを分離する:
- 開発者やアプリケーションサービスアカウントに
cluster-admin権限を決して与えないでください。 - 必要な昇格された権限のみを持つ特定の管理
ClusterRolesを作成します(例:cluster-reader、node-reader)。
- 開発者やアプリケーションサービスアカウントに
アプリケーションにサービスアカウントを活用する:
- クラスター内で実行されるアプリケーションは、
ServiceAccountsを使用してKubernetes APIと対話する必要があります。 - 各アプリケーションまたはマイクロサービスには、最小限の権限を持つ専用の
ServiceAccountを理想的に持たせる必要があります。 - Kubernetes APIアクセスを必要としないポッドについては、ポッドまたはサービスアカウントで
automountServiceAccountToken: falseを設定します。
- クラスター内で実行されるアプリケーションは、
外部ID管理と統合する:
- 人間のユーザーの場合、認証とグループ管理のためにKubernetesを外部IDプロバイダー(例:OIDC、LDAP、Active Directory)と統合します。
- 管理を容易にするために、外部グループをKubernetesの
RoleBindingsまたはClusterRoleBindingsにマッピングします。
GitOpsでRBAC管理を自動化する:
- RBACポリシーをコードとして扱います。バージョン管理されたリポジトリ(Git)に保存します。
- GitOpsの原則を使用してRBAC構成を管理およびデプロイし、一貫性、トレーサビリティ、およびロールバックの容易さを確保します。
監査ログを介してRBACイベントを監視する:
- Kubernetes監査ログを有効にして構成し、誰がいつどのようなアクションを実行したかを含むAPIリクエストを追跡します。
- 監査ログを定期的に確認して、不正なアクセス試行やRBACに関連する不審なアクティビティを検出します。
Kubernetesを定期的に更新する:
- セキュリティパッチとRBACの強化を含む改善の恩恵を受けるために、Kubernetesバージョンを最新の状態に保ちます。
よくある落とし穴とその回避方法
- 過度に寛大なワイルドカード:
apiGroups: ["*"]、resources: ["*"]、またはverbs: ["*"]を付与することは、主要なセキュリティリスクです。常に明示的にしてください。 - デフォルトの
cluster-adminの使用: 日常業務でsystem:mastersグループまたはcluster-adminClusterRoleを使用したり、管理者以外のユーザーに割り当てたりしないでください。どちらもクラスターに対する広範な制御を提供します。 automountServiceAccountTokenの無視: 多くのクラスターでは、自動マウントを無効にしない限り、ポッドはサービスアカウントトークンを受け取ります。ポッドがKubernetes APIと対話する必要がない場合は、ポッド仕様またはサービスアカウント定義でautomountServiceAccountToken: falseを設定して、攻撃対象領域を減らします。- 監査の欠如: 定期的なレビューがないと、クラスターのニーズが進化するにつれて、RBACポリシーが古くなったり、過度に寛大になったりする可能性があります。レビュープロセスを実装します。
RoleとClusterRoleの混同: スコープを誤解すると、名前空間スコープのアクセスのみが意図されていた場合に、クラスター全体のアクセスを付与することにつながる可能性があります。
まとめ
RBACは、退屈で具体的に保つことで最も効果的に機能します。アプリケーションチームには名前空間スコープのロール、狭いサービスアカウント権限、レビューなしのワイルドカードなし、定期的なkubectl auth can-iチェックです。すべてのバインディングを本番コードとして扱います。Kubernetesクラスターでは、事実上そうだからです。