Creación e implementación de una aplicación web de Python de Flask en Azure con una identidad administrada asignada por el sistema

En este tutorial, se implementa código Python Flask para crear e implementar una aplicación web que se ejecuta en Azure App Service. La aplicación web utiliza su identidad administrada asignada por el sistema (conexiones sin contraseña) con el control de acceso basado en roles de Azure para acceder a los recursos Azure Storage y Azure Database for PostgreSQL - Servidor Flexible. El código utiliza la clase DefaultAzureCredential de la biblioteca de clientes Azure Identity para Python. La clase DefaultAzureCredential detecta automáticamente que existe una identidad administrada para el App Service y la utiliza para acceder a otros recursos de Azure.

Puede configurar conexiones sin contraseña a servicios Azure usando Service Connector o puede configurarlas manualmente. Este tutorial muestra cómo se usa Service Connector. Para obtener más información sobre las conexiones sin contraseña, consulte Conexiones sin contraseña para servicios de Azure. Para obtener información sobre Service Connector, consulte la documentación de Service Connector.

Este tutorial muestra cómo crear e implementar una aplicación web de Python utilizando la CLI de Azure. Los comandos de este tutorial están escritos para ejecutarse en un shell Bash. Puede ejecutar los comandos del tutorial en cualquier entorno Bash con la CLI instalada, como su entorno local o Azure Cloud Shell. Con algunas modificaciones —por ejemplo, estableciendo y usando variables de entorno—, puede ejecutar estos comandos en otros entornos como el shell de comandos de Windows. Para ver ejemplos de uso de una identidad gestionada asignada por el usuario, consulte Creación e implementación una aplicación web Django en Azure con una identidad administrada asignada por el usuario.

Obtención de la aplicación de ejemplo

Hay disponible una aplicación Python de ejemplo que utiliza el framework Flask que le ayudará a seguir este tutorial. Descargue o clone una de las aplicaciones de ejemplo en la estación de trabajo local.

  1. Clone el ejemplo en una sesión de Azure Cloud Shell.

    git clone https://github.com/Azure-Samples/msdocs-flask-web-app-managed-identity.git
    
  2. Vaya a la carpeta de la aplicación.

    cd msdocs-flask-web-app-managed-identity
    

Examine el código de autenticación

La aplicación web de ejemplo necesita autenticarse en dos almacenes de datos diferentes:

  • El servidor de almacenamiento blob de Azure, donde almacena y recupera las fotos enviadas por los revisores.
  • Una base de datos Azure Database for PostgreSQL - Servidor Flexible donde almacena los restaurantes y las reseñas.

Usa DefaultAzureCredential para autenticarse en ambos almacenes de datos. Con DefaultAzureCredential, la aplicación puede configurarse para ejecutarse bajo la identidad de diferentes principales de servicio, dependiendo del entorno en el que se esté ejecutando, sin realizar cambios en el código. Por ejemplo, en un entorno de desarrollo local, la aplicación puede ejecutarse con la identidad del desarrollador que ha iniciado sesión en la CLI de Azure, mientras que en Azure, como en este tutorial, puede ejecutarse con la identidad gestionada asignada por el sistema.

En cualquier caso, el principal de seguridad bajo el que se ejecuta la aplicación debe tener un rol en cada recurso Azure que la aplicación utiliza que le permita realizar las acciones en el recurso que la aplicación requiere. En este tutorial, utilizará conectores de servicio para habilitar automáticamente la identidad administrada asignada por el sistema en su aplicación en Azure y para asignar a esa identidad los roles adecuados en su cuenta de almacenamiento de Azure y en el servidor Azure Database for PostgreSQL.

Una vez habilitada la identidad administrada asignada por el sistema y asignados los roles adecuados en los almacenes de datos, puede utilizar DefaultAzureCredential para autenticarse con los recursos de Azure necesarios.

El siguiente código se utiliza para crear un cliente de almacenamiento blob para subir fotos en app.py. Se proporciona una instancia de DefaultAzureCredential al cliente, que usa para adquirir tokens de acceso para realizar operaciones en el almacenamiento de Azure.

from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient

azure_credential = DefaultAzureCredential()
blob_service_client = BlobServiceClient(
    account_url=account_url,
    credential=azure_credential)

También se utiliza una instancia de DefaultAzureCredential para obtener un token de acceso para Azure Database for PostgreSQL en ./azureproject/get_conn.py. En este caso, el token se adquiere directamente llamando a get_token en la instancia de credenciales y pasándole el valor scope apropiado. A continuación, se usa el token en lugar de la contraseña en el URI de conexión PostgreSQL devuelto al autor de la llamada.

azure_credential = DefaultAzureCredential()
token = azure_credential.get_token("https://ossrdbms-aad.database.windows.net")
conn = str(current_app.config.get('DATABASE_URI')).replace('PASSWORDORTOKEN', token.token)

Para obtener más información sobre la autenticación de sus aplicaciones con los servicios Azure, consulte Autenticación de aplicaciones Python en los servicios Azure mediante el SDK de Azure para Python. Para obtener más información sobre DefaultAzureCredential, incluido cómo personalizar la cadena de credenciales que evalúa para su entorno, consulte Introducción a DefaultAzureCredential.

Crear un servidor Azure PostgreSQL

  1. Configure las variables de entorno necesarias para el tutorial.

    LOCATION="eastus"
    RAND_ID=$RANDOM
    RESOURCE_GROUP_NAME="msdocs-mi-web-app"
    APP_SERVICE_NAME="msdocs-mi-web-$RAND_ID"
    DB_SERVER_NAME="msdocs-mi-postgres-$RAND_ID"
    ADMIN_USER="demoadmin"
    ADMIN_PW="ChAnG33#ThsPssWD$RAND_ID"
    

    Importante

    La ADMIN_PW debe contener entre 8 y 128 caracteres de tres de las siguientes categorías: Letras del alfabeto inglés mayúsculas y minúsculas, números y caracteres no alfanuméricos. Al crear nombres de usuario o contraseñas, no use el carácter $. Más adelante creará variables de entorno con estos valores, donde el carácter $ tiene un significado especial dentro del contenedor de Linux que se usa para ejecutar aplicaciones de Python.

  2. Para crear un grupo de recursos, use el comando az group create.

    az group create --location $LOCATION --name $RESOURCE_GROUP_NAME
    
  3. Cree un servidor PostgreSQL con el comando az postgres flexible-server create. (Este comando y los siguientes usan el carácter de continuación de línea de Bash Shell ('\'). Cambie el carácter de continuación de línea para su shell si es necesario).

    az postgres flexible-server create \
      --resource-group $RESOURCE_GROUP_NAME \
      --name $DB_SERVER_NAME \
      --location $LOCATION \
      --admin-user $ADMIN_USER \
      --admin-password $ADMIN_PW \
      --sku-name Standard_D2ds_v4
    

    El sku-name es el nombre del nivel de precios y de la configuración informática. Para más información, consulte los precios de Azure Database for PostgreSQL. Para enumerar las SKU disponibles, use az postgres flexible-server list-skus --location $LOCATION.

  4. Cree una base de datos denominada restaurant mediante el comando az postgres flexible-server execute.

    az postgres flexible-server execute \
      --name $DB_SERVER_NAME \
      --admin-user $ADMIN_USER \
      --admin-password $ADMIN_PW \
      --database-name postgres \
      --querytext 'create database restaurant;'
    

Creación de un Azure App Service e implementación del código

  1. Cree un servicio de aplicación con el comando az webapp up.

    az webapp up \
      --resource-group $RESOURCE_GROUP_NAME \
      --name $APP_SERVICE_NAME \
      --runtime PYTHON:3.9 \
      --sku B1
    

    El sku define el tamaño (CPU, memoria) y el coste del plan de App Service. El plan de servicio B1 (Básico) incurre en un pequeño coste en su suscripción Azure. Para obtener una lista completa de los planes de App Service, vea la página Precios de App Service.

  2. Configura App Service para usar el start.sh en el repo con el comando az webapp config set.

    az webapp config set \
      --resource-group $RESOURCE_GROUP_NAME \
      --name $APP_SERVICE_NAME \
      --startup-file "start.sh"
    

Creación de conectores sin contraseña a los recursos de Azure

Los comandos Service Connector configuran los recursos Azure Storage y Azure Database for PostgreSQL para usar la identidad administrada y el control de acceso basado en roles de Azure. Los comandos crean configuraciones de aplicación en App Service que conectan su aplicación web a estos recursos. La salida de los comandos enumera las acciones del conector de servicio realizadas para habilitar la capacidad sin contraseña.

  1. Agregue un conector de servicio PostgreSQL con el comando az webapp connection create postgres-flexible. La identidad administrada asignada por el sistema se usa para autenticar la aplicación web en el recurso de destino, PostgreSQL, en este caso.

    az webapp connection create postgres-flexible \
      --resource-group $RESOURCE_GROUP_NAME \
      --name $APP_SERVICE_NAME \
      --target-resource-group $RESOURCE_GROUP_NAME \
      --server $DB_SERVER_NAME \
      --database restaurant \
      --client-type python \
      --system-identity
    
  2. Agregue un conector de servicio de almacenamiento con el comando az webapp connection create storage-blob.

    Este comando también agrega una cuenta de almacenamiento y añade la aplicación web con el rol Colaborador de datos de blobs de almacenamiento a la cuenta de almacenamiento.

    STORAGE_ACCOUNT_URL=$(az webapp connection create storage-blob \
      --new true \
      --resource-group $RESOURCE_GROUP_NAME \
      --name $APP_SERVICE_NAME \
      --target-resource-group $RESOURCE_GROUP_NAME \
      --client-type python \
      --system-identity \
      --query configurations[].value \
      --output tsv)
    STORAGE_ACCOUNT_NAME=$(cut -d . -f1 <<< $(cut -d / -f3 <<< $STORAGE_ACCOUNT_URL))
    

Creación de un contenedor en la cuenta de almacenamiento

La aplicación Python de ejemplo almacena las fotos enviadas por los revisores como blobs en un contenedor de su cuenta de almacenamiento.

  • Cuando un usuario envía una foto con su revisión, la aplicación de ejemplo escribe la imagen en el contenedor utilizando su identidad administrada asignada por el sistema para la autenticación y autorización. Esta funcionalidad se configuró en la última sección.

  • Cuando un usuario consulta las reseñas de un restaurante, la aplicación devuelve un enlace a la foto en el Blob Storage para cada reseña que tenga una asociada. Para que el navegador muestre la foto, debe poder acceder a ella en su cuenta de almacenamiento. Los datos blob deben estar disponibles para su lectura pública a través de un acceso anónimo (no autenticado).

Para mejorar la seguridad, las cuentas de almacenamiento se crean con el acceso anónimo a los datos blob desactivado por defecto. En esta sección, habilitará el acceso anónimo de lectura en su cuenta de almacenamiento y luego creará un contenedor llamado fotos que proveerá acceso público (anónimo) a sus blobs.

  1. Actualice la cuenta de almacenamiento para permitir el acceso anónimo de lectura a los blobs con el comando az storage account update.

    az storage account update \
      --name $STORAGE_ACCOUNT_NAME \
      --resource-group $RESOURCE_GROUP_NAME \
      --allow-blob-public-access true
    

    La habilitación del acceso anónimo en la cuenta de almacenamiento no afecta al acceso a blobs individuales. Debe habilitar explícitamente el acceso público a los blobs a nivel de contenedor.

  2. Cree un contenedor llamado fotos en la cuenta de almacenamiento con el comando az storage container create. Permita el acceso anónimo de lectura (público) a los blobs en el contenedor recién creado.

    az storage container create \
      --account-name $STORAGE_ACCOUNT_NAME \
      --name photos \
      --public-access blob \
      --account-key $(az storage account keys list --account-name $STORAGE_ACCOUNT_NAME \
          --query [0].value --output tsv) 
    

    Nota:

    Para abreviar, este comando utiliza la clave de cuenta de almacenamiento para autorizar con la cuenta de almacenamiento. Para la mayoría de los escenarios, el enfoque recomendado por Microsoft es usar Microsoft Entra ID y roles Azure (RBAC). Para obtener un conjunto rápido de instrucciones, consulte Inicio rápido: Crear, descargar y listar blobs con Azure CLI. Tenga en cuenta que varios roles de Azure le permiten crear contenedores en una cuenta de almacenamiento, incluidos "Propietario", "Colaborador", "Propietario de datos de bloques de almacenamiento" y "Colaborador de datos de bloques de almacenamiento".

Para obtener más información sobre el acceso de lectura anónimo a los datos de blob, consulte Configuración del acceso de lectura anónimo para contenedores y blobs.

Prueba de la aplicación web Python en Azure

La aplicación Python de ejemplo utiliza el paquete azure.identity y su clase DefaultAzureCredential. Cuando la app se ejecuta en Azure, DefaultAzureCredential detecta automáticamente si existe una identidad administrada para el App Service y, si es así, la usa para acceder a otros recursos de Azure (almacenamiento y PostgreSQL en este caso). No es necesario proporcionar claves de almacenamiento, certificados o credenciales al App Service para acceder a estos recursos.

  1. Vaya a la aplicación implementada en la dirección URL http://$APP_SERVICE_NAME.azurewebsites.net.

    La aplicación puede tardar uno o dos minutos en iniciarse. Si ve una página de aplicación predeterminada que no es la página de aplicación de muestra predeterminada, espere un minuto y actualice el navegador.

  2. Pruebe la funcionalidad de la aplicación de ejemplo y añada un restaurante y algunas reseñas con fotos del restaurante.

    La información del restaurante y las reseñas se almacenan en Azure Database for PostgreSQL y las fotos se almacenan en Azure Storage. He aquí una captura de pantalla de ejemplo:

    Captura de pantalla de la aplicación de ejemplo que muestra la funcionalidad de reseñas de restaurantes mediante Azure App Service, Azure PostgreSQL Database y Azure Storage.

Limpiar

En este tutorial, todos los recursos Azure se crearon en el mismo grupo de recursos. Eliminar el grupo de recursos con el comando az group delete elimina todos los recursos del grupo de recursos y es la forma más rápida de eliminar todos los recursos de Azure utilizados para su app.

az group delete  --name $RESOURCE_GROUP_NAME 

Opcionalmente, puede agregar el argumento --no-wait para permitir que el comando devuelva antes de que se complete la operación.

Pasos siguientes