前情提介
現況用 Service Account 會有什麼問題?
當我們希望與第三方的服務與 GCP 作整合時,
傳統的(我之前的)作法是透過建立 Service Account Key 去提供給第三方資源存取的權限。
這會產生資安隱患,主要是這把 Key 的權粒度大難以稽核,有效期長風險,
而要定期更換 Key 會變成一個麻煩的管理問題。
需求介紹
我目前透過 GCS 並掛載 Load Balancing 部署靜態網站,
而 CI/CD 是透過 Service Account 的 Key 去執行工作,
這是一種有資安隱憂的作法,所以我試著使用 Workload Identity Federation 取代
概念
TLDR;
而 Workload Identity Federation 是基於 IAM 機制,允許第三方服務整合 GCP 資源,
背後的技術原理是基於 OIDC, 在這裡我們不過度展開,簡單描述如下:
- Gitlab CI/CD 首先取 Gitlab OIDC Token,取得 Token 的作法可以參考官方文件,下面是個簡單的範例:
1 |
|
|OIDC 是基於 Oauth2 的標準,簡單可以想成 Oauth2 再加上身份驗証。
2. 有了 Gitlab OIDC Token,我們可以透過 GOOGLE STS(Security Token Service) API 取得 Federated Token
在這裡我們需要先建立好 Workload Identity Provider(IdP),而可以設定 Attribute Conditions 來作限制
3. 這個時候可以用 Federated Token 與 GCP IAM API 交換來一個短周期的 Access Token
4. 本質上還是用 Service Account 在作事,但是用短周期的 Access Token 取代 Key, 從而簡化了 Key 的管理工作
實作步驟
建立 Workload Identity Pool
1
2
3
4
5
6Update $GCP_PROJECT_ID value
gcloud iam workload-identity-pools create gitlab-test-wip \
--location="global" \
--description="Gitlab demo workload Identity pool" \
--display-name="gitlab-test-wip" \
--project=$GCP_PROJECT_ID設定 workload identity pool provider 並建立 Attribute conditions,
這步的關鍵是讓只符合你條件設定的 User 才能取得 Token1
2
3
4
5
6
7
8
9Update GITLAB_NAMESPACE_PATH value
gcloud iam workload-identity-pools providers create-oidc gitlab-identity-provider --location="global" \
--workload-identity-pool="gitlab-test-wip" \
--issuer-uri="https://gitlab.com" \
--allowed-audiences=https://gitlab.com \
--attribute-mapping="google.subject=assertion.sub,attribute.aud=assertion.aud,attribute.project_path=assertion.project_path,attribute.project_id=assertion.project_id,attribute.namespace_id=assertion.namespace_id,attribute.namespace_path=assertion.namespace_path,attribute.user_email=assertion.user_email,attribute.ref=assertion.ref,attribute.ref_type=assertion.ref_type" \
--attribute-condition="assertion.namespace_path.startsWith(\"$GITLAB_NAMESPACE_PATH\")" \
--attribute-condition="assertion.namespace_path.startsWith(\"marsen\")" \
--project=$GCP_PROJECT_ID建立 GCP Service Account
在我的例子中1
2
3
4
5
6
7Create a service account
gcloud iam service-accounts create gitlab-runner-sa --project=$GCP_PROJECT_ID
Add sample permissions to the Service account
gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \
--member=serviceAccount:gitlab-wif-demo@${GCP_PROJECT_ID}.iam.gserviceaccount.com \
--role=roles/storage.admin建立 Service Account 與 WIP 的角色關係綁定
可以先取得專案的 GCP Project Id
1
PROJECT_NUMBER=$(gcloud projects describe $(gcloud config get-value core/project) --format=value\(projectNumber\) --project $GCP_PROJECT_ID)
設定 Service Account 的角色為 workloadIdentityUser,並將其設定為 workloadIdentityPools 的服務帳戶
1
2
3gcloud iam service-accounts add-iam-policy-binding gitlab-runner-sa@${GCP_PROJECT_ID}.iam.gserviceaccount.com \
--role=roles/iam.workloadIdentityUser \
--member="principalSet://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/gitlab-test-wip/*"建立 Gitlab CI/CD 進行測試
1 | image: node:20.9.0-alpine |
參考
- https://cloud.google.com/iam/docs/workload-identity-federation
- https://www.youtube.com/watch?v=4vajaXzHN08
- GCP IAM generateAccessToken
- Security Token Service API
- Workload 可能的資安風險:How Attackers Can Exploit GCP’s Multicloud Workload Solution
- OIDC 相關
- OIDC(OpenID Connection)
- Ory - OAuth2 and OpenID Connect
- Gitlab OIDC
- 一文带你搞懂OAuth2.0
- 彻底搞懂OAuth2.0第三方授权免登原理
- 認識 OAuth 2.0:一次了解各角色、各類型流程的差異
- Google Oauth2 API Explained
- 深入淺出 OpenID Connect (一)
- Use Workload Identity Federation with another GCP project
- How does the GCP Workload Identity Federation work with Github Provider?
- How to use GCP services securely from AWS with Workload Identity Federation
- [實作筆記] Gitlab CI/CD 與 GCP 相關文章
(fin)