GKE 用のマネージド ワークロード ID 認証を構成する

このドキュメントでは、GKE フリート管理クラスタで Google Kubernetes Engine(GKE)のマネージド Workload Identity を構成する方法について説明します。また、ワークロードをデプロイし、ワークロードの ID と証明書を検証する方法についても説明します。

GKE 用マネージド Workload Identity を設定して使用する手順は次のとおりです。

  1. マネージド ワークロード ID の証明書を発行するように Certificate Authority Service を構成します

  2. CA を Workload Identity プールにバインドします

  3. マネージド ワークロード ID に CA プールの証明書に対するリクエストを許可します。

  4. マネージド ワークロード ID を使用してワークロードをデプロイする

Google マネージド Workload Identity プール

クラスタを GKE フリートに追加すると、フリートは自動的に Google マネージド Workload Identity プールを作成します。このプールは、信頼ドメインのルートとして機能します。Google マネージド Workload Identity プールには次の制約があります。

  • Google がプールを完全に管理するため、名前空間、ID、ID プロバイダなどのサブリソースを作成することはできません。

  • このプールは GKE ワークロードにのみ使用できます。Compute Engine VM などの他のタイプのワークロードをプールに追加することはできません。

  • プール内のすべてのクラスタには、標準の Kubernetes 名前空間同一性モデルが適用されます。つまり、プール内のすべてのクラスタは同等の権限を持つことになります。プール内のいずれかのクラスタで実行されるワークロードは、プール内の任意の ID を使用できます。

マルチプロジェクト構成

このドキュメントで使用するTrusted Cloud リソース(GKE クラスタ、ルート CA、下位 CA など)は、別々のプロジェクトに存在できます。これらのリソースを参照する場合は、--project フラグを使用して、各リソースの正しいプロジェクトを指定します。

始める前に

  1. Create or select a Trusted Cloud project.

    • Create a Trusted Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Trusted Cloud project you are creating.

    • Select the Trusted Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Trusted Cloud project name.

  2. マネージド ワークロード ID について理解する。

  3. 少なくとも 1 つの GKE クラスタがあることを確認する。クラスタでバージョン 1.33.0-gke.2248000 以降が実行されていることを確認する。

  4. クラスタを GKE フリートに追加する。クラスタが Autopilot の場合は、--enable-workload-identity を省略します。フリートは、信頼ドメインとして機能する Google マネージド Workload Identity プールを自動的に作成します。

    次のコマンドを実行して、GKE フリートを有効にします。

    gcloud container clusters update CLUSTER_NAME \
        --workload-pool=PROJECT_ID.svc.id.goog \
        --enable-fleet \
        --fleet-project=PROJECT_ID
    

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

    • CLUSTER_NAME: GKE フリートに登録する GKE クラスタの名前
    • PROJECT_ID: GKE フリート ホスト プロジェクト ID
  5. Enable the IAM and Certificate Authority Service APIs:

    gcloud services enable cloudresourcemanager.googleapis.com iam.googleapis.com privateca.googleapis.com

  6. 課金と割り当てのプロジェクトを使用するように Google Cloud CLI を構成します。

    gcloud config set billing/quota_project PROJECT_ID
    

    PROJECT_ID は、フリート プロジェクトの ID に置き換えます。

必要なロール

マネージド ワークロード ID を作成し、マネージド ワークロード ID 証明書をプロビジョニングするために必要な権限を取得するには、プロジェクトに対する次の IAM ロールを付与するよう管理者に依頼してください。

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

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

マネージド ワークロード ID の証明書を発行するように CA Service を構成する

GKE 用にマネージド ワークロード ID を構成するには、まず認証局(CA)と 1 つ以上の下位 CA を構成する必要があります。この構成は CA 階層と呼ばれます。

この階層は CA Service プールを使用して設定できます。この階層では、下位 CA プールがワークロードに X.509 ワークロード ID 証明書を発行します。

ルート CA プールを構成する

ルート CA プールを作成するには、次の操作を行います。

gcloud privateca pools create を使用して、エンタープライズ ティアにルート CA プールを作成します。この階層は、有効期間が長く、少量の証明書の発行に適しています。

gcloud privateca pools create ROOT_CA_POOL_ID \
    --location=REGION \
    --project=CA_PROJECT_ID \
    --tier=enterprise

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

  • ROOT_CA_POOL_ID: ルート CA プールの一意の ID。ID は 64 文字以下で、大文字と小文字の英数字、アンダースコア、ハイフンのみを使用できます。プール ID はリージョン内で一意である必要があります。

  • REGION: ルート CA プールが配置されているリージョン。

  • CA_PROJECT_ID: ルート CA を作成するプロジェクト ID。

CA プール、階層、リージョンの詳細については、CA プールの作成をご覧ください。

ルート CA を構成する

gcloud privateca roots create を使用して、ルート CA プールにルート CA を作成します。これがルート CA プールの唯一の CA である場合は、ルート CA を有効にすることを求めるメッセージが表示される場合があります。

ルート CA を作成するには、次のコマンドを実行します。

gcloud privateca roots create ROOT_CA_ID \
    --pool=ROOT_CA_POOL_ID \
    --subject="CN=ROOT_CA_CN, O=ROOT_CA_ORGANIZATION" \
    --key-algorithm="KEY_ALGORITHM" \
    --max-chain-length=1 \
    --location=REGION \
    --project=CA_PROJECT_ID \
    --auto-enable

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

  • ROOT_CA_ID: ルート CA の一意の名前。CA 名は 64 文字以下で、大文字と小文字の英数字、アンダースコア、ハイフンのみを使用できます。CA 名はリージョン内で一意である必要があります。
  • ROOT_CA_POOL_ID: ルート CA プールの ID。
  • ROOT_CA_CN: ルート CA の共通名。
  • ROOT_CA_ORGANIZATION: ルート CA の組織。
  • KEY_ALGORITHM: 鍵アルゴリズム(例: ec-p256-sha256)。
  • REGION: ルート CA プールが配置されているリージョン。
  • CA_PROJECT_ID: ルート CA を作成したプロジェクト ID。

CA の subject フィールドの詳細については、サブジェクトをご覧ください。

必要に応じて、ルート CA プールに追加のルート CA を作成します。これは、ルート CA のローテーションに役立ちます。

下位 CA を構成する

必要に応じて、下位 CA を構成できます。下位 CA を構成すると、次のことが可能になります。

  • 複数の証明書発行シナリオ: 証明書発行シナリオが複数ある場合は、シナリオごとに下位 CA を作成できます。

  • ロード バランシングの改善: CA プールに複数の下位 CA を追加すると、証明書リクエストのロード バランシングを改善できます。

下位 CA プールと下位 CA を作成するには、次の操作を行います。

  1. DevOps 階層に下位 CA プールを作成します。これは、有効期間の短い証明書を大量に発行する場合に適しています。

    gcloud privateca pools create SUBORDINATE_CA_POOL_ID \
        --location=REGION \
        --project=CA_PROJECT_ID \
        --tier=devops
    

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

    • SUBORDINATE_CA_POOL_ID: 下位 CA プールの一意の ID。ID は 64 文字以下で、小文字と大文字の英数字、アンダースコア、ハイフンのみを使用できます。プール ID はリージョン内で一意である必要があります。
    • REGION: 下位 CA プールを作成するリージョン。
    • CA_PROJECT_ID: 下位 CA を作成したプロジェクトの ID。

    詳細については、CA プールの作成をご覧ください。

  2. 下位 CA プールに下位 CA を作成します。デフォルトの構成ベースの発行モードは変更しないでください。

    gcloud privateca subordinates create SUBORDINATE_CA_ID \
        --pool=SUBORDINATE_CA_POOL_ID \
        --location=REGION \
        --issuer-pool=ROOT_CA_POOL_ID \
        --issuer-location=REGION \
        --subject="CN=SUBORDINATE_CA_CN, O=SUBORDINATE_CA_ORGANIZATION" \
        --key-algorithm="KEY_ALGORITHM" \
        --use-preset-profile=subordinate_mtls_pathlen_0 \
        --project=CA_PROJECT_ID \
        --auto-enable
    

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

    • SUBORDINATE_CA_ID: 下位 CA の一意の名前。名前は 64 文字以下で、小文字と大文字の英数字、アンダースコア、ハイフンのみを使用できます。プール名はリージョン内で一意である必要があります。
    • SUBORDINATE_CA_POOL_ID: 下位 CA プールの名前。
    • REGION: 下位 CA プールが配置されているリージョン。
    • ROOT_CA_POOL_ID: ルート CA プールの ID。
    • REGION: ルート CA プールのリージョン。
    • SUBORDINATE_CA_CN: 下位 CA の共通名。
    • SUBORDINATE_CA_ORGANIZATION: 下位 CA 発行組織の名前。
    • KEY_ALGORITHM: 鍵アルゴリズム(例: ec-p256-sha256)。
    • CA_PROJECT_ID: 下位 CA を作成したプロジェクトの ID。

    CA の subject フィールドの詳細については、サブジェクトをご覧ください。

証明書発行の構成ファイルを作成する

CA を Workload Identity プールにバインドするには、証明書発行の構成が必要です。必要に応じて、複数の信頼ドメイン間でワークロードを認証する必要がある場合は、信頼構成を使用してプールを更新することもできます。

証明書発行の構成を構成するには、証明書発行の構成ファイルを作成します。ファイルの形式は次のようになります。

{
  "inlineCertificateIssuanceConfig": {
      "caPools": {
        "REGION1": "projects/CA_PROJECT_NUMBER1/locations/REGION1/caPools/SUBORDINATE_CA_POOL_ID1",
        "REGION2": "projects/CA_PROJECT_NUMBER2/locations/REGION2/caPools/SUBORDINATE_CA_POOL_ID2"
      },
      "lifetime": "DURATION",
      "rotationWindowPercentage": ROTATION_WINDOW_PERCENTAGE,
      "keyAlgorithm": "ALGORITHM"
  }
}

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

  • REGION: CA が配置されているリージョン。

  • CA_PROJECT_NUMBER: 下位 CA プールを作成したプロジェクトのプロジェクト番号。CA_PROJECT_ID プロジェクトからプロジェクト番号を取得するには、次のコマンドを実行します。

    gcloud projects describe CA_PROJECT_ID --format="value(projectNumber)"
    
  • SUBORDINATE_CA_POOL_ID: 下位 CA プールの名前。

  • ALGORITHM: 省略可。秘密鍵の生成に使用される暗号化アルゴリズム。有効な値は ECDSA_P256(デフォルト)、ECDSA_P384RSA_2048RSA_3072RSA_4096 です。

  • DURATION: 省略可。リーフ証明書の有効期間(秒単位)。値は 86400(1 日)~2592000(30 日)の範囲で指定する必要があります。指定しない場合、デフォルト値の 86400(1 日)が使用されます。発行された証明書の実際の有効期間は発行元の CA によって異なります。これは、発行された証明書の有効期間が制限される可能性があるためです。

  • ROTATION_WINDOW_PERCENTAGE: 省略可。証明書の全期間で更新がトリガーされる割合。値は 1~600 の範囲で指定する必要があります。デフォルト値は 50 です。

信頼構成ファイルを作成する

デフォルトでは、同じ信頼ドメイン内のワークロードは、マネージド ワークロード ID を使用して相互に認証できます。異なる信頼ドメインにあるワークロードを相互に認証する場合は、Workload Identity プールで信頼関係を明示的に宣言する必要があります。これを行うには、各ドメインの証明書を提供する inlineTrustConfig を含む信頼構成ファイルを作成します。

信頼構成ファイルには、マネージド ワークロード ID がピア証明書の検証に使用するトラスト アンカーのセットが含まれています。信頼構成ファイルは、SPIFFE 信頼ドメインを CA 証明書にマッピングします。

信頼構成ファイルを作成する手順は次のとおりです。

  1. 証明書をダウンロードします。

    gcloud privateca pools get-ca-certs ROOT_CA_POOL_ID \
        --output-file=CERTIFICATE_PATH \
        --location=REGION
    

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

    • ROOT_CA_POOL_ID: ルート CA プールの ID
    • CERTIFICATE_PATH: PEM エンコードされた証明書を出力するパス
    • REGION: ルート CA プールのリージョン

  2. PEM 形式の証明書を含む、インライン信頼構成を含むファイルを作成します。ファイルは次のようになります。
    {
      "inlineTrustConfig": {
        "additionalTrustBundles": {
          "TRUST_DOMAIN_NAME1": {
            "trustAnchors": [
              {
                  "pemCertificate": "-----BEGIN CERTIFICATE-----\nCERTIFICATE_MATERIAL1\n-----END CERTIFICATE-----"
              },
              {
                  "pemCertificate": "-----BEGIN CERTIFICATE-----\nCERTIFICATE_MATERIAL2\n-----END CERTIFICATE-----"
              }
            ]
          },
          "TRUSTED_DOMAIN_NAME2": {
            "trustAnchors": [
              {
                  "pemCertificate": "-----BEGIN CERTIFICATE-----\nCERTIFICATE_MATERIAL3\n-----END CERTIFICATE-----"
              },
              {
                  "pemCertificate": "-----BEGIN CERTIFICATE-----\nCERTIFICATE_MATERIAL4\n-----END CERTIFICATE-----"
              }
            ]
          }
        }
      }
    }
    

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

    • TRUST_DOMAIN_NAME: 信頼ドメイン名。形式は次のとおりです。
      PROJECT_ID.svc.id.goog
      
    • CERTIFICATE_MATERIAL: 信頼ドメインで証明書を発行するために信頼されている、PEM 形式の CA 証明書のセット。

CA を Workload Identity プールにバインドする

CA 階層を作成し、各 CA の証明書発行構成を作成したら、CA を Workload Identity プールにバインドします。CA を Workload Identity プールにバインドするには、CA の証明書発行の構成を使用して Workload Identity プールを更新します。その後、プールが更新されたことを確認します。

Workload Identity プールを更新する

プールを更新するには、次のコマンドを実行します。

gcloud iam workload-identity-pools update TRUST_DOMAIN_NAME \
    --location="global" \
    --inline-certificate-issuance-config-file=CIC_JSON_FILE_PATH \
    --inline-trust-config-file=TC_JSON_FILE_PATH \
    --project=PROJECT_ID

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

  • TRUST_DOMAIN_NAME: 信頼ドメインの名前。形式は次のとおりです。

    PROJECT_ID.svc.id.goog
    
  • CIC_JSON_FILE_PATH: 前に作成した JSON 形式の証明書発行の構成ファイル(cic.json)のパス。

  • TC_JSON_FILE_PATH: 省略可。以前に作成した JSON 形式の信頼構成ファイル(tc.json)のパス。ワークロードが異なる信頼ドメイン間で認証を行う場合は、このファイルを指定する必要があります。それ以外の場合は、--inline-trust-config を省略できます。

Workload Identity プールが更新されたことを確認する

証明書発行の構成と信頼構成とともに Workload Identity プールが更新されたことを確認するには、次のコマンドを実行します。

gcloud iam workload-identity-pools describe TRUST_DOMAIN_NAME \
    --location="global" \
    --project=PROJECT_ID

TRUST_DOMAIN_NAME は、このドキュメントの前半で Workload Identity プールを更新するために使用した信頼ドメイン名に置き換えます。

コマンドの出力は次のようになります。

inlineCertificateIssuanceConfig:
    caPools:
      REGION1: projects/PROJECT_NUMBER1/locations/REGION1/caPools/SUBORDINATE_CA_POOL_ID1,
      REGION2: projects/PROJECT_NUMBER2/locations/REGION2/caPools/SUBORDINATE_CA_POOL_ID2
    keyAlgorithm: ALGORITHM
    lifetime: DURATION
    rotationWindowPercentage: ROTATION_WINDOW_PERCENTAGE
inlineTrustConfig:
    additionalTrustBundles:
      example.com:
          trustAnchors:
          - pemCertificate: |-
            -----BEGIN CERTIFICATE-----
            CERTIFICATE_MATERIAL1
            -----END CERTIFICATE-----
          - pemCertificate: |-
            -----BEGIN CERTIFICATE-----
            CERTIFICATE_MATERIAL2
            -----END CERTIFICATE-----
      myorg.com:
          trustAnchors:
          - pemCertificate: |-
            -----BEGIN CERTIFICATE-----
            CERTIFICATE_MATERIAL3
            -----END CERTIFICATE-----
          - pemCertificate: |-
            -----BEGIN CERTIFICATE-----
            CERTIFICATE_MATERIAL4
            -----END CERTIFICATE-----
name: PROJECT_ID.svc.id.goog
state: ACTIVE

コマンド出力に inlineCertificateIssuanceConfig または inlineTrustConfig が存在しない場合は、課金と割り当てに正しいプロジェクトを使用するように gcloud CLI が正しく構成されていることを確認します。gcloud CLI の新しいバージョンへの更新が必要になることがあります。

CA プールの証明書のリクエストをマネージド ワークロード ID に許可する

CA を Workload Identity プールにバインドしたら、マネージド ワークロード ID に CA プールからの証明書のリクエストを許可する必要があります。これらの ID を承認するには、次の操作を行います。

  1. 各下位 CA プールに対する CA サービス ワークロード証明書リクエスト元(roles/privateca.workloadCertificateRequesterの IAM ロールを信頼ドメインに付与します。次の gcloud privateca pools add-iam-policy-binding コマンドにより、CA Service 証明書チェーンから証明書をリクエストする信頼ドメインを承認します。

    gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_ID \
        --location=REGION \
        --role=roles/privateca.workloadCertificateRequester \
        --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/name/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog" \
        --project=CA_PROJECT_ID
    

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

    • SUBORDINATE_CA_POOL_ID: 下位 CA プールの ID。
    • REGION: 下位 CA プールのリージョン。
    • PROJECT_NUMBER: Workload Identity プールを含むプロジェクトのプロジェクト番号。

      PROJECT_ID から PROJECT_NUMBER を取得するには、次のコマンドを実行します。

      gcloud projects describe PROJECT_ID --format="value(projectNumber)"
      
    • PROJECT_ID: フリート ホスト プロジェクトのプロジェクト ID。

    • CA_PROJECT_ID: 下位 CA を作成したプロジェクトの ID。

  2. 下位 CA プールに対する CA サービスプール読み取り(roles/privateca.poolReaderのロールをマネージド ワークロード ID に付与します。これにより、CA の証明書チェーンからの署名付き X.509 証明書の取得がマネージド ワークロード ID に許可されます。

    gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_ID \
        --location=REGION \
        --role=roles/privateca.poolReader \
        --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/name/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog" \
        --project=CA_PROJECT_ID
    

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

    • SUBORDINATE_CA_POOL_ID: 下位 CA プールの ID。
    • REGION: 下位 CA プールのリージョン。
    • PROJECT_NUMBER: Workload Identity プールを含むプロジェクトのプロジェクト番号。
    • PROJECT_ID: フリート ホスト プロジェクトのプロジェクト ID。
    • CA_PROJECT_ID: 下位 CA を作成したプロジェクトの ID。

マネージド ワークロード ID を使用してワークロードをデプロイする

マネージド ワークロード ID の証明書を発行するように CA プールを構成したら、マネージド ワークロード ID を持つワークロードをデプロイできます。

このセクションでは、マネージド ワークロード ID を持つテスト ワークロードをデプロイする方法について説明します。これを行うには、Pod をデプロイし、認証情報が生成されたことを確認して、証明書と SPIFFE ID を確認します。

Pod をデプロイする

クラスタにテスト Pod をデプロイする手順は次のとおりです。

  1. クラスタの認証情報を取得します。

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=CLUSTER_ZONE \
        --project=CLUSTER_PROJECT_ID
    
  2. Kubernetes Namespace を作成します。

    kubectl create namespace KUBERNETES_NAMESPACE
    
  3. テスト用の PodSpec をデプロイします。

    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      namespace: KUBERNETES_NAMESPACE
      name: example-pod
    spec:
      containers:
      - name: main
        image: debian
        command: ['sleep', 'infinity']
        volumeMounts:
        - name: fleet-spiffe-credentials
          mountPath: /var/run/secrets/workload-spiffe-credentials
          readOnly: true
      nodeSelector:
        iam.gke.io/gke-metadata-server-enabled: "true"
      volumes:
      - name: fleet-spiffe-credentials
        csi:
          driver: podcertificate.gke.io
          volumeAttributes:
            signerName: spiffe.gke.io/fleet-svid
            trustDomain: fleet-project/svc.id.goog
    EOF
    

ワークロードの認証情報の一覧を取得する

ワークロード認証情報の一覧を取得するには、次のコマンドを実行します。認証情報の作成には数分かかることがあります。

kubectl exec -it example-pod -n KUBERNETES_NAMESPACE -- ls  /var/run/secrets/workload-spiffe-credentials

次の出力が表示されます。

ca_certificates.pem
certificates.pem
private_key.pem
trust_bundles.json

証明書を確認する

証明書を確認する手順は次のとおりです。

  1. 証明書を別の 1 つのファイルにエクスポートします。

    kubectl exec -it example-pod --namespace=KUBERNETES_NAMESPACE -- cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -noout -text > certfile
    
  2. 証明書ファイルを確認します。

    cat certfile
    

    証明書の X509v3 Subject Alternative Name 属性に、次の形式の SPIFFE ID が表示されます。spiffe://PROJECT_ID.svc.id.goog/ns/KUBERNETES_NAMESPACE/sa/default

    default は、デフォルトの Kubernetes ServiceAccount を指します。

ワークロード間の認証をテストする

ワークロード間の認証をテストするには、Go を使用して mTLS 認証をテストするをご覧ください。

リポジトリのサンプルコードは、クライアント ワークロードとサーバー ワークロードを作成します。このドキュメントで前述した証明書を使用して、ワークロード間の相互認証をテストできます。

次のステップ