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