对应用服务和 Azure Functions 使用应用程序配置引用(预览版)

本主题介绍如何在应用服务或 Azure Functions 应用程序中使用配置数据,而无需更改任何代码。 Azure 应用程序配置是一项可集中管理应用程序配置的服务。 此外,随时间或版本的变化,对于配置值而言它是一种高效审核工具。

向应用授予访问应用程序配置的权限

若要开始在应用服务中使用应用程序配置引用,首先需要应用程序配置存储区,并向应用提供用于访问存储中的配置键值的权限。

  1. 按照应用程序配置快速入门创建应用程序配置存储区。

    备注

    应用程序配置引用尚不支持网络受限的配置存储区。

  2. 为应用程序创建一个托管标识

    默认情况下,应用程序配置引用将使用应用系统分配的标识,但你可以指定用户分配的标识

  3. 使新创建的标识能够在应用程序配置存储区上拥有一组正确的访问权限。 更新存储的角色分配。 将为此标识分配 App Configuration Data Reader 角色,范围限定于资源。

使用用户分配的标识访问应用程序配置存储区

系统分配的标识尚不可用时,某些应用可能需要在创建时引用配置。 在这些情况下,可以提前创建用户分配的标识并为其授予对应用程序配置存储区的访问权限。 按照以下步骤为应用程序配置存储区创建用户分配的标识

被授予对用户分配的标识的权限后,请执行以下步骤:

  1. 将标识分配到应用程序(如果尚未分配)。

  2. 通过将 keyVaultReferenceIdentity 属性设置为用户分配的标识的资源 ID,配置应用以将此标识用于应用程序配置引用操作。 尽管属性的名称中含有 keyVault,但标识也将应用于应用程序配置引用。

    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}'}}"
    

此配置将应用于此应用的所有引用。

授予应用对引用的密钥保管库的访问权限

除了存储原始配置值外,Azure 应用程序配置还具有自己的格式来存储密钥保管库引用。 如果应用程序配置引用的值是应用程序配置存储中的密钥保管库引用,则应用还需要具有访问所指定的密钥保管库的权限。

注意

不应将 Azure 应用程序配置密钥保管库引用概念应用服务和 Azure Functions 密钥保管库引用概念混淆。 你的应用可以使用它们的任意组合,但有一些重要的区别需要注意。 如果你的保管库需要网络受限,或者需要应用定期更新到最新版本,请考虑使用应用服务和 Azure Functions 直接方法,而不是使用应用程序配置引用。

  1. 确定用于应用程序配置引用的标识。 必须向同一标识授予对保管库的访问权限。

  2. 在密钥保管库中为该标识创建访问策略。 在此策略上启用“获取”机密权限。 请勿配置“授权的应用程序”或 applicationId 设置,因为这与托管标识不兼容。

引用语法

应用程序配置引用采用 @Microsoft.AppConfiguration({referenceString}) 形式,其中 {referenceString} 替换为以下内容:

引用字符串部分 说明
Endpoint=endpoint; Endpoint 是引用字符串的必需部分。 Endpoint 的值应包含应用程序配置资源的 URL。
Key=keyName; Key 构成引用字符串的必需部分。 Key 的值应为要分配给应用设置的键名。
Label=label Label 是引用字符串中的可选部分。 Label 应为 Key 中指定的键的 Label 值

例如,带有 Label 的完整引用如下所示,

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

或者不带任何 Label

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

任何导致站点重启的应用配置更改都会立即从应用程序配置存储区中重新提取所有被引用的键值。

来自应用程序配置的源应用程序设置

应用程序配置引用可用作应用程序设置的值,支持将配置数据保留在应用程序配置中,而不是站点配置中。应用程序设置和应用程序配置键值都安全地进行静态加密。 如果需要集中的配置管理能力,那么配置数据应进入应用程序配置。

若要将应用程序配置引用用于应用设置,请将引用设置为设置的值。 应用可以像往常一样通过其键引用配置值。 不需更改代码。

提示

应将大多数使用应用程序配置引用的应用程序设置标记为槽设置,因为你应该为每个环境设置单独的存储区或标签。

Azure 文件存储装载注意事项

应用可使用 WEBSITE_CONTENTAZUREFILECONNECTIONSTRING 应用程序设置将 Azure 文件存储装载为文件系统。 此设置有额外的验证检查,旨在确保该应用可以正常启动。 平台依赖于在 Azure 文件存储中拥有内容共享,而且除非通过 WEBSITE_CONTENTSHARE 设置指定名称,否则其会采用默认名称。 对于修改这些设置的任何请求,平台将尝试验证此内容共享是否存在,如果不存在,将尝试创建共享。 如果找不到或无法创建内容共享,系统会阻止请求。

如果为此设置使用应用程序配置引用,默认情况下,此验证检查将失败,因为在处理传入请求时无法解析连接本身。 若要避免此问题,可以通过将 WEBSITE_SKIP_CONTENTSHARE_VALIDATION 设置为“1”来跳过验证。 此设置将绕过所有检查,且不会创建内容共享。 应确保提前创建内容共享。

注意

如果跳过验证,并且连接字符串或内容共享无效,该应用将无法正常启动,并且只会显示 HTTP 500 错误。

在创建站点的过程中,也可能会因为未传播托管标识权限,或未设置虚拟网络集成,导致内容共享装载尝试失败。 可推迟到稍后在部署模板中设置 Azure 文件存储,以适应所需设置。 若要了解更多信息,请参阅 Azure 资源管理器部署。 应用服务将使用默认文件系统,直至 Azure 文件存储设置完毕,并且不会复制文件,因此请确保在装载 Azure 文件存储之前的过渡期内不会进行任何部署尝试。

Azure 资源管理器部署

通过 Azure 资源管理器模板自动进行资源部署时,可能需要将依赖项按特定的顺序排列,这样才能使该功能发挥作用。 请注意,需要将应用程序设置定义为其自身的资源,而不是使用站点定义中的 siteConfig 属性。 这是因为,站点需先进行定义,这样才能使用它来创建系统分配标识并将该标识用在访问策略中。

以下是具有应用程序配置引用的函数应用的示例伪模板:

{
    "$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": "China North 2",
        "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"
            }
        }
    ]
}

注意

在此示例中,源代码管理部署取决于应用程序设置。 这通常是不安全的行为,因为应用设置更新是以异步方式表现的。 不过,由于我们已包括 WEBSITE_ENABLE_SYNC_UPDATE_SITE 应用程序设置,因此更新是同步的。 这意味着源代码管理部署只有在应用程序设置已完全更新后才会开始。 有关更多应用设置,请参阅 Azure 应用服务中的环境变量和应用设置

对应用程序配置引用进行故障排除

如果未正确解析某个引用,将改用引用值。 对于应用程序设置,将创建一个环境变量,其值采用 @Microsoft.AppConfiguration(...) 语法。 它可能会导致错误,因为应用程序需要配置值。

最常见的情况是,此错误可能是由于应用程序配置访问策略配置不当导致的。 但是,也可能是由于引用中的语法错误或存储中不存在配置键值。

后续步骤