Compartir vía


Autenticación de aplicaciones hospedadas en Azure en recursos de Azure con el SDK de Azure para Go

Al hospedar una aplicación en Azure mediante servicios como Azure App Service, Azure Virtual Machines o Azure Container Instances, el enfoque recomendado para autenticar una aplicación en los recursos de Azure es con identidad administrada.

Una identidad administrada proporciona una identidad para la aplicación de modo que pueda conectarse a otros recursos de Azure sin necesidad de usar una clave secreta u otro secreto de aplicación. Internamente, Azure conoce la identidad de la aplicación y a qué recursos puede conectarse. Azure usa esta información para obtener automáticamente tokens de Microsoft Entra para la aplicación para permitir que se conecte a otros recursos de Azure, todo ello sin tener que administrar ningún secreto de aplicación.

Nota

Las aplicaciones que se ejecutan en Azure Kubernetes Service (AKS) pueden usar una identidad de carga de trabajo para autenticarse con recursos de Azure. En AKS, una identidad de carga de trabajo representa una relación de confianza entre una identidad administrada y una cuenta de servicio de Kubernetes. Si una aplicación implementada en AKS está configurada con una cuenta de servicio de Kubernetes en dicha relación, DefaultAzureCredential autentica la aplicación en Azure mediante la identidad administrada. La autenticación mediante una identidad de carga de trabajo se describe en Uso del identificador de carga de trabajo de Microsoft Entra con Azure Kubernetes Service. Para obtener pasos sobre cómo configurar la identidad de carga de trabajo, consulte Implementación y configuración de la identidad de carga de trabajo en un clúster de Azure Kubernetes Service (AKS).

Tipos de identidad administrada

Hay dos tipos de identidades administradas:

  • identidades administradas asignadas por el sistema: este tipo de identidad administrada se proporciona mediante y está vinculado directamente a un recurso de Azure. Al habilitar la identidad administrada en un recurso de Azure, obtendrá una identidad administrada asignada por el sistema para ese recurso. Una identidad administrada asignada por el sistema está asociada al ciclo de vida del recurso de Azure al que está asociado. Cuando se elimina el recurso, Azure elimina automáticamente la identidad por ti. Dado que todo lo que tiene que hacer es habilitar la identidad administrada para el recurso de Azure que hospeda el código, este enfoque es el tipo más fácil de identidad administrada que se va a usar.
  • identidades administradas asignadas por el usuario: también puede crear una identidad administrada como un recurso de Azure independiente. Este enfoque se usa con más frecuencia cuando la solución tiene varias cargas de trabajo que se ejecutan en varios recursos de Azure que todos necesitan compartir la misma identidad y los mismos permisos. Por ejemplo, si la solución tenía componentes que se ejecutan en varias instancias de App Service y máquina virtual que todos necesitan acceso al mismo conjunto de recursos de Azure, tiene sentido una identidad administrada asignada por el usuario que se usa en esos recursos.

En este artículo se describen los pasos para habilitar y usar una identidad administrada asignada por el sistema para una aplicación. Si necesita usar una identidad administrada asignada por el usuario, consulte el artículo Administración de identidades administradas asignadas por el usuario para ver cómo crear una identidad administrada asignada por el usuario.

1: Habilitación de la identidad administrada en el recurso de Azure que hospeda la aplicación

El primer paso es habilitar la identidad administrada en el recurso de Azure que hospeda la aplicación. Por ejemplo, si hospeda una aplicación de Gin mediante Azure Container Apps, debe habilitar la identidad administrada para la aplicación contenedora. Si usa una máquina virtual para hospedar la aplicación, habilitaría la máquina virtual para usar la identidad administrada.

Puede permitir que la identidad administrada se use para un recurso de Azure mediante Azure Portal o la CLI de Azure.

Los comandos de la CLI de Azure se pueden ejecutar en Azure Cloud Shell o en una estación de trabajo que tenga la CLI de Azure instalada.

Los comandos de la CLI de Azure que se usan para habilitar la identidad administrada para un recurso de Azure tienen el formato az <command-group> identity --resource-group <resource-group-name> --name <resource-name>. A continuación se muestran comandos específicos para los servicios populares de Azure.

az containerapp identity assign \
    --resource-group <resource-group-name> \
    --name <container-app-name> \
    --system-assigned

La salida será similar a la siguiente.

{
  "principalId": "aaaaaaaa-bbbb-cccc-1111-222222222222",
  "tenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee",
  "type": "SystemAssigned",
  "userAssignedIdentities": null
}

El valor principalId es el identificador único de la identidad administrada. Mantenga una copia de esta salida, ya que necesitará estos valores en el paso siguiente.

2: Asignación de roles a la identidad administrada

A continuación, debe determinar qué roles (permisos) necesita la aplicación y asignar la identidad administrada a esos roles en Azure. Se pueden asignar roles a una identidad administrada en un recurso, un grupo de recursos o ámbito de suscripción. En este ejemplo se muestra cómo asignar roles en el ámbito del grupo de recursos, ya que la mayoría de las aplicaciones agrupan todos sus recursos de Azure en un único grupo de recursos.

A una identidad administrada se le asigna un rol en Azure mediante el comando az role assignment create. Para el usuario asignado, use el principalId que copió en el paso 1.

az role assignment create --assignee {managedIdentityprincipalId} \
    --scope /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName} \
    --role "{roleName}" 

Para obtener los nombres de roles a los que se puede asignar una entidad de servicio, use el comando az role definition list.

az role definition list \
    --query "sort_by([].{roleName:roleName, description:description}, &roleName)" \
    --output table

Por ejemplo, para permitir que la identidad administrada con ID de aaaaaaaa-bbbb-cccc-1111-222222222222 lea, escriba y elimine el acceso a los contenedores y datos de blobs de Azure Storage para todas las cuentas de almacenamiento del grupo de recursos your-resource-group-name en la suscripción con ID aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e, asignaría el rol de Colaborador de datos de blobs de almacenamiento a la entidad de servicio de la aplicación mediante el siguiente comando.

az role assignment create --assignee aaaaaaaa-bbbb-cccc-1111-222222222222 \
    --scope /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/your-resource-group-name \
    --role "Storage Blob Data Contributor"

Para obtener información sobre cómo asignar permisos en el nivel de recurso o suscripción mediante la CLI de Azure, consulte el artículo Asignación de roles de Azure mediante la CLI de Azure.

3- Implementar DefaultAzureCredential en la aplicación

Cuando el código se ejecuta en Azure y la identidad administrada se ha habilitado en el recurso de Azure que hospeda la aplicación, el DefaultAzureCredential determina las credenciales que se usarán en el orden siguiente:

  1. Comprueba el entorno de una entidad de servicio tal como se define en las variables de entorno AZURE_CLIENT_ID, AZURE_TENANT_ID y AZURE_CLIENT_SECRET o AZURE_CLIENT_CERTIFICATE_PATH y (opcionalmente) AZURE_CLIENT_CERTIFICATE_PASSWORD.
  2. Compruebe la variable de entorno AZURE_CLIENT_ID para el identificador de cliente de una identidad administrada asignada por el usuario.
  3. Use la identidad administrada asignada por el sistema para el recurso de Azure si está habilitada.

En este artículo, se usa la identidad administrada asignada por el sistema para una aplicación contenedora de Azure, por lo que no es necesario configurar una identidad administrada en el entorno ni pasarla como parámetro. En los pasos siguientes se muestra cómo usar DefaultAzureCredential.

En primer lugar, agregue el paquete azidentity a la aplicación.

go get github.com/Azure/azure-sdk-for-go/sdk/azidentity

A continuación, para cualquier código Go que instancie un cliente del Azure SDK en su aplicación, deberá:

  1. Importe el paquete de azidentity.
  2. Cree una instancia de tipo DefaultAzureCredential.
  3. Pase la instancia de tipo DefaultAzureCredential al constructor del cliente del SDK de Azure.

En el siguiente segmento de código se muestra un ejemplo de estos pasos con un cliente de blobs de Azure Storage.

import (
	"context"

	"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
	"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
)

const (
	account       = "https://<replace_with_your_storage_account_name>.blob.core.windows.net/"
	containerName = "sample-container"
	blobName      = "sample-blob"
	sampleFile    = "path/to/sample/file"
)

func main() {
    // create a credential
    cred, err := azidentity.NewDefaultAzureCredential(nil)
    if err != nil {
      // TODO: handle error
    }
    
    // create a client for the specified storage account
    client, err := azblob.NewClient(account, cred, nil)
    if err != nil {
      // TODO: handle error
    }
    
    // TODO: perform some action with the azblob Client
    // _, err = client.DownloadFile(context.TODO(), <containerName>, <blobName>, <target_file>, <DownloadFileOptions>)
}

Como se describe en el artículo introducción a la autenticación de Azure SDK para Go, DefaultAzureCredential admite varios métodos de autenticación y determina el método de autenticación que se usa en tiempo de ejecución. La ventaja de este enfoque es que la aplicación puede usar diferentes métodos de autenticación en distintos entornos sin implementar código específico del entorno. Cuando el código anterior se ejecuta en la estación de trabajo durante el desarrollo local, DefaultAzureCredential usará, según la configuración del entorno, un principal de servicio de aplicación o las credenciales de la herramienta de desarrollador para autenticarse con otros recursos de Azure. Por lo tanto, se puede usar el mismo código para autenticar la aplicación en los recursos de Azure durante el desarrollo local y cuando se implementa en Azure.

Importante

DefaultAzureCredential simplifica la autenticación al desarrollar aplicaciones que se implementan en Azure mediante la combinación de credenciales usadas en entornos de hospedaje de Azure y credenciales usadas en el desarrollo local. En producción, es mejor usar un tipo de credencial específico para que la autenticación sea más predecible y fácil de depurar.

4- Implementación de ManagedIdentityCredential en la aplicación

Los pasos para implementar ManagedIdentityCredential son los mismos que los de tipo DefaultAzureCredential.

En primer lugar, agregue el paquete azidentity a la aplicación.

go get github.com/Azure/azure-sdk-for-go/sdk/azidentity

A continuación, para cualquier código de Go que cree una instancia de un cliente del SDK de Azure en tu aplicación, debe:

  1. Importe el paquete de azidentity.
  2. Cree una instancia de tipo ManagedIdentityCredential.
  3. Pase la instancia de tipo ManagedIdentityCredential al constructor del cliente del SDK de Azure.

En el siguiente segmento de código se muestra un ejemplo de estos pasos con un cliente de blobs de Azure Storage.

import (
	"context"

	"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
	"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
)

const (
	account       = "https://<replace_with_your_storage_account_name>.blob.core.windows.net/"
	containerName = "sample-container"
	blobName      = "sample-blob"
	sampleFile    = "path/to/sample/file"
)

func main() {
    // create a credential
    cred, err := azidentity.NewManagedIdentityCredential(nil)
    
    // When using User Assigned Managed Identity use this instead and pass your client id in the options
    // clientID := azidentity.ClientID("abcd1234-...")
    // opts := azidentity.ManagedIdentityCredentialOptions{ID: clientID}
    // cred, err := azidentity.NewManagedIdentityCredential(&opts)
    
    if err != nil {
      // TODO: handle error
    }
    
    // create a client for the specified storage account
    client, err := azblob.NewClient(account, cred, nil)
    if err != nil {
      // TODO: handle error
    }
    
    // TODO: perform some action with the azblob Client
    // _, err = client.DownloadFile(context.TODO(), <containerName>, <blobName>, <target_file>, <DownloadFileOptions>)
}