ロールベースのアクセス制御

このページでは、Kubernetes が提供するロールベースのアクセス制御(RBAC)システムの概要と、Google Kubernetes Engine(GKE)で Kubernetes RBAC を使用する方法について説明します。

概要

Kubernetes にはロールベースのアクセス制御(RBAC)メカニズムが組み込まれています。このメカニズムを使用すると、権限セットを構成し、特定の Google Cloud ユーザーまたはユーザー グループがクラスタやクラスタの特定の Namespace 内にある Kubernetes オブジェクトを操作する方法を定義できます。

Kubernetes RBAC はデフォルトで有効になっています。

始める前に

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

次のいずれかの方法で gcloud のデフォルトの設定を指定します。

  • gcloud init。デフォルトの設定全般を確認する場合に使用します。
  • gcloud config。プロジェクト ID、ゾーン、リージョンを個別に設定する場合に使用します。

gcloud init の使用

エラー One of [--zone, --region] must be supplied: Please specify location を受信した場合は、このセクションの内容を実施します。

  1. gcloud init を実行して、次の操作を行います。

    gcloud init

    リモート サーバーで SSH を使用している場合は、--console-only フラグを指定して、コマンドがブラウザを起動しないようにします。

    gcloud init --console-only
  2. 手順に従って gcloud を承認し、Google Cloud アカウントを使用します。
  3. 新しい構成を作成するか、既存の構成を選択します。
  4. Google Cloud プロジェクトを選択します。
  5. デフォルトの Compute Engine ゾーンを選択します。

gcloud config の使用

  • デフォルトのプロジェクト ID を設定します。
    gcloud config set project project-id
  • ゾーンクラスタを使用する場合は、デフォルトのコンピューティング ゾーンを設定します。
    gcloud config set compute/zone compute-zone
  • リージョン クラスタを使用する場合は、デフォルトのコンピューティング リージョンを設定します。
    gcloud config set compute/region compute-region
  • gcloud を最新バージョンに更新します。
    gcloud components update

Identity and Access Management とのやり取り

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

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

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

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

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

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

v1.11.x 以前の GKE クラスタで Kubernetes RBAC を使用する場合の前提条件

GKE v1.11.x 以前の GKE クラスタでは、Cloud IAM は Kubernetes RBAC のRole または ClusterRole を作成する権限を付与できません。ただし、Cloud IAM ロールの Kubernetes Engine 管理者を使用すると、Kubernetes RBAC の RoleBinding または ClusterRoleBinding の作成権限を任意のユーザー(自身を含む)に付与できます。これにより、Google Cloud ユーザーを事前定義の RBAC ロールにバインドできます。

事前定義の cluster-admin RBAC ロールは、クラスタに対する完全な権限をユーザーに付与します。したがって、RBAC の Role と ClusterRole を作成できるようにユーザーをブートストラップするには、次のコマンドを実行します。user-account は、対象ユーザーの Google Cloud ログイン メールアドレスに置き換えます。

kubectl create clusterrolebinding cluster-admin-binding \
  --clusterrole cluster-admin \
  --user user-account

GKE 向け Google グループ

以前は、Google Cloud のユーザー アカウントまたは Cloud IAM サービス アカウントにのみロールを付与できました。GKE 向け Google グループ(ベータ版)では、G Suite Google グループのメンバーにロールを付与できます。このメカニズムでは、ユーザーとグループは Kubernetes や Cloud Console の外部から G Suite 管理者によって管理されるので、クラスタ管理者がユーザーの詳細情報を維持する必要はありません。また、既存のユーザー アカウント管理機能と連携することもできます。たとえば、社員が退職したときに、そのユーザーのアクセス権を取り消すことができます。

この機能を使用するには、次のタスクを行います。

要件

GKE 向け Google グループを使用するには、次の要件があります。

  • G Suite または Cloud Identity のサブスクリプションが必要です。

RBAC で使用する Google グループの構成

この機能を使用するクラスタの構成方法と Kubernetes RBAC で G Suite Google グループを参照する構文については、このトピックの後半で説明します。まず、次の手順で Google グループを設定します。

  1. ドメインに、gke-security-groups@yourdomain.com という名前の G Suite Google グループを作成します。グループ名は gke-security-groups にする必要があります。gke-security-groups グループにグループ メンバーに対するメンバーの表示権限があることを確認します。G Suite 管理コンソールで設定する方法については、こちらの記事をご覧ください。

    G Suite でのグループの管理については、グループ ヘルプセンターをご覧ください。

  2. クラスタに別の権限を持つユーザー グループまたはグループを作成します(まだ存在しない場合)。各グループには、グループ メンバーに対するメンバーの表示権限が必要です。

  3. これらのグループ(ユーザーではありません)を gke-security-groups@yourdomain.com のメンバーシップに追加します。

クラスタのリソースを作成、変更、表示する権限がグループのメンバーシップに基づいてユーザーに付与されているかどうか確認するため、GKE は、ユーザーがアクセス権を持つグループのメンバーかどうか、およびグループがドメインの gke-security-groups グループの直接的なメンバーかどうかを確認します。ユーザーは、グループおよびクラスタと同じドメインに属している必要があります。つまり、クロスドメインの承認はこの機能では使用できません。

G Suite Google グループのメンバーシップに関する情報は、しばらくの間キャッシュに保存されます。グループのメンバーシップに対する変更がすべてのクラスタに反映されるまでに数分かかることがあります。グループの変更によるレイテンシに加えて、クラスタ上のユーザー認証情報の標準的なキャッシュは約 1 時間です。

GKE 向け Google グループを使用するクラスタの構成

G Suite Google グループ管理者がグループを設定したら、gcloud コマンドで新しいクラスタを作成します。--security-group="gke-security-groups@yourdomain.com" フラグを追加して独自のドメイン名を指定します。

以下に、cluster create コマンドの例を示します。

gcloud beta container clusters create cluster-name \
  --security-group="gke-security-groups@yourdomain.com"

これで、G Suite Google グループを参照する Role、ClusterRole、RoleBinding、ClusterRoleBinding を作成できます。

権限の定義と割り当て

RBAC 権限を定義するには、次の種類の Kubernetes オブジェクトを作成します。

  • ClusterRole または Role: リソースタイプとオペレーションのセットを定義します。これは、クラスタ内のユーザーまたはユーザー グループ(ClusterRole の場合)または名前空間(Role)に割り当てることができますが、ユーザーまたはユーザー グループは指定しません。
  • ClusterRoleBinding または RoleBinding: ユーザーまたはユーザー グループに ClusterRole または Role を割り当てます。ClusterRoleBinding は ClusterRole と一緒に使用し、RoleBinding は ClusterRole または Role と一緒に使用します。

RBAC ロールは純粋に付加的なものであり、「拒否」ルールはありません。RBAC ロールを構成するときは、クラスタ リソースへのアクセスをユーザーに「許可する」ことについて考える必要があります。

Role または ClusterRole を使用した権限の定義

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

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

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

RoleClusterRole

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

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

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

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

Subject のタイプ kind の値 name の値
Google Cloud ユーザー アカウント User Google Cloud の登録済みメールアドレス
Kubernetes サービス アカウント ServiceAccount クラスタ内の Kubernetes ServiceAccount オブジェクトの名前
Cloud IAM サービス アカウント User 自動的に生成された Cloud IAM サービス アカウントのメールアドレス
確認済みドメインの G Suite Google グループのアドレス(ベータ版) Group Google グループ gke-security-groups@ yourdomain.com のメンバーになっている Google グループのメールアドレス。

次の RoleBinding は、ユーザー、Kubernetes サービス アカウント、Cloud 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
# Cloud IAM service account
- kind: User
  name: test-account@test-project-123456.google.com.iam.gserviceaccount.com
# G Suite Google Group
- kind: Group
  name: accounting-group@example.com
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

API の使用法と例

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

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

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

Google グループとの統合に関する問題のデバッグ

次の手順では、ログを表示して、クラスタが RBAC の RoleBinding で Google グループを使用するように正常に構成されているかどうかを検証できます。

要件

ログを調べる前に、次のことを確認してください。

  • 少なくとも 1 時間以上は、テスト対象のクラスタの操作(kubectl コマンドの実行など)をしていない。認証は 1 時間キャッシュされ、リクエストが発生したときにログに記録されるようにする必要があります。
  • gke-security-groups に含まれるグループの 1 つ以上のメンバーである。これにより、一部の Google グループ情報がログに入力されます。

ログの構成

ログを使用して RBAC で Google グループをデバッグするには、次の手順を行います。

  1. Google Cloud プロジェクトのデータアクセスロギングを有効にします。ロギングを有効にするには、次の手順を行います。

    1. Cloud Console で、[Cloud IAM]メニューの [監査ログ]ページに移動します。

      [監査ログ] ページに移動

    2. 表で、[Kubernetes Engine API]を選択します。

    3. [ログの種類]メニューで、次のいずれかを選択します。

      • 管理読み取り
      • データ読み取り
      • データ書き込み
    4. [保存] をクリックします。

    監査ロギングを有効にする方法の詳細については、Cloud 管理ツールのドキュメントの Cloud Console でのデータアクセス ログの構成をご覧ください。

  2. クラスタで kubectl を使用してコマンドを実行します。これは kubectl create ns helloworld のような簡単なコマンドで構いません。

  3. [ログビューア] ページでカスタムクエリを入力します。クエリを実行するには:

    1. Cloud Console で、[Logging] メニューの [ログビューア] ページに移動します。

      ログビューア ページに移動

    2. ページ上部の [クエリのプレビュー] ボックスにある矢印をクリックします。

    3. 表示されるプルダウン ボックスで、次のクエリをコピーして貼り付けます。

      resource.type="k8s_cluster"
      resource.labels.location="cluster-region"
      resource.labels.cluster_name="cluster-name"
      protoPayload.resourceName="authorization.k8s.io/v1beta1/subjectaccessreviews"
      protoPayload.response.spec.user="email-address"
      

      ここで

      • cluster-region は、クラスタのリージョンまたはゾーンです。
      • cluster-name は、クラスタの名前です。
      • email-address は、Google アカウントの登録メールアドレスです。
    4. [クエリを実行] を選択します。少なくとも 1 つの結果が表示されます。そうでない場合は、時間範囲を広げてみてください。

    5. 確認するクラスタを選択します。

    6. [ネストされたフィールドを展開] をクリックします。

    7. フィールド protoPayload.request.spec.group には、次のようなグループが含まれます。

      • gke-security-group のメンバーであるグループ。
      • 自分自身がメンバーであるグループ。

      このリストは、メンバーになっているグループのセットと一致する必要があります。グループが存在しない場合は、グループの設定方法に問題がある可能性があります。

  4. 必要に応じて、データアクセス ロギングを以前の設定に戻します。

制限事項

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

デフォルトの検出ロール

クラスタは、デフォルトの ClusterRole と ClusterRoleBinding のセットで作成されます。有効な認証情報で行われたリクエストは system:authenticated グループに配置され、それ以外のリクエストは system:unauthenticated に配置されます。バージョン 1.14 以前の Kubernetes では、system:authenticatedsystem:unauthenticated の両方がデフォルトで system:basic-usersystem:discovery の ClusterRole を付与します。

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

Kubernetes 1.14 では、匿名ユーザー(system:unauthenticated)に system:basic-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
    

次のステップ