Skip to main content

透過 GitHub Actions 向 Google Cloud 進行身份驗證

google-github-actions/auth 提供了三種方式向 Google Cloud 進行身份驗證:

  1. (Preferred) Direct Workload Identity Federation
  2. Workload Identity Federation through a Service Account
  3. Service Account Key JSON

目前最推薦的身份驗證方式是使用 Direct Workload Identity Federation, 這種方法允許 Workload Identity Pool 直接對 Google Cloud 資源擁有 IAM 權限,無需透過中介的服務帳戶 (Service Account) 或密鑰 (Key) 進行身份驗證, 這邊記錄一下如何使用這個方式進行身份驗證

前提

上面的操作前提基於已經有一個 Google Cloud 的專案, 並且已經在該專案中建立了一個 Service Account 以及賦予相關操作的權限, 以便於待會我們使用 gcloud 進行後續操作

Workload Identity Pool

建立 Workload Identity Pool

gcloud iam workload-identity-pools create "${POOL_NAME}" \
--project="${PROJECT_ID}" \
--location="global" \
--display-name="${DISPLAY_NAME}"
  • PROJECT_ID: Google Cloud 專案 ID
  • POOL_NAME: Workload Identity Pool 名稱
  • DISPLAY_NAME: Workload Identity Pool 顯示名稱

google-auth-1.png

取得 Workload Identity Pool ID

gcloud iam workload-identity-pools describe "${POOL_NAME}" \
--project="${PROJECT_ID}" \
--location="global" \
--format="value(name)"

會得到以下格式的值

projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${POOL_NAME}

建立 Workload Identity Provider (OIDC)

gcloud iam workload-identity-pools providers create-oidc "${PROVIDER_NAME}" \
--project="${PROJECT_ID}" \
--location="global" \
--workload-identity-pool="${POOL_NAME}" \
--display-name="${PROVIDER_DISPLAY_NAME}" \
--attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository,attribute.repository_owner=assertion.repository_owner" \
--attribute-condition="assertion.repository_owner == '${GITHUB_ORG}'" \
--issuer-uri="https://token.actions.githubusercontent.com"

google-auth-2.png

這個指令用於建立一個 OpenID Connect (OIDC) 類型的 Workload Identity Provider, 它允許 Google Cloud 服務通過外部身份提供者 (在這邊是 GitHub Actions) 進行身份驗證.

  • PROVIDER_NAME: Workload Identity Provider 名稱
  • --attribute-mapping: 將來自 GitHub Actions 的身份驗證聲明 (claims) 轉換為 Google Cloud 可識別的身份屬性
  • PROVIDER_DISPLAY_NAME: Workload Identity Provider 顯示名稱
  • GITHUB_ORG: GitHub 組織名稱
  • --issuer-uri: 指定發行者的統一資源標識符(uri), 這邊設定 GitHub Actions 的 OIDC 發行者 uri, Google Cloud 會使用這個 uri 來驗證來自 GitHub Actions 的 OIDC token
  • --attribute-condition: 為了增加安全性, 建議限制訪問的條件, 這邊設定只有來自指定 GitHub 組織的身份才能通過驗證

取得 Workload Identity Provider resource name

gcloud iam workload-identity-pools providers describe "${PROVIDER_NAME}" \
--project="${PROJECT_ID}" \
--location="global" \
--workload-identity-pool="${POOL_NAME}" \
--format="value(name)"

會得到以下格式的值

projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${POOL_NAME}/providers/${PROVIDER_NAME}

在 GitHub Actions 中設定

ci.yml
name: Action
env:
GAR_LOCATION: YOUR_ARTIFACT_REGISTRY_LOCATION # ex: asia-east1
REPOSITORY: YOUR_ARTIFACT_REGISTRY_REPOSITORY_NAME # ex: my-repo

jobs:
api:
# Add "id-token" with the intended permissions.
permissions:
id-token: write
contents: read
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4 # Must come first!

- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v2
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
workload_identity_provider: ${{ secrets.WIF_PROVIDER }}

- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v2

- name: Build and Push to Gcs
run: |
gsutil cp gs://${{ env.BUCKET_FOLDER }}/api/.env.staging apps/api/.env
gcloud auth configure-docker ${{ env.GAR_LOCATION }}-docker.pkg.dev
service=api
tag=${{ github.event.inputs.tag }}
docker build --build-arg TURBO_TOKEN=${{ secrets.TURBO_TOKEN }} --build-arg TURBO_TEAM=${{ secrets.TURBO_TEAM }} -t ${{ env.GAR_LOCATION }}-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/${{ env.REPOSITORY }}/$service:$tag -f ./dockerfiles/$service.Dockerfile . --no-cache
docker push "${{ env.GAR_LOCATION }}-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/${{ env.REPOSITORY }}/$service:$tag"
note

機密資訊應放在 GitHub Secrets 中, ex: WIF_PROVIDER

google-auth-3.png

允許 Workload Identity Pool 到 Google Cloud 資源進行身份驗證

為了讓 github action 可以將 resource 存取至 Google Artifact Registry (GAR), 需要將 Workload Identity Pool 設定為具有相應的 IAM 權限

gcloud projects add-iam-policy-binding "my-secret" \
--project="${PROJECT_ID}" \
--member="principalSet://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${POOL_NAME}/attribute.repository/${REPO}"
--role="roles/artifactregistry.writer"
--condition="expression=resource.type=='artifactregistry.googleapis.com/Repository',title=Artifact Registry Write Access"
  • REPO: 完整的 GitHub Repository 名稱, 包含組織(使用者)名稱, ex: my-org/my-repo
  • --role: 設定 Workload Identity Pool 的 IAM 權限, 這邊設定為 roles/artifactregistry.writer, 允許 Workload Identity Pool 寫入 Artifact Registry
  • --condition: 限制 Workload Identity Pool 的訪問條件, 這邊設定為只有當 resource type 為 artifactregistry.googleapis.com/Repository 時才允許寫入

當上面指令完成後, 可以至 GCP 的 IAM 底下看到我們剛剛建立的 Workload Identity Pool 所對應的 IAM 權限及對應的 Role (你也可以再手動調整成所需權限)

google-auth-4.png


最後就可以執行 GitHub Actions 測試

google-auth-5.png

refs