サービス プリンシパルによる Azure Container Registry 認証

Microsoft Entra サービス プリンシパルを使って、コンテナー レジストリに対するプッシュ、プル、またはその他のアクセスを提供できます。 サービス プリンシパルを使うことで、「ヘッドレス」のサービスとアプリケーションへのアクセスを提供できます。

サービス プリンシパルとは

Microsoft Entra ID の "サービス プリンシパル" は、サブスクリプション内の Azure リソースへのアクセスを提供します。 サービス プリンシパルはサービスのユーザー ID と考えることができます。ここで "サービス" は、リソースへのアクセスが必要なアプリケーション、サービス、またはプラットフォームです。 指定したそれらのリソースのみをスコープとするアクセス権を持つサービス プリンシパルを構成できます。 その後、サービス プリンシパルの資格情報を使用してそれらのリソースにアクセスするようにアプリケーションまたはサービスを構成します。

Azure Container Registry のコンテキストでは、Azure 内のプライベート レジストリに対するプル、プッシュとプル、またはその他のアクセス許可を持つ Microsoft Entra サービス プリンシパルを作成できます。 完全な一覧については、Azure Container Registry のロールとアクセス許可に関するページを参照してください。

サービス プリンシパルを使う理由

Microsoft Entra サービス プリンシパルを使うことで、プライベート コンテナー レジストリへのスコープが設定されたアクセスを提供できます。 各アプリケーションや各サービスに異なるサービス プリンシパルを作成し、それぞれにレジストリへの調整済みのアクセス権を持たせます。 また、サービスやアプリケーションの間での資格情報の共有を避けることができるため、資格情報を交換したり、選択したサービス プリンシパル (および対象とするアプリケーション) のみのアクセスを取り消したりできます。

たとえば、イメージの pull アクセスのみを提供するサービス プリンシパルを使用するように Web アプリケーションを構成し、一方でビルド システムでは pushpull 両方のアクセスを提供するサービス プリンシパルを使用します。 アプリケーション開発の所有者が変わった場合は、ビルド システムに影響を与えずにそのサービス プリンシパルの資格情報を交換することができます。

サービス プリンシパルを使う場合

サービス プリンシパルは、ヘッドレス シナリオでレジストリへのアクセスを提供する際に使う必要があります。 つまり、自動的にまたはそれ以外の無人の方法でコンテナー イメージをプッシュまたはプルする必要があるすべてのアプリケーション、サービス、またはスクリプトが対象です。 次に例を示します。

  • Pull: レジストリからオーケストレーション システム (Kubernetes、DC/OS、Docker Swarm など) にコンテナーをデプロイします。 また、コンテナー レジストリから、App ServiceBatchService Fabric などの関連する Azure サービスにプルすることもできます。

    ヒント

    Azure コンテナー レジストリからイメージをプルするには、いくつかの Kubernetes シナリオでサービス プリンシパルをお勧めします。 またAzure Kubernetes Service (AKS) を使用して、クラスターのマネージド ID を有効にすることで、自動メカニズムを使用してターゲット レジストリ で認証することもできます。

    • Push: コンテナー イメージを作成し、継続的インテグレーションと Azure Pipelines や Jenkins などのデプロイ ソリューションを使用してレジストリにプッシュします。

コンテナー イメージを開発用ワークステーションに手動でプルするときなど、レジストリへの個別アクセスでは、代わりに各自の Microsoft Entra の ID を使ってレジストリにアクセスすることをお勧めします (az acr login を使うなど)。

サービス プリンシパルの作成

コンテナー レジストリへのアクセス権を持つサービス プリンシパルを作成するには、Azure Cloud Shell または Azure CLI のローカル インストールで、次のスクリプトを実行します。 スクリプトは Bash シェル用に書式設定されています。

スクリプトを実行する前に、ACR_NAME 変数をコンテナー レジストリの名前で更新します。 SERVICE_PRINCIPAL_NAME の値は、Microsoft Entra テナント内で一意である必要があります。 "'http://acr-service-principal' already exists." エラーが発生した場合は、別のサービス プリンシパルの名前を指定します。

別のアクセス権を付与する場合は、必要に応じて --role コマンドの --role の値を変更することができます。 ロールの一覧については、ACR のロールとアクセス許可に関するページを参照してください。

スクリプトを実行した後、サービス プリンシパルの IDパスワードを書き留めます。 その資格情報を作成したら、サービス プリンシパルとして、コンテナー レジストリに対する認証を受けるアプリケーションやサービスを構成できます。

#!/bin/bash
# This script requires Azure CLI version 2.25.0 or later. Check version with `az --version`.

# Modify for your environment.
# ACR_NAME: The name of your Azure Container Registry
# SERVICE_PRINCIPAL_NAME: Must be unique within your AD tenant
ACR_NAME=$containerRegistry
SERVICE_PRINCIPAL_NAME=$servicePrincipal

# Obtain the full registry ID
ACR_REGISTRY_ID=$(az acr show --name $ACR_NAME --query "id" --output tsv)
# echo $registryId

# Create the service principal with rights scoped to the registry.
# Default permissions are for docker pull access. Modify the '--role'
# argument value as desired:
# acrpull:     pull only
# acrpush:     push and pull
# owner:       push, pull, and assign roles
PASSWORD=$(az ad sp create-for-rbac --name $SERVICE_PRINCIPAL_NAME --scopes $ACR_REGISTRY_ID --role acrpull --query "password" --output tsv)
USER_NAME=$(az ad sp list --display-name $SERVICE_PRINCIPAL_NAME --query "[].appId" --output tsv)

# Output the service principal's credentials; use these in your services and
# applications to authenticate to the container registry.
echo "Service principal ID: $USER_NAME"
echo "Service principal password: $PASSWORD"

既存のサービス プリンシパルの使用

既存のサービス プリンシパルにレジストリへのアクセスを与えるには、サービス プリンシパルに新しいロールを割り当てる必要があります。 新しいサービス プリンシパルの作成と同様に、特に、プル、プッシュとプル、所有者のアクセスを付与できます。

次のスクリプトでは、az role assignment create コマンドを使って、SERVICE_PRINCIPAL_ID 変数で指定したサービス プリンシパルにプル アクセス許可を付与します。 異なるレベルのアクセスを付与する場合は、--role の値を調整します。

#!/bin/bash
# Modify for your environment. The ACR_NAME is the name of your Azure Container
# Registry, and the SERVICE_PRINCIPAL_ID is the service principal's 'appId' or
# one of its 'servicePrincipalNames' values.
ACR_NAME=$containerRegistry
SERVICE_PRINCIPAL_ID=$servicePrincipal

# Populate value required for subsequent command args
ACR_REGISTRY_ID=$(az acr show --name $ACR_NAME --query id --output tsv)

# Assign the desired role to the service principal. Modify the '--role' argument
# value as desired:
# acrpull:     pull only
# acrpush:     push and pull
# owner:       push, pull, and assign roles
az role assignment create --assignee $SERVICE_PRINCIPAL_ID --scope $ACR_REGISTRY_ID --role acrpull

サンプルのスクリプト

Azure CLI の以前のサンプル スクリプトを GitHub 上で検索できます。各バージョンの Azure PowerShell についても同様です。

サービス プリンシパルでの認証

コンテナー レジストリへのアクセスが許可されているサービス プリンシパルがある場合は、"ヘッドレス" サービスおよびアプリケーションにアクセスするための資格情報を構成するか、docker login コマンドを使用してそれらを入力することができます。 次の値を使用します。

  • ユーザー名 - サービス プリンシパルのアプリケーション (クライアント) ID
  • パスワード - サービス プリンシパルのパスワード (クライアント シークレット)

Username 値の形式は xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx です。

ヒント

az ad sp credential reset コマンドを実行することで、サービス プリンシパルのパスワード (クライアント シークレット) を再生成できます。

Azure サービスで資格情報を使用する

サービス プリンシパルの資格情報は、Azure コンテナー レジストリに対して認証を行うあらゆる Azure サービスから使用できます。 さまざまなシナリオで、レジストリの管理者の資格情報の代わりにサービス プリンシパルの資格情報を使用します。

Docker ログインで使用する

サービス プリンシパルを使用して docker login を実行できます。 次の例では、サービス プリンシパルのアプリケーション ID が環境変数 $SP_APP_ID に、パスワードが変数 $SP_PASSWD に渡されます。 Docker 資格情報の管理の推奨プラクティスについては、docker login コマンドのリファレンスを参照してください。

# Log in to Docker with service principal credentials
docker login myregistry.azurecr.io --username $SP_APP_ID --password $SP_PASSWD

ログインすると、Docker によって資格情報がキャッシュされます。

証明書と共に使用する

サービス プリンシパルに証明書を追加した場合は、証明書ベースの認証を使用して Azure CLI にサインインし、az acr login コマンドを使用してレジストリにアクセスできます。 パスワードの代わりに証明書をシークレットとして使用すると、CLI を使用するときのセキュリティが強化されます。

サービス プリンシパルを作成するときに、自己署名証明書を作成できます。 または、既存のサービス プリンシパルに 1 つ以上の証明書を追加します。 たとえば、この記事のスクリプトの 1 つを使用して、レジストリからイメージをプルまたはプッシュする権限を持つサービス プリンシパルを作成または更新する場合は、az ad sp credential reset コマンドを使用して証明書を追加します。

証明書と共にサービス プリンシパルを使用して Azure CLI にサインインするには、証明書を PEM 形式にして、秘密キーを含める必要があります。 証明書が必要な形式ではない場合は、openssl などのツールを使用して変換します。 az login を実行し、サービス プリンシパルを使用して CLI にサインインする場合は、サービス プリンシパルのアプリケーション ID と Active Directory テナント ID も指定します。 これらの値を環境変数として指定する例を次に示します。

az login --service-principal --username $SP_APP_ID --tenant $SP_TENANT_ID  --password /path/to/cert/pem/file

次に、az acr login を実行し、レジストリによる認証を受けます。

az acr login --name myregistry

CLI では、az login を実行したときに作成されたトークンが使用され、セッションがレジストリによる認証を受けます。

テナント間シナリオ用のサービス プリンシパルを作成する

サービス プリンシパルは、ある Microsoft Entra ID (テナント) 内のコンテナー レジストリから別のテナント内のサービスまたはアプリにイメージをプルする必要がある Azure のシナリオでも使用できます。 たとえば、組織は、テナント B の共有コンテナー レジストリからイメージをプルする必要があるアプリをテナント A で実行する場合があります。

テナント間のシナリオでコンテナー レジストリで認証できるサービス プリンシパルを作成するには、以下を行います。

  • テナント A でマルチテナント アプリ (サービス プリンシパル) を作成する
  • テナント B でアプリをプロビジョニングする
  • テナント B のレジストリからプルするサービス プリンシパルのアクセス許可を付与する
  • 新しいサービス プリンシパルを使用して認証を行うテナント A のサービスまたはアプリを更新する

手順の例については、「コンテナー レジストリから別の AD テナント内の AKS クラスターにイメージ をプルする」を参照してください。

サービス プリンシパルの更新

サービス プリンシパルは、有効期間 1 年で作成されます。 有効期間を 1 年より長くするオプションがあり、az ad sp credential reset コマンドを使って有効期限を指定することもできます。

次のステップ

  • Azure コンテナー レジストリによる認証を受けるその他のシナリオについては、認証の概要に関する記事を参照してください。

  • Azure キー コンテナーを使用してコンテナー レジストリのサービス プリンシパルの資格情報を格納および取得する例については、ACR タスクを使用したコンテナー イメージの構築とデプロイに関するチュートリアルを参照してください。