ロールベース アクセス制御を使用してクラスタ内でのアクションを認可する


このページでは、Kubernetes に組み込まれたロールベース アクセス制御(RBAC)メカニズムを使用して、Google Kubernetes Engine(GKE)クラスタ内のリソースに対するアクションを認可する方法について説明します。

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

始める前に

作業を始める前に、次のことを確認してください。

  • Google Kubernetes Engine API を有効にする。
  • Google Kubernetes Engine API の有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。すでに gcloud CLI をインストールしている場合は、gcloud components update を実行して最新のバージョンを取得する。

Identity and Access Management とのやり取り

GKE クラスタへのアクセス制御には、Identity and Access Management(IAM) Kubernetes RBAC の両方を使用できます。

  • IAM は Kubernetes 固有のものではなく、複数の Google Cloud プロダクトの ID 管理を行います。基本的に、Google Cloud プロジェクトのレベルで機能します。

  • Kubernetes RBAC は Kubernetes のコア コンポーネントです。これにより、ロール(権限のセット)を作成してクラスタ内のオブジェクトやオブジェクト タイプに付与できます。

  • アクションを認可するために、GKE はまず RBAC ポリシーを確認します。RBAC ポリシーがない場合、GKE は IAM 権限を確認します。

GKE では、IAM と Kubernetes RBAC が連携し、いずれかのツールにより、十分な権限があるユーザーに操作の実行を許可します。デフォルトでは、Google Cloud ユーザーには Kubernetes RBAC RoleBinding がないため、これは GKE クラスタのブートストラップで重要な部分となります。

Google Cloud アカウントを使用してユーザーを認証するには、これらのアカウントを使用して認証を行うようにクライアントが構成されている必要があります。たとえば、kubectl を使用する場合、認証を必要とするコマンドを実行する前に、Google Cloud で認証を行うように kubectl コマンドを構成する必要があります。

ほとんどの場合、IAM の代わりに Kubernetes RBAC を使用できます。GKE ユーザーには、少なくともクラスタを含むプロジェクトの container.clusters.get IAM 権限が必要です。この権限は、container.clusterViewer ロールだけでなく、より権限の高いロールにも含まれています。container.clusters.get 権限は、ユーザーがプロジェクトのクラスタに対する認証を行う場合に必要ですが、ユーザーがこれらのクラスタ内でアクションを実行することは許可されません。認可は、IAM または Kubernetes RBAC によって行われます。

権限を定義して割り当てる

次のように、ClusterRole オブジェクトと Role オブジェクトで RBAC ルールを定義してから、それらのルールを ClusterRoleBinding オブジェクトと RoleBinding オブジェクトに割り当てることができます。

  • クラスタ ロール: リソースと許可されたオペレーションのクラスタレベルのグループ化のことで、RoleBinding または ClusterRoleBinding を使用してユーザーまたはグループに割り当てることができます。
  • ロール: リソースと許可されたオペレーションの名前空間のグループ化のことで、RoleBinding を使用してユーザーまたはユーザー グループに割り当てることができます。
  • クラスタ ロール バインディング: クラスタ内のすべての名前空間のユーザーまたはグループに ClusterRole を割り当てます。
  • ロール バインディング: Role または ClusterRole を特定の名前空間内のユーザーまたはグループに割り当てます。

RoleBinding を使用してユーザーまたはグループに ClusterRole を割り当てると、それらのユーザーとグループは、RoleBinding で指定した名前空間のリソースにのみアクセスできます。ユーザーまたはグループがすべての名前空間のリソースにアクセスできるようにするには、代わりに ClusterRoleBinding を使用します。

Role または ClusterRole を使用して権限を定義する

権限は、Role または ClusterRole オブジェクト内で定義します。ロールが 1 つの名前空間内のリソースに対するアクセス権を定義するのに対し、クラスタロールはクラスタ全体のリソースに対するアクセス権を定義します。

ロールとクラスタロールの構文は同じです。どちらにも rules セクションがあり、ここでは、ロールに対して、ルールによってオペレーションが適用され許可されたリソースを定義します。たとえば、次の Role は、accounting 名前空間のすべての Pod に対する読み取りアクセス権(getwatchlist)を付与します。

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: accounting
  name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

許可されているフィールドの詳細な一覧については、RoleClusterRole の API ドキュメントをご覧ください。

RoleClusterRole

クラスタロールによって付与される権限はクラスタ全体に適用されます。クラスタロールを使用すると、ロールの場合と異なる種類のリソースへのアクセスを制御できます。たとえば、次のようなものです。

  • ノードなどのクラスタ スコープのリソース
  • リソース以外の REST エンドポイント(/healthz など)
  • Namespace 全体の名前空間を指定されたリソース(Namespace に関係なく、クラスタ全体のすべての Pod)

RoleBinding または ClusterRoleBinding を使用してロールを割り当てる

Role または ClusterRole を作成したら、RoleBinding または ClusterRoleBinding を使用してユーザーまたはユーザー グループにロールを割り当てます。ユーザーとグループは subjects と呼ばれ、次のいずれかになります。

Subject のタイプ kind の値 name の値
Google Cloud ユーザー アカウント User Google Cloud の登録済みメールアドレス
Kubernetes サービス アカウント ServiceAccount クラスタ内の Kubernetes ServiceAccount オブジェクトの名前
IAM サービス アカウント User 自動的に生成された IAM サービス アカウントのメールアドレス
確認済みドメインの Google グループのアドレス Group gke-security-groups グループのメンバーである Google Workspace グループのメールアドレス。RBAC 向け Google グループの設定手順については、RBAC 向け Google グループを構成するをご覧ください。

次の RoleBinding は、ユーザー、Kubernetes サービス アカウント、IAM サービス アカウント、Google グループに pod-reader Role を割り当てます。

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: pod-reader-binding
  namespace: accounting
subjects:
# Google Cloud user account
- kind: User
  name: janedoe@example.com
# Kubernetes service account
- kind: ServiceAccount
  name: johndoe
# IAM service account
- kind: User
  name: test-account@test-project.iam.gserviceaccount.com
# Google Group
- kind: Group
  name: accounting-group@example.com
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

kubectl を使用して API アクセスを確認する

kubectl には、API 承認レイヤにすばやくクエリを実行するための auth can-i サブコマンドが用意されています。プラットフォーム管理者として、実行できる操作を決定するために、ユーザーになりすますことが必要な場合があります。auth can-i を使用して、追加の --as フラグを渡します。

--as フラグを指定せずに kubectl auth can-i コマンドを実行すると、Identity and Access Management(IAM)が認可を行います。一方、--as フラグを追加すると、Kubernetes RBAC が認可を行います。したがって、RBAC に必要な Role オブジェクトと RoleBinding オブジェクトを作成する必要があります。

詳細については、Checking API Access をご覧ください。

API の使用法と例

Kubernetes API を使用して RBAC に必要な RoleClusterRoleRoleBindingClusterRoleBinding オブジェクトを作成する方法については、Kubernetes ドキュメントのロールベース アクセス制御による承認をご覧ください。

トラブルシューティングとデバッグ

RBAC に関する問題をデバッグするには、管理アクティビティ監査ログを使用します。これはすべてのクラスタでデフォルトで有効になっています。十分な権限がないためにリソースまたはオペレーションへのアクセスが拒否される場合は、API サーバーで RBAC DENY エラーと、ユーザーの暗黙的および明示的なグループ メンバーシップなどの追加情報がログに記録されます。Google Groups for RBAC を使用している場合は、ログ メッセージに google groups が表示されます。

制限事項

以降のセクションでは、Kubernetes RBAC および IAM の使用でわかりにくい点について説明します。

デフォルトの検出ロール

クラスタは、デフォルトの ClusterRole と ClusterRoleBinding のセットで作成されます。有効な認証情報で行われたリクエストは system:authenticated グループに配置され、それ以外のリクエストは system:unauthenticated に配置されます。

system:basic-user ClusterRole を使用すると、SelfSubjectAccessReviews を作成してクラスタ内の権限をテストできます。system:discovery ロールを使用すると、クラスタに追加された CustomResourceDefinitions に関する情報を表示できるディスカバリ API を読み取ることができます。

匿名ユーザー(system:unauthenticated)は system:public-info-viewer ClusterRole を受け取ります。これにより、/healthz API と /version API への読み取り専用アクセス権が付与されます。

system:discovery ClusterRole で許可される API エンドポイントを確認するには、次のコマンドを実行します。

kubectl get clusterroles system:discovery -o yaml

Google Cloud VM インスタンスのサービス アカウントで発生する Forbidden エラー

VM インスタンスに userinfo-email スコープがない場合、次のエラーが発生することがあります。

Error from server (Forbidden): error when creating ... "role-name" is forbidden: attempt to grant extra privileges:...

たとえば、VM に cloud-platform スコープがあり、userinfo-email スコープがないとします。VM がアクセス トークンを取得すると、Google Cloud はそのトークンを cloud-platform のスコープに関連付けます。Kubernetes API サーバーがアクセス トークンに関連する ID を Google Cloud に確認すると、サービス アカウントのメールアドレスではなく、サービス アカウント固有の ID が返されます。

認証に成功するには、userinfo-email スコープの新しい VM を作成するか、一意の ID を使用する新しいロール バインディングを作成します。

userinfo-email スコープを持つ新しい VM インスタンスを作成するには、次のコマンドを実行します。

gcloud compute instances create INSTANCE_NAME \
    --service-account SERVICE_ACCOUNT_EMAIL \
    --scopes userinfo-email

すでに存在する VM のサービス アカウントの一意の ID を使用する新しいロール バインディングを作成するには、次の操作を行います。

  1. サービス アカウントの一意の ID を特定します。

    gcloud iam service-accounts describe SERVICE_ACCOUNT_EMAIL
    

    たとえば、次の出力では my-iam-account@somedomain.com サービス アカウントの uniqueId が表示されています。

    displayName: Some Domain IAM service account
    email: my-iam-account@somedomain.com
    etag: BwWWja0YfJA
    name: projects/project-name/serviceAccounts/my-iam-account@somedomain.com
    oauth2ClientId: '123456789012345678901'
    projectId: project-name
    uniqueId: '123456789012345678901'
    
  2. サービス アカウントの uniqueId を使用してロール バインディングを作成します。

    kubectl create clusterrolebinding CLUSTERROLEBINDING_NAME \
        --clusterrole cluster-admin \
        --user UNIQUE_ID
    

ロールとロール バインディングを作成または更新するための権限

Kubernetes では、次の条件を満たす場合にのみ、特定の権限を持つロールまたはロール バインディングを作成または更新できます。

  • ロールの作成または更新: ロールに付与する同じ権限を持っている必要があります。あるいは、ロールで escalate 動詞を実行する権限が必要です。
  • ロール バインディングの作成または更新: バインドされるロールに付与されている権限と、ロール バインディングと同じスコープが付与されている必要があります。あるいは、参照されるロールで bind 動詞を実行するための権限が必要です。

ロールで付与する権限が RBAC ではなく IAM 許可ポリシーを使用して最初に付与されている場合、ロールまたはロール バインディングのリクエストが失敗することがあります。たとえば、IAM 権限 container.pods.*container.roles.create が付与されたユーザーからの、次のロール作成リクエストについて考えてみます。

kubectl create role allowed-to-view-pods --resource pods --verb list,get

IAM を使用して、ユーザーにこれらの権限のみが付与されていた場合、次のエラーが発生する可能性があります。

Error from server (Forbidden): clusterroles.rbac.authorization.k8s.io "allowed-to-view-pods" is forbidden:
user "caller@example.com" (groups=["system:authenticated"]) is attempting to grant RBAC permissions not currently held:
{APIGroups:[""], Resources:["pods"], Verbs:["list" "get"]}

この制限を緩和するには、IAM ではなく RBAC を使用して、呼び出し元にこのロールの権限を付与します。

代わりに、RBAC または IAM を使用して、呼び出し元に escalate 動詞、bind 動詞、またはそれらの両方を付与できます。ただし、呼び出し元は任意のロールに任意の権限を付与可能になるため、GKE ではこの方法はおすすめしません。

次のステップ