ACR タスクでの Azure マネージド ID を使用したクロスレジストリ認証

ACR タスクで、Azure リソースのマネージド ID を有効にすることができます。 その ID をタスクで使用すれば、資格情報を渡したり管理したりしなくても、他の Azure リソースにアクセスすることができます。

この記事では、タスクの実行に使用されるレジストリとは異なるレジストリからイメージをプルするためのタスクでマネージド ID を有効にする方法について説明します。

Azure リソースを作成するために、この記事では Azure CLI バージョン 2.0.68 以降を実行する必要があります。 バージョンを確認するには、az --version を実行します。 インストールまたはアップグレードする必要がある場合は、Azure CLI のインストールに関するページを参照してください。

シナリオの概要

この例のタスクでは、別の Azure コンテナー レジストリから基本イメージをプルし、アプリケーション イメージをビルドしてプッシュします。 基本イメージをプルするために、マネージド ID を使用してタスクを構成し、それに適切なアクセス許可を割り当てます。

この例では、ユーザー割り当てのマネージド ID またはシステム割り当てのマネージド ID を使用する手順について説明します。 どちらの ID を選ぶかは、所属する組織のニーズによって異なります。

実際のシナリオでは、組織は、アプリケーションをビルドするために、すべての開発チームが使用する一連の基本イメージを保持する場合があります。 これらの基本イメージは企業レジストリに保存され、各開発チームはプル権限のみ所有します。

前提条件

この記事では、次の 2 つの Azure コンテナー レジストリが必要です。

  • 最初のレジストリは、ACR タスクを作成して実行するために使います。 この記事では、このレジストリの名前を myregistry にします。
  • 2 番目のレジストリでは、タスクでイメージをビルドするときに使用される基本イメージをホストします。 この記事では、2 番目のレジストリの名前を mybaseregistry にします。

後のステップで、独自のレジストリ名に置き換えてください。

必要な Azure コンテナー レジストリがまだない場合は、「クイックスタート: Azure CLI を使用したプライベート コンテナー レジストリの作成」を参照してください。 まだレジストリにイメージをプッシュする必要はありません。

基本レジストリの準備

デモンストレーション目的で、1 回限りの操作として、[az acr import][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: ユーザー割り当て ID を使用してタスクを作成する

このセクションの手順では、タスクを作成してユーザー割り当て ID を有効にします。 システム割り当て ID を有効にする場合は、「オプション 2: システム割り当て ID を使用してタスクを作成する」を参照してください。

ユーザー割り当て ID を作成する

az identity create コマンドを使って、サブスクリプションに myACRTasksId という名前の ID を作成します。 前にコンテナー レジストリを作成するために使ったものと同じリソース グループ、または別のリソース グループを使用できます。

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

後の手順でユーザー割り当て ID を構成するために、az identity show コマンドを使用して、ID のリソース 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 を参照します。 ユーザー割り当て ID のリソース ID を --assign-identity パラメーターで渡します。

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

コマンドの出力の identity セクションでは、タスクで UserAssigned 型の ID が設定されたことが示されています。

[...]
"identity": {
    "principalId": null,
    "tenantId": null,
    "type": "UserAssigned",
    "userAssignedIdentities": {
      "/subscriptions/xxxxxxxx-d12e-4760-9ab6-xxxxxxxxxxxx/resourcegroups/myResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myACRTasksId": {
        "clientId": "xxxxxxxx-f17e-4768-bb4e-xxxxxxxxxxxx",
        "principalId": "xxxxxxxx-1335-433d-bb6c-xxxxxxxxxxxx"
      }
[...]

基本レジストリに対するプル アクセス許可を ID に付与する

このセクションでは、基本レジストリ mybaseregistry からプルするためのアクセス許可をマネージド ID に付与します。

az acr show コマンドを使用して基本レジストリのリソース ID を取得し、変数に格納します。

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

az role assignment create コマンドを使用して、基本レジストリに対する acrpull ロールを ID に割り当てます。 このロールには、レジストリからイメージをプルするためのアクセス許可のみがあります。

az role assignment create \
  --assignee $principalID \
  --scope $baseregID \
  --role acrpull

ターゲット レジストリの資格情報をタスクに追加する」に進んでください。

オプション 2:システム割り当て ID を使用してタスクを作成する

このセクションの手順では、タスクを作成してシステム割り当て ID を有効にします。 ユーザー割り当て ID を有効にする場合は、「オプション 1: ユーザー割り当て ID を使用してタスクを作成する」を参照してください。

タスクを作成する

次の az acr task create コマンドを実行して、タスク helloworldtask を作成します。 このタスクはソース コードのコンテキストなしで実行され、このコマンドは作業ディレクトリ内のファイル helloworldtask.yaml を参照します。 --assign-identity パラメーターを値なしで指定すると、システム割り当て ID がタスクで有効になります。

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

コマンドの出力の identity セクションでは、タスクで SystemAssigned 型の ID が設定されたことが示されています。 principalId は、タスク ID のプリンシパル ID です。

[...]
  "identity": {
    "principalId": "xxxxxxxx-2703-42f9-97d0-xxxxxxxxxxxx",
    "tenantId": "xxxxxxxx-86f1-41af-91ab-xxxxxxxxxxxx",
    "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)

基本レジストリに対するプル アクセス許可を ID に付与する

このセクションでは、基本レジストリ mybaseregistry からプルするためのアクセス許可をマネージド ID に付与します。

az acr show コマンドを使用して基本レジストリのリソース ID を取得し、変数に格納します。

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

az role assignment create コマンドを使用して、基本レジストリに対する acrpull ロールを ID に割り当てます。 このロールには、レジストリからイメージをプルするためのアクセス許可のみがあります。

az role assignment create \
  --assignee $principalID \
  --scope $baseregID \
  --role acrpull

ターゲット レジストリの資格情報をタスクに追加する

ここで、az acr task credential add コマンドを使用して、基本レジストリで ID の資格情報を使用して認証するためのタスクを有効にします。 タスクで有効にしたマネージド ID の種類に対応するコマンドを実行します。 ユーザー割り当て ID を有効にした場合は、ID のクライアント ID を指定して --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]

タスクを手動で実行する

マネージド ID を有効にしたタスクが正常に実行されていることを確認するには、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

次のステップ