サードパーティの ID を証明する証明書を発行する
このチュートリアルでは、ID リフレクションと Workload Identity プールを使用して、サードパーティの ID を証明する証明書を発行する方法について説明します。
ID リフレクションを使用して、証明書リクエスト元の確認済み ID と一致する証明書を作成できます。ID リフレクションを使用すると、権限のない証明書リクエスト元が、認証情報内の ID に対応するサブジェクト代替名(SAN)を持つ証明書のみをリクエストするよう制限できます。
目標
このチュートリアルでは、Workload Identity プールで CA Service を使用してサードパーティの ID を連携し、この ID の証明を行う証明書を取得する方法について説明します。
準備
始める前に、次のコンセプトを理解しておいてください。
- Workload Identity プール: Workload Identity プールを使用すると、サードパーティ ID プロバイダを管理できます。詳細については、Workload Identity プールとプロバイダを管理するをご覧ください。
- Workload Identity 連携: Workload Identity 連携では、Workload Identity プールを利用して、サードパーティ ID に Google Cloud サービスへのアクセスを許可します。詳細については、Workload Identity 連携をご覧ください。
- Security Token Service(STS): Security Token Service を使用すると、サードパーティの認証情報をファーストパーティ(Google Cloud)トークンと交換できます。詳細については、Security Token Service をご覧ください。
- ID リフレクション: ID リフレクション機能を使用すると、証明書リクエスト元の確認済み ID をリクエストされた証明書に渡すことができます。詳細については、ID リフレクションをご覧ください。
次の IAM ロールがあることを確認してください。
- 認証局(CA)と CA プールを管理し、証明書をリクエストするには、CA Service オペレーション マネージャー(
privateca.caManager
)のロールが必要です。CA Service の IAM ロールの詳細については、IAM を使用したアクセス制御をご覧ください。 - Workload Identity プールとプロバイダを管理するには、Workload Identity プール管理者(
iam.workloadIdentityPoolAdmin
)のロールが必要です。 - サービス アカウントを作成するには、サービス アカウント管理者(
iam.serviceAccountAdmin
)のロールが必要です。
IAM ロールの付与については、プロジェクト、フォルダ、組織へのアクセスを管理するをご覧ください。必要な IAM ロールは、Google アカウント、サービス アカウント、Google グループ、Google Workspace アカウント、または Cloud Identity ドメインに付与できます。
Workload Identity プールとプロバイダを設定する
このチュートリアルでは、Google OpenID Connect(OIDC)プロバイダをサービス アカウントと組み合わせて、サードパーティの ID として機能する方法について説明します。Google アカウントの OIDC プロバイダはサードパーティ ID プロバイダ(IdP)として機能し、Google Cloud サービス アカウントは、この IDP によってアサートされるサードパーティ ID のサンプルです。
Workload Identity プールは、Microsoft Azure / オンプレミスの Active Directory、AWS、SAML ベースの ID プロバイダなど、さまざまな ID プロバイダをサポートしています。
Workload Identity プールとプロバイダを設定するには、以下の手順を行います。 1. 信頼できる連携 ID のセットを表現するには、Workload Identity プールを作成します。
```
gcloud iam workload-identity-pools create IDENTITY_POOL_ID --location global --display-name "tutorial-wip"
```
Replace the following:
- <var>IDENTITY_POOL_ID</var>: The unique identifier of the new workload
identity pool.
サードパーティの ID プロバイダの Workload Identity プール プロバイダを作成します。
gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID --location global --workload-identity-pool IDENTITY_POOL_ID --display-name "tutorial-oidc" --attribute-mapping "google.subject=assertion.sub" --issuer-uri="https://accounts.google.com"
以下を置き換えます。
- PROVIDER_ID: Workload Identity プールに作成する ID プロバイダの固有識別子。
ユースケースに合わせて、次のフラグをカスタマイズできます。
attribute-mapping
: このフラグは、サードパーティのクレームと Google プリンシパル クレームgoogle.subject
のマッピングを設定します。google.subject
は、CEL 式を使用して任意のクレームまたはクレームの組み合わせに設定できる必須のマッピングです。詳細については、属性のマッピングと条件を定義するをご覧ください。issuer-uri
: OIDC プロバイダの場合、このフラグは一般公開されるエンドポイントであり、サードパーティ トークンの検証用に Google から到達します。詳細については、外部 ID プロバイダの準備をご覧ください。
Workload Identity プロバイダの設定の詳細については、Workload Identity 連携の構成をご覧ください。
CA プールと発行 CA を作成する
このセクションでは、CA プールを作成してルート CA を追加する方法について説明します。この CA プールを使用して、ID が反映された証明書を発行できます。既存の CA プールと CA を使用する場合は、このセクションをスキップできます。
ルート CA の代わりに下位 CA を作成することもできます。ルート CA を作成すると、手順を短縮できます。
DevOps ティアに CA プールを作成します。
gcloud privateca pools create CA_POOL_ID --location LOCATION --tier devops
以下を置き換えます。
- CA_POOL_ID - 証明書を発行する CA Service の CA プールの ID。
- LOCATION - CA プールのロケーション。
CA プールの作成の詳細については、CA プールを作成するをご覧ください。
ルート CA を作成します。
gcloud privateca roots create CA_ID --pool CA_POOL_ID --location LOCATION --subject "CN=test,O=test-org"
以下を置き換えます。
- CA_ID - 証明書を発行する認証局の ID。
- CA_POOL_ID - 証明書を発行する CA Service の CA プールの ID。
- LOCATION - CA プールのロケーション。
ルート CA の作成について詳しくは、ルート CA を作成するをご覧ください。
Workload Identity プールの ID 連携を有効にして、CA プールから証明書を発行します。ID リフレクションには、
CreateCertificate
のリクエスト元に対する CA サービス ワークロード証明書リクエスト元(roles/privateca.workloadCertificateRequester
)の IAM ロールが必要です。Workload Identity プールのプリンシパルは、単一のサブジェクトからプロバイダ全体のプール内のすべての ID まで、さまざまな粒度で表現できます。詳細については、ユースケースに最適な利用可能なプリンシパルまたはプリンシパル セット([Google Cloud CLI] タブを使用)をご覧ください。
gcloud privateca pools add-iam-policy-binding CA_POOL_ID --location LOCATION --role roles/privateca.workloadCertificateRequester --member "principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/*"
以下を置き換えます。
- PROJECT_NUMBER - Workload Identity プールを作成したプロジェクトのプロジェクト番号。
サードパーティの ID を表すサービス アカウントを作成する
次の手順では、サービス アカウントがサードパーティを表すことを前提としています。このセクションでは、GenerateIdToken
IAM エンドポイントを使用して、OIDC トークンの形式でサードパーティの ID を取得する方法について説明します。ユースケースによっては、選択したサードパーティ ID トークンを取得するために異なる手順が必要になる場合があります。
gcloud iam service-accounts create SERVICE_ACCOUNT
以下を置き換えます。
- SERVICE_ACCOUNT - サードパーティの ID を表すサービス アカウントの ID。
サードパーティの ID を証明する証明書を発行する
始める前に、サービス アカウント トークン作成者(roles/iam.serviceAccountTokenCreator
)の IAM ロールがあることを確認します。GenerateIdToken
API を呼び出すには、この IAM ロールが必要です。
サードパーティの ID を証明する証明書を取得するには、次の手順を行います。
サードパーティの ID プロバイダからサードパーティの ID トークンを取得します。
curl
export ID_TOKEN=`curl -d '{"audience":"//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/providers/PROVIDER_ID"}' -H 'Content-Type: application/json' -H "Authorization: Bearer $(gcloud auth print-access-token)" https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com:generateIdToken | python3 -c "import sys;import json;print(json.load(sys.stdin)['token'])"`
以下を置き換えます。
- PROJECT_ID - リソースを作成するプロジェクトの Google Cloud プロジェクト ID。
クライアント ライブラリ
サードパーティ トークンにプログラムでアクセスするには、ファイル提供の認証情報または URL 提供の認証情報からトークンを取得します。詳細については、クライアント ライブラリ、gcloud CLI、または Terraform を使用した認証をご覧ください。このチュートリアルでは、ファイル提供の認証情報ワークフローに従います。
証明書のリクエスト元が読み取り可能なパスに認証情報を読み込みます。
curl -d '{"audience":"//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/providers/PROVIDER_ID"}' -H 'Content-Type: application/json' -H "Authorization: Bearer $(gcloud auth print-access-token)" https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com:generateIdToken | python3 -c "import sys;import json; print(json.load(sys.stdin)['token']) > /tmp/oidc_token.txt
以下を置き換えます。
- PROJECT_ID: リソースを作成するプロジェクトのプロジェクト ID。
STS
token
エンドポイントを使用して、サードパーティ トークンを連携 OAuth トークンと交換します。curl
export STS_TOKEN=`curl -L -X POST 'https://sts.googleapis.com/v1/token' -H 'Content-Type: application/json' \ -d '{ "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", "audience": "//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/providers/PROVIDER_ID", "requested_token_type": "urn:ietf:params:oauth:token-type:access_token", "scope": "https://www.googleapis.com/auth/cloud-platform", "subject_token": "'$ID_TOKEN'", "subject_token_type": "urn:ietf:params:oauth:token-type:jwt" }' | python3 -c "import sys;import json; print(json.load(sys.stdin)['access_token'])"`
クライアント ライブラリ
- 証明書をリクエストするコードが読み取ってトークン交換を実行できる
oidc_token.txt
という名前の認証情報構成ファイルを作成します。
gcloud iam workload-identity-pools create-cred-config projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID --output-file=/tmp/cred_config.json --credential-source-file=/tmp/oidc_token.txt
oidc_token.txt
ファイルを読み取り、クライアント ライブラリの承認メカニズムを設定します。
python
import json from google.auth import identity_pool with open('/tmp/cred_config.json', 'r') as f: json_config_info = json.loads(f.read()) credentials = identity_pool.Credentials.from_info(json_config_info) scoped_credentials = credentials.with_scopes( ['https://www.googleapis.com/auth/cloud-platform'])
- 証明書をリクエストするコードが読み取ってトークン交換を実行できる
REFLECTED_SPIFFE
サブジェクト リクエスト モードで CA Service にリクエストを送信します。curl
省略可: CSR がない場合は、次のコマンドを実行して CSR を作成します。
export TUTORIAL_CSR=$(openssl req -newkey rsa:2048 -nodes -subj / -keyout tutorial_do_not_use.key)
CSR、有効期間、反映されたサブジェクト リクエスト モードを使用して証明書をリクエストします。
curl -H "Authorization: Bearer $(echo $STS_TOKEN)" https://privateca.googleapis.com/v1/projects/PROJECT_NUMBER/locations/LOCATION/caPools/CA_POOL_ID/certificates\?alt\=json -X POST -H "Content-Type: application/json" -H 'Accept: application/json' --data '{"lifetime": "100s", "pemCsr": "'$TUTORIAL_CSR'", "subjectMode": "REFLECTED_SPIFFE"}'
クライアント ライブラリ
自社トークンを CA Service に転送するには、認証されたクライアントを作成する必要があります。この認証されたクライアントを使用して、証明書リクエストを行うことができます。
認証された CA Service クライアントを開始します。
python
caServiceClient = privateca_v1.CertificateAuthorityServiceClient(credentials=scoped_credentials)
証明書をリクエストする
Python
CA Service への認証を行うには、アプリケーションのデフォルト認証情報を設定します。 詳細については、ローカル開発環境の認証の設定をご覧ください。
証明書を確認します。証明書には、単一の URI SAN を含むサブジェクトが必要です。ID を証明する SAN の形式は次のとおりです。
spiffe://IDENTITY_POOL_ID.PROJECT_NUMBER.global.workload.id.goog/subject/<oidc_subject_number>
以下のように置き換えます。
- IDENTITY_POOL_ID: Workload Identity プールの固有識別子。
- PROJECT_NUMBER - Workload Identity プールを作成したプロジェクトのプロジェクト番号。
クリーンアップ
このドキュメントに従って作成した CA Service リソースについて、Google Cloud アカウントに課金されないようにするには、Google Cloud CLI を使用して次の操作を行います。
作成した CA を削除します。
CA を無効にします。
gcloud privateca roots disable CA_ID --pool CA_POOL_ID --location LOCATION
以下のように置き換えます。
- CA_ID: CA の固有識別子。
- CA_POOL_ID: CA プールの固有識別子。
- LOCATION: CA プールのロケーション。
CA を削除します。
gcloud privateca roots delete CA_ID --pool CA_POOL_ID --location LOCATION --ignore-active-certificates
以下のように置き換えます。
- CA_ID: CA の固有識別子。
- CA_POOL_ID: CA プールの固有識別子。
- LOCATION: CA プールのロケーション。
作成した CA プールを削除します。
gcloud privateca pools delete CA_POOL_ID --location LOCATION
以下のように置き換えます。
- CA_POOL_ID: CA プールの固有識別子。
- LOCATION: CA プールのロケーション。
gcloud privateca pools delete
コマンドの詳細については、gcloud privateca pools delete をご覧ください。作成した Workload Identity プールを削除します。
gcloud iam workload-identity-pools delete IDENTITY_POOL_ID --location global
以下のように置き換えます。
- IDENTITY_POOL_ID: Workload Identity プールの固有識別子。
作成したサービス アカウントを削除します。
gcloud iam service-accounts delete SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com
以下のように置き換えます。
- SERVICE_ACCOUNT: Workload Identity プールの固有識別子。
- PROJECT_ID: サービス アカウントを所有するプロジェクト。
CA Service ワークロード証明書リクエスト元(privateca.workloadCertificateRequester
)の IAM ロールにより、発行される証明書のサブジェクトがリクエスト元の ID のみに制限されます。ID リフレクション機能を使用するユーザーまたはワークロードに、CA Service ワークロード証明書リクエスト元(privateca.workloadCertificateRequester
)の IAM ロールのみが付与されていることを確認します。最小権限の原則に従うことで、CA Service 証明書リクエスト元(privateca.certificateRequester
)の IAM ロールの付与を回避できます。
次のステップ
- 反映された ID を超えてリクエストされた証明書のプロパティを制御できる、さまざまなポリシー制御について確認する。
- さまざまなポリシー制御を構成して管理する方法を確認する。