GitHub ActionsでWorkload Identityでの認証を入れてGoogle CloudのAPIを叩く
概要
正直難しいと思ってたのですが、資料を読んでいくと表面上、実装は難しくありませんでした。
GitHub ActionsとGoogle Cloudを連携する場合、json管理とかしなくても済むし、基本的にやっておいて損はないと思います。
ユースケースとしては、例えば、GitHub Actionsで実行した結果(report)をGoogle Cloud Storageにデータを送りたいなどの際に使えると思います。
Identity Poolに対して、providerは複数作成できるため、いろんな GitHub Actionsから利用されるようなパターンでも、provider:script=1:1のような形にしておくのが良いのかと思いました
手順
- Google Cloud上でworkload Identityのpoolの作成する
- その中に認証providerを作成する
- poolに対して、サービスアカウントを紐付ける
- GitHub Actionsのstepとpermissionに追加する
- この時点でApplication Default Credentials(ADC)に入る https://github.com/google-github-actions/auth
実際にやってみる
基本はこちらのsetupの部分をなぞって行きます。
-
Google Cloud上でworkload Identityのpoolの作成する
-
利用したいprojectのIDを環境変数にセットしておく
export PROJECT_ID="my-project" # update with your value
-
APIを利用できるようにする
gcloud services enable iamcredentials.googleapis.com --project "${PROJECT_ID}"
-
poolを作成する(locationは
global
でよいかとgcloud iam workload-identity-pools create "my-pool" --project="${PROJECT_ID}" --location="global" --display-name="Demo pool"
-
作成したpoolのIDを保存しておく
export WORKLOAD_IDENTITY_POOL_ID=$(gcloud iam workload-identity-pools describe "my-pool" --project="${PROJECT_ID}" --location="global" --format="value(name)")
-
-
その中に認証providerを作成する
-
prividerを作成する
gcloud iam workload-identity-pools providers create-oidc "my-provider" \ --project="${PROJECT_ID}" \ --location="global" \ --workload-identity-pool="my-pool" \ --display-name="sample provider" \ --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository" \ --issuer-uri="https://token.actions.githubusercontent.com"
-
-
poolに対して、サービスアカウントを紐付ける
-
紐付ける予定のサービスアカウントを作成する
gcloud iam service-accounts create "my-service-account" \ --project "${PROJECT_ID}"
-
poolとservice accountを紐付ける
# レポジトリを指定します export REPO="username/name" gcloud iam service-accounts add-iam-policy-binding "my-service-account@${PROJECT_ID}.iam.gserviceaccount.com" \ --project="${PROJECT_ID}" \ --role="roles/iam.workloadIdentityUser" \ --member="principalSet://iam.googleapis.com/${WORKLOAD_IDENTITY_POOL_ID}/attribute.repository/${REPO}"
-
作成できたproviderのIDを取得する
gcloud iam workload-identity-pools providers describe "my-provider" \ --project="${PROJECT_ID}" \ --location="global" \ --workload-identity-pool="my-pool" \ --format="value(name)"
- workload identity poolのマッピングを構成してから、権限が利用可能になるまで、最大5分かかることがあるようなので、少し待ちます
-
-
GitHub Actionsのstepとpermissionに追加する
jobs: job_id: # Add "id-token" with the intended permissions. permissions: contents: 'read' id-token: 'write' steps: - uses: 'actions/checkout@v3' # 大体のユースケースではcheckoutはしていると思うのですが、これが無いとディレクトリがないためworningがでます - id: 'auth' name: 'Authenticate to Google Cloud' uses: 'google-github-actions/auth@v1' with: workload_identity_provider: 'projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider' service_account: 'my-service-account@my-project.iam.gserviceaccount.com'
google-github-actions/auth failed with: retry function failed after 4 attempts: gitHub Actions did not inject $ACTIONS_ID_TOKEN_REQUEST_TOKEN or $ACTIONS_ID_TOKEN_REQUEST_URL into this job. This most likely means the GitHub Actions workflow permissions are incorrect, or this job is being run from a fork. For more information, please see https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token
- workload_identity_providerは
poolに対して、サービスアカウントを紐付ける
で取得したproviderのIDを入れる - service_accountは
poolに対して、サービスアカウントを紐付ける
で作成したサービスアカウントのemailを入れる
- workload_identity_providerは
これでGitHub Actionsの後ろのstepに環境変数にADCとして、サービスアカウントが認証されている状態になります。必要な権限を与えてあげて、スクリプトを叩くなりしても良いと思います。
疑問点
Q.workload_identity_providerとservice_accountがバレているとGitHub Actionsからなら、どこからでもできてしまうんでないの?
A. access tokenが取得できないため、できませんでした。
詳しい図などは、こちらの方の記事の図を参考にしていただけると幸いです
-
動作確認してみた感じできる用に見える(認証ができていてjsonが作成できている)
Run google-github-actions/auth@v1 with: workload_identity_provider: projects/{projectId}/locations/global/workloadIdentityPools/{poolId}/providers/{providerId} service_account: service-account@{project}.iam.gserviceaccount.com create_credentials_file: true export_environment_variables: true cleanup_credentials: true access_token_lifetime: 3600s access_token_scopes: https://www.googleapis.com/auth/cloud-platform retries: 3 backoff: 250 id_token_include_email: false Created credentials file at "/home/runner/work/test-github-actions/test-github-actions/gha-creds-375e94e42c109da8.json"
-
ただし、そのアクセストークンを使ってgcloud コマンドを叩こうとすると、gcloudのsetupはできるがaccess tokenが作成できないというエラーで落ちます。(Unable to acquire impersonated credentials=偽装された認証情報を取得できませんって言っているので、ダメ
一応権限もつけてみたけどダメなものはダメ。変わらずエラーでしたRun google-github-actions/setup-gcloud@v1 with: skip_install: false version: latest env: CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE: /home/runner/work/test-github-actions/test-github-actions/gha-creds-375e94e42c109da8.json GOOGLE_APPLICATION_CREDENTIALS: /home/runner/work/test-github-actions/test-github-actions/gha-creds-375e94e42c109da8.json GOOGLE_GHA_CREDS_PATH: /home/runner/work/test-github-actions/test-github-actions/gha-creds-375e94e42c109da8.json CLOUDSDK_CORE_PROJECT: {projectId} CLOUDSDK_PROJECT: {projectId} GCLOUD_PROJECT: {projectId} GCP_PROJECT: {projectId} GOOGLE_CLOUD_PROJECT: {projectId} /usr/bin/tar xz --warning=no-unknown-keyword --overwrite -C /home/runner/work/_temp/6053ebc2-0e1e-41e6-a3d4-2a27248306f0 -f /home/runner/work/_temp/a1627134-a18d-4916-9fe6-2fdf46d1d97b Successfully authenticated Run gcloud storage cp gs://{gcs_path}/hoge.txt ./hoge.txt gcloud storage cp gs://{gcs_path}/hoge.txt ./hoge.txt shell: /usr/bin/bash -e {0} env: CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE: /home/runner/work/test-github-actions/test-github-actions/gha-creds-375e94e42c109da8.json GOOGLE_APPLICATION_CREDENTIALS: /home/runner/work/test-github-actions/test-github-actions/gha-creds-375e94e42c109da8.json GOOGLE_GHA_CREDS_PATH: /home/runner/work/test-github-actions/test-github-actions/gha-creds-375e94e42c109da8.json CLOUDSDK_CORE_PROJECT: {projectId} CLOUDSDK_PROJECT: {projectId} GCLOUD_PROJECT: {projectId} GCP_PROJECT: {projectId} GOOGLE_CLOUD_PROJECT: {projectId} CLOUDSDK_METRICS_ENVIRONMENT: github-actions-setup-gcloud CLOUDSDK_METRICS_ENVIRONMENT_VERSION: 1.1.1 ERROR: (gcloud.storage.cp) There was a problem refreshing your current auth tokens: ('Unable to acquire impersonated credentials', '{ "error": { "code": 403, "message": "Permission \'iam.serviceAccounts.getAccessToken\' denied on resource (or it may not exist).", "status": "PERMISSION_DENIED", "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "IAM_PERMISSION_DENIED", "domain": "iam.googleapis.com", "metadata": { "permission": "iam.serviceAccounts.getAccessToken" } } ] } } ') Please run: $ gcloud auth login to obtain new credentials. If you have already logged in with a different account, run: $ gcloud config set account ACCOUNT to select an already authenticated account to use.
Discussion