GCP API を GCP の外から利用するためには、一般に Service Account を利用します。その際に Service Account の鍵ファイルを利用すると、鍵ファイルの流出によるリスクが発生します。Workload identity federation という機能を用いることで、鍵を用いない認証の仕組みを実現できます。
上記の処理の流れを実現するために、以下の設定が必要となります。
参考資料: Workload identity federation
Cloud Console または以下のコマンドで作成します。
gcloud iam workload-identity-pools create my-aws-pool --location='global'
参考資料: Create the workload identity pool and provider
Cloud Console または以下のコマンドで作成します。
gcloud iam workload-identity-pools providers create-aws my-aws-provider \
--location=global \
--workload-identity-pool=my-aws-pool \
--account-id=123412341234 \
--attribute-mapping='google.subject=assertion.arn,attribute.aws_role=assertion.arn.contains("assumed-role") ? assertion.arn.extract("{account_arn}assumed-role/") + "assumed-role/" + assertion.arn.extract("assumed-role/{role_name}/") : assertion.arn'
OpenID Connect (OIDC) をサポートする任意の Identity Provider を利用できます。特に AWS の場合は必要な設定値が用意されているため、簡単に利用を始められます。
AWS アカウント ID を指定します。
AWS を Identity Provider として利用する際の、標準的な Attribute Mapping が自動で設定されます。
参考資料: Workload identity providers
Workload Identity Pool に登録された Identity Provider によって提供される GCP 外部の Identity は、GCP STS によって federated access token を得ます。GCP 外部の Identity は GCP の principal としては以下のように表現されます。
principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT_NAME
Service Account の Permission において、上記 principal が roles/iam.workloadIdentityUser ロールを持つように grant しておきます。
iam.serviceAccounts.get
iam.serviceAccounts.getAccessToken
iam.serviceAccounts.getOpenIdToken
iam.serviceAccounts.list
iam.serviceAccounts.getAccessToken
permission を持つため、federated access token を用いることで short-lived OAuth 2.0 access token を取得できるようになります。この access token を用いることで Service Account を利用します。
GCP 外部の Identity に roles/iam.workloadIdentityUser を付与する対象となる Service Account を選択します。
STS によって federated access token を取得するための情報が記載された JSON ファイルがダウンロードできます。認証情報ではないため、例えば Secret Manager 等で守る必要のある情報ではありません。
$ cat clientLibraryConfig-my-aws-provider.json
{
"type": "external_account",
"audience": "//iam.googleapis.com/projects/912480652101/locations/global/workloadIdentityPools/my-aws-pool-20211030/providers/my-aws-provider",
"subject_token_type": "urn:ietf:params:aws:token-type:aws4_request",
"service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/mysa-457@myproject-20210411.iam.gserviceaccount.com:generateAccessToken",
"token_url": "https://sts.googleapis.com/v1/token",
"credential_source": {
"environment_id": "aws1",
"region_url": "http://169.254.169.254/latest/meta-data/placement/availability-zone",
"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials",
"regional_cred_verification_url": "https://sts.{region}.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15"
}
}
選択した Service Account に対して、リソースレベルの IAM 権限の設定がなされていることも確認できます。
参考資料: Service account impersonation
Service Account を GCP 外部 Identity が利用するためには、以下のステップが必要となります。
参考資料: Obtaining short-lived credentials with identity federation
google-auth を利用します。
python3 -m pip install -U google-auth
IAM role が割り当てられた AWS EC2 インスタンスで以下のコマンドを実行します。
export GOOGLE_APPLICATION_CREDENTIALS=`pwd`/clientLibraryConfig-my-aws-provider.json
python3 -m IPython
from google.cloud import storage
import google.auth
scopes=['https://www.googleapis.com/auth/cloud-platform']
credentials, project = google.auth.default(scopes=scopes)
client = storage.Client(project=project, credentials=credentials)
for bucket in client.list_buckets():
print(bucket.name)
参考資料:
CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE
環境変数を利用することで対応できます。gsutil
および bq
コマンドは対応していません。
export CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE=`pwd`/clientLibraryConfig-my-aws-provider.json
gcloud compute instances list
参考資料:
Attribute Mapping で Key として設定されている attribute.aws_role
または google.subject
を用いて、特定の Identity のみが Service Account を利用できるように制限できます。例えば aws_role
を my-role-20211027
に限定するためには、以下のように設定します。
Identity Provider 側の設定によって制限することも可能です。
関連資料:
Workload Identity Federation を用いる場合、Service Account の鍵は不要となります。組織のポリシーによって制限することが可能です。
また、Identity Provider を AWS に制限することや、AWS のアカウント ID を制限することも可能です。
インターネットへのアクセスが制限されている環境においては sts.googleapis.com
によるトークン発行が失敗します。
Security Token Service (STS) は、こちらのページに記載の VPC-SC および Private Google Access でサポートされています。これを利用することでインターネット接続ができない環境であっても STS を利用できます。
同様に AWS STS へのアクセスをインターネットを経由せずに実現するためには、AWS PrivateLink を利用します: Using AWS STS interface VPC endpoints