Мой вопрос касается кода С# для прозрачного чтения секретов, хранящихся в Key Vault в виде конфигурации. Например, сейчас у меня есть файл appsettings.json:
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "mydomain.com",
"TenantId": "...coming from Connected Services/Secrets",
"ClientId": "...coming from Connected Services/Secrets",
"ClientSecret": "...coming from Connected Services/Secrets",
"CallbackPath": "/signin-oidc",
"Scopes": "access_as_user"
},
Во время разработки эти секреты настраиваются с помощью Services/Secrets, поэтому секреты не передаются в репозиторий.
Как я могу использовать и настроить средство чтения конфигурации в сборке выпуска, которое прозрачно считывает эти значения конфигурации из моего Azure Key Vault? Я имею в виду, что само приложение не знает, откуда поступает настроенный секрет?
Например, у меня есть заявление builder.Configuration.GetSection("AzureAd") и я хотел бы, чтобы эта работа была прозрачной...
(Я знаю, как развернуть мое приложение ASP.NET Core в службах приложений Azure, как создавать секреты в Azure Key Vault и как предоставить доступ к развернутой службе приложений в Key Vault, поэтому этот вопрос не об этом)





Вы можете сделать следующее.
Для иерархических ключей в KeyVault вы можете создавать их следующим образом:
AzureAd--Secret1
AzureAd--Level1--Secret2
Ваши локальные секреты должны быть настроены в вашем
secrets.json. Щелкните правой кнопкой мыши свой проект: «Управление секретами пользователя».
Добавьте флаг IS_LOCAL к своему launchSettings.json:
"Your project Local": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:5000",
"launchUrl": "api/v2/swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"IS_LOCAL": "true"
}
Тогда в вашем Startup.cs или Program.cs:
if (!env.IsLocal())
{
configuration.AddAzureKeyVault(
new Uri(configuration.GetValue<string>("YourKeyToAzureKeyVaultCredentials")),
new DefaultAzureCredential());
}
IsLocal() — это расширение:
public static class HostEnvironmentExtensions
{
public static bool IsLocal(this IHostEnvironment _)
=> Environment.GetEnvironmentVariable("IS_LOCAL")?.Equals("true") ?? false;
}
А еще в вашем Program.cs:
services.Configure<YourConfiguration>(configuration);
YourConfiguration Класс должен выглядеть так:
public class YourConfiguration
{
public SecretConfiguration AzureAd{ get; set; }
}
А SecretConfiguration — это просто POCO-класс:
public class SecretConfiguration
{
public string Secret1{ get; set; }
public string Secret2{ get; set; }
}
Теперь вы можете прозрачно внедрить класс YourConfiguration в свои сервисы — и он будет использовать ваш secrets.json в локальном режиме или ваш Azure Key Vault на сервере:
// When Service is Scoped
public class ServiceA (IOptionsSnapshot<YourConfiguration> configuration)
{
public void SomeMethod()
{
var secret1 = configuration.Value.AzureAd.Secret1;
}
}
Он считывает иерархические данные из ваших appsettings.json, secrets.json и из Azure Key Vault, вам просто нужно создать класс YourConfiguration соответственно. Если у вас есть уровень в AzureAd, вам понадобится свойство из другого класса, который снова имеет свойства и так далее.
Я использую это решение уже много лет, и это именно то, что вы описали: «... и я хотел бы, чтобы эта работа была прозрачной». И это так. Просто попробуйте.
и каково синтаксическое правило для размещения иерархических данных в Key Vault, это плоский список...
Вы можете написать «AzureAd--Secret1», «AzureAd--Level2--Secret1» и так далее. Вы можете задать иерархию этих элементов в KeyVault, используя «--».
много спасибо. Это ответ. пожалуйста, включите это в ответ, и я приму это.
идеальный. Я сделаю.
Это добавлено. Спасибо за принятие. :)
Я не вижу, как это решение читает иерархические данные. Appsettings.json представляет собой иерархические данные, в нем есть разделы, а компоненты MS, такие как .AddMicrosoftIdentityWebApp(), ожидают данные раздела иерархической конфигурации... в моем образце файла конфигурации AzureAd...