Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье объясняется, как использовать поставщик конфигурации Azure Key Vault для загрузки значений конфигурации приложения из секретов Key Vault. Key Vault — это облачная служба, которая помогает защитить криптографические ключи и секреты, используемые приложениями и службами. Ниже приведены распространенные сценарии использования Key Vault с приложениями ASP.NET Core:
- Управление доступом к конфиденциальным данным конфигурации.
- Удовлетворение требования по сертификации аппаратных модулей безопасности (HSM) уровня FIPS 140-2 Level 2 при хранении данных конфигурации.
Packages
Добавьте ссылки на пакеты для следующих пакетов:
Пример приложения
Пример приложения выполняется в любом из двух режимов, #define определенных директивой препроцессора в верхней части файла Program.cs :
Certificate. Демонстрирует использование идентификатора клиента Key Vault и сертификата X.509 для доступа к секретам, хранящимся в key vault. Вы можете запускать пример в любом месте — как в Служба приложений Azure, так и на любом хосте, который может размещать приложение ASP.NET Core.Managed: демонстрирует, как использовать управляемые удостоверения для ресурсов Azure. Управляемое удостоверение выполняет аутентификацию приложения в Key Vault с помощью функции «Управляемые удостоверения для ресурсов Azure» без хранения учетных данных в коде приложения или конфигурации. ВерсияManagedпримера должна быть развернута в Azure. Следуйте инструкциям в разделе "Использование управляемых удостоверений для ресурсов Azure".
Дополнительные сведения о настройке тестового приложения с помощью #define см. в разделе Директивы препроцессора в примере кода.
Просмотреть или скачать образец кода (описание загрузки)
Хранилище секретов в среде разработки
Задайте секреты локально с помощью средства диспетчера секретов . При запуске примера приложения на локальном компьютере в Development среде секреты загружаются из локального хранилища секретов пользователей.
Для диспетчера секретов требуется наличие свойства <UserSecretsId> в файле проекта приложения. Задайте значение свойства ({GUID}) для любого уникального GUID:
<PropertyGroup>
<UserSecretsId>{GUID}</UserSecretsId>
</PropertyGroup>
Секреты создаются в формате пар "имя-значение". Иерархические значения (разделы конфигурации) используют двоеточия (:) в качестве разделителей в именах ключей конфигурации ASP.NET Core.
Диспетчер секретов используется в командной оболочке (или терминале), открытой в корневом каталоге содержимого проекта, где {SECRET NAME} — имя, а {SECRET VALUE} — значение:
dotnet user-secrets set "{SECRET NAME}" "{SECRET VALUE}"
Выполните следующие команды в командной оболочке из корневого каталога содержимого проекта. Команды задают секреты для примера приложения:
dotnet user-secrets set "SecretName" "secret_value_1_dev"
dotnet user-secrets set "Section:SecretName" "secret_value_2_dev"
Если эти секреты хранятся в Key Vault, как описано в разделе Хранение секретов в рабочей среде с помощью Key Vault, суффикс _dev меняется на _prod. Суффикс предоставляет визуальный сигнал в выходных данных приложения, указывающий источник значений конфигурации.
Хранение секретов в промышленной среде с Key Vault
Создайте хранилище ключей Azure и сохраните образцы секретов приложения, выполнив следующие действия. Дополнительные сведения см. в разделе Quickstart: установка и получение секрета из Key Vault с помощью Azure CLI.
Откройте Azure Cloud Shell с помощью любого из следующих методов на портале Azure:
- Нажмите кнопку Попробовать в правом верхнем углу блока с кодом. Используйте строку поиска Azure CLI в текстовом поле.
- Откройте Cloud Shell в браузере с помощью кнопки Launch Cloud Shell .
- Нажмите кнопку меню Cloud Shell в правом верхнем углу окна портала Azure.
Дополнительные сведения см. в документации Azure CLI и Overview Azure Cloud Shell.
Если вы еще не прошли проверку подлинности, выполните вход с помощью
az loginкоманды.Создайте группу ресурсов со следующей командой, где
{RESOURCE GROUP NAME}— это имя новой группы ресурсов, а{LOCATION}— регион Azure:az group create --name "{RESOURCE GROUP NAME}" --location {LOCATION}Создайте хранилище ключей Azure в группе ресурсов со следующей командой, где
{KEY VAULT NAME}— это имя нового хранилища и{LOCATION}— это регион Azure:az keyvault create --name {KEY VAULT NAME} --resource-group "{RESOURCE GROUP NAME}" --location {LOCATION}Создайте секреты в хранилище в виде пар "имя-значение".
Key Vault имена секретов могут состоять из буквенно-цифровых символов и дефисов (
-). Иерархические значения (разделы конфигурации) используют в качестве разделителя два тире или дефиса (--). Символ двоеточия не разрешен в именах секретов Key Vault. Двоеточия разделяют раздел и подключ в конфигурации ASP.NET Core. Последовательность из двух тире заменяется двоеточием при загрузке секретов в конфигурацию приложения.Следующие секреты предназначены для использования с примером приложения. Значения содержат суффикс
_prod, который отличает их от значений с суффиксом_dev, загруженных в средеDevelopmentчерез диспетчер секретов. Замените{KEY VAULT NAME}именем созданного ранее хранилища ключей:az keyvault secret set --vault-name {KEY VAULT NAME} --name "SecretName" --value "secret_value_1_prod" az keyvault secret set --vault-name {KEY VAULT NAME} --name "Section--SecretName" --value "secret_value_2_prod"
Использование идентификатора приложения и сертификата X.509 для приложений, не размещенных в Azure
Настройте Key Vault и приложение для использования идентификатора приложения Microsoft Entra ID и сертификата X.509 для аутентификации в хранилище когда приложение размещено за пределами Azure. См. дополнительные сведения о ключах, секретах и сертификатах.
Note
Хотя использование идентификатора приложения и сертификата X.509 поддерживается для приложений, размещенных в Azure, этот подход не рекомендуется. Вместо этого используйте управляемые идентификаторы Azure для ресурсов при размещении приложения в Azure. Управляемые удостоверения не требуют хранения сертификата в приложении или в Development среде.
В примере приложения используются идентификатор приложения и сертификат X.509, когда директива препроцессора #define в верхней части файла Program.cs установлена в значение Certificate.
Создайте сертификат архива PKCS#12 (PFX). Параметры создания сертификатов включают New-SelfSignedCertificate в Windows и OpenSSL.
Установите сертификат в личное хранилище сертификатов текущего пользователя. Маркировка ключа как экспортируемого является необязательным. Обратите внимание на отпечаток сертификата, который используется позже в этом процессе.
Экспортируйте сертификат архива PKCS#12 (PFX) в виде сертификата в кодировке DER (.cer).
Зарегистрируйте приложение с помощью идентификатора Microsoft Entra (Регистрация приложений).
Отправьте сертификат в кодировке DER (.cer) в Microsoft Entra ID:
- Выберите приложение в идентификаторе Microsoft Entra.
- Перейдите к сертификатам и секретам.
- Выберите " Отправить сертификат", чтобы отправить сертификат , содержащий открытый ключ. Допустим сертификат .cer, .pem или .crt.
Сохраните имя хранилища ключей, идентификатор приложения и отпечаток сертификата в файле appsettings.json приложения.
На портале Azure перейдите к Key Vaults.
Выберите хранилище ключей, созданное в хранилище Secret в рабочей среде с разделом Azure Key Vault.
Выберите политики доступа и нажмите кнопку "Добавить политику доступа".
Откройте разрешения для секретов и предоставьте приложению разрешения Get и List.
Выберите субъект. Выберите зарегистрированные приложения по имени и нажмите кнопку "Выбрать".
Выберите ОК, затем выберите Сохранить.
Разверните приложение.
Пример Certificate приложения получает значения конфигурации из IConfigurationRoot того же имени, что и имя секрета:
- Неиерархические значения: значение для
SecretNameполучается с помощьюconfig["SecretName"]. - Иерархические значения (разделы): используйте запись с двоеточием (
:) или метод GetSection. Используйте один из следующих подходов для получения значения конфигурации:config["Section:SecretName"]config.GetSection("Section")["SecretName"]
Операционная система управляет сертификатом X.509. Приложение вызывает AddAzureKeyVault метод со значениями, предоставленными файлом appsettings.json :
using System.Security.Cryptography.X509Certificates;
using Azure.Identity;
var builder = WebApplication.CreateBuilder(args);
if (builder.Environment.IsProduction())
{
using var x509Store = new X509Store(StoreLocation.CurrentUser);
x509Store.Open(OpenFlags.ReadOnly);
var x509Certificate = x509Store.Certificates
.Find(
X509FindType.FindByThumbprint,
builder.Configuration["AzureADCertThumbprint"],
validOnly: false)
.OfType<X509Certificate2>()
.Single();
builder.Configuration.AddAzureKeyVault(
new Uri($"https://{builder.Configuration["KeyVaultName"]}.vault.azure.net/"),
new ClientCertificateCredential(
builder.Configuration["AzureADDirectoryId"],
builder.Configuration["AzureADApplicationId"],
x509Certificate));
}
var app = builder.Build();
Примеры значений:
- Имя хранилища ключей:
contosovault - ИД приложения:
00001111-aaaa-2222-bbbb-3333cccc4444 - Отпечаток сертификата:
fe14593dd66b2406c5269d742d04b6e1ab03adb1
Значения в файле appsettings.json :
{
"KeyVaultName": "Key Vault Name",
"AzureADApplicationId": "Azure AD Application ID",
"AzureADCertThumbprint": "Azure AD Certificate Thumbprint",
"AzureADDirectoryId": "Azure AD Directory ID"
}
При запуске приложения веб-страница отображает загруженные значения секретов.
Development В этой среде секретные значения загружаются с суффиксом _dev. В среде Production значения загружаются с суффиксом _prod.
Использование управляемых удостоверений для ресурсов Azure
Приложение, развернутое в Azure , может воспользоваться управляемыми удостоверениями для ресурсов Azure. Управляемое удостоверение позволяет приложению проходить проверку подлинности с помощью Azure Key Vault с помощью проверки подлинности Microsoft Entra ID без хранения учетных данных в коде приложения или конфигурации.
В примере приложения используется управляемое удостоверение, назначаемое системой, когда #define директива препроцессора в верхней части файла Program.cs задана Managed. Сведения о создании управляемого удостоверения для приложения Службы приложений Azure см. в статье Использование управляемых удостоверений для службы приложений и функций Azure. После создания управляемой идентичности обратите внимание на идентификатор объекта приложения, который отображается в портале Azure на панели Identity службы приложений.
Введите имя хранилища ключей в файл appsettings.json приложения. Пример приложения не требует идентификатора приложения и пароля (секрет клиента) при настройке Managed версии, поэтому эти записи конфигурации можно игнорировать. Приложение развертывается в Azure и Azure проверяет подлинность приложения для доступа к Key Vault только с помощью имени хранилища, хранящегося в файле appsettings.json.
Разверните пример приложения в службе приложение Azure.
С помощью Azure CLI и идентификатора объекта приложения предоставьте приложению разрешения list и get для доступа к хранилищу ключей:
az keyvault set-policy --name {KEY VAULT NAME} --object-id {OBJECT ID} --secret-permissions get list
Перезапустите приложение с помощью Azure CLI, Azure PowerShell или портала Azure.
Пример приложения создает экземпляр DefaultAzureCredential класса. Учетные данные аутентификации пытаются получить токен доступа из среды для ресурсов Azure.
using Azure.Identity;
var builder = WebApplication.CreateBuilder(args);
if (builder.Environment.IsProduction())
{
builder.Configuration.AddAzureKeyVault(
new Uri($"https://{builder.Configuration["KeyVaultName"]}.vault.azure.net/"),
new DefaultAzureCredential());
}
Note
В предыдущем примере используется класс DefaultAzureCredential для упрощения проверки подлинности при разработке приложений, развертываемых в Azure. Этот подход объединяет учетные данные, используемые в средах размещения Azure с учетными данными, используемыми в локальной разработке. При переносе реализации в рабочую среду лучше выбрать альтернативу, например класс ManagedIdentityCredential. Дополнительные сведения см. в разделе Проверка подлинности размещенных в Azure приложений .NET для доступа к ресурсам Azure с помощью управляемого удостоверения, назначаемого системой.
Пример имени хранилища ключей: contosovault
Значение имени в файле appsettings.json :
{
"KeyVaultName": "Key Vault Name"
}
Для приложений, использующих управляемое удостоверение, назначаемое пользователем, настройте идентификатор клиента управляемого удостоверения с помощью одного из следующих подходов:
Установите переменную среды
AZURE_CLIENT_ID.Задайте свойство DefaultAzureCredentialOptions.ManagedIdentityClientId при вызове метода
AddAzureKeyVault:builder.Configuration.AddAzureKeyVault( new Uri($"https://{builder.Configuration["KeyVaultName"]}.vault.azure.net/"), new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = builder.Configuration["AzureADManagedIdentityClientId"] }));
При запуске приложения веб-страница отображает загруженные значения секретов.
Development В среде значения секретов имеют _dev суффикс, так как они предоставляются Менеджером секретов. В среде Production значения загружаются с суффиксом _prod, поскольку они предоставлены через Azure Key Vault.
Если вы получаете ошибку Access denied, убедитесь, что приложение зарегистрировано в Microsoft Entra ID и имеет доступ к хранилищу. Убедитесь, что вы перезапустили службу в Azure.
Дополнительные сведения об использовании поставщика с управляемым удостоверением и Azure Pipelines см. в разделе Подключение к Azure с помощью подключения к службе Azure Resource Manager.
Параметры конфигурации
Метод AddAzureKeyVault может принять AzureKeyVaultConfigurationOptions объект:
// using Azure.Extensions.AspNetCore.Configuration.Secrets;
builder.Configuration.AddAzureKeyVault(
new Uri($"https://{builder.Configuration["KeyVaultName"]}.vault.azure.net/"),
new DefaultAzureCredential(),
new AzureKeyVaultConfigurationOptions
{
// ...
});
Объект AzureKeyVaultConfigurationOptions содержит следующие свойства:
| Property | Description |
|---|---|
| Manager | Указывает экземпляр KeyVaultSecretManager, используемый для управления загрузкой секретов. |
| ReloadInterval | Указывает время ожидания TimeSpan между попытками опроса хранилища ключей на наличие изменений. Значением по умолчанию является null (конфигурация не перезагрузится). |
Использование префикса имени ключа
Метод AddAzureKeyVault предоставляет перегрузку, принимающую реализацию KeyVaultSecretManager, позволяющую управлять тем, как секреты Key Vault преобразуются в ключи конфигурации. Например, интерфейс можно реализовать для загрузки значений секретов на основе значения префикса, предоставленного при запуске приложения. Этот метод позволяет, например, загружать секреты на основе версии приложения.
Important
Не используйте префиксы в секретах Key Vault для:
- Поместите секреты для нескольких приложений в одно хранилище ключей.
- Поместите секреты для разных сред (например, секреты
DevelopmentиProduction) в одно хранилище ключей.
Различные приложения и среды разработки и рабочей среды должны использовать отдельные хранилища ключей для изоляции сред приложений для наивысшего уровня безопасности.
В следующем примере секрет устанавливается в Key Vault (с помощью диспетчера секретов для среды Development) для 5000-AppSecret (периоды не допускаются в именах секретов Key Vault). Этот секрет представляет собой секрет приложения версии 5.0.0.0. Для другой версии приложения 5.1.0.0 секрет добавляется в то же хранилище ключей (с помощью диспетчера секретов) для 5100-AppSecret. Каждая версия приложения загружает значение секрета своей версии в конфигурацию как AppSecret, удаляя версию при загрузке секрета.
Метод AddAzureKeyVault вызывается с пользовательской KeyVaultSecretManager реализацией:
// using Azure.Extensions.AspNetCore.Configuration.Secrets;
builder.Configuration.AddAzureKeyVault(
new Uri($"https://{builder.Configuration["KeyVaultName"]}.vault.azure.net/"),
new DefaultAzureCredential(),
new SamplePrefixKeyVaultSecretManager("5000"));
Реализация реагирует на префиксы версий секретов, чтобы загрузить соответствующий секрет в конфигурацию:
- Метод
Loadзагружает секрет, когда его имя начинается с префикса. Другие секреты не загружаются. - Метод:
GetKey- Удаляет префикс из имени секрета.
- Заменяет два дефиса (
--) в любом имени наKeyDelimiter. Этот разделитель (обычно двоеточие:) используется в конфигурации, так как Key Vault не допускает двоеточие (:) в именах секретов.
public class SamplePrefixKeyVaultSecretManager : KeyVaultSecretManager
{
private readonly string _prefix;
public SamplePrefixKeyVaultSecretManager(string prefix)
=> _prefix = $"{prefix}-";
public override bool Load(SecretProperties properties)
=> properties.Name.StartsWith(_prefix);
public override string GetKey(KeyVaultSecret secret)
=> secret.Name[_prefix.Length..].Replace("--", ConfigurationPath.KeyDelimiter);
}
Алгоритм поставщика данных вызывает метод Load и перебирает секреты в хранилище ключей, чтобы найти секреты с префиксом версии. При обнаружении префикса версии с помощью Load, алгоритм использует метод GetKey для возврата имени конфигурации секрета. Он удаляет префикс версии из имени секрета. Оставшаяся часть имени секрета возвращается для загрузки в конфигурацию приложения в виде пар «имя — значение».
При реализации этого подхода выполните следующие действия.
Укажите версию приложения в файле проекта приложения. В следующем примере для версии приложения задано значение
5.0.0.0:<PropertyGroup> <Version>5.0.0.0</Version> </PropertyGroup>Убедитесь, что свойство
<UserSecretsId>определено в файле проекта приложения, где{GUID}— GUID, предоставленный пользователем:<PropertyGroup> <UserSecretsId>{GUID}</UserSecretsId> </PropertyGroup>Сохраните следующие секреты локально с помощью диспетчера секретов:
dotnet user-secrets set "5000-AppSecret" "5.0.0.0_secret_value_dev" dotnet user-secrets set "5100-AppSecret" "5.1.0.0_secret_value_dev"Сохраните секреты в Azure Key Vault с помощью следующих команд Azure CLI:
az keyvault secret set --vault-name {KEY VAULT NAME} --name "5000-AppSecret" --value "5.0.0.0_secret_value_prod" az keyvault secret set --vault-name {KEY VAULT NAME} --name "5100-AppSecret" --value "5.1.0.0_secret_value_prod"
Процесс выполняет следующие задачи:
При запуске приложения реализация загружает секреты хранилища ключей. Строковый секрет
5000-AppSecretсоответствует версии приложения, указанной в файле проекта приложения (5.0.0.0).Версия (
5000с дефисом) удаляется из имени ключа. В приложении чтение конфигурации с ключомAppSecretзагружает секретное значение.Если версия приложения изменена в файле проекта на
5.1.0.0и приложение снова запускается, возвращаемое значение секрета —5.1.0.0_secret_value_devв средеDevelopmentи5.1.0.0_secret_value_prodвProduction.
Note
Вы также можете передать собственную реализацию SecretClient в метод AddAzureKeyVault. Настраиваемый клиент позволяет использовать один экземпляр клиента во всём приложении.
Привязка массива к классу
Поставщик может считывать значения конфигурации в массив для привязки к массиву POCO.
При чтении из источника конфигурации, позволяющего ключам содержать разделители двоеточий (:) числовой сегмент ключа используется для различения ключей, составляющих массив (:0:, :1:... :{n}:). Дополнительные сведения см. в разделе "Конфигурация: привязка массива к классу".
ключи Key Vault не могут использовать двоеточие (:) в качестве разделителя. Описанный в этой статье подход использует двойные дефисы (--) в качестве разделителя для иерархических значений (разделов). Ключи массива хранятся в Key Vault с двойными дефисами и числовыми сегментами ключей (--0--, --1--, ... --{n}--).
Изучите следующую конфигурацию поставщика ведения журнала Serilog , указанную в JSON-файле. В массиве определены два литерала объектов WriteTo, которые отражают два приёмника Serilog, описывающих места назначения для вывода данных журналирования.
"Serilog": {
"WriteTo": [
{
"Name": "AzureTableStorage",
"Args": {
"storageTableName": "logs",
"connectionString": "DefaultEnd...ountKey=Eby8...GMGw=="
}
},
{
"Name": "AzureDocumentDB",
"Args": {
"endpointUrl": "https://contoso.documents.azure.com:443",
"authorizationKey": "Eby8...GMGw=="
}
}
]
}
Конфигурация в JSON-файле хранится в Key Vault с помощью двойного дефиса (--) нотации и числовых сегментов:
| Key | Value |
|---|---|
Serilog--WriteTo--0--Name |
AzureTableStorage |
Serilog--WriteTo--0--Args--storageTableName |
logs |
Serilog--WriteTo--0--Args--connectionString |
DefaultEnd...ountKey=Eby8...GMGw== |
Serilog--WriteTo--1--Name |
AzureDocumentDB |
Serilog--WriteTo--1--Args--endpointUrl |
https://contoso.documents.azure.com:443 |
Serilog--WriteTo--1--Args--authorizationKey |
Eby8...GMGw== |
Перезагрузить секреты
По умолчанию поставщик конфигурации кэширует секреты для времени существования приложения. Приложение игнорирует секреты, которые впоследствии были отключены или обновлены в хранилище ключей.
Чтобы перезагрузить секреты, вызовите IConfigurationRoot.Reload метод:
config.Reload();
Чтобы периодически загружать секреты с определенным интервалом, установите свойство AzureKeyVaultConfigurationOptions.ReloadInterval. Дополнительные сведения см. в разделе Параметры конфигурации.
Отключенные и истекшие секреты
Секреты с истекшим сроком действия включаются по умолчанию в поставщик конфигурации. Чтобы исключить значения этих секретов из конфигурации приложения, обновите просроченный секрет или предоставьте конфигурацию с помощью пользовательского поставщика конфигурации:
class SampleKeyVaultSecretManager : KeyVaultSecretManager
{
public override bool Load(SecretProperties properties) =>
properties.ExpiresOn.HasValue &&
properties.ExpiresOn.Value > DateTimeOffset.Now;
}
Передайте этот настраиваемый KeyVaultSecretManager поставщик в AddAzureKeyVault метод:
// using Azure.Extensions.AspNetCore.Configuration.Secrets;
builder.Configuration.AddAzureKeyVault(
new Uri($"https://{builder.Configuration["KeyVaultName"]}.vault.azure.net/"),
new DefaultAzureCredential(),
new SampleKeyVaultSecretManager());
Отключенные секреты не могут быть получены из Key Vault и никогда не включаются.
Note
В предыдущем примере используется класс DefaultAzureCredential для упрощения проверки подлинности при разработке приложений, развертываемых в Azure. Этот подход объединяет учетные данные, используемые в средах размещения Azure с учетными данными, используемыми в локальной разработке. При развертывании реализации в рабочей среде лучше выбрать другой вариант, например класс ManagedIdentityCredential. Дополнительные сведения см. в разделе Аутентификация размещённых в Azure приложений .NET для доступа к ресурсам Azure при помощи управляемой идентичности, назначаемой системой.
Устранение неполадок с загрузкой конфигурации
Если приложению не удается загрузить конфигурацию с помощью поставщика, сообщение об ошибке записывается в инфраструктуру ведения журнала ASP.NET Core.
Следующие условия могут препятствовать загрузке конфигурации:
- Приложение или сертификат настроены неправильно в идентификаторе Microsoft Entra.
- Хранилище ключей не существует в Azure Key Vault.
- Приложение не авторизовано для доступа к хранилищу.
- Политика доступа не включает
GetиListразрешения. - В хранилище данные конфигурации (пара "имя-значение") неправильно называются, отсутствуют или отключены.
- Приложение имеет неправильное имя хранилища ключей (
KeyVaultName), идентификатор приложения Microsoft Entra ID (AzureADApplicationId), отпечаток сертификата Microsoft Entra ID (AzureADCertThumbprint) или идентификатор каталога Microsoft Entra ID (AzureADDirectoryId). - При добавлении политики доступа Key Vault для приложения политика успешно создается, но пользователь не выбирает Сохранение в диалоговом окне Access policies.
Связанный контент
- Просмотреть или скачать образец кода (описание загрузки)
- Конфигурация в ASP.NET Core
- Документация по Azure Key Vault
- Импорт ключей, защищенных HSM, в Azure Key Vault
- Краткое руководство: клиентская библиотека секретов Azure Key Vault для .NET
- Руководство. Использование Azure Key Vault с виртуальной машиной в .NET
В этой статье описывается использование поставщика конфигурации Azure Key Vault для загрузки значений конфигурации приложения, используя секреты Azure Key Vault в качестве источника. Azure Key Vault — это облачная служба, которая помогает защитить криптографические ключи и секреты, используемые приложениями и службами. Распространенные сценарии использования Azure Key Vault с приложениями ASP.NET Core включают:
- Управление доступом к конфиденциальным данным конфигурации.
- Удовлетворение требования по сертификации аппаратных модулей безопасности (HSM) уровня FIPS 140-2 Level 2 при хранении данных конфигурации.
Packages
Добавьте ссылки на пакеты для следующих пакетов:
Пример приложения
Пример приложения выполняется в любом из двух режимов, #define определенных директивой препроцессора в верхней части Program.cs:
-
Certificate: демонстрирует использование идентификатора клиента Azure Key Vault и сертификата X.509 для доступа к секретам, хранящимся в Azure Key Vault. Этот пример можно запустить из любого расположения, будь то развернутое в службе приложений Azure или на любом узле, который может обслуживать приложение ASP.NET Core. -
Managed: демонстрирует, как использовать управляемые удостоверения для ресурсов Azure. Управляемое удостоверение аутентифицирует приложение в Azure Key Vault, используя управляемые удостоверения для ресурсов Azure, без хранения учетных данных в коде или конфигурации приложения. При использовании управляемых удостоверений для проверки подлинности не требуются идентификатор приложения и пароль (секрет клиента) для управляемых удостоверений ресурсов Azure. ВерсияManagedпримера должна быть развернута в Azure. Следуйте инструкциям в разделе "Использование управляемых удостоверений для ресурсов Azure".
Дополнительные сведения о настройке примера приложения с помощью директив препроцессора (#define) см. в обзоре ASP.NET Core.
Просмотреть или скачать образец кода (описание загрузки)
Хранилище секретов данных Development в среде
Задайте секреты локально с помощью Secret Manager. При запуске примера приложения на локальном компьютере в Development среде секреты загружаются из локального хранилища секретов пользователей.
Для диспетчера секретов требуется <UserSecretsId> свойство в файле проекта приложения. Задайте значение свойства ({GUID}) для любого уникального GUID:
<PropertyGroup>
<UserSecretsId>{GUID}</UserSecretsId>
</PropertyGroup>
Секреты создаются в формате пар "имя-значение". Иерархические значения (разделы конфигурации) используют двоеточие (:) в качестве разделителя в ключах конфигурации ASP.NET Core.
Диспетчер секретов используется из командной оболочки, открытой в корневом каталоге содержимого проекта
dotnet user-secrets set "{SECRET NAME}" "{SECRET VALUE}"
Выполните следующие команды в командной оболочке из корневого каталога содержимого проекта, чтобы задать секреты для примера приложения:
dotnet user-secrets set "SecretName" "secret_value_1_dev"
dotnet user-secrets set "Section:SecretName" "secret_value_2_dev"
Если эти секреты хранятся в разделе Production в среде, суффикс _dev изменяется на _prod. Суффикс предоставляет визуальный сигнал в выходных данных приложения, указывающий источник значений конфигурации.
Хранилище секретов в среде Production с Azure Key Vault
Выполните следующие действия, чтобы создать Azure Key Vault и сохранить в нем секреты примера приложения. Для получения дополнительной информации см. краткое руководство: настройка и получение секрета из Azure Key Vault с использованием Azure CLI.
Откройте Azure Cloud Shell с помощью одного из следующих методов в Портал Azure:
- Нажмите кнопку Попробовать в правом верхнем углу блока с кодом. Используйте строку поиска Azure CLI в текстовом поле.
- Откройте Cloud Shell в браузере с помощью кнопки Launch Cloud Shell .
- Нажмите кнопку меню Cloud Shell в правом верхнем углу окна портала Azure.
Дополнительные сведения см. в Azure CLI и обзоре Azure Cloud Shell.
Если вы еще не прошли проверку подлинности, выполните вход с помощью
az loginкоманды.Создайте группу ресурсов со следующей командой, где
{RESOURCE GROUP NAME}имя новой группы ресурсов и{LOCATION}регион Azure:az group create --name "{RESOURCE GROUP NAME}" --location {LOCATION}Создайте Key Vault в группе ресурсов с помощью следующей команды, где
{KEY VAULT NAME}находится имя нового хранилища и{LOCATION}является регионом Azure:az keyvault create --name {KEY VAULT NAME} --resource-group "{RESOURCE GROUP NAME}" --location {LOCATION}Создайте секреты в хранилище в виде пар "имя-значение".
Имена секретов Azure Key Vault ограничены буквенно-цифровыми символами и дефисами. Иерархические значения (разделы конфигурации) используют
--(два дефиса) в качестве разделителя, так как двоеточия не допускаются в именах секретов Key Vault. Двоеточия разделяют раздел и подключ в конфигурации ASP.NET Core. Последовательность из двух тире заменяется двоеточием, когда секреты загружаются в конфигурацию приложения.Следующие секреты предназначены для использования с примером приложения. Значения включают суффикс
_prodдля их отличия от значений с суффиксом_dev, загружаемых в средуDevelopmentиз Secret Manager. Замените{KEY VAULT NAME}именем хранилища ключей, созданного на предыдущем шаге:az keyvault secret set --vault-name {KEY VAULT NAME} --name "SecretName" --value "secret_value_1_prod" az keyvault secret set --vault-name {KEY VAULT NAME} --name "Section--SecretName" --value "secret_value_2_prod"
Использование идентификатора приложения и сертификата X.509 для приложений, не размещенных в Azure
Настройте Azure Key Vault и приложение для использования идентификатора приложения Microsoft Entra ID и сертификата X.509 для проверки подлинности в хранилище при размещении приложения за пределами Azure. См. дополнительные сведения о ключах, секретах и сертификатах.
Note
Хотя использование идентификатора приложения и сертификата X.509 поддерживается для приложений, размещенных в Azure, не рекомендуется. Вместо этого используйте управляемые идентификаторы Azure для ресурсов при размещении приложения в Azure. Управляемые удостоверения не требуют хранения сертификата в приложении или в Development среде.
В примере приложения используется идентификатор приложения и сертификат X.509, когда директива препроцессора #define в начале Program.cs установлена как Certificate.
- Создайте сертификат архива PKCS#12 (PFX). Параметры создания сертификатов включают New-SelfSignedCertificate в Windows и OpenSSL.
- Установите сертификат в личное хранилище сертификатов текущего пользователя. Маркировка ключа как экспортируемого является необязательным. Обратите внимание на отпечаток сертификата, который используется позже в этом процессе.
- Экспортируйте сертификат архива PKCS#12 (PFX) в виде сертификата в кодировке DER (.cer).
- Зарегистрируйте приложение с помощью идентификатора Microsoft Entra (Регистрация приложений).
- Загрузите сертификат в кодировке DER (.cer) на Microsoft Entra ID.
- Выберите приложение в идентификаторе Microsoft Entra.
- Перейдите к сертификатам и секретам.
- Выберите " Отправить сертификат", чтобы отправить сертификат , содержащий открытый ключ. Допустим сертификат .cer, .pem или .crt.
- Сохраните имя Key Vault, идентификатор приложения и отпечаток сертификата в файле приложения
appsettings.json. - Перейдите в Хранилища ключей в портале Azure.
- Выберите хранилище ключей, которое вы создали в разделе «Хранение секретов в среде
Productionс помощью Azure Key Vault». - Выберите Политики доступа.
- Выберите Добавить политику доступа.
- Откройте разрешения для секретов и предоставьте приложению разрешения Get и List.
- Выберите принципал и выберите зарегистрированное приложение по имени. Выберите кнопку Выбрать.
- Нажмите ОК.
- Нажмите кнопку "Сохранить".
- Разверните приложение.
Пример Certificate приложения получает значения конфигурации из IConfigurationRoot того же имени, что и имя секрета:
- Неиерархические значения: значение для
SecretNameполучено с помощьюconfig["SecretName"]. - Иерархические значения (разделы): используйте нотацию
:(двоеточие) или метод GetSection. Используйте один из следующих методов для получения значения конфигурации:config["Section:SecretName"]config.GetSection("Section")["SecretName"]
Сертификат X.509 управляется ОС. Приложение вызывает AddAzureKeyVault со значениями, предоставленными файлом appsettings.json.
// using System.Linq;
// using System.Security.Cryptography.X509Certificates;
// using Azure.Extensions.AspNetCore.Configuration.Secrets;
// using Azure.Identity;
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
if (context.HostingEnvironment.IsProduction())
{
var builtConfig = config.Build();
using var store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var certs = store.Certificates.Find(
X509FindType.FindByThumbprint,
builtConfig["AzureADCertThumbprint"], false);
config.AddAzureKeyVault(new Uri($"https://{builtConfig["KeyVaultName"]}.vault.azure.net/"),
new ClientCertificateCredential(builtConfig["AzureADDirectoryId"], builtConfig["AzureADApplicationId"], certs.OfType<X509Certificate2>().Single()),
new KeyVaultSecretManager());
store.Close();
}
})
.ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());
Примеры значений:
- Имя хранилища ключей:
contosovault - ИД приложения:
00001111-aaaa-2222-bbbb-3333cccc4444 - Отпечаток сертификата:
fe14593dd66b2406c5269d742d04b6e1ab03adb1
appsettings.json:
{
"KeyVaultName": "Key Vault Name",
"AzureADApplicationId": "Azure AD Application ID",
"AzureADCertThumbprint": "Azure AD Certificate Thumbprint",
"AzureADDirectoryId": "Azure AD Directory ID"
}
При запуске приложения веб-страница отображает загруженные значения секретов.
Development В этой среде секретные значения загружаются с суффиксом _dev. В среде Production значения загружаются с суффиксом _prod.
Использование управляемых удостоверений для ресурсов Azure
Приложение, развернутое в Azure , может воспользоваться управляемыми удостоверениями для ресурсов Azure. Управляемое удостоверение позволяет приложению аутентифицироваться в Azure Key Vault с помощью Microsoft Entra ID без учёта необходимости хранения учётных данных (идентификатор приложения и секрет клиента) внутри приложения.
Когда в примере приложения директива препроцессора #define в начале Program.cs установлена на значение Managed, используются управляемые удостоверения для ресурсов Azure.
Введите название хранилища в файл appsettings.json приложения. Пример приложения не требует идентификатора приложения и пароля (секрет клиента) при настройке Managed версии, поэтому эти записи конфигурации можно игнорировать. Приложение развертывается в Azure, и Azure проверяет подлинность приложения для доступа к Azure Key Vault только с помощью имени хранилища, хранящегося в appsettings.json файле.
Разверните пример приложения в службе приложение Azure.
Приложение, развернутое в службе приложение Azure, автоматически регистрируется с идентификатором Microsoft Entra при создании службы. Получите идентификатор объекта из развертывания для использования в следующей команде. Идентификатор объекта отображается в портале Azure на Identity панели Службы приложений.
С помощью Azure CLI и идентификатора объекта приложения предоставьте приложению list и get разрешения для доступа к хранилищу:
az keyvault set-policy --name {KEY VAULT NAME} --object-id {OBJECT ID} --secret-permissions get list
Перезапустите приложение с помощью Azure CLI, PowerShell или портал Azure.
Пример приложения:
- Создает экземпляр класса DefaultAzureCredential. Учетные данные пытаются получить маркер доступа из среды для ресурсов Azure.
- Создается новый SecretClient с использованием экземпляра
DefaultAzureCredential. - Экземпляр
SecretClientиспользуется с экземпляром KeyVaultSecretManager, который загружает значения секретов и заменяет двойные тире (--) двоеточиями (:) в именах ключей.
// using Azure.Security.KeyVault.Secrets;
// using Azure.Identity;
// using Azure.Extensions.AspNetCore.Configuration.Secrets;
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
if (context.HostingEnvironment.IsProduction())
{
var builtConfig = config.Build();
var secretClient = new SecretClient(
new Uri($"https://{builtConfig["KeyVaultName"]}.vault.azure.net/"),
new DefaultAzureCredential());
config.AddAzureKeyVault(secretClient, new KeyVaultSecretManager());
}
})
.ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());
Note
В предыдущем примере используется DefaultAzureCredential для упрощения проверки подлинности при разработке приложений, развертываемых в Azure, путем объединения учетных данных, используемых в средах размещения Azure с учетными данными, используемыми в локальной разработке. При переходе в рабочую среду альтернатива является лучшим выбором, например ManagedIdentityCredential. Дополнительные сведения см. в статье Аутентификация размещенных в Azure приложений .NET в ресурсах Azure с помощью управляемого удостоверения, назначаемого системой.
Пример значения имени Key Vault: contosovault
appsettings.json:
{
"KeyVaultName": "Key Vault Name"
}
При запуске приложения веб-страница отображает загруженные значения секретов.
Development В среде значения секретов имеют _dev суффикс, так как они предоставляются Менеджером секретов. В среде Production значения загружаются с суффиксом _prod, поскольку они предоставлены через Azure Key Vault.
Если появится ошибка Access denied, убедитесь, что приложение зарегистрировано с помощью Microsoft Entra ID и ему предоставлен доступ к хранилищу. Убедитесь, что вы перезагрузили службу в Azure.
Сведения об использовании поставщика с управляемым удостоверением и Azure Pipelines см. в статье Создание подключения службы Azure Resource Manager к виртуальной машине с управляемым удостоверением службы.
Параметры конфигурации
AddAzureKeyVault может принять AzureKeyVaultConfigurationOptions объект:
config.AddAzureKeyVault(
new SecretClient(
new Uri("Your Key Vault Endpoint"),
new DefaultAzureCredential(),
new AzureKeyVaultConfigurationOptions())
{
...
});
Note
В предыдущем примере используется DefaultAzureCredential для упрощения проверки подлинности при разработке приложений, развертываемых в Azure, путем объединения учетных данных, используемых в средах размещения Azure с учетными данными, используемыми в локальной разработке. При переходе в рабочую среду альтернатива является лучшим выбором, например ManagedIdentityCredential. Дополнительные сведения см. в статье Аутентификация размещенных в Azure приложений .NET в ресурсах Azure с помощью управляемого удостоверения, назначаемого системой.
Объект AzureKeyVaultConfigurationOptions содержит следующие свойства.
| Property | Description |
|---|---|
| Manager | KeyVaultSecretManager экземпляр, используемый для управления загрузкой секретов. |
| ReloadInterval |
TimeSpan ожидание между попытками опроса хранилища для внесения изменений. Значением по умолчанию является null (конфигурация не перезагрузится). |
Использование префикса имени ключа
AddAzureKeyVault предоставляет перегрузку, которая принимает реализацию KeyVaultSecretManager, которая позволяет управлять преобразованием секретов Key Vault в ключи конфигурации. Например, интерфейс можно реализовать для загрузки значений секретов на основе значения префикса, предоставленного при запуске приложения. Этот метод позволяет, например, загружать секреты на основе версии приложения.
Warning
Не используйте префиксы в секретах Key Vault для:
- Поместите секреты для нескольких приложений в одно хранилище.
- Поместите секреты среды (например, секреты разработки и производства) в один и тот же хранилище.
Различные приложения и среды разработки и рабочей среды должны использовать отдельные хранилища ключей для изоляции сред приложений для наивысшего уровня безопасности.
В следующем примере секрет создаётся в Key Vault (и с помощью Secret Manager для среды Development) для 5000-AppSecret (знаки препинания не допускаются в именах секретов Key Vault). Этот секрет представляет собой секрет приложения версии 5.0.0.0. Для другой версии приложения 5.1.0.0 секрет добавляется в хранилище (и с помощью диспетчера секретов).5100-AppSecret Каждая версия приложения загружает значение секрета своей версии в конфигурацию как AppSecret, удаляя версию при загрузке секрета.
AddAzureKeyVault вызывается с пользовательской KeyVaultSecretManager реализацией:
config.AddAzureKeyVault(
$"https://{builtConfig["KeyVaultName"]}.vault.azure.net/",
builtConfig["AzureADApplicationId"],
certs.OfType<X509Certificate2>().Single(),
new PrefixKeyVaultSecretManager(versionPrefix));
Реализация реагирует на префиксы версий секретов, чтобы загрузить соответствующий секрет в конфигурацию:
-
Loadзагружает секрет, если его имя начинается с префикса. Другие секреты не загружаются. -
GetKey:- Удаляет префикс из имени секрета.
- Заменяет два дефиса в любом имени на
KeyDelimiter, который является разделителем, используемым в конфигурации (обычно двоеточие). Azure Key Vault не разрешает использовать двоеточие в названиях секретов.
public class PrefixKeyVaultSecretManager : KeyVaultSecretManager
{
private readonly string _prefix;
public PrefixKeyVaultSecretManager(string prefix)
{
_prefix = $"{prefix}-";
}
public override bool Load(SecretProperties secret)
{
return secret.Name.StartsWith(_prefix);
}
public override string GetKey(KeyVaultSecret secret)
{
return secret.Name
.Substring(_prefix.Length)
.Replace("--", ConfigurationPath.KeyDelimiter);
}
}
Метод Load вызывается алгоритмом поставщика, который выполняет итерацию по секретам хранилища, чтобы найти секреты, префиксированные версией. При обнаружении префикса версии с помощью Load, алгоритм использует метод GetKey для возврата имени конфигурации секрета. Он удаляет префикс версии из имени секрета. Остаток секретного имени возвращается для загрузки в конфигурационные пары "имя-значение" приложения.
При реализации этого подхода:
Версия приложения, указанная в файле проекта приложения. В следующем примере для версии приложения задано
5.0.0.0значение :<PropertyGroup> <Version>5.0.0.0</Version> </PropertyGroup>Убедитесь, что свойство
<UserSecretsId>присутствует в файле проекта приложения, где{GUID}— GUID, предоставленный пользователем.<PropertyGroup> <UserSecretsId>{GUID}</UserSecretsId> </PropertyGroup>Сохраните следующие секреты с помощью Менеджера секретов локально:
dotnet user-secrets set "5000-AppSecret" "5.0.0.0_secret_value_dev" dotnet user-secrets set "5100-AppSecret" "5.1.0.0_secret_value_dev"Секреты сохраняются в Azure Key Vault с помощью следующих команд Azure CLI:
az keyvault secret set --vault-name {KEY VAULT NAME} --name "5000-AppSecret" --value "5.0.0.0_secret_value_prod" az keyvault secret set --vault-name {KEY VAULT NAME} --name "5100-AppSecret" --value "5.1.0.0_secret_value_prod"При запуске приложения загружаются секреты Key Vault. Строковый секрет
5000-AppSecretсоответствует версии приложения, указанной в файле проекта приложения (5.0.0.0).Версия (
5000с дефисом) удаляется из имени ключа. В приложении чтение конфигурации с ключомAppSecretзагружает секретное значение.Если версия приложения изменена в файле
5.1.0.0проекта и приложение запускается снова, возвращается секретное значение5.1.0.0_secret_value_devвDevelopmentсреде и5.1.0.0_secret_value_prodвProduction.
Note
Вы также можете предоставить собственную SecretClient реализацию для AddAzureKeyVault. Настраиваемый клиент разрешает общий доступ к одному экземпляру клиента в приложении.
Привязка массива к классу
Поставщик может считывать значения конфигурации в массив для привязки к массиву POCO.
При чтении из источника конфигурации, позволяющего ключам содержать разделители двоеточий (:) числовой сегмент ключа используется для различения ключей, составляющих массив (:0:, :1:... :{n}:). Дополнительные сведения см. в разделе "Конфигурация: привязка массива к классу".
Ключи Azure Key Vault не могут использовать двоеточие в качестве разделителя. Описанный в этой статье подход использует двойные дефисы (--) в качестве разделителя для иерархических значений (разделов). Ключи массива хранятся в Azure Key Vault с двойными дефисами и числовыми сегментами ключей (--0--, --1--... --{n}--).
Изучите следующую конфигурацию поставщика ведения журнала Serilog , предоставляемую JSON-файлом. В массиве определены два литерала объектов WriteTo, которые отражают два приёмника Serilog, описывающих места назначения для вывода данных журналирования.
"Serilog": {
"WriteTo": [
{
"Name": "AzureTableStorage",
"Args": {
"storageTableName": "logs",
"connectionString": "DefaultEnd...ountKey=Eby8...GMGw=="
}
},
{
"Name": "AzureDocumentDB",
"Args": {
"endpointUrl": "https://contoso.documents.azure.com:443",
"authorizationKey": "Eby8...GMGw=="
}
}
]
}
Конфигурация, показанная в предыдущем JSON-файле, хранится в Azure Key Vault с помощью двойного дефиса (--) нотации и числовых сегментов:
| Key | Value |
|---|---|
Serilog--WriteTo--0--Name |
AzureTableStorage |
Serilog--WriteTo--0--Args--storageTableName |
logs |
Serilog--WriteTo--0--Args--connectionString |
DefaultEnd...ountKey=Eby8...GMGw== |
Serilog--WriteTo--1--Name |
AzureDocumentDB |
Serilog--WriteTo--1--Args--endpointUrl |
https://contoso.documents.azure.com:443 |
Serilog--WriteTo--1--Args--authorizationKey |
Eby8...GMGw== |
Перезагрузить секреты
Секреты кэшируются до вызова IConfigurationRoot.Reload. Впоследствии отключенные или обновленные секреты в хранилище не учитываются приложением, пока Reload не будет выполнено.
Configuration.Reload();
Отключенные и истекшие секреты
Секреты с истекшим сроком действия включаются по умолчанию в поставщик конфигурации. Чтобы исключить значения для этих секретов в конфигурации приложения, обновите истекший секрет или предоставьте конфигурацию с помощью пользовательского поставщика конфигурации.
class SampleKeyVaultSecretManager : KeyVaultSecretManager
{
public override bool Load(SecretProperties properties) =>
properties.ExpiresOn.HasValue &&
properties.ExpiresOn.Value > DateTimeOffset.Now;
}
Передайте этот пользовательский KeyVaultSecretManager код в AddAzureKeyVault:
// using Azure.Extensions.AspNetCore.Configuration.Secrets;
config.AddAzureKeyVault(
new Uri($"https://{builder.Configuration["KeyVaultName"]}.vault.azure.net/"),
new DefaultAzureCredential(),
new SampleKeyVaultSecretManager());
Отключенные секреты не могут быть получены из Key Vault и никогда не учитываются.
Note
В предыдущем примере используется DefaultAzureCredential для упрощения проверки подлинности при разработке приложений, развертываемых в Azure, путем объединения учетных данных, используемых в средах размещения Azure с учетными данными, используемыми в локальной разработке. При переходе в рабочую среду альтернатива является лучшим выбором, например ManagedIdentityCredential. Дополнительные сведения см. в статье Аутентификация размещенных в Azure приложений .NET в ресурсах Azure с помощью управляемого удостоверения, назначаемого системой.
Troubleshoot
Если приложению не удается загрузить конфигурацию при помощи поставщика, сообщение об ошибке записывается в инфраструктуру ASP.NET Core Logging. Следующие условия препятствуют загрузке конфигурации:
- Приложение или сертификат настроены неправильно в идентификаторе Microsoft Entra.
- Хранилище ключей не существует в Azure Key Vault.
- Приложение не авторизовано для доступа к хранилищу.
- Политика доступа не включает
GetиListразрешения. - В хранилище данные конфигурации (пара "имя-значение") неправильно называются, отсутствуют или отключены.
- Приложение имеет неправильное имя Хранилища ключей (
KeyVaultName), идентификатор приложения Microsoft Entra ID (AzureADApplicationId), отпечаток сертификата Microsoft Entra ID (AzureADCertThumbprint) или идентификатор каталога Microsoft Entra ID (AzureADDirectoryId). - При добавлении политики доступа Key Vault для приложения была создана политика, но кнопка "Сохранить " не была выбрана в пользовательском интерфейсе политик доступа.
Дополнительные ресурсы
- Просмотреть или скачать образец кода (описание загрузки)
- Конфигурация в ASP.NET Core
- Microsoft Azure: документация по Key Vault
- Создание и передача ключей, защищенных HSM для Azure Key Vault
- Краткое руководство. Установка и извлечение секрета из Azure Key Vault с помощью веб-приложения .NET
- Руководство. Использование Azure Key Vault с виртуальной машиной Windows в .NET
ASP.NET Core