Использование ссылок Key Vault в качестве параметров приложения в Служба приложений Azure и Функции Azure

В этой статье показано, как использовать секреты из azure Key Vault в качестве значений параметров приложения или строк подключения в Служба приложений или Функции Azure приложениях.

Служба Azure Key Vault обеспечивает централизованное управление секретами и полный контроль над политиками доступа и журналами аудита. Если параметр приложения или строка подключения являются ссылкой на хранилище ключей, код приложения может использовать его, как и любой другой параметр приложения или строку подключения. Таким образом, вы можете хранить секреты отдельно от конфигурации приложения. Параметры приложения безопасно шифруются при хранении, но если вам нужны возможности управления секретами, они должны перейти в хранилище ключей.

Предоставление приложению доступа к хранилищу ключей

Чтобы считывать секреты из хранилища ключей, необходимо создать хранилище и предоставить приложению разрешение на доступ к нему.

  1. Чтобы создать хранилище ключей, изучите краткое руководство по Key Vault.

  2. Создайте для приложения управляемое удостоверение.

    Ссылки на хранилище ключей по умолчанию используют назначаемое системой удостоверение приложения, но вы можете указать удостоверение, назначаемое пользователем.

  3. Авторизация доступа на чтение к секретам хранилища ключей для управляемого удостоверения, созданного ранее. Способ выполнения зависит от модели разрешений хранилища ключей:

Хранилища с ограниченным доступом из сети

Если в хранилище настроены ограничения сети, убедитесь, что приложение имеет сетевой доступ. Хранилища не должны зависеть от общедоступных исходящих IP-адресов приложения, так как IP-адрес источника запроса секрета может отличаться. Вместо этого хранилище должно быть настроено для приема трафика из виртуальной сети, используемой приложением.

  1. Убедитесь, что в приложении настроены исходящие сетевые возможности, как описано в статье Сетевые функции Службы приложений и Параметры сети для Функций Azure.

    Приложения Linux, которые подключаются к частным конечным точкам, должны быть явно настроены для маршрутизации всего трафика через виртуальную сеть. В будущем обновлении это требование будет отменено. Чтобы настроить этот параметр, выполните следующую команду:

    az webapp config set --subscription <sub> -g <group-name> -n <app-name> --generic-configurations '{"vnetRouteAllEnabled": true}'
    
  2. Убедитесь, что конфигурация хранилища разрешает доступ к сети или подсети, которые используются приложением.

Доступ к хранилищам с помощью удостоверения, назначаемого пользователем

Некоторые приложения должны ссылаться на секреты во время создания, когда удостоверение, назначаемое системой, еще недоступно. В таких случаях можно создать удостоверение, назначаемое пользователем, и заранее предоставить доступ к хранилищу.

После предоставления разрешений для удостоверения, назначаемого пользователем, выполните следующие действия.

  1. Назначьте это удостоверение8 приложению, если вы этого еще не сделали.

  2. Настройте приложение для использования этого удостоверения для операций со ссылками на хранилище ключей, задав keyVaultReferenceIdentity для свойства идентификатор ресурса назначаемого пользователем удостоверения.

    identityResourceId=$(az identity show --resource-group <group-name> --name <identity-name> --query id -o tsv)
    az webapp update --resource-group <group-name> --name <app-name> --set keyVaultReferenceIdentity=${identityResourceId}
    

Этот параметр применяется ко всем ссылкам на хранилище ключей для приложения.

Поворот

Если версия секрета не указана в ссылке, приложение использует последнюю версию, которая существует в хранилище ключей. Когда становятся доступны новые версии, например с событием смены, приложение автоматически обновляется и начинает использовать последнюю версию в течение 24 часов. Задержка происходит потому, что служба приложений кэширует значения ссылок на хранилище ключей и повторно извлекает их каждые 24 часа. Любое изменение конфигурации приложения приводит к перезапуску приложения и немедленному повторному выбору всех указанных секретов.

Параметры исходного приложения из хранилища ключей

Чтобы использовать ссылку на хранилище ключей, задайте ссылку в качестве значения параметра . Приложения смогут использовать секрет через ключ параметра, как обычно. Изменения кода не требуются.

Совет

Большинство параметров приложений, использующих ссылки на хранилище ключей, должны быть помечены как параметры слота, так как для каждой среды должны быть отдельные хранилища.

Ссылка на хранилище ключей имеет вид @Microsoft.KeyVault({referenceString}), где {referenceString} имеет один из следующих форматов:

Строка ссылки Описание
SecretUri=secretUri SecretUri должен быть полным URI плоскости данных секрета в хранилище, при необходимости включая версию, например или https://myvault.vault.azure.net/secrets/mysecret/https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931
VaultName=vaultName;SecretName=secretName;SecretVersion=secretVersion Имя хранилища является обязательным и является именем хранилища. Имя секрета является обязательным и является именем секрета. SecretVersion — (необязательно) при наличии указывает используемую версию секрета.

Например, полная ссылка будет выглядеть следующим образом:

@Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret/)

Еще один вариант:

@Microsoft.KeyVault(VaultName=myvault;SecretName=mysecret)

Рекомендации по подключению службы "Файлы Azure"

Приложения могут использовать WEBSITE_CONTENTAZUREFILECONNECTIONSTRING параметр приложения для подключения Файлы Azure в качестве файловой системы. Этот параметр выполняет проверки, чтобы убедиться, что приложение может быть правильно запущено. Платформа использует общую папку содержимого в службе "Файлы Azure" и принимает имя по умолчанию, если не указано иное с помощью параметра WEBSITE_CONTENTSHARE. Для любых запросов, изменяющих эти параметры, платформа проверяет, существует ли эта общая папка содержимого, и пытается создать ее, если нет. Если не удается найти или создать общую папку содержимого, запрос блокируется.

При использовании ссылок на хранилище ключей в этом параметре проверка проверки по умолчанию завершается сбоем, так как сам секрет не может быть разрешен при обработке входящего запроса. Чтобы избежать этой проблемы, можно пропустить проверку, задав для параметра WEBSITE_SKIP_CONTENTSHARE_VALIDATION значение 1. Этот параметр сообщает Служба приложений обходить все проверки и не создает общую папку содержимого. Убедитесь, что он создан заранее.

Внимание!

Если проверка пропущена и либо строка подключения, либо общая папка содержимого являются недопустимыми, приложение не сможет правильно запуститься и будет обслуживать только ошибки HTTP 500.

При создании приложения попытка подключения общей папки содержимого может завершиться сбоем из-за того, что разрешения управляемого удостоверения не распространяются или интеграция с виртуальной сетью не настроена. Вы можете отложить настройку службы "Файлы Azure" до последующего использования в шаблоне развертывания. Дополнительные сведения см. в статье Развертывание Azure Resource Manager. В этом случае Служба приложений использует файловую систему по умолчанию, пока не будет настроена Файлы Azure и файлы не будут скопированы. Перед подключением Файлы Azure необходимо убедиться в отсутствии попыток развертывания в течение промежуточного периода.

Рекомендации по инструментированию Application Insights

Приложения могут использовать APPINSIGHTS_INSTRUMENTATIONKEY параметры приложения или APPLICATIONINSIGHTS_CONNECTION_STRING для интеграции с Application Insights. Интерфейсы портала для Служба приложений и Функции Azure также использовать эти параметры для получения данных телеметрии из ресурса. Если на эти значения ссылается Key Vault, эти возможности недоступны, и вместо этого вам нужно работать непосредственно с ресурсом Application Insights для просмотра данных телеметрии. Однако эти значения не считаются секретами, поэтому можно также настроить их напрямую вместо использования ссылок на хранилище ключей.

Развертывание Azure Resource Manager

При автоматизации развертывания ресурсов с помощью шаблонов Azure Resource Manager вам может потребоваться определенный порядок размещения зависимостей, без которого эта функция не будет работать. Не забудьте определить параметры приложения как собственный ресурс, а не использовать siteConfig свойство в определении приложения. Это связано с тем, что сначала необходимо определить приложение, чтобы с его помощью было создано удостоверение, назначаемое системой, и его можно было использовать в политике доступа.

Следующий псевдо-шаблон является примером того, как может выглядеть приложение-функция:

{
    //...
    "resources": [
        {
            "type": "Microsoft.Storage/storageAccounts",
            "name": "[variables('storageAccountName')]",
            //...
        },
        {
            "type": "Microsoft.Insights/components",
            "name": "[variables('appInsightsName')]",
            //...
        },
        {
            "type": "Microsoft.Web/sites",
            "name": "[variables('functionAppName')]",
            "identity": {
                "type": "SystemAssigned"
            },
            //...
            "resources": [
                {
                    "type": "config",
                    "name": "appsettings",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
                        "[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]",
                        "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), variables('storageConnectionStringName'))]",
                        "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), variables('appInsightsKeyName'))]"
                    ],
                    "properties": {
                        "AzureWebJobsStorage": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('storageConnectionStringName')).secretUriWithVersion, ')')]",
                        "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('storageConnectionStringName')).secretUriWithVersion, ')')]",
                        "APPINSIGHTS_INSTRUMENTATIONKEY": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('appInsightsKeyName')).secretUriWithVersion, ')')]",
                        "WEBSITE_ENABLE_SYNC_UPDATE_SITE": "true"
                        //...
                    }
                },
                {
                    "type": "sourcecontrols",
                    "name": "web",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
                        "[resourceId('Microsoft.Web/sites/config', variables('functionAppName'), 'appsettings')]"
                    ],
                }
            ]
        },
        {
            "type": "Microsoft.KeyVault/vaults",
            "name": "[variables('keyVaultName')]",
            //...
            "dependsOn": [
                "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]"
            ],
            "properties": {
                //...
                "accessPolicies": [
                    {
                        "tenantId": "[reference(resourceId('Microsoft.Web/sites/', variables('functionAppName')), '2020-12-01', 'Full').identity.tenantId]",
                        "objectId": "[reference(resourceId('Microsoft.Web/sites/', variables('functionAppName')), '2020-12-01', 'Full').identity.principalId]",
                        "permissions": {
                            "secrets": [ "get" ]
                        }
                    }
                ]
            },
            "resources": [
                {
                    "type": "secrets",
                    "name": "[variables('storageConnectionStringName')]",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]",
                        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
                    ],
                    "properties": {
                        "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountResourceId'),'2019-09-01').key1)]"
                    }
                },
                {
                    "type": "secrets",
                    "name": "[variables('appInsightsKeyName')]",
                    //...
                    "dependsOn": [
                        "[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]",
                        "[resourceId('Microsoft.Insights/components', variables('appInsightsName'))]"
                    ],
                    "properties": {
                        "value": "[reference(resourceId('microsoft.insights/components/', variables('appInsightsName')), '2019-09-01').InstrumentationKey]"
                    }
                }
            ]
        }
    ]
}

Примечание

В этом примере развертывание системы управления версиями зависит от параметров приложения. Такое поведение обычно считается небезопасным, так как обновление параметров приложения выполняется асинхронно. Но в этом примере оно будет синхронным, так как мы добавили параметр приложения WEBSITE_ENABLE_SYNC_UPDATE_SITE. Это означает, что развертывания системы управления версиями начнется только после того, как завершится обновление параметров приложения. Дополнительные параметры приложения описаны в разделе Переменные среды и параметры приложения в службе приложений Azure.

Устранение неполадок со ссылками на хранилище ключей

Если ссылка не разрешается должным образом, вместо нее используется строка ссылки (например, @Microsoft.KeyVault(...)). Это может привести к возникновению ошибок в приложении, так как ожидается секрет другого значения.

Сбой решения обычно происходит из-за неправильной настройки политики доступа Key Vault. Однако это также может быть вызвано тем, что секрет больше не существует или есть синтаксическая ошибка в самой ссылке.

Если синтаксис правильный, можно поискать другие причины ошибки, проверив текущее состояние разрешения на портале. Перейдите к параметрам приложения и выберите "Изменить" для требуемой ссылки. В диалоговом окне редактирования отображаются сведения о состоянии, включая все ошибки. Если сообщение о состоянии не отображается, это означает, что синтаксис является недопустимым и не распознается как ссылка на хранилище ключей.

Для получения дополнительных сведений можно также использовать один из встроенных детекторов.

Использование детектора для Службы приложений

  1. На портале перейдите к вашему приложению.
  2. Выберите колонку Диагностика и решение проблем.
  3. Выберите Доступность и производительность , а затем веб-приложение не работает.
  4. В поле поиска найдите и выберите Key Vault Диагностика параметров приложения.

Использование детектора для Функций Azure

  1. На портале перейдите к вашему приложению.
  2. Перейдите к разделу Функции платформы.
  3. Выберите колонку Диагностика и решение проблем.
  4. Выберите Доступность и производительность , а затем выберите Приложение-функция не работает или сообщает об ошибках.
  5. Выберите Key Vault Диагностика параметров приложения.