使用 App Service 與 Azure Functions 的應用程式組態參考 (預覽)

此主題示範如何在 App Service 或 Azure Functions 應用程式中使用設定資料,而不需要變更任何程式碼。 Azure 應用程式組態是可集中管理應用程式組態的服務。 此外,這也是針對一段時間或不同版本之設定值的有效稽核工具。

授與應用程式存取權給應用程式組態

若要開始在 App Service 中使用應用程式組態參考,您必須先有應用程式組態存放區,並提供您的應用程式權限來存取存放區中的組態索引鍵值。

  1. 遵循應用程式組態快速入門來建立應用程式組態存放區。

    注意

    應用程式組態參考尚未支援網路限制的組態存放區。

  2. 為您的應用程式建立受控識別

    根據預設,應用程式組態參考會使用應用程式之系統指派的身分識別,但您可以指定使用者指派的身分識別

  3. 讓新建立的身分識別在應用程式組態存放區上擁有正確的存取權限集。 更新存放區的角色指派。 您會將 App Configuration Data Reader 角色指派給此身分識別,超出資源範圍。

使用使用者指派的身分識別存取應用程式組態存放區

若系統指派的身分識別尚無法使用,則某些應用程式必須在建立時參考組態。 在這些情況下,則可事先建立使用者指派的身分識別,並授與應用程式組態存放區的存取權。 請遵循下列步驟,為應用程式組態存放區建立使用者指派的身分識別

已授與權限給使用者指派的身分識別後,請遵循下列步驟:

  1. 指派身分識別給應用程式 (若尚未進行)。

  2. keyVaultReferenceIdentity 屬性設定為使用者指派之身分識別的資源識別碼,以便將應用程式設定為使用此身分識別進行應用程式組態參考作業。 雖然該屬性在名稱中有 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 應用程式組態也有自己的格式來儲存 Key Vault 參考。 如果應用程式組態參考的值是應用程式組態存放區中的 Key Vault 參考,則您的應用程式也必須具有存取所指定金鑰保存庫的權限。

注意

Azure 應用程式組態 Key Vault 參考概念 不應與 App Service 和 Azure Functions Key Vault 參考概念混淆。 您的應用程式可能會使用這些組合,但有一些重要的差異必須注意。 如果您的保存庫需要受到網路限制,或您需要應用程式定期更新至最新版本,請考慮使用 App Service 和 Azure Functions 的直接方法,而不是使用應用程式設定參考。

  1. 識別您用於應用程式組態參考的身分識別。 必須向同一身分識別授與保存庫的存取權。

  2. 在該身分識別的 Key Vault 中建立存取原則。 啟用此原則的 [取得] 祕密使用權限。 請勿設定「授權的應用程式」或 applicationId 設定,因為這與受控識別不相容。

參考語法

應用程式組態參考的格式為 @Microsoft.AppConfiguration({referenceString}),其 {referenceString} 取代方式如下:

參考字串部分 描述
Endpoint=endpoint; Endpoint 是參考字串的必要部分。 Endpoint 的值應該具有您應用程式組態資源的 URL。
Key=keyName; Key 格式是參考字串的必要部分。 Key 的值應該是您要指派給應用程式設定的金鑰名稱。
Label=label Label 是參考字串中的選擇性部分。 Label 應該是 Key 中所指定金鑰的標籤值

例如,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 Resource Manager 部署。 在 Azure 檔案儲存體設定好之前,App Service 將使用預設的檔案系統,且不會複製檔案,因此在掛接 Azure 檔案儲存體前的過渡期間,請勿嘗試進行任何部署。

Azure Resource Manager 部署

透過 Azure Resource Manager 範本將資源部署自動化時,您可能需要以特定順序來排序相依性,才能使此功能運作。 請注意,您必須將應用程式設定定義為其本身的資源,而不是使用網站定義中的 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": "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"
            }
        }
    ]
}

注意

在此範例中,原始檔控制部署取決於應用程式設定。 這通常是不安全的行為,因為應用程式設定更新會以非同步方式運作。 不過,因為我們已包含 WEBSITE_ENABLE_SYNC_UPDATE_SITE 應用程式設定,所以更新會同步。 這表示,原始檔控制部署將只會在應用程式設定已完全更新之後開始。 如需應用程式設定的詳細資訊,請參閱 Azure App Service 中的環境變數和應用程式設定

針對應用程式組態參考進行疑難排解

若參考未正確解析,則會改用參考值。 針對應用程式設定,將建立環境變數,其值具有 @Microsoft.AppConfiguration(...) 語法。 這可能會導致錯誤,因為應用程式原本預期的是設定值。

最常見的情況是,此錯誤可能是因為應用程式組態存取原則的設定錯誤。 然而,這也可能是因為參考中的語法錯誤,或是存放區中不存在的組態索引鍵值。

下一步