Autenticación de aplicaciones Python en servicios de Azure durante el desarrollo local mediante entidades de servicio
Al crear aplicaciones en la nube, los desarrolladores necesitan depurar y probar aplicaciones en su estación de trabajo local. Cuando se ejecuta una aplicación en la estación de trabajo de un desarrollador durante el desarrollo local, esta debe autenticarse en los servicios de Azure que usa. En este artículo se explica cómo configurar objetos de entidad de servicio de aplicación dedicados que se usarán durante el desarrollo local.
Las entidades de servicio de aplicaciones dedicadas para el desarrollo local permiten seguir el principio de privilegios mínimos durante el desarrollo de aplicaciones. Dado que los permisos tienen como ámbito exactamente lo que se necesita para la aplicación durante el desarrollo, se impide que el código de la aplicación acceda accidentalmente a un recurso de Azure destinado al uso por otra aplicación. Esto también impide que se produzcan errores cuando la aplicación se mueve al entorno de producción debido a un exceso de privilegios de la aplicación en el entorno de desarrollo.
Cuando la aplicación se registra en Azure, se configura una entidad de servicio de aplicación. Al registrar aplicaciones para el desarrollo local, se recomienda lo siguiente:
- Crear registros de aplicaciones independientes para cada desarrollador que trabaje en la aplicación. Esto creará entidades de servicio de aplicación independientes para que las puedan usar cada desarrollador durante el desarrollo local y evitará la necesidad de que los desarrolladores compartan credenciales para una única entidad de servicio de aplicación.
- Crear registros de aplicaciones independientes por cada aplicación. Esto limita los permisos de la aplicación solo a lo que necesita la aplicación.
Durante el desarrollo local, las variables de entorno se establecen con la identidad de la entidad de servicio de la aplicación. El SDK de Azure para Python lee estas variables de entorno y usa esta información para autenticar la aplicación en los recursos de Azure que necesita.
1: Registro de la aplicación en Azure
Los objetos de la entidad de servicio de la aplicación se crean con un registro de aplicación en Azure. Esto puede hacerse 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 con la CLI de Azure instalada.
En primer lugar, use el comando az ad sp create-for-rbac para crear una nueva entidad de servicio para la aplicación. El comando también crea el registro de aplicación para la aplicación al mismo tiempo.
az ad sp create-for-rbac --name <service-principal-name>
El resultado de este comando tendrá un aspecto similar al siguiente. Anote estos valores o mantenga esta ventana abierta, ya que necesitará estos valores en los pasos siguientes y no podrá volver a ver el valor de la contraseña (secreto del cliente). Sin embargo, si es necesario, se puede agregar una nueva contraseña posteriormente sin invalidar la entidad de servicio ni las contraseñas existentes.
{
"appId": "00001111-aaaa-2222-bbbb-3333cccc4444",
"displayName": "<service-principal-name>",
"password": "Ee5Ff~6Gg7.-Hh8Ii9Jj0Kk1Ll2Mm3_Nn4Oo5Pp6",
"tenant": "aaaabbbb-0000-cccc-1111-dddd2222eeee"
}
2 - Creación de un grupo de seguridad de Microsoft Entra para el desarrollo local
Dado que normalmente hay varios desarrolladores que trabajan en una aplicación, se recomienda crear un grupo de seguridad de Microsoft Entra para encapsular los roles (permisos) que necesita la aplicación en el desarrollo local, en lugar de asignar los roles a objetos de entidad de servicio individuales. Esto ofrece las ventajas que se indican a continuación:
- Todos los desarrolladores están seguros de tener asignados los mismos roles, ya que los roles se asignan en el nivel de grupo.
- Si se necesita un nuevo rol para la aplicación, solo es necesario agregarlo al grupo Microsoft Entra para la aplicación.
- Si un nuevo desarrollador se une al equipo, se crea una nueva entidad de servicio de aplicación para el desarrollador y esta se agrega al grupo, lo que garantiza que el desarrollador tiene los permisos adecuados para trabajar en la aplicación.
El comando az ad group create se usa para crear grupos de seguridad en Microsoft Entra ID. Los parámetros --display-name
y --main-nickname
son obligatorios. El nombre proporcionado al grupo debe basarse en el nombre de la aplicación. También resulta útil incluir una cadena como “local-dev” en el nombre del grupo para indicar el propósito del grupo.
az ad group create \
--display-name MyDisplay \
--mail-nickname MyDisplay \
--description "<group-description>"
Copie el valor de la propiedad id
en la salida del comando. Es el identificador de objeto del grupo. Lo necesitará en pasos posteriores. También puede usar el comando az ad group show para recuperar esta propiedad.
Para agregar miembros al grupo, necesitará el id. de objeto de la entidad de servicio de la aplicación, que es diferente al id. de la aplicación. Use az ad sp list para enumerar las entidades de servicio disponibles. El comando de parámetro --filter
acepta filtros de estilo de OData y se puede usar para filtrar la lista como se muestra. El parámetro --query
limita las columnas solo a aquellas de interés.
az ad sp list \
--filter "startswith(displayName, 'msdocs')" \
--query "[].{objectId:id, displayName:displayName}" \
--output table
El comando az ad group member add se puede usar para agregar miembros a grupos.
az ad group member add \
--group <group-name> \
--member-id <object-id>
Nota:
De forma predeterminada, la creación de grupos de seguridad de Microsoft Entra se limita a determinados roles con privilegios en un directorio. Si no puede crear un grupo, póngase en contacto con un administrador del directorio. Si no puede agregar miembros a un grupo existente, póngase en contacto con el propietario del grupo o con un administrador de directorios. Para obtener más información, consulte Administración de grupos de Microsoft Entra y pertenencia a grupos.
3: Asignación de roles a la aplicación
A continuación, debe determinar qué roles (permisos) necesita la aplicación y en qué recursos para, a continuación, asignar dichos roles a la aplicación. En este ejemplo, los roles se asignan al grupo Microsoft Entra creado en el paso 2. Los roles se pueden asignar en el ámbito de recurso, grupo de recursos o 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 un usuario, grupo o entidad de servicio de aplicación se le asigna el rol en Azure con el comando az role assignment create. Puede especificar un grupo con su identificador de objeto. Puede especificar una entidad de servicio de aplicación con su appId.
az role assignment create --assignee <appId or objectId> \
--scope /subscriptions/<subscriptionId>/resourceGroups/<resourceGroupName> \
--role "<roleName>"
Para obtener los nombres de roles que se pueden asignar, 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 entidad de servicio de aplicación con el appId de 00001111-aaaa-2222-bbbb-3333cccc4444
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 msdocs-python-sdk-auth-example 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 00001111-aaaa-2222-bbbb-3333cccc4444 \
--scope /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-python-sdk-auth-example \
--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.
4 - Configuración de variables del entorno de desarrollo local
El objeto DefaultAzureCredential
buscará información sobre la entidad de servicio en un conjunto de variables de entorno en tiempo de ejecución. Dado que la mayoría de los desarrolladores trabajan en varias aplicaciones, se recomienda usar un paquete como python-dotenv para acceder al entorno desde un archivo .env
almacenado en el directorio de la aplicación durante el desarrollo. Esto limita las variables de entorno que se usan para autenticar la aplicación en Azure de modo que esta aplicación solo las pueda usar.
El archivo .env
nunca está protegido en el control de código fuente, ya que contiene la clave secreta de aplicación para Azure. El archivo .gitignore estándar para Python excluye automáticamente el archivo .env
de la protección.
Para usar el paquete python-dotenv, instale primero el paquete en la aplicación.
pip install python-dotenv
A continuación, cree un archivo .env
en el directorio raíz de la aplicación. Establezca los valores de las variables de entorno con los valores obtenidos del proceso de registro de aplicaciones de la siguiente manera:
AZURE_CLIENT_ID
→ Valor del id. de la aplicación.AZURE_TENANT_ID
→ Valor del id. de inquilino.AZURE_CLIENT_SECRET
→ Contraseña o credencial generada para la aplicación.
AZURE_CLIENT_ID=00001111-aaaa-2222-bbbb-3333cccc4444
AZURE_TENANT_ID=aaaabbbb-0000-cccc-1111-dddd2222eeee
AZURE_CLIENT_SECRET=Ee5Ff~6Gg7.-Hh8Ii9Jj0Kk1Ll2Mm3_Nn4Oo5Pp6
Por último, en el código de inicio de la aplicación, use la biblioteca python-dotenv
para leer las variables de entorno del archivo .env
al iniciarse.
from dotenv import load_dotenv
if ( os.environ['ENVIRONMENT'] == 'development'):
print("Loading environment variables from .env file")
load_dotenv(".env")
5: Implementación de DefaultAzureCredential en la aplicación
Para autenticar objetos de cliente del SDK de Azure en Azure, la aplicación debe usar la clase DefaultAzureCredential
del paquete azure.identity
. En este escenario, DefaultAzureCredential
detectará que las variables de entorno AZURE_CLIENT_ID
, AZURE_TENANT_ID
y AZURE_CLIENT_SECRET
están establecidas y las leerá para obtener la información de la entidad de servicio de la aplicación con la que conectarse a Azure.
Empiece agregando el paquete azure.identity a la aplicación.
pip install azure-identity
A continuación, para cualquier código Python que cree un objeto de cliente del SDK de Azure en la aplicación, querrá:
- Importar la clase
DefaultAzureCredential
desde el móduloazure.identity
. - Crear un objeto
DefaultAzureCredential
. - Pasar el objeto
DefaultAzureCredential
al constructor de objetos de cliente del SDK de Azure.
En el segmento de código siguiente se muestra un ejemplo de esto.
from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient
# Acquire a credential object
token_credential = DefaultAzureCredential()
blob_service_client = BlobServiceClient(
account_url="https://<my_account_name>.blob.core.windows.net",
credential=token_credential)