使用服务主体的 Azure 容器注册表身份验证Azure Container Registry authentication with service principals

可以使用 Azure Active Directory (Azure AD) 服务主体提供对容器注册表的容器映像 docker pushpull 访问权限。You can use an Azure Active Directory (Azure AD) service principal to provide container image docker push and pull access to your container registry. 通过使用服务主体,可以提供对“无外设”服务和应用程序的访问权限。By using a service principal, you can provide access to "headless" services and applications.

什么是服务主体?What is a service principal?

Azure AD“服务主体” 提供对订阅中的 Azure 资源的访问权限。Azure AD service principals provide access to Azure resources within your subscription. 可以将服务主体视为某个服务的用户标识,其中,“服务”是需要访问资源的任何应用程序、服务或平台。You can think of a service principal as a user identity for a service, where "service" is any application, service, or platform that needs to access the resources. 可以为服务主体配置作用域仅限于你指定的那些资源的访问权限。You can configure a service principal with access rights scoped only to those resources you specify. 然后,将应用程序或服务配置为使用服务主体的凭据来访问这些资源。Then, configure your application or service to use the service principal's credentials to access those resources.

在 Azure 容器注册表的上下文中,你可以创建对 Azure 中的专用注册表具有拉取、推送和拉取或其他权限的 Azure AD 服务主体。In the context of Azure Container Registry, you can create an Azure AD service principal with pull, push and pull, or other permissions to your private registry in Azure. 有关完整列表,请参阅 Azure 容器注册表的角色和权限For a complete list, see Azure Container Registry roles and permissions.

为何使用服务主体?Why use a service principal?

通过使用 Azure AD 服务主体,可以针对专用容器注册表提供具有作用域的访问权限。By using an Azure AD service principal, you can provide scoped access to your private container registry. 可以为每个应用程序或服务创建不同的服务主体,每个服务主体对注册表具有定制的访问权限。Create different service principals for each of your applications or services, each with tailored access rights to your registry. 而且,因为你可以避免在各个服务和应用程序之间共享凭据,因此可以仅针对你选择的服务主体(和涉及的应用程序)滚动更新凭据或撤销访问权限。And, because you can avoid sharing credentials between services and applications, you can rotate credentials or revoke access for only the service principal (and thus the application) you choose.

例如,将 Web 应用程序配置为使用仅为其提供了映像 pull 访问权限的服务主体,而生成系统则使用为其提供了 pushpull 访问权限的服务主体。For example, configure your web application to use a service principal that provides it with image pull access only, while your build system uses a service principal that provides it with both push and pull access. 如果应用程序开发变更了人手,则你可以滚动更新其服务主体凭据且不会影响生成系统。If development of your application changes hands, you can rotate its service principal credentials without affecting the build system.

何时使用服务主体When to use a service principal

无外设方案中,应当使用服务主体来提供注册表访问。You should use a service principal to provide registry access in headless scenarios. 即,任何必须以自动或其他无人参与方式来推送或拉取容器映像的应用程序、服务或脚本。That is, any application, service, or script that must push or pull container images in an automated or otherwise unattended manner. 例如:For example:

  • 拉取:将容器从注册表部署到业务流程系统(包括 Kubernetes、DC/OS 和 Docker Swarm)。Pull: Deploy containers from a registry to orchestration systems including Kubernetes, DC/OS, and Docker Swarm. 还可以从容器注册表拉取到相关的 Azure 服务,例如 Azure Kubernetes 服务 (AKS)应用服务BatchService Fabric,等等。You can also pull from container registries to related Azure services such as Azure Kubernetes Service (AKS), App Service, Batch, Service Fabric, and others.

  • Push:构建容器映像并使用持续集成和部署解决方案(例如 Azure Pipelines 或 Jenkins)将它们推送到注册表。Push: Build container images and push them to a registry using continuous integration and deployment solutions like Azure Pipelines or Jenkins.

若要对注册表进行个人访问,例如手动将容器映像拉取到开发工作站时,我们建议改用你自己的 Azure AD 标识进行注册表访问(例如使用 az acr login)。For individual access to a registry, such as when you manually pull a container image to your development workstation, we recommend using your own Azure AD identity instead for registry access (for example, with az acr login).

创建服务主体Create a service principal

若要创建可以访问容器注册表的服务主体,请在本地安装的 Azure CLI 中运行以下脚本。To create a service principal with access to your container registry, run the following script in a local installation of the Azure CLI. 此脚本已针对 Bash Shell 格式化。The script is formatted for the Bash shell.

运行脚本之前,请将 ACR_NAME 变量更新为容器注册表的名称。Before running the script, update the ACR_NAME variable with the name of your container registry. SERVICE_PRINCIPAL_NAME 值必须在 Azure Active Directory 租户中唯一。The SERVICE_PRINCIPAL_NAME value must be unique within your Azure Active Directory tenant. 如果收到“'http://acr-service-principal' already exists.”错误,请为服务主体指定另一名称。If you receive an "'http://acr-service-principal' already exists." error, specify a different name for the service principal.

如果需要授予其他权限,可以选择修改 az ad sp create-for-rbac 命令中的 --role 值。You can optionally modify the --role value in the az ad sp create-for-rbac command if you want to grant different permissions.

运行脚本后,请记下服务主体的 ID密码After you run the script, take note of the service principal's ID and password. 获得其凭据后,可以配置应用程序和服务使其作为服务主体对容器注册表进行身份验证。Once you have its credentials, you can configure your applications and services to authenticate to your container registry as the service principal.

#!/bin/bash

# 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=<container-registry-name>
SERVICE_PRINCIPAL_NAME=acr-service-principal

# Obtain the full registry ID for subsequent command args
ACR_REGISTRY_ID=$(az acr show --name $ACR_NAME --query id --output tsv)

# Create the service principal with rights scoped to the registry.
# Default permissions are for docker pull access. Modify the '--role'
# argument value as desired:
# reader:      pull only
# contributor: push and pull
# owner:       push, pull, and assign roles
SP_PASSWD=$(az ad sp create-for-rbac --name $SERVICE_PRINCIPAL_NAME --scopes $ACR_REGISTRY_ID --role reader --query password --output tsv)
SP_APP_ID=$(az ad sp show --id http://$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: $SP_APP_ID"
echo "Service principal password: $SP_PASSWD"

使用现有的服务主体Use an existing service principal

若要向现有服务主体授予注册表访问权限,必须为服务主体分配新角色。To grant registry access to an existing service principal, you must assign a new role to the service principal. 与创建新的服务主体一样,可以授予“拉取”、“推送和拉取”以及“所有者”访问权限。As with creating a new service principal, you can grant pull, push and pull, and owner access.

以下脚本使用 az role assignment create 命令向 SERVICE_PRINCIPAL_ID 变量中指定的服务主体授予“拉取”权限。The following script uses the az role assignment create command to grant pull permissions to a service principal you specify in the SERVICE_PRINCIPAL_ID variable. 如果要授予不同的访问级别,请调整 --role 值。Adjust the --role value if you'd like to grant a different level of access.

#!/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=mycontainerregistry
SERVICE_PRINCIPAL_ID=<service-principal-ID>

# 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:
# reader:      pull only
# contributor: push and pull
# owner:       push, pull, and assign roles
az role assignment create --assignee $SERVICE_PRINCIPAL_ID --scope $ACR_REGISTRY_ID --role reader

示例脚本Sample scripts

可以在 GitHub 上找到前面的 Azure CLI 示例脚本以及 Azure PowerShell 所对应的版本:You can find the preceding sample scripts for Azure CLI on GitHub, as well as versions for Azure PowerShell:

使用服务主体进行身份验证Authenticate with the service principal

你拥有已授予对容器注册表的访问权限的服务主体后,就可以配置其凭据以访问“无外设”服务和应用程序,或者使用 docker login 命令输入它们。Once you have a service principal that you've granted access to your container registry, you can configure its credentials for access to "headless" services and applications, or enter them using the docker login command. 使用以下值:Use the following values:

  • 用户名 - 服务主体应用程序 ID(也称为客户端 IDUser name - service principal application ID (also called client ID)
  • 密码 - 服务主体密码(也称为客户端密码Password - service principal password (also called client secret)

每个值都是格式为 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 的 GUID。Each value is a GUID of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.

提示

可通过运行 az ad sp reset-credentials 命令重新生成服务主体的密码。You can regenerate the password of a service principal by running the az ad sp reset-credentials command.

在 Azure 服务中使用凭据Use credentials with Azure services

可以使用通过 Azure 容器注册表进行身份验证的任何 Azure 服务的服务主体凭据。You can use service principal credentials from any Azure service that authenticates with an Azure container registry. 许多情况下可以使用服务主体凭据来代替注册表的管理员凭据。Use service principal credentials in place of the registry's admin credentials for a variety of scenarios.

在 docker login 中使用Use with docker login

可以使用服务主体运行 docker loginYou can run docker login using a service principal. 在以下示例中,服务主体应用程序 ID 将传入到环境变量 $SP_APP_ID 中,密码将传入到变量 $SP_PASSWD 中。In the following example, the service principal application ID is passed in the environment variable $SP_APP_ID, and the password in the variable $SP_PASSWD. 有关管理 Docker 凭据的最佳做法,请参阅 docker login 命令参考。For best practices to manage Docker credentials, see the docker login command reference.

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

登录后,Docker 将缓存凭据。Once logged in, Docker caches the credentials.

与证书一起使用Use with certificate

如果已将证书添加到服务主体,则可使用基于证书的身份验证登录到 Azure CLI,然后使用 az acr login 命令访问注册表。If you've added a certificate to your service principal, you can sign into the Azure CLI with certificate-based authentication, and then use the az acr login command to access a registry. 使用 CLI 时,使用证书作为机密而不是密码可以提高安全性。Using a certificate as a secret instead of a password provides additional security when you use the CLI.

可以在创建服务主体时创建自签名证书。A self-signed certificate can be created when you create a service principal. 也可向现有服务主体添加一个或多个证书。Or, add one or more certificates to an existing service principal. 例如,如果使用本文中的多个脚本中的一个来创建或更新有权通过注册表拉取或推送映像的服务主体,请使用 az ad sp credential reset 命令来添加证书。For example, if you use one of the scripts in this article to create or update a service principal with rights to pull or push images from a registry, add a certificate using the az ad sp credential reset command.

若要使用服务主体和证书登录到 Azure CLI,证书必须为 PEM 格式且包含私钥。To use the service principal with certificate to sign into the Azure CLI, the certificate must be in PEM format and include the private key. 如果证书未采用所需格式,请使用 openssl 之类的工具来转换它。If your certificate isn't in the required format, use a tool such as openssl to convert it. 当你运行 az login 以使用服务主体登录到 CLI 时,另请提供服务主体的应用程序 ID 和 Active Directory 租户 ID。When you run az login to sign into the CLI using the service principal, also provide the service principal's application ID and the Active Directory tenant ID. 下面的示例演示这些充当环境变量的值:The following example shows these values as environment variables:

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

然后运行 az acr login,通过注册表进行身份验证:Then, run az acr login to authenticate with the registry:

az acr login --name myregistry

CLI 使用你运行 az login 时创建的令牌,通过注册表对会话进行身份验证。The CLI uses the token created when you ran az login to authenticate your session with the registry.

后续步骤Next steps