Managed Identity 是 Azure 提供的一種身份服務,專為 Azure 資源(如虛擬機、App Service、Functions 等)設計,用於簡化對其他 Azure 資源的安全存取。
啟用 Managed Identity 後,不需要手動管理資源的密碼或憑證,Azure 會自動為資源管理存取的權限。
Managed Identity 分為兩種類型
實作將透過 Azure App Service 進行,啟用 Managed Identity 後驗證是否正確以指定權限存取 Azure 資源。
# 透過 az-cli 登入 Azure
az login
# 建立資源群組
az group create -n <name> --location japanwest
# 建立 App Service Plan (價格方案)
az appservice plan create -n<name> -g <group-name> --sku FREE --is-linux
# 建立 App Service
az webapp create -n jj-appsvc -g jj-identity-gp -p <plan-name> --runtime "NODE:20-lts"
執行完以上指令建立完相關的資源後,可以回到 Azure Portal 查看。
az webapp identity assign -g <group-name> -n <webapp-name> --role reader --scope $(az group show -n <group-name> --query id --output tsv)
使用 Azure Portal
進入 Azure Portal 後,在建立出來的 App Service 開啟「系統指派」身分識別。
選擇角色指派
身分識別啟用後,在角色指派中設定對於 Azure 資源的存取權限,舉例:指定 App Service 可以對資源群組以 Reader 的角色進行操作。
啟用身分識別以及設定角色指派完成後,以下步驟以 API 方式存取 Azure 資源
curl "$IDENTITY_ENDPOINT?api-version=2019-08-01&resource=https://management.azure.com/" \
-H "Metadata: true" \
-H "X-IDENTITY-HEADER: $IDENTITY_HEADER"
在 App Service 開啟身分識別後會自動新增兩個系統變數,分別為 IDENTITY_ENDPOINT
和 IDENTITY_HEADER
,IDENTITY_ENDPOINT
為用來頒發 Token 的 Endpoint,IDENTITY_HEADER
為安全標頭,需帶在 X-IDENTITY-HEADER
,以防止 SSRF 攻擊。
{
"access_token": "<jwt-token>",
"expires_on": "1736323721",
"resource": "https://management.azure.com/",
"token_type": "Bearer",
"client_id": "<client-id>"
}
access_token="<access_token>"
subscription_id="<subscription_id>"
curl "https://management.azure.com/subscriptions/$subscription_id/resourceGroups/<group-name>/resources?api-version=2021-04-01" -H "Authorization: Bearer $access_token"
{
"value": [
{
"id": "<resource-id>",
"name": "jj-vm-ip",
"type": "Microsoft.Network/publicIPAddresses",
"sku": {
"name": "Basic"
},
"location": "japaneast"
}
... 以下省略
]
}
{
"error": {
"code": "AuthorizationFailed",
"message": "The client '<client-id>' with object id '<object-id>' does not have authorization to perform action 'Microsoft.Resources/subscriptions/resourceGroups/read' over scope '<subscription>' or the scope is invalid. If access was recently granted, please refresh your credentials."
}
}