Usar referencias de App Configuration para App Service y Azure Functions

En este tema se muestra cómo trabajar con datos de configuración en la aplicación de App Service o Azure Functions sin necesidad de realizar cambios en el código. Azure App Configuration es un servicio para administrar la configuración de la aplicación de forma centralizada. Además, es una herramienta de auditoría eficaz para los valores de configuración a lo largo del tiempo o las versiones.

Concesión de acceso a la aplicación a App Configuration

Para empezar a usar las referencias de App Configuration en App Service, primero necesitará un almacén de App Configuration y proporcionar permiso de aplicación para el acceso a los valores de claves de configuración del almacén.

  1. Cree un almacén de App Configuration siguiendo el inicio rápido de App Configuration.

  2. Cree una identidad administrada para la aplicación.

    Las referencias de App Configuration usarán la identidad asignada por el sistema de la aplicación de forma predeterminada, pero puede especificar una identidad asignada por el usuario.

  3. Habilite la identidad recién creada para que tenga el conjunto adecuado de permisos de acceso en el almacén de App Configuration. Actualice las asignaciones de roles del almacén. A esta identidad se le asignará el rol App Configuration Data Reader, con ámbito sobre el recurso.

Acceso al almacén de App Configuration con una identidad asignada por el usuario

Algunas aplicaciones pueden necesitar hacer referencia a la configuración en el momento de la creación, cuando una identidad asignada por el sistema aún no está disponible. En estos casos, se puede crear una identidad asignada por el usuario y concederle acceso al almacén de App Configuration de antemano. Siga estos pasos para crear una identidad asignada por el usuario para el almacén de App Configuration.

Una vez que haya concedido permisos a la identidad asignada por el usuario, siga estos pasos:

  1. Asigne la identidad a la aplicación si aún no lo ha hecho.

  2. Configure la aplicación para que use esta identidad en las operaciones de referencias de App Configuration estableciendo la propiedad keyVaultReferenceIdentity en el identificador de recurso de la identidad asignada por el usuario. Aunque la propiedad tiene keyVault en el nombre, la identidad también se aplicará a las referencias de App Configuration.

    userAssignedIdentityResourceId=$(az identity show -g MyResourceGroupName -n MyUserAssignedIdentityName --query id -o tsv)
    appResourceId=$(az webapp show -g MyResourceGroupName -n MyAppName --query id -o tsv)
    az rest --method PATCH --uri "${appResourceId}?api-version=2021-01-01" --body "{'properties':{'keyVaultReferenceIdentity':'${userAssignedIdentityResourceId}'}}"
    

Esta configuración se aplicará a todas las referencias de esta aplicación.

Concesión de acceso a la aplicación a los almacenes de claves con referencia

Además de almacenar los valores de configuración sin procesar, Azure App Configuration tiene su propio formato para almacenar las referencias Key Vault. Si el valor de una referencia de App Configuration es una referencia de Key Vault en el almacén de App Configuration, la aplicación también tendrá que tener permiso para acceder al almacén de claves especificado.

Nota:

El concepto de referencias de Key Vault de Azure App Configuration no debe confundirse con el concepto de referencias de App Service y de Azure Functions Key Vault. La aplicación puede usar cualquier combinación de estas, aunque hay ciertas diferencias importantes que se deben tener en cuenta. Si el almacén debe estar restringido a la red o necesita que la aplicación actualice periódicamente a las versiones más recientes, considere la posibilidad de usar el enfoque directo de App Service y Azure Functions en lugar de usar una referencia de App Configuration.

  1. Identifique la identidad que usó para la referencia de App Configuration. Se debe conceder acceso al almacén a esa misma identidad.

  2. Cree una directiva de acceso en Key Vault para esa identidad. Habilite el permiso secreto "Get" en esta directiva. No configure la "aplicación autorizada" o la configuración applicationId, ya que no es compatible con una identidad administrada.

Sintaxis de referencia

Una referencia de App Configuration tiene el formato @Microsoft.AppConfiguration({referenceString}), donde {referenceString} se reemplaza por lo siguiente:

Partes de cadena de referencia Descripción
Endpoint=endpoint; Endpoint es la parte necesaria de la cadena de referencia. El valor de Endpoint debe tener la dirección URL del recurso de App Configuration.
Key=keyName; Key forma la parte necesaria de la cadena de referencia. El valor de Key debe ser el nombre de la clave que quiere asignar a la configuración de la aplicación.
Label=label La parte Label es opcional en la cadena de referencia. Label debe ser el valor de etiqueta de la clave especificada en Key.

Por ejemplo, una referencia completa con Label se parecería a la siguiente:

@Microsoft.AppConfiguration(Endpoint=https://myAppConfigStore.azconfig.io; Key=myAppConfigKey; Label=myKeysLabel)​

Como alternativa, sin Label:

@Microsoft.AppConfiguration(Endpoint=https://myAppConfigStore.azconfig.io; Key=myAppConfigKey)​

Cualquier cambio de configuración en la aplicación provoca un reinicio del sitio que provoca una captura inmediata de todos los valores de clave a los que se hace referencia desde el almacén de App Configuration.

Nota:

Actualmente no se admite la actualización automática o la nueva captura de estos valores cuando los valores de clave se han actualizado en App Configuration.

Configuración de la aplicación de origen desde App Config

Las referencias de App Configuration se pueden usar como valores para Configuración de la aplicación, lo que le permite mantener los datos de configuración en App Configuration en lugar de en la configuración del sitio. Los valores de claves de Configuración de la aplicación y de App Configuration se cifran de forma segura en reposo. Si necesita funcionalidades de administración de configuración centralizadas, los datos de configuración deben ir a App Config.

Para usar una referencia de App Configuration para una configuración de la aplicación, establezca la referencia como valor de la configuración. La aplicación puede hacer referencia al valor de configuración mediante su clave como es habitual. No se requiere ningún cambio de código.

Sugerencia

La mayoría de los valores de configuración que usan referencias de App Configuration se deben marcar como configuración de ranuras, así que debe tener distintos almacenes o etiquetas para cada entorno.

Consideraciones para el montaje de Azure Files

Las aplicaciones pueden usar la configuración de la aplicación WEBSITE_CONTENTAZUREFILECONNECTIONSTRING para montar Azure Files como el sistema de archivos. Esta configuración tiene comprobaciones de validación adicionales para garantizar que la aplicación se puede iniciar correctamente. La plataforma se basa en tener un recurso compartido de contenido dentro de Azure Files y supone un nombre predeterminado a menos que se especifique uno a través de la configuración WEBSITE_CONTENTSHARE. Para las solicitudes que modifican esta configuración, la plataforma intentará validar si existe este recurso compartido de contenido, e intentará crearlo si no existe. Si no se puede encontrar o crear el recurso compartido de contenido, la solicitud se bloquea.

Cuando se usen referencias de App Configuration para esta configuración, esta comprobación de validación producirá un error de manera predeterminada, ya que la conexión no se puede resolver al procesar la solicitud entrante. Para evitar este problema, puede omitir la validación al establecer el valor de WEBSITE_SKIP_CONTENTSHARE_VALIDATION en "1". Este valor omitirá todas las comprobaciones y el recurso compartido de contenido no se creará automáticamente. Debe asegurarse de crearlo de antemano.

Precaución

Si omite la validación y, además, la cadena de conexión o el recurso compartido de contenido no son válidos, la aplicación no podrá iniciarse correctamente y solo generará errores HTTP 500.

Como parte de la creación del sitio, también es posible que se pueda generar un error al intentar montar el recurso compartido de contenido debido a que no se hayan propagado los permisos de identidad administrada, o a que no se haya configurado la integración de la red virtual. Puede aplazar la configuración de Azure Files hasta más adelante en la plantilla de implementación para admitir la configuración necesaria. Para más información, consulte Implementación de Azure Resource Manager. App Service usará sistema de archivos predeterminado hasta que Azure Files esté configurado y los archivos no se hayan copiado, así que asegúrese de que no se produzca ningún intento de implementación durante el período transitorio antes de montar Azure Files.

Implementación de Azure Resource Manager

Al automatizar las implementaciones de recursos mediante plantillas de Azure Resource Manager, puede que deba secuenciar sus dependencias en un orden determinado para que esta característica funcione. Cabe señalar que deberá definir la configuración de la aplicación como su propio recurso en lugar de usar una propiedad siteConfig en la definición del sitio. El motivo es que primero es necesario definir el sitio para que la identidad asignada por el sistema se cree con él y se pueda usar en la directiva de acceso.

A continuación se muestra una pseudoplantilla de ejemplo para una aplicación de funciones con referencias de App Configuration:

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "roleNameGuid": {
            "type": "string",
            "defaultValue": "[newGuid()]",
            "metadata": {
                "description": "A new GUID used to identify the role assignment"
            }
        }
    },
    "variables": {
        "functionAppName": "DemoMBFunc",
        "appConfigStoreName": "DemoMBAppConfig",
        "resourcesRegion": "West US2",
        "appConfigSku": "standard",
        "FontNameKey": "FontName",
        "FontColorKey": "FontColor",
        "myLabel": "Test",
        "App Configuration Data Reader": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', '516239f1-63e1-4d78-a4de-a74fb236a071')]"
    },
    "resources": [
        {
            "type": "Microsoft.Web/sites",
            "name": "[variables('functionAppName')]",
            "apiVersion": "2021-03-01",
            "location": "[variables('resourcesRegion')]",
            "identity": {
                "type": "SystemAssigned"
            },
            //...
            "resources": [
                {
                    "type": "config",
                    "name": "appsettings",
                    "apiVersion": "2021-03-01",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
                        "[resourceId('Microsoft.AppConfiguration/configurationStores', variables('appConfigStoreName'))]"
                    ],
                    "properties": {
                        "WEBSITE_FONTNAME": "[concat('@Microsoft.AppConfiguration(Endpoint=', reference(resourceId('Microsoft.AppConfiguration/configurationStores', variables('appConfigStoreName'))).endpoint,'; Key=',variables('FontNameKey'),'; Label=',variables('myLabel'), ')')]",
                        "WEBSITE_FONTCOLOR": "[concat('@Microsoft.AppConfiguration(Endpoint=', reference(resourceId('Microsoft.AppConfiguration/configurationStores', variables('appConfigStoreName'))).endpoint,'; Key=',variables('FontColorKey'),'; Label=',variables('myLabel'), ')')]",
                        "WEBSITE_ENABLE_SYNC_UPDATE_SITE": "true"
                        //...
                    }
                },
                {
                    "type": "sourcecontrols",
                    "name": "web",
                    "apiVersion": "2021-03-01",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
                        "[resourceId('Microsoft.Web/sites/config', variables('functionAppName'), 'appsettings')]"
                    ]
                }
            ]
        },
        {
            "type": "Microsoft.AppConfiguration/configurationStores",
            "name": "[variables('appConfigStoreName')]",
            "apiVersion": "2019-10-01",
            "location": "[variables('resourcesRegion')]",
            "sku": {
                "name": "[variables('appConfigSku')]"
            },
            //...
            "dependsOn": [
                "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]"
            ],
            "properties": {
            },
            "resources": [
                {
                    "type": "keyValues",
                    "name": "[variables('FontNameKey')]",
                    "apiVersion": "2021-10-01-preview",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.AppConfiguration/configurationStores', variables('appConfigStoreName'))]"

                    ],
                    "properties": {
                        "value": "Calibri",
                        "contentType": "application/json"
                    }
                },
                {
                    "type": "keyValues",
                    "name": "[variables('FontColorKey')]",
                    "apiVersion": "2021-10-01-preview",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.AppConfiguration/configurationStores', variables('appConfigStoreName'))]"

                    ],
                    "properties": {
                        "value": "Blue",
                        "contentType": "application/json"
                    }
                }
            ]
        },
        {
            "scope": "[resourceId('Microsoft.AppConfiguration/configurationStores', variables('appConfigStoreName'))]",
            "type": "Microsoft.Authorization/roleAssignments",
            "apiVersion": "2020-04-01-preview",
            "name": "[parameters('roleNameGuid')]",
            "properties": {
                "roleDefinitionId": "[variables('App Configuration Data Reader')]",
                "principalId": "[reference(resourceId('Microsoft.Web/sites/', variables('functionAppName')), '2020-12-01', 'Full').identity.principalId]",
                "principalType": "ServicePrincipal"
            }
        }
    ]
}

Nota

En este ejemplo, la implementación del control de código fuente depende de la configuración de la aplicación. Este comportamiento es normalmente poco seguro, ya que la actualización de la configuración de la aplicación se comporta de forma asincrónica. Sin embargo, como hemos incluido la configuración de la aplicación WEBSITE_ENABLE_SYNC_UPDATE_SITE, la actualización es sincrónica. Esto significa que la implementación del control de código fuente solo comenzará una vez que la configuración de la aplicación se haya actualizado completamente. Para conocer más opciones de configuración de la aplicación, vea Variables de entorno y configuración de la aplicación en Azure App Service.

Solución de problemas de las referencias de App Configuration

Si alguna referencia no se resuelve correctamente, se usará el valor de la referencia. En la configuración de la aplicación, se creará una variable de entorno cuyo valor tiene la sintaxis @Microsoft.AppConfiguration(...). Esto puede provocar un error, ya que lo que esperaba la aplicación era un valor de configuración.

Normalmente, este error podría deberse a una configuración incorrecta de la directiva de acceso de App Configuration. Sin embargo, también podría deberse a un error de sintaxis en la referencia o al valor de clave de configuración no existente en el almacén.

Pasos siguientes