Autenticación externa en una tarea de ACR mediante una identidad administrada por Azure

En una tarea de ACR, puede habilitar una identidad administrada para recursos de Azure. La tarea puede usar la identidad para acceder a otros recursos de Azure, sin necesidad de proporcionar o de administrar credenciales.

En este artículo, aprenderá a habilitar una identidad administrada en una tarea que tiene acceso a los secretos almacenados en un almacén de claves de Azure.

Para crear los recursos de Azure, en este artículo es necesario ejecutar la CLI de Azure versión 2.0.68 o posterior. Ejecute az --version para encontrar la versión. Si necesita instalarla o actualizarla, vea Instalación de la CLI de Azure.

Información general de escenario

La tarea de ejemplo lee las credenciales de Docker Hub almacenadas en un almacén de claves de Azure. Las credenciales son para una cuenta de Docker Hub con permisos de escritura (envío de cambios) en un repositorio privado de Docker Hub. Para leer las credenciales, configurará la tarea con una identidad administrada y le asignará los permisos adecuados. La tarea asociada a la identidad crea una imagen e inicia sesión en Docker Hub para insertar la imagen en el repositorio privado.

Los pasos que se muestran en este ejemplo utilizan una identidad administrada, bien asignada por el usuario o bien asignada por el sistema. Su elección de identidad dependerá de las necesidades de su organización.

En un escenario real, una empresa puede publicar imágenes en un repositorio privado de Docker Hub como parte de un proceso de compilación.

Requisitos previos

Necesita un registro de contenedor de Azure en el que ejecutar la tarea. En este artículo, este registro se denomina myregistry. Reemplácelo por su propio nombre de registro en los pasos posteriores.

Si aún no tiene un registro de contenedor de Azure, consulte Inicio rápido: Creación de un registro de contenedor privado con la CLI de Azure. No tiene que insertar imágenes en el registro todavía.

También necesita un repositorio privado en Docker Hub y una cuenta de Docker Hub con permisos para escribir en el repositorio. En este ejemplo, este repositorio se denomina hubuser/hubrepo.

Creación de un almacén de claves y almacenamiento de secretos

En primer lugar, y si es necesario, cree un grupo de recursos denominado myResourceGroup en la ubicación eastus con el comando siguiente az group create:

az group create --name myResourceGroup --location eastus

Use el comando az keyvault create para crear un almacén de claves. Asegúrese de especificar un nombre de almacén de claves único.

az keyvault create --name mykeyvault --resource-group myResourceGroup --location eastus

Almacene las credenciales necesarias de Docker Hub en el almacén de claves mediante el comando az keyvault secret set. En estos comandos, los valores se pasan en las variables de entorno:

# Store Docker Hub user name
az keyvault secret set \
  --name UserName \
  --value $USERNAME \
  --vault-name mykeyvault

# Store Docker Hub password
az keyvault secret set \
  --name Password \
  --value $PASSWORD \
  --vault-name mykeyvault

En un escenario real, es probable que los secretos se establezcan y se mantengan en un proceso independiente.

Definición de los pasos de la tarea en el archivo YAML

Los pasos de esta tarea de ejemplo se definen en un archivo YAML. Cree un archivo denominado dockerhubtask.yaml en un directorio de trabajo local y pegue el siguiente contenido: Asegúrese de reemplazar el nombre del almacén de claves del archivo por el nombre de su almacén de claves.

version: v1.1.0
# Replace mykeyvault with the name of your key vault
secrets:
  - id: username
    keyvault: https://mykeyvault.vault.azure.net/secrets/UserName
  - id: password
    keyvault: https://mykeyvault.vault.azure.net/secrets/Password
steps:
# Log in to Docker Hub
  - cmd: bash echo '{{.Secrets.password}}' | docker login --username '{{.Secrets.username}}' --password-stdin 
# Build image
  - build: -t {{.Values.PrivateRepo}}:$ID https://github.com/Azure-Samples/acr-tasks.git -f hello-world.dockerfile
# Push image to private repo in Docker Hub
  - push:
    - {{.Values.PrivateRepo}}:$ID

Los pasos de la tarea son los siguientes:

  • Administrar las credenciales de secretos para autenticarse en Docker Hub
  • Pasar los secretos al comando docker login para autenticarse en Docker Hub
  • Crear una imagen con un Dockerfile de ejemplo en el repositorio Azure-Samples/acr-tasks.
  • Insertar la imagen en el repositorio privado de Docker Hub

Opción 1: Creación de una tarea con una identidad asignada por el sistema

En los pasos de esta sección se crea una tarea y se habilita una identidad asignada por el usuario. Si en su lugar quiere habilitar una identidad asignada por el sistema, consulte Opción 2: Creación de una tarea con una identidad asignada por el sistema.

Creación de una identidad asignada por el usuario

Cree una identidad denominada myACRTasksId en la suscripción con el comando az identity create. Puede usar el mismo grupo de recursos que usó anteriormente para crear un registro de contenedor o uno diferente.

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

Para configurar la identidad asignada por el usuario en los pasos siguientes, use el comando az identity show para almacenar en variables los identificadores de recurso, de entidad de seguridad y de cliente de la identidad.

# 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)

Crear la tarea

Cree la tarea dockerhubtask mediante la ejecución del comando az acr task create. La tarea se ejecuta sin contexto de código fuente y el comando hace referencia al archivo dockerhubtask.yaml del directorio de trabajo. El parámetro --assign-identity pasa el identificador de recurso de la identidad asignada por el usuario.

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

En la salida del comando, la sección identity muestra que en la tarea se establece la identidad de tipo UserAssigned:

[...]
"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"
      }
[...]

Concesión a la identidad acceso al almacén de claves

Ejecute el comando az keyvault set-policy siguiente para establecer una directiva de acceso en el almacén de claves. En el ejemplo siguiente se permite que la identidad lea secretos del almacén de claves.

az keyvault set-policy --name mykeyvault \
  --resource-group myResourceGroup \
  --object-id $principalID \
  --secret-permissions get

Proceda a Ejecutar manualmente la tarea.

Opción 2: Creación de una tarea con una identidad asignada por el sistema

En los pasos de esta sección se crea una tarea y se habilita una identidad asignada por el sistema. Si, en cambio, quiere habilitar una identidad asignada por el usuario, consulte Opción 1: Creación de una tarea con una identidad asignada por el usuario.

Crear la tarea

Cree la tarea dockerhubtask mediante la ejecución del comando az acr task create. La tarea se ejecuta sin contexto de código fuente y el comando hace referencia al archivo dockerhubtask.yaml del directorio de trabajo. El parámetro --assign-identity sin valor habilita la identidad asignada por el sistema en la tarea.

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

En la salida del comando, la sección identity muestra que en la tarea se establece una identidad de tipo SystemAssigned. principalId es el identificador de entidad de seguridad de la identidad de la tarea:

[...]
  "identity": {
    "principalId": "xxxxxxxx-2703-42f9-97d0-xxxxxxxxxxxx",
    "tenantId": "xxxxxxxx-86f1-41af-91ab-xxxxxxxxxxxx",
    "type": "SystemAssigned",
    "userAssignedIdentities": null
  },
  "location": "eastus",
[...]

Use el comando az acr task show para almacenar principalId en una variable, para su uso en comandos posteriores. Sustituya el nombre de la tarea y el registro en el siguiente comando:

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

Concesión a la identidad acceso al almacén de claves

Ejecute el comando az keyvault set-policy siguiente para establecer una directiva de acceso en el almacén de claves. En el ejemplo siguiente se permite que la identidad lea secretos del almacén de claves.

az keyvault set-policy --name mykeyvault \
  --resource-group myResourceGroup \
  --object-id $principalID \
  --secret-permissions get

Ejecución manual de la tarea

Para comprobar que la tarea en la que habilitó una identidad administrada se ejecuta correctamente, desencadene manualmente la tarea con el comando az acr task run. El parámetro --set se usa para pasar el nombre del repositorio privado a la tarea. En este ejemplo, el nombre del repositorio del marcador de posición es hubuser/hubrepo.

az acr task run --name dockerhubtask --registry myregistry --set PrivateRepo=hubuser/hubrepo

Cuando la tarea se ejecuta correctamente, la salida muestra una autenticación correcta en Docker Hub y la imagen se crea y se inserta correctamente en el repositorio privado:

Queued a run with ID: cf24
Waiting for an agent...
2019/06/20 18:05:55 Using acb_vol_b1edae11-30de-4f2b-a9c7-7d743e811101 as the home volume
2019/06/20 18:05:58 Creating Docker network: acb_default_network, driver: 'bridge'
2019/06/20 18:05:58 Successfully set up Docker network: acb_default_network
2019/06/20 18:05:58 Setting up Docker configuration...
2019/06/20 18:05:59 Successfully set up Docker configuration
2019/06/20 18:05:59 Logging in to registry: myregistry.azurecr.io
2019/06/20 18:06:00 Successfully logged into myregistry.azurecr.io
2019/06/20 18:06:00 Executing step ID: acb_step_0. Timeout(sec): 600, Working directory: '', Network: 'acb_default_network'
2019/06/20 18:06:00 Launching container with name: acb_step_0
[...]
Login Succeeded
2019/06/20 18:06:02 Successfully executed container: acb_step_0
2019/06/20 18:06:02 Executing step ID: acb_step_1. Timeout(sec): 600, Working directory: '', Network: 'acb_default_network'
2019/06/20 18:06:02 Scanning for dependencies...
2019/06/20 18:06:04 Successfully scanned dependencies
2019/06/20 18:06:04 Launching container with name: acb_step_1
Sending build context to Docker daemon    129kB
[...]
2019/06/20 18:06:07 Successfully pushed image: hubuser/hubrepo:cf24
2019/06/20 18:06:07 Step ID: acb_step_0 marked as successful (elapsed time in seconds: 2.064353)
2019/06/20 18:06:07 Step ID: acb_step_1 marked as successful (elapsed time in seconds: 2.594061)
2019/06/20 18:06:07 Populating digests for step ID: acb_step_1...
2019/06/20 18:06:09 Successfully populated digests for step ID: acb_step_1
2019/06/20 18:06:09 Step ID: acb_step_2 marked as successful (elapsed time in seconds: 2.743923)
2019/06/20 18:06:09 The following dependencies were found:
2019/06/20 18:06:09
- image:
    registry: registry.hub.docker.com
    repository: hubuser/hubrepo
    tag: cf24
    digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a
  runtime-dependency:
    registry: registry.hub.docker.com
    repository: library/hello-world
    tag: latest
    digest: sha256:0e11c388b664df8a27a901dce21eb89f11d8292f7fca1b3e3c4321bf7897bffe
  git:
    git-head-revision: b0ffa6043dd893a4c75644c5fed384c82ebb5f9e

Run ID: cf24 was successful after 15s

Para confirmar que la imagen se ha insertado, busque la etiqueta (cf24 en este ejemplo) en el repositorio privado de Docker Hub.

Pasos siguientes