OIDCを利用したGitHub Actionsから Google CloudへのDocker Pushの設定方法
2022/07/07
累計閲覧数 949 PV
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もいけるはず)
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@v4
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 できる状態になります。
手順はSetting up Workload Identity Federationに則って実施します。
Google Cloud に Project を用意すると Project ID が発行されるので変数に格納します。
export PROJECT_ID="my-project"
gcloud iam service-accounts create "my-service-account" --project "${PROJECT_ID}"
# Unique IDが自動的に発行されます
Service Accountは以下から確認できます。
また、すでに Service Account に Role が付与されている場合は、IAM から確認することができます。 Role が存在しない場合は IAM に登場しないため、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 |
[+ Create Role]
をクリック[+Add permissions]
を入力Storage Object Viewer
、Storage Legacy Bucket Writer
、Storage Admin
をフィルターに追加し残った Permission をすべて追加します。
※ 権限が足りない場合、Access Denied
など様々なエラーがでるため、混乱することになります。
[IAM & Admin] > [IAM]
へ移動し、ADD
から先ほど作成した Service Account と Role を結びつけます
サービスアカウントはメールアドレスのフォーマットで生成されたものを利用します。
gcloud
コマンドの場合次のコマンドで有効化できます。
gcloud services enable iamcredentials.googleapis.com \
--project "${PROJECT_ID}"
コンソールの画面からだと、[IAM & Admin] > [Workload Identity Federation]
に行き、GET STARTED
をクリックすると有効化されます。
Workload ID Pool は外部サービスとの連携のために利用され、少なくとも 1 つ以上の Provider に接続することが必要です。
# プール名は後から変更できないので注意
gcloud iam workload-identity-pools create "my-pool" \
--project="${PROJECT_ID}" \
--location="global" \
--display-name="Demo pool"
gcloud iam workload-identity-pools describe "my-pool" \
--project="${PROJECT_ID}" \
--location="global" \
--format="value(name)"
変数に格納
export WORKLOAD_IDENTITY_POOL_ID="..."
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 |
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}"
コンソールでは、以下の手順で実施します。
GRANT ACCESS
をクリックして、権限移譲先のService Accountを選択するOnly identities matching the filter
を選択すると、先程登録したAttributeのrepository
を選択DOWNLOAD CONFIG
のポップアップが出てくるが不要なのでDISMISS
Service AccountにWorkload Identity User
のRoleが付与されていることが確認できます。
gcloud iam workload-identity-pools providers describe "my-provider" \
--project="${PROJECT_ID}" \
--location="global" \
--workload-identity-pool="my-pool" \
--format="value(name)"
以下の2つを利用してGitHub ActionsがらGoogle Cloudの認証を得ることができます。 裏側ではOIDCトークンの交換が行われています。
projects/$PROJECT_ID/locations/global/workloadIdentityPools/$WORKLOAD_IDENTITY_POOL_ID/providers/$PROVIDER_ID
のフォーマットhttps://iam.googleapis.com/
以降の文字列が同等Workload Identity User
の権限とContainer Registryにdocker pushするのに十分な権限を持つService Account最初実施すると手順は厄介ですが、地道に手を動かしてみると必要十分な手順であることがわかります。
認証のためにGitHub Actionsに指定するパラメーターがWorkload Identity Provider ID
とService Account email
のみになり、シークレットーキーをダウンロードする行為から開放されます。