【How-to Guides】MultiCloud — 以 Identity Federation 建立跨雲信任機制(GCP to Azure Part1.)

Establishing Cross-Cloud Trust with Identity Federation: GCP to Azure (Part 1)

Kellen
17 min readJun 16, 2024
Amsterdam

接續前篇 Multi Cloud 跨雲溝通,這次來驗證 GCP to Azure 這段!

📕 【How-to Guides】MultiCloud — 以 Identity Federation 建立跨雲信任機制(Azure to GCP)

目的與上篇一致,是希望作到以身份來進行授權認證,解決配發 credential 後的保管、輪替及外洩等議題。

我們先來看看一般外部存取 Azure 資源常見狀況

  1. 首先在 Azure AD 中建立 App Registration,並在 Azure 中為其授予必要的權限
  2. 接續可能會配置應用程序的 credential,並在 Google 的服務中使用該 credential 從 Azure AD 請求該應用程式的存取權杖

建議上述的流程是可以改成 Azure AD workload identity federation,例如當有需要跨雲溝通時 GCP➡️Azure,可以避免在 Azure AD 中建立這些機密及延伸後續管理、更換議題,比較好的作法是將 Azure AD 應用程式設定為信任 Google 所頒發的令牌,從 Google 服務使用 Azure AD 工作負載身分聯合簡單分為兩個部分:

  1. 設定 Google Cloud 中的服務帳號,Google 將向其頒發令牌,配置 Azure AD 應用程式以信任該 Google 令牌
  2. 資訊流的話會先在 GCP 取得服務的令牌並將其兌換為 Azure AD 令牌後,存取 Azure 資源

Step1. 設定篇

  1. 拿取 Google Service Account 的 Unique ID
  2. Configure Azure AD application 以信任 Google Service Account

Step2. 資訊流 — 在 Azure 的視角來看

  1. 請求外部 IdP 的令牌:外部工作負載(如 GCP workload)向外部 IdP(如 GCP)請求令牌
  2. 外部 IdP 發出令牌:外部 IdP 向外部工作負載發出令牌
  3. 外部工作負載向 Microsoft identity platform 請求存取權杖:外部工作負載(如 GCP)將該令牌發送給 Microsoft identity platform,並請求存取權杖
  4. 驗證信任關係和外部令牌:Microsoft identity platform 檢查在 user-assigned managed identityapp registration 上的信任關係,並根據外部 IdP 的 OIDC 發行者 URL 驗證外部令牌
  5. 發出存取權杖:當所有檢查滿足條件後,Microsoft identity platform 向外部工作負載發出存取權杖
  6. 使用存取權杖訪問 Microsoft Entra 保護的資源:外部工作負載使用從 Microsoft identity platform 獲取的存取權杖來訪問 Microsoft Entra 保護的資源。例如,GCP 工作流使用存取權杖將 GCP function 結束時進行 Teams 通知或是再續接 logic app 作業

官方解釋原文出處參考

https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation


簽名密鑰管理:Microsoft identity platform 僅儲存從外部 IdP 的 OIDC 端點下載的前 100 個簽名密鑰。如果外部 IdP 暴露超過 100 個簽名密鑰,可能會在使用工作負載身份聯合時出現錯誤。

Step by step part.

👣 Step00: 準備好 Google Cloud 的 service account 及相關資訊

GCP 上的 Access Token 是不可解碼的,而 ID Token 是基於 JWT 格式,可以解碼並檢查其內容。Azure 需要檢查令牌的內容來映射應用程式註冊,並確認令牌的頒發者是 Google

GCP > IAM > Service Account 找到 unique id

每個服務帳戶都有一個「唯一ID」,然後複製其唯一 ID

當您在 Azure 中設定 Identity Federation 認證時,需要指定外部(例如GCP)工作負載的身份標識,以建立與之的「信任」關係。這個身份標識通常是外部識別提供者(IdP)中的特定使用者、群組或服務帳戶。

對於外部軟體工作負載,可能會有不同的身份標識格式,這取決於使用的外部識別提供者和其特定配置。因此,在設定 Identity Federation 認證時,必須確保提供正確的 subject 資訊,以便 Azure Active Directory 可以驗證外部軟體工作負載的身份,例如使用者(userPrincipalName 或 objectId)、群組(group objectId)、服務主體(servicePrincipalName 或 objectId)。

為了建立與 Azure AD 應用程式的信任,您需要在 Google Cloud 中建立一個專用服務帳戶,並將其與您的 Azure AD 應用程式關聯。當 Google 向服務帳戶頒發令牌時,這些令牌將包含唯一的 ID 作為主題聲明,而發行者聲明將為「https://accounts.google.com」。這些詳細資訊將用於配置對 Azure AD 應用程式的信任,以允許您的應用程式信任 Google 向您的服務帳戶發出的令牌。

👣 Step01: 在 Azure 新增 App Registration

目的是在 Azure 中配置 App Registration 以允許來自來源 GCP 服務帳戶

az ad sp create-for-rbac \
--name gcp-to-azure \
--role "Reader" \
--scopes "/subscriptions/<subscription>"

👣 Step02: 在 Azure 中準備 credential.json 文件

Issuer: https://accounts.google.com
Subject: 1234567890987654321
Audience: api://AzureADTokenExchange

實際用途
作為 Step03 前置作業,準備聯邦憑證用意主要是用於允許從 GCP 到 Azure 的 workload identity federation,這意味著 GCP 上的服務帳戶可以通過這個憑證來訪問 Azure 資源,這個前置 JSON 文件包含創建聯邦憑證所需參數

credential.json sample

{ 
"name": "AccessFromGoogle",
"issuer": "https://accounts.google.com",
"subject": "1234567890987654321",
"audiences": ["api://AzureADTokenExchange"],
"description": "This is GCP to Azure workload identity federatoin"
}
  • audiences:指定聯邦憑證可以使用的受眾(audience),本例採 Azure 建議 api://AzureADTokenExchange
  • description:描述這個聯邦憑證的用途
  • issuer:這與身分提供者頒發的令牌中的「iss」聲明相符。這必須是符合 OIDC 規範的 URL。 Azure AD 將使用此頒發者 URL 來取得驗證令牌所需的金鑰。對 GCP 而言,發行者是 https://accounts.google.com
  • name:聯邦憑證的名稱
  • subject:這應該與其他身分提供者(例如 Google)頒發的令牌中的「sub」聲明相符。這是您計劃使用的服務帳戶的唯一 ID,也是聯邦憑證的主體,放入 👣 Step01 準備好的 GCP service account 唯一用戶 ID

👣 Step03: 在 Azure 創建 federated credentials in App Registration

接續在 Azure Active Directory(Azure AD)應用程式中創建一個聯邦憑證(federated credential),然後他的實際用途是望這個聯邦憑證用於允許從 GCP 到 Azure 的 workload identity federation,這意味著 GCP 上的服務帳戶可以通過這個憑證來訪問 Azure 資源。

指令說明

命令 az ad app federated-credential create 用來創建一個聯邦憑證

  • --id <appid>:指定 Azure AD 應用程式的 ID。
  • --parameters credential.json:指定包含聯邦憑證參數的 JSON 文件。

此操作發生在 Azure Active Directory 中應用程式註冊的聯合憑證部分,需要指定受信任的發行者、主題與 audi

# azure cli 解說
# az ad app federated-credential create 用來創建一個聯邦憑證
# --id 指定 Azure AD 應用程式的 ID
# --parameters credential.json:指定包含聯邦憑證參數的 JSON 文件

az ad app federated-credential create --id <appid> \
--parameters credential.json


# 執行後結果
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#applications('xxx')/federatedIdentityCredentials/$entity",
"audiences": [
"api://AzureADTokenExchange"
],
"description": "This is GCP to Azure workload identity federatoin",
"id": "xxx",
"issuer": "https://accounts.google.com",
"name": "AccessFromGoogle",
"subject": "102736331473793152012"
}

回傳結果解釋

  • @odata.context:表示返回資料的上下文 URL
  • audiences:指明聯邦憑證可使用的受眾
  • description:描述聯邦憑證的用途
  • id:聯邦憑證的唯一 ID
  • issuer:憑證的簽發者
  • name:聯邦憑證的名稱
  • subject:聯邦憑證的主體

總結
這段指令和回傳結果顯示了如何在 Azure AD 中設置聯邦身份憑證,使得來自 GCP 身份可以訪問 Azure 的資源,實現跨平台的身份聯邦和資源訪問。現在我們已經將 Azure AD 應用程式設定為信任 Google 服務帳戶,我們準備從 Google 取得令牌並將其交換為 Azure AD 存取權令牌,

👣 Step04: 產生 GCP ID Token

首先,需要代表來源服務帳戶產生 ID Token(❶❷)!這裡我們需要一個 JWT 令牌,Azure 需要能夠檢查令牌的內容以映射另一側的應用程式註冊並檢查頒發者是否是 Google(❸)。

對於此步驟,如果您的工作負載在 GCP 中運行,可以使用元資料伺服器,也可以使用 gcloud CLI(或任何其他可用的方法)。結果將返回一個有效的 ID Token。

註:要將 audience 與前面配置 audience 相符 api://AzureADTokenExchange

method1. 使用 gcloud CLI(我選用此測試)

# 僅用於測試目的,營運使用會有效能等議題
gcloud auth print-identity-token \
--impersonate-service-account=SOURCE_SERVICE_ACCOUNT_EMAIL \
--audiences=api://AzureADTokenExchange

method2. 使用神奇的元資料伺服器 URL

# 進入到 GCP VM 裡頭之中
curl -H "Metadata-Flavor: Google" \
'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=api://AzureADTokenExchange'
Result

取得您的 Google 服務帳戶的 ID 令牌
如前所述,Google 雲端資會自動使用您的 Google 專案的預設服務帳戶。也可以在部署服務時將應用程式引擎配置為使用不同的服務帳戶。服務可以從處理此類請求的「元資料服務端點」請求該服務帳戶的ID 令牌。透過這種方法,您的服務帳戶不需要任何金鑰:這些都由 Google 管理。
📕 Authenticating applications directly with access tokens

👣 Step05: 將 GCP ID 令牌交換為 Azure 存取權杖

➍➎使用身份令牌獲取 Azure 的訪問令牌并解析 JSON 響應

最後您需要將 GCP ID 令牌交換為 Azure 存取權杖(➍➎),您需要透過指定下列參數向 Azure Oauth2 授權伺服器發出請求(➏)

  • client_id 到您的應用程式註冊 ID
  • scope 根據您的代幣的未來使用情況,達到所需的範圍,
  • client_assertion_typeurn:ietf:params:oauth:client-assertion-type:jwt-bearer
  • grant_typeclient_credentials
  • 最重要的是 GCP ID 令牌是 client_assertion

解析 JSON 響應拿到 Azure 存取權杖,以便在 Azure 端執行您想要的操作

👣 Step06: 在 GCP 端中執行對 Azure 資源的存取

例如本例對 subscription 項下的 resource group 作 list

https://learn.microsoft.com/en-us/rest/api/resources/resource-groups/list?view=rest-resources-2021-04-01

👣 Step07: 驗證程式

先來看一下成果,程式碼是沒有 crediential 的喔!

測試程式碼 id-test.sh

# Step04: 產生 GCP ID Token
sa_token=$(gcloud auth print-identity-token \
--impersonate-service-account=gcp-to-azure@helloworld.iam.gserviceaccount.com \
--audiences=api://AzureADTokenExchange)

# Step05: 產生 GCP ID Token
# 使用身份令牌獲取 Azure 的訪問令牌並解析 JSON 響應
response=$(curl -X POST 'https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=xxxx' \
--data-urlencode 'scope=https://management.azure.com/.default' \
--data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
--data-urlencode "client_assertion=${sa_token}" \
--data-urlencode 'grant_type=client_credentials')

# Step06: 在 GCP 端中執行對 Azure 資源的存取
# 提取 access_token 並保存到變量中
access_token=$(echo $response | jq -r '.access_token')
curl -X GET 'https://management.azure.com/subscriptions/{subscription-id}/resourcegroups?api-version=2021-04-01' \
--header 'Authorization: Bearer $access_token'

Step 5 輸出示意參考

# Step05 Reponse sample
{
"token_type": "Bearer",
"expires_in": 3599,
"ext_expires_in": 3599,
"access_token": "eyJ0eXAiO********" # JWT token
}

成功,測通 end-to-end 的授權認證的測試後,可以再開始改使用 SDK 就比較快速也比較理解 MultiCloud 身份認證的原理。

從 GCP impersonate 服務帳戶的權限開始訪問 Azure 資源

--

--

Kellen

Backend(Python)/K8s and Container eco-system/Technical&Product Manager/host Developer Experience/早期投入資料創新與 ETL 工作,近期研究 GCP/Azure/AWS 相關的解決方案的 implementation