Kubernetes との Workload Identity 連携を構成する

このガイドでは、Workload Identity 連携を使用して、Azure Kubernetes Service(AKS)、Amazon Elastic Kubernetes Service、またはセルフホストの Kubernetes クラスタで実行されるワークロードを Google Cloud で認証できるようにする方法について説明します。

Kubernetes では、ワークロードが予測ボリュームから Kubernetes ServiceAccount トークンを取得できるように、クラスタを構成できます。Workload Identity 連携を設定すると、ワークロードはこれらの Kubernetes ServiceAccount トークンで Google Cloud への認証ができるようになります。

GKE を使用している場合は、Workload Identity 連携を構成する代わりに Workload Identity Federation for GKE を使用します。

始める前に

Workload Identity 連携を構成する前に、Kubernetes クラスタが次の条件を満たしていることを確認してください。

GKE

Google Kubernetes Engine(GKE)ユーザーの場合は、GKE ワークロードから Google Cloud APIs に対する認証を行うをご覧ください。

AKS

クラスタが次の条件を満たしていることを確認します。

  • OIDC 発行者機能を有効にしている。

    Workload Identity 連携が OpenID Connect メタデータとクラスタの JSON Web Key Set(JWKS)にアクセスできるように、この機能を有効にする必要があります。

EKS

EKS 構成を変更する必要はありません。

Kubernetes

クラスタが次の条件を満たしていることを確認します。

  • Kubernetes 1.20 以降を実行している。

    以前のバージョンの Kubernetes では、このドキュメントの手順と互換性のない別の ServiceAccount トークン形式が使用されていました。

  • ServiceAccount トークン ボリュームの予測をサポートするように kube-apiserver を構成している。

クラスタにインターネット経由でアクセスできるようにする必要はありません。

Workload Identity 連携を構成する

この手順は、各 Kubernetes クラスタに対して 1 回ずつ実行すれば十分です。これにより、複数の Kubernetes Pod と複数の Google Cloud プロジェクトで同じ Workload Identity のプールとプロバイダを使用できます。

Workload Identity 連携の構成を開始するには、次の操作を行います。

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  2. Workload Identity のプールとプロバイダの管理に専用のプロジェクトを使用することをおすすめします。
  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the IAM, Resource Manager, Service Account Credentials, and Security Token Service APIs.

    Enable the APIs

属性のマッピングと条件を定義する

Kubernetes ServiceAccount トークンには、次のような複数のクレームが含まれています。

  • sub: ServiceAccount の Namespace と名前(例: system:serviceaccount:NAMESPACE:KSA_NAME)が含まれます。ここで、NAMESPACE は ServiceAccount の Namespace、KSA_NAME は ServiceAccount の名前です。
  • "kubernetes.io".namespace: ServiceAccount の Namespace が含まれます。
  • "kubernetes.io".serviceaccount.name: ServiceAccount の名前が含まれます。
  • "kubernetes.io".pod.name: Pod の名前が含まれます。

Google Cloud で sub をサブジェクト識別子(google.subject)として使用するには、次のマッピングを使用します。

google.subject=assertion.sub

必要に応じて、追加の属性をマッピングできます。これにより、リソースへのアクセス権を付与する際にこれらの属性を参照できます。例:

google.subject=assertion.sub,
attribute.namespace=assertion['kubernetes.io']['namespace'],
attribute.service_account_name=assertion['kubernetes.io']['serviceaccount']['name'],
attribute.pod=assertion['kubernetes.io']['pod']['name']

必要に応じて、属性条件を定義します。属性条件は、アサーション属性とターゲット属性をチェックする CEL 式です。特定の認証情報の属性条件が true と評価されると、認証情報が受け入れられます。それ以外の場合、認証情報は拒否されます。

属性条件を使用して、Workload Identity 連携で有効期間の短い Google Cloud トークンを取得できる Kubernetes ServiceAccount を制限できます。たとえば、次の条件は、backend Namespace と monitoring Namespace からの Kubernetes ServiceAccount へのアクセスを制限します。

assertion['kubernetes.io']['namespace'] in ['backend', 'monitoring']

Workload Identity のプールとプロバイダを作成する

必要なロール

Workload Identity 連携の構成に必要な権限を取得するため、プロジェクトに対して次の IAM ロールを付与するよう管理者に依頼してください。

ロールの付与については、プロジェクト、フォルダ、組織へのアクセス権の管理をご覧ください。

必要な権限は、カスタムロールや他の事前定義ロールから取得することもできます。

また、IAM オーナー(roles/owner)の基本ロールには ID 連携を構成する権限も含まれています。本番環境では基本ロールを付与すべきではありません。基本ロールは、開発環境またはテスト環境で付与してください。

Workload Identity のプールとプロバイダを作成する手順は次のとおりです。

AKS

  1. AKS クラスタの発行元 URL を確認します。

    az aks show -n NAME -g RESOURCE_GROUP --query "oidcIssuerProfile.issuerUrl" -otsv
    

    次のように置き換えます。

    • NAME: クラスタの名前
    • RESOURCE_GROUP: クラスタのリソース グループ

    このコマンドによって発行元の URL が出力されます。次のいずれかの手順で発行元の URL が必要になります。

    コマンドで発行元の URL が返されない場合は、OIDC 発行者機能が有効になっていることを確認します。

  2. Workload Identity プールを新規作成します。

    gcloud iam workload-identity-pools create POOL_ID \
        --location="global" \
        --description="DESCRIPTION" \
        --display-name="DISPLAY_NAME"
    

    次のように置き換えます。

    • POOL_ID: プールの一意の ID。
    • DISPLAY_NAME: プールの名前。
    • DESCRIPTION: 選択したプールの説明。この説明は、プール ID へのアクセス権を付与するときに表示されます。
  3. AKS クラスタを Workload Identity プール プロバイダとして追加します。

    gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \
        --location="global" \
        --workload-identity-pool="POOL_ID" \
        --issuer-uri="ISSUER" \
        --attribute-mapping="MAPPINGS" \
        --attribute-condition="CONDITIONS"
    

    次のように置き換えます。

    • PROVIDER_ID: 一意の Workload Identity プール プロバイダ ID。
    • POOL_ID: 前に作成した Workload Identity プール ID。
    • ISSUER: 前に確認した発行元 URI。
    • MAPPINGS: このガイドの前半で作成した属性マッピングのカンマ区切りリスト。
    • CONDITIONS: このガイドの前半で作成した属性条件。属性条件がない場合は、パラメータを削除します。

EKS

  1. EKS クラスタの発行元 URL を確認します。

    aws eks describe-cluster --name NAME --query "cluster.identity.oidc.issuer" --output text
    

    NAME は、クラスタの名前に置き換えます。

    このコマンドによって発行元の URL が出力されます。次のいずれかの手順で発行元の URL が必要になります。

  2. Workload Identity プールを新規作成します。

    gcloud iam workload-identity-pools create POOL_ID \
        --location="global" \
        --description="DESCRIPTION" \
        --display-name="DISPLAY_NAME"
    

    次のように置き換えます。

    • POOL_ID: プールの一意の ID。
    • DISPLAY_NAME: プールの名前。
    • DESCRIPTION: 選択したプールの説明。この説明は、プール ID へのアクセス権を付与するときに表示されます。
  3. EKS クラスタを Workload Identity プール プロバイダとして追加します。

    gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \
        --location="global" \
        --workload-identity-pool="POOL_ID" \
        --issuer-uri="ISSUER" \
        --attribute-mapping="MAPPINGS" \
        --attribute-condition="CONDITIONS"
    

    次のように置き換えます。

    • PROVIDER_ID: 一意の Workload Identity プール プロバイダ ID。
    • POOL_ID: 前に作成した Workload Identity プール ID。
    • ISSUER: 前に確認した発行元 URI。
    • MAPPINGS: このガイドの前半で作成した属性マッピングのカンマ区切りリスト。
    • CONDITIONS: このガイドの前半で作成した属性条件。属性条件がない場合は、パラメータを削除します。

Kubernetes

  1. Kubernetes クラスタに接続し、kubectl を使用してクラスタの発行元 URL を確認します。

    kubectl get --raw /.well-known/openid-configuration | jq -r .issuer
    

    次のいずれかの手順で発行元の URL が必要になります。

  2. クラスタの JSON Web Key Set(JWKS)をダウンロードします。

    kubectl get --raw /openid/v1/jwks > cluster-jwks.json
    

    次のいずれかの手順で JWKS をアップロードして、Workload Identity 連携によりクラスタで発行された Kubernetes ServiceAccount トークンの信頼性を確認できるようにします。

  3. Workload Identity プールを新規作成します。

    gcloud iam workload-identity-pools create POOL_ID \
        --location="global" \
        --description="DESCRIPTION" \
        --display-name="DISPLAY_NAME"
    

    次のように置き換えます。

    • POOL_ID: プールの一意の ID。
    • DISPLAY_NAME: プールの名前。
    • DESCRIPTION: 選択したプールの説明。この説明は、プール ID へのアクセス権を付与するときに表示されます。
  4. Kubernetes クラスタを Workload Identity プールのプロバイダとして追加し、クラスタの JWKS をアップロードします。

    gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \
        --location="global" \
        --workload-identity-pool="POOL_ID" \
        --issuer-uri="ISSUER" \
        --attribute-mapping="MAPPINGS" \
        --attribute-condition="CONDITIONS" \
        --jwk-json-path="cluster-jwks.json"
    

    次のように置き換えます。

    • PROVIDER_ID: 一意の Workload Identity プール プロバイダ ID。
    • POOL_ID: 前に作成した Workload Identity プール ID。
    • ISSUER: 前に確認した発行元 URI。
    • MAPPINGS: このガイドの前半で作成した属性マッピングのカンマ区切りリスト。
    • CONDITIONS: このガイドの前半で作成した属性条件。属性条件がない場合は、パラメータを削除します。

Kubernetes ワークロードへのアクセス権を付与する

このセクションでは、Workload Identity 連携のリソースへの直接アクセスまたはサービス アカウントの権限借用を使用して、Google Cloud APIs にアクセスするように Kubernetes ワークロードを構成する方法について説明します。

この手順は、Google Cloud にアクセスする必要がある Kubernetes ワークロードごとに 1 回行う必要があります。

Workload Identity 連携を使用することをおすすめします。ただし、ID 連携を使用すると、一部の API メソッドに制限が適用される場合があります。制限事項の一覧については、ID 連携: プロダクトと制限事項をご覧ください。

ワークロードで使用しているメソッドにこのような制限がある場合は、代わりに IAM の権限借用を使用できます。

Workload Identity 連携を使用してリソースへの直接アクセス権を付与する

このセクションでは、Workload Identity 連携を使用して Kubernetes ServiceAccount に IAM ロールを付与し、Google Cloud リソースに直接アクセスできるようにします。

Kubernetes ServiceAccount を作成してロールを付与するには、次の操作を行います。

  1. Kubernetes ServiceAccount を作成します。

    kubectl create serviceaccount KSA_NAME --namespace NAMESPACE
    

    次のように置き換えます。

    • KSA_NAME: ServiceAccount の名前。
    • NAMESPACE: ServiceAccount を作成する Namespace。
  2. Google Cloud リソースの Kubernetes ServiceAccount に IAM アクセス権を付与します。

    最小権限の原則に従い、アプリケーションがアクセスする必要があるリソースに固有のロールのみを付与することをおすすめします。

    次の例では、作成した ServiceAccount に Kubernetes Engine クラスタ閲覧者roles/container.clusterViewer)のロールを付与します。このコマンドは、前述のマッピングしたサブジェクトを使用します。

    gcloud projects add-iam-policy-binding projects/PROJECT_ID \
        --role=roles/container.clusterViewer \
        --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/MAPPED_SUBJECT \
        --condition=None
    

    次のように置き換えます。

    • PROJECT_NUMBER: プロジェクト ID に関連付けられている数値の Google Cloud プロジェクト番号。

    • POOL_ID: Workload Identity プール ID。

    • MAPPED_SUBJECT: google.subject にマッピングした ID トークンのクレームから取得した Kubernetes ServiceAccount。たとえば、google.subject=assertions.sub をマッピングし、ID トークンに "sub": "system:serviceaccount:default:my-kubernetes-serviceaccount" が含まれている場合、MAPPED_SUBJECTsystem:serviceaccount:default:my-kubernetes-serviceaccount です。

    IAM 許可ポリシーをサポートする任意の Google Cloud リソースにロールを付与できます。プリンシパル ID の構文は、Kubernetes リソースによって異なります。サポートされている ID のリストについては、Workload Identity Federation for GKE のプリンシパル ID をご覧ください。

Kubernetes ServiceAccount を使用して、アクセス権を付与した Google Cloud リソースにアクセスするワークロードをデプロイできます。

代替手段: IAM サービス アカウントの権限借用を使用してアクセス権を付与する

IAM サービス アカウントの権限借用を使用するように Kubernetes ServiceAccount を構成する手順は次のとおりです。

  1. Kubernetes ServiceAccount をまだ作成していない場合は、作成します。

    kubectl create serviceaccount KSA_NAME --namespace NAMESPACE
    

    次のように置き換えます。

    • KSA_NAME: ServiceAccount の名前
    • NAMESPACE: ServiceAccount を作成する Namespace。
  2. ワークロードを表す IAM サービス アカウントを作成します。

    サービス アカウントは、Workload Identity プールと同じプロジェクトにある必要はありませんが、参照するときにサービス アカウントを含むプロジェクトを指定する必要があります。

    gcloud iam service-accounts create IAM_SA_NAME \
        --project=IAM_SA_PROJECT_ID
    

    次のように置き換えます。

    • IAM_SA_NAME: サービス アカウントの名前
    • IAM_SA_PROJECT_ID: サービス アカウントのプロジェクト ID
  3. Kubernetes ワークロードにアクセスを許可する特定の Google Cloud リソースに対する IAM サービス アカウントのアクセス権を付与します。

    gcloud projects add-iam-policy-binding IAM_SA_PROJECT_ID \
        --member="serviceAccount:IAM_SA_NAME@IAM_SA_PROJECT_ID.iam.gserviceaccount.com" \
        --role="ROLE"
    

    次のように置き換えます。

    • IAM_SA_PROJECT_ID: サービス アカウントを作成したプロジェクトの ID
    • IAM_SA_NAME: サービス アカウントの名前
    • ROLE: ロールの名前。例: roles/container.clusterViewer
  4. Kubernetes ServiceAccount に IAM サービス アカウントの権限借用を許可します。

    gcloud iam service-accounts add-iam-policy-binding \
      IAM_SA_NAME@IAM_SA_PROJECT_ID.iam.gserviceaccount.com \
        --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/MAPPED_SUBJECT" \
        --role=roles/iam.workloadIdentityUser
    
    

    次のように置き換えます。

    • IAM_SA_NAME: サービス アカウントの名前
    • PROJECT_ID: Kubernetes を実行するプロジェクトの ID
    • IAM_SA_PROJECT_NUMBER: サービス アカウントを作成したプロジェクトのプロジェクト番号
    • POOL_ID: Workload Identity プール ID。
    • MAPPED_SUBJECT: google.subject にマッピングした ID トークンのクレームから取得した Kubernetes ServiceAccount。たとえば、google.subject=assertions.sub をマッピングし、ID トークンに "sub": "system:serviceaccount:default:my-kubernetes-serviceaccount" が含まれている場合、MAPPED_SUBJECTsystem:serviceaccount:default:my-kubernetes-serviceaccount です。

    IAM サービス アカウントから Google Cloud APIs へのアクセスを承認する方法については、サービス アカウントについてをご覧ください。

これで、Kubernetes ServiceAccount と IAM サービス アカウントを使用して、アクセスを許可した Google Cloud リソースにアクセスするワークロードをデプロイできるようになりました。

Kubernetes ワークロードをデプロイする

Google Cloud リソースにアクセスできる Kubernetes ワークロードをデプロイするには、次の操作を行います。

  1. 認証情報構成ファイルを作成します。

    gcloud iam workload-identity-pools create-cred-config \
        projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \
        --service-account=SERVICE_ACCOUNT_EMAIL \
        --credential-source-file=/var/run/service-account/token \
        --credential-source-type=text \
        --output-file=credential-configuration.json

    次のように置き換えます。

    • PROJECT_NUMBER: Workload Identity プールを含むプロジェクトのプロジェクト番号
    • POOL_ID: Workload Identity プールの ID
    • PROVIDER_ID: Workload Identity プール プロバイダの ID
    • SERVICE_ACCOUNT_EMAIL: IAM サービス アカウントの権限借用を使用するように Kubernetes ServiceAccount を構成した場合は、サービス アカウントのメールアドレス。リソースへの直接アクセスを使用するように Kubernetes ServiceAccount を構成した場合は、このフラグを省略します。

    認証情報の構成ファイルを使用すると、Cloud クライアント ライブラリ、gcloud CLI、Terraform で次の情報を確認できます。

    • 外部認証情報の取得元
    • 使用する Workload Identity プールとプロバイダ
    • 権限を借用するサービス アカウント
  2. 認証情報構成ファイルを ConfigMap としてインポートします。

    kubectl create configmap CONFIGMAP_NAME \
      --from-file credential-configuration.json \
      --namespace NAMESPACE
    

    次のように置き換えます。

    • CONFIGMAP_NAME: ConfigMap の名前。
    • NAMESPACE: ConfigMap を作成する Namespace。
  3. ワークロードをデプロイして、Kubernetes ServiceAccount と ConfigMap を使用できるようにします。

    マニフェストを作成して次のように構成します。

    • ワークロードがローカル ファイルから Kubernetes ServiceAccount トークンを取得できるように、予測されたトークン ボリュームをマウントします。Kubernetes ServiceAccount トークンが、Workload Identity プール プロバイダが想定するオーディエンスを使用するように、ボリュームを構成します。
    • ワークロードが Workload Identity 連携を使用するために必要な構成にアクセスできるように、認証情報の構成ファイルを含む ConfigMap をマウントします。
    • ワークロードがファイルを検出できるように、認証情報の構成ファイルのパスを含む環境変数 GOOGLE_APPLICATION_CREDENTIALS を追加します。

    Kubernetes ServiceAccount と ConfigMap を使用して Google Cloud CLI が Google Cloud に対して認証されるようにするマニフェストの例を次に示します。

    apiVersion: v1
    kind: Pod
    metadata:
      name: example
      namespace: NAMESPACE
    spec:
      containers:
      - name: example
        image: google/cloud-sdk:alpine
        command: ["/bin/sh", "-c", "gcloud auth login --cred-file $GOOGLE_APPLICATION_CREDENTIALS && gcloud auth list && sleep 600"]
        volumeMounts:
        - name: token
          mountPath: "/var/run/service-account"
          readOnly: true
        - name: workload-identity-credential-configuration
          mountPath: "/etc/workload-identity"
          readOnly: true
        env:
        - name: GOOGLE_APPLICATION_CREDENTIALS
          value: "/etc/workload-identity/credential-configuration.json"
    
      serviceAccountName: KSA_NAME
      volumes:
      - name: token
        projected:
          sources:
          - serviceAccountToken:
              audience: https://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID
              expirationSeconds: 3600
              path: token
      - name: workload-identity-credential-configuration
        configMap:
          name: CONFIGMAP_NAME

    同じ方法で、次のいずれかのクライアント ライブラリを使用するツールとワークロードで認証情報を自動的に検索できます。

    C++

    C++ 用 Google Cloud クライアント ライブラリは、バージョン v2.6.0 から Workload Identity 連携をサポートしています。Workload Identity 連携を使用するには、バージョン 1.36.0 以降の gRPC でクライアント ライブラリをビルドする必要があります。

    Go

    Go 用クライアント ライブラリは、golang.org/x/oauth2 モジュールのバージョン v0.0.0-20210218202405-ba52d332ba99 以降を使用している場合、Workload Identity 連携をサポートします。

    クライアント ライブラリが使用しているこのモジュールのバージョンを確認するには、次のコマンドを実行します。

    cd $GOPATH/src/cloud.google.com/go
    go list -m golang.org/x/oauth2
    

    Java

    Java 用クライアント ライブラリは、com.google.auth:google-auth-library-oauth2-http アーティファクトのバージョン 0.24.0 以降を使用している場合、Workload Identity 連携をサポートします。

    クライアント ライブラリで使用しているこのアーティファクトのバージョンを確認するには、アプリケーション ディレクトリで次の Maven コマンドを実行します。

    mvn dependency:list -DincludeArtifactIds=google-auth-library-oauth2-http
    

    Node.js

    Node.js 用クライアント ライブラリは、google-auth-library パッケージのバージョン 7.0.2 以降を使用している場合、Workload Identity 連携をサポートします。

    クライアント ライブラリで使用されているこのパッケージのバージョンを確認するには、アプリケーション ディレクトリで次のコマンドを実行します。

    npm list google-auth-library
    

    GoogleAuth オブジェクトを作成するときに、プロジェクト ID を指定できます。また、GoogleAuth で自動的にプロジェクト ID を検出することもできます。プロジェクト ID を自動的に検出するには、構成ファイルのサービス アカウントに、プロジェクト上でブラウザのロール(roles/browser)または同等の権限を持つロールが付与されている必要があります。詳細については、google-auth-library パッケージの README をご覧ください。

    Python

    Python 用クライアント ライブラリは、google-auth パッケージのバージョン 1.27.0 以降を使用している場合、Workload Identity 連携をサポートします。

    クライアント ライブラリで使用されているこのパッケージのバージョンを確認するには、パッケージがインストールされている環境で次のコマンドを実行します。

    pip show google-auth
    

    認証クライアントのプロジェクト ID を指定するには、GOOGLE_CLOUD_PROJECT 環境変数を設定するか、クライアントがプロジェクト ID を自動的に検出するようにします。プロジェクト ID を自動的に検出するには、構成ファイルのサービス アカウントに、プロジェクト上でブラウザのロール(roles/browser)または同等の権限を持つロールが付与されている必要があります。詳細については、google-auth パッケージのユーザーガイドをご覧ください。

    gcloud

    Workload Identity 連携を使用して認証するには、gcloud auth login コマンドを使用します。

    gcloud auth login --cred-file=FILEPATH.json
    

    FILEPATH は、認証情報の構成ファイルのパスに置き換えます。

    gcloud CLI での Workload Identity 連携は、gcloud CLI のバージョン 363.0.0 以降でサポートされています。

    Terraform

    バージョン 3.61.0 以降を使用している場合、Google Cloud プロバイダは Workload Identity 連携をサポートしています。

    terraform {
      required_providers {
        google = {
          source  = "hashicorp/google"
          version = "~> 3.61.0"
        }
      }
    }
    

    bq

    Workload Identity 連携を使用して認証するには、次のように gcloud auth login コマンドを使用します。

    gcloud auth login --cred-file=FILEPATH.json
    

    FILEPATH は、認証情報の構成ファイルのパスに置き換えます。

    bq での Workload Identity 連携は、gcloud CLI のバージョン 390.0.0 以降でサポートされています。

  4. 必要に応じて、次のコマンドを実行して、認証が正しく機能することを確認します。

    kubectl exec example --namespace NAMESPACE -- gcloud auth print-access-token

次のステップ