OIDCを利用したGitHub ActionsからGoogle CloudへのDocker Pushの設定方法
GitHub ActionsからDocker ImageをGoogle Cloudにpushしたい
2022年現在だとOpenID Connect(OIDC)トークンを利用した方法がセキュアなようです。
GitHub Actions からのキーなしの認証の有効化 | Google Cloud Blog
この方法を用いると、GCP から Secret Key などをダウンロードして GitHub Actions の Secret に登録して環境変数で読み込む..といったことをする必要がなくなります。
正確な情報は他の記事を読むことを推奨しますが、とっつきにくいので噛み砕いて説明すると、 GCP 側で認証が必要な操作を特定のリポジトリのGitHub Actions で予め許可し、要求があったとき(実行時)に有効期限の認証情報を生成して利用する、 という感じのようです。
したがって、Google Cloud側でGitHub ActionsがOIDCを利用して認証できるように設定を行い、このとき発行されたService Account や Workload Identify Providerをセットする作業が必要になります。 そこそこ手順が多く、ちょっとめげそうになりますがなんとか作成できたので解説しながら紹介していきます。
ゴール
GitHub ActionsからGoogle CloudのContainer Registryに対してdocker pushを実現するところまで。 (ほんの少し設定をを変えるだけでArtifactory Registryもいけるはず)
最終的なGitHub Actions
name: Docker Build & Push
on:
release:
types: [created]
jobs:
docker-push:
runs-on: ubuntu-latest
# 必須
permissions:
contents: "read"
id-token: "write"
steps:
- uses: actions/checkout@v3
with:
ref: main
# https://github.com/google-github-actions/auth
- id: "auth"
name: "Authenticate to Google Cloud"
uses: "google-github-actions/auth@v0"
with:
token_format: "access_token"
workload_identity_provider: # ここを発行する
service_account: # ここを発行する
# https://github.com/docker/login-action#google-container-registry-gcr
- name: Login to GCR
uses: docker/login-action@v2
with:
registry: asia.gcr.io
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}
- name: "Docker Build & Push"
uses: docker/build-push-action@v3
with:
push: true
tags: gcr.io/your/image:latest
GitHub Actions の Marketplace からは以下の Actions を利用します。 あらゆる手続き的な処理が隠蔽されて設定だけを記述すれば GCP に docker push できる状態になります。
- actions/checkout@v3
- リポジトリをチェックアウトするために使う。
- google-github-actions/auth@v0
- Google Cloud への認証を確立するために利用する。checkout 後に利用する必要がある。
- docker/login-action@v2
- docker login を実施する。認証情報は前ステップの auth から access token で受け取る
- docker/build-push-action
- コンテナのビルドと push を実施する。
workload_identity_provider と service_account を発行する手順
手順はSetting up Workload Identity Federationに則って実施します。
1. Project を用意する
Google Cloud に Project を用意すると Project ID が発行されるので変数に格納します。
export PROJECT_ID="my-project"
2. Service Account を作成 (Optional)
- すでに権限が十分な Service Account が存在する場合はスキップして 4 に進んでください。
- Service Account は存在するが、権限が不十分な場合は 3 に進んでください。
gcloud iam service-accounts create "my-service-account" --project "${PROJECT_ID}"
# Unique IDが自動的に発行されます
3.権限(Permission)の付与 (Optional)
Service Accountは以下から確認できます。
また、すでに Service Account に Role が付与されている場合は、IAM から確認することができます。 Role が存在しない場合は IAM に登場しないため、Role をバインドする必要があります。
3.1 Role の作成
今回、Container Registry に対して Docker Image を Push するので、それに必要なアクセス権を持つ Service Account がすでにあれば、それを利用することも可能です。新規作成や最小構成で作りたい場合は、IAM を使用したアクセス制御 | Container Registry のドキュメント | Google Cloudに従って、Role の作成と Service Account へ権限を付与する必要があります。
必要なアクセス権 | Role |
---|---|
pull に必要 | roles/storage.objectViewer |
push 及び pull に必要 | roles/storage.legacyBucketWriter |
レジストリホストの追加とバケット作成に必要 | roles/storage.admin |
- https://console.cloud.google.com/iam-admin/rolesへ移動
[+ Create Role]
をクリック- Title/Description/ID を埋めていく
- ここでは Title をDocker Push for GitHub Actionsとしておく。
[+Add permissions]
を入力Storage Object Viewer
、Storage Legacy Bucket Writer
、Storage Admin
をフィルターに追加し残った Permission をすべて追加します。
※ 権限が足りない場合、Access Denied
など様々なエラーがでるため、混乱することになります。
3.2 Service Account と Role のバインド
[IAM & Admin] > [IAM]
へ移動し、ADD
から先ほど作成した Service Account と Role を結びつけます
サービスアカウントはメールアドレスのフォーマットで生成されたものを利用します。
4. IAM Credentials AP を有効にする
gcloud
コマンドの場合次のコマンドで有効化できます。
gcloud services enable iamcredentials.googleapis.com \
--project "${PROJECT_ID}"
コンソールの画面からだと、[IAM & Admin] > [Workload Identity Federation]
に行き、GET STARTED
をクリックすると有効化されます。
5. Workload Identity Pool を作成する
Workload ID Pool は外部サービスとの連携のために利用され、少なくとも 1 つ以上の Provider に接続することが必要です。
# プール名は後から変更できないので注意
gcloud iam workload-identity-pools create "my-pool" \
--project="${PROJECT_ID}" \
--location="global" \
--display-name="Demo pool"
6. Workload Identity Pool のフル ID を取得
gcloud iam workload-identity-pools describe "my-pool" \
--project="${PROJECT_ID}" \
--location="global" \
--format="value(name)"
変数に格納
export WORKLOAD_IDENTITY_POOL_ID="..."
7. Workload Identify Pool に対して Provider を作成する
gcloud iam workload-identity-pools providers create-oidc "github-actions-provider" \
--project="${PROJECT_ID}" \
--location="global" \
--workload-identity-pool="github-actions-pool" \
--display-name="GitHub Actions Provider" \
--attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository" \
--issuer-uri="https://token.actions.githubusercontent.com"
Provider Attributesのマッピングは以下の通り
Google N | OIDC N |
---|---|
google.subject | assertion.sub |
attribute.actor | assertion.actor |
attribute.repository | assertion.repository |
8. リポジトリから発信されるワークロードIDプロバイダからの認証が、上記で作成したサービスアカウントになりすますことを許可する。
export REPO="username/name" # 信頼するGitHub Repository (e.g. "google/chrome")
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}"
コンソールでは、以下の手順で実施します。
- Workload Identity Federationへ行く
- Workload Identify Poolを選択
GRANT ACCESS
をクリックして、権限移譲先のService Accountを選択するOnly identities matching the filter
を選択すると、先程登録したAttributeのrepository
を選択- リポジトリ名を登録
DOWNLOAD CONFIG
のポップアップが出てくるが不要なのでDISMISS
Service AccountにWorkload Identity User
のRoleが付与されていることが確認できます。
9. Workload Identity Providerのリソース名を抽出する。
gcloud iam workload-identity-pools providers describe "my-provider" \
--project="${PROJECT_ID}" \
--location="global" \
--workload-identity-pool="my-pool" \
--format="value(name)"
10. 完了
以下の2つを利用してGitHub ActionsがらGoogle Cloudの認証を得ることができます。 裏側ではOIDCトークンの交換が行われています。
- Workload Identity Provider ID
projects/$PROJECT_ID/locations/global/workloadIdentityPools/$WORKLOAD_IDENTITY_POOL_ID/providers/$PROVIDER_ID
のフォーマット- ProviderのEdit画面で
https://iam.googleapis.com/
以降の文字列が同等
- Service Account email
Workload Identity User
の権限とContainer Registryにdocker pushするのに十分な権限を持つService Account
まとめ
最初実施すると手順は厄介ですが、地道に手を動かしてみると必要十分な手順であることがわかります。
認証のためにGitHub Actionsに指定するパラメーターがWorkload Identity Provider ID
とService Account email
のみになり、シークレットーキーをダウンロードする行為から開放されます。