共用方式為


在 ACR 工作中使用 Azure 受控識別進行跨登錄認證

ACR 工作中,您可以為 Azure 資源啟用受控識別。 工作可以使用該身分識別來存取其他 Azure 資源,而無需提供或管理認證。

本文說明如何在工作中啟用受控識別,以便從不同於執行工作所用的登錄提取映像。

若要建立 Azure 資源,本文需要您執行 Azure CLI 2.0.68 (含) 以上版本。 執行 az --version 以尋找版本。 如果您需要安裝或升級,請參閱安裝 Azure CLI

案例概觀

範例工作會從另一個 Azure 容器登錄提取基礎映像,以建立並推送應用程式映像。 要提取基礎映像,您需要將工作設定為受控識別並分配適當的權限。

此範例示範使用使用者指派或系統指派受控識別的步驟。 您選擇的身分識別取決於組織的需求。

在真實情境中,組織可能會維護一組基礎映像,供所有開發團隊用來建置其應用程式。 這些基礎映像存放在企業登錄中,每個開發團隊僅具有提取權限。

先決條件

本文需要兩個 Azure 容器登錄:

  • 您使用第一個登錄來建立並執行 ACR 工作。 在本文中,此登錄命名為 myregistry
  • 第二個登錄用來放置工作用於建立映像的基礎映像。 在本文中,第二個登錄命名為 mybaseregistry

在後續步驟中請以您自己的登錄名稱替換。

如果您尚未擁有所需的 Azure 容器登錄,請參考快速入門:使用 Azure CLI 建立私人容器登錄。 目前您尚不需要將映像推送至該登錄。

準備基礎登錄

為了示範,作為一次性操作,執行 az acr import 將 Docker Hub 的公開 Node.js 映像匯入您的基礎登錄。 實務上,組織中的其他團隊或流程可能會維護基礎登錄中的映像。

az acr import --name mybaseregistry \
  --source docker.io/library/node:15-alpine \
  --image baseimages/node:15-alpine 

在 YAML 檔案中定義工作步驟

此範例的多步驟工作步驟定義於 YAML 檔案中。 在本機工作目錄建立名為 helloworldtask.yaml 的檔案,並貼上以下內容。 在建置步驟中,將 REGISTRY_NAME 的值更新為您的基礎登錄的伺服器名稱。

version: v1.1.0
steps:
# Replace mybaseregistry with the name of your registry containing the base image
  - build: -t $Registry/hello-world:$ID  https://github.com/Azure-Samples/acr-build-helloworld-node.git#main -f Dockerfile-app --build-arg REGISTRY_NAME=mybaseregistry.azurecr.io
  - push: ["$Registry/hello-world:$ID"]

建置步驟使用 Azure-Samples/acr-build-helloworld-node 存放庫中的 Dockerfile-app 檔案來建立映像。 --build-arg 參考基礎登錄以提取基礎映像。 建置成功後,映像會推送到用於執行工作的登錄。

選項 1:使用使用者指派身分識別建立工作

本節中的步驟會建立一個工作並啟用使用者指派身分識別。 如果您想改為啟用系統指派身分識別,請參閱選項 2:使用系統指派身分識別建立工作

建立使用者指派的身分識別

使用 az identity create 命令在您的訂閱中建立名為 myACRTasksId 的身分識別。 您可以使用之前建立容器登錄檔的相同資源群組,或使用不同的資源群組。

az identity create \
  --resource-group myResourceGroup \
  --name myACRTasksId

在後續步驟中設定使用者指派身分識別時,使用 az identity show 命令將身分識別的資源 ID、主要 ID 與用戶端 ID 存入變數。

# Get resource ID of the user-assigned identity
resourceID=$(az identity show \
  --resource-group myResourceGroup \
  --name myACRTasksId \
  --query id --output tsv)

# Get principal ID of the task's user-assigned identity
principalID=$(az identity show \
  --resource-group myResourceGroup \
  --name myACRTasksId \
  --query principalId --output tsv)

# Get client ID of the user-assigned identity
clientID=$(az identity show \
  --resource-group myResourceGroup \
  --name myACRTasksId \
  --query clientId --output tsv)

建立工作

執行 az acr task create 命令建立工作 helloworldtask。 該工作在沒有原始程式碼內容的情況下執行,且命令會參考工作目錄中的 helloworldtask.yaml 檔案。 --assign-identity 參數會傳遞使用者指派身分識別的資源識別碼。

az acr task create \
  --registry myregistry \
  --name helloworldtask \
  --context /dev/null \
  --file helloworldtask.yaml \
  --assign-identity $resourceID

在命令輸出中,identity 區段會顯示已在工作中設定類型為 UserAssigned 的身分識別:

[...]
"identity": {
    "principalId": null,
    "tenantId": null,
    "type": "UserAssigned",
    "userAssignedIdentities": {
      "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/myResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myACRTasksId": {
        "clientId": "00001111-aaaa-2222-bbbb-3333cccc4444",
        "principalId": "aaaaaaaa-bbbb-cccc-1111-222222222222"
      }
[...]

授予身分識別對基礎登錄檔的提取權限。

在本節中,賦予受控識別從基礎登錄 mybaseregistry 提取的權限。

使用 az acr show 命令取得基礎登錄檔的資源 ID 並存入變數:

baseregID=$(az acr show --name mybaseregistry --query id --output tsv)

使用 az role assignment create 命令,將身分識別指派正確的角色給基底登錄。 此角色指派僅授與從映像庫提取映像的許可權。

角色指派中應使用的正確角色取決於登錄中心是否啟用 ABAC

ROLE="Container Registry Repository Reader" # For ABAC-enabled registries. For non-ABAC registries, use AcrPull.
az role assignment create \
  --assignee $principalID \
  --scope $baseregID \
  --role "$ROLE"

接著前往新增目標登錄憑證至工作

選項 2:使用系統指派身分識別建立工作

本節中的步驟會建立一個工作並啟用系統指派身分識別。 如果您想改為啟用使用者指派身分識別,請參閱選項 1:使用使用者指派身分識別建立工作

建立工作

執行 az acr task create 命令建立工作 helloworldtask。 該工作在沒有原始程式碼內容的情況下執行,且命令會參考工作目錄中的 helloworldtask.yaml 檔案。 不指定值的 --assign-identity 參數會在工作上啟用系統指派身分識別。

az acr task create \
  --registry myregistry \
  --name helloworldtask \
  --context /dev/null \
  --file helloworldtask.yaml \
  --assign-identity 

在命令輸出中,identity 區段會顯示已在工作中設定類型為 SystemAssigned 的身分識別。 principalId 是工作身分識別的主體識別碼:

[...]
  "identity": {
    "principalId": "aaaaaaaa-bbbb-cccc-1111-222222222222",
    "tenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee",
    "type": "SystemAssigned",
    "userAssignedIdentities": null
  },
  "location": "eastus",
[...]

使用 az acr task show 命令,將 principalId 儲存在變數中,以供後續命令使用。 請在下列命令中取代為您的工作名稱與登錄名稱:

principalID=$(az acr task show \
  --name <task_name> --registry <registry_name> \
  --query identity.principalId --output tsv)

授予身分識別對基礎登錄檔的提取權限。

在本節中,賦予受控識別從基礎登錄 mybaseregistry 提取的權限。

使用 az acr show 命令取得基礎登錄檔的資源 ID 並存入變數:

baseregID=$(az acr show --name mybaseregistry --query id --output tsv)

使用 az role assignment create 命令,將身分識別指派正確的角色給基底登錄。 此角色指派僅授與從映像庫提取映像的許可權。

角色指派中應使用的正確角色取決於登錄中心是否啟用 ABAC

ROLE="Container Registry Repository Reader" # For ABAC-enabled registries. For non-ABAC registries, use AcrPull.
az role assignment create \
  --assignee $principalID \
  --scope $baseregID \
  --role "$ROLE"

新增目標登錄憑證至工作

現在使用 az acr task credential add 命令,使工作能使用身份憑證與基礎登錄驗證。 依您在工作中啟用的受控識別類型,執行對應命令。 如果啟用的是使用者指派的身份,請傳入 --use-identity 並指定身份的用戶端 ID。 如果啟用的是系統指派的身份,請傳入 --use-identity [system]

# Add credentials for user-assigned identity to the task
az acr task credential add \
  --name helloworldtask \
  --registry myregistry \
  --login-server mybaseregistry.azurecr.io \
  --use-identity $clientID

# Add credentials for system-assigned identity to the task
az acr task credential add \
  --name helloworldtask \
  --registry myregistry \
  --login-server mybaseregistry.azurecr.io \
  --use-identity [system]

手動執行工作

若要驗證已啟用受控識別的工作是否成功執行,請使用 az acr task run 命令手動觸發工作。

az acr task run \
  --name helloworldtask \
  --registry myregistry

若工作執行成功,輸出類似如下:

Queued a run with ID: cf10
Waiting for an agent...
2019/06/14 22:47:32 Using acb_vol_dbfbe232-fd76-4ca3-bd4a-687e84cb4ce2 as the home volume
2019/06/14 22:47:39 Creating Docker network: acb_default_network, driver: 'bridge'
2019/06/14 22:47:40 Successfully set up Docker network: acb_default_network
2019/06/14 22:47:40 Setting up Docker configuration...
2019/06/14 22:47:41 Successfully set up Docker configuration
2019/06/14 22:47:41 Logging in to registry: myregistry.azurecr.io
2019/06/14 22:47:42 Successfully logged into myregistry.azurecr.io
2019/06/14 22:47:42 Logging in to registry: mybaseregistry.azurecr.io
2019/06/14 22:47:43 Successfully logged into mybaseregistry.azurecr.io
2019/06/14 22:47:43 Executing step ID: acb_step_0. Timeout(sec): 600, Working directory: '', Network: 'acb_default_network'
2019/06/14 22:47:43 Scanning for dependencies...
2019/06/14 22:47:45 Successfully scanned dependencies
2019/06/14 22:47:45 Launching container with name: acb_step_0
Sending build context to Docker daemon   25.6kB
Step 1/6 : ARG REGISTRY_NAME
Step 2/6 : FROM ${REGISTRY_NAME}/baseimages/node:15-alpine
15-alpine: Pulling from baseimages/node
[...]
Successfully built 41b49a112663
Successfully tagged myregistry.azurecr.io/hello-world:cf10
2019/06/14 22:47:56 Successfully executed container: acb_step_0
2019/06/14 22:47:56 Executing step ID: acb_step_1. Timeout(sec): 600, Working directory: '', Network: 'acb_default_network'
2019/06/14 22:47:56 Pushing image: myregistry.azurecr.io/hello-world:cf10, attempt 1
The push refers to repository [myregistry.azurecr.io/hello-world]
[...]
2019/06/14 22:48:00 Step ID: acb_step_1 marked as successful (elapsed time in seconds: 2.517011)
2019/06/14 22:48:00 The following dependencies were found:
2019/06/14 22:48:00
- image:
    registry: myregistry.azurecr.io
    repository: hello-world
    tag: cf10
    digest: sha256:611cf6e3ae3cb99b23fadcd89fa144e18aa1b1c9171ad4a0da4b62b31b4e38d1
  runtime-dependency:
    registry: mybaseregistry.azurecr.io
    repository: baseimages/node
    tag: 15-alpine
    digest: sha256:e8e92cffd464fce3be9a3eefd1b65dc9cbe2484da31c11e813a4effc6105c00f
  git:
    git-head-revision: 0f988779c97fe0bfc7f2f74b88531617f4421643

Run ID: cf10 was successful after 32s

執行 az acr repository show-tags 命令,以驗證映像已建置並成功推送至 myregistry

az acr repository show-tags --name myregistry --repository hello-world --output tsv

範例輸出︰

cf10

後續步驟