Я пытаюсь создать веб-приложение, в котором пользователь может просматривать секретную информацию Azure Keyvault, к которой явно имеет доступ их учетная запись Azure Ad. По сути, это панель мониторинга Azure Keyvault. Я использую проверку подлинности Azure Active Directory, когда пользователь входит в приложение. Это приложение размещается как служба приложений Azure.
Сама проверка подлинности Azure Active Directory работает нормально, но когда я пытаюсь подключиться к Azure Keyvault с помощью SecretClient
и DefaultAzureCredential
из Azure, она не работает.
Вот код, который я использую для сбора секретной информации:
var client = new SecretClient(new Uri(this.azureKeyVaultSettings.Value.KeyVaultBaseUrl),
new DefaultAzureCredential(new DefaultAzureCredentialOptions()
{
ExcludeSharedTokenCacheCredential = false
}));
var secrets = client.GetPropertiesOfSecretsAsync();
await foreach (SecretProperties secret in secrets)
{
...
}
Ниже приведен код, который у меня есть в Startup.cs
. Я чувствую, что часть, которую мне не хватает, — это хранение токена, который я получаю после входа через oidc и каким-то образом использую его в SecretClient
. Сначала я подумал, что это то, что EnableTokenAcquisitionToCallDownstreamApi
и AddInMemoryTokenCaches
делают ниже, и каким-то образом DefaultAzureCredential
будет использовать это, но это явно не работает.
public void ConfigureServices(IServiceCollection services)
{
...
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(this.Configuration,
"AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi(new string[]
{
"user.read"
})
.AddInMemoryTokenCaches();
services.AddMvc(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
}).AddMicrosoftIdentityUI();
...
AppSettings.json:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "mydomain.com",
"TenantId": "c9db0b8f-****-****-****-************",
"ClientId": "318b64c3-****-****-****-************",
"ClientSecret": "vh27Q*********************",
"CallbackPath": "/signin-oidc"
},
"AzureKeyVaultSettings": {
"KeyVaultBaseUrl": "https://myspecialvault.vault.azure.net/"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
Ошибки, которые я получаю в своей службе приложений Azure:
2022-03-19 11:32:49.842 +00:00 [Critical] AzureKeyVaultDashboard.Web.Controllers.HomeController: Azure.Identity.CredentialUnavailableException: DefaultAzureCredential failed to retrieve a token from the included credentials. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/defaultazurecredential/troubleshoot
- EnvironmentCredential authentication unavailable. Environment variables are not fully configured. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/environmentcredential/troubleshoot- ManagedIdentityCredential authentication unavailable. Multiple attempts failed to obtain a token from the managed identity endpoint.- SharedTokenCacheCredential authentication unavailable. No accounts were found in the cache.- Visual Studio Token provider can't be accessed at D:\DWASFiles\Sites\myazkvdashboard\LocalAppData\.IdentityService\AzureServiceAuth\tokenprovider.json- Stored credentials not found. Need to authenticate user in VSCode Azure Account. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/vscodecredential/troubleshoot- Azure CLI not installed- PowerShell is not installed.---> System.AggregateException: Multiple exceptions were encountered while attempting to authenticate. (EnvironmentCredential authentication unavailable. Environment variables are not fully configured. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/environmentcredential/troubleshoot) (ManagedIdentityCredential authentication unavailable. Multiple attempts failed to obtain a token from the managed identity endpoint.) (SharedTokenCacheCredential authentication unavailable. No accounts were found in the cache.) (Visual Studio Token provider can't be accessed at D:\DWASFiles\Sites\myazkvdashboard\LocalAppData\.IdentityService\AzureServiceAuth\tokenprovider.json) (Stored credentials not found. Need to authenticate user in VSCode Azure Account. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/vscodecredential/troubleshoot) (Azure CLI not installed) (PowerShell is not installed.)---> Azure.Identity.CredentialUnavailableException: EnvironmentCredential authentication unavailable. Environment variables are not fully configured. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/environmentcredential/troubleshootat Azure.Identity.CredentialDiagnosticScope.FailWrapAndThrow(Exception ex, String additionalMessage)at Azure.Identity.EnvironmentCredential.GetTokenImplAsync(Boolean async, TokenRequestContext requestContext, CancellationToken cancellationToken)at Azure.Identity.EnvironmentCredential.GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)at Azure.Identity.DefaultAzureCredential.GetTokenFromSourcesAsync(TokenCredential[] sources, TokenRequestContext requestContext, Boolean async, CancellationToken cancellationToken)--- End of inner exception stack trace ------> (Inner Exception #1) Azure.Identity.CredentialUnavailableException: ManagedIdentityCredential authentication unavailable. Multiple attempts failed to obtain a token from the managed identity endpoint.---> System.AggregateException: Retry failed after 4 tries. Retry settings can be adjusted in ClientOptions.Retry. (An attempt was made to access a socket in a way forbidden by its access permissions. (100.100.100.100:80)) (An attempt was made to access a socket in a way forbidden by its access permissions. (100.100.100.100:80)) (An attempt was made to access a socket in a way forbidden by its access permissions. (100.100.100.100:80)) (An attempt was made to access a socket in a way forbidden by its access permissions. (100.100.100.100:80))
Все эти функции работают нормально при локальном тестировании.
я использую
@Thomas В моей регистрации приложения в разделе «Разрешения API» у меня есть запись для Azure Key Vault, где «Тип» разрешения настроен как «Делегированный», и в этом разрешении он также указан как «user_impersonation».
Это хорошее начало. Я думаю, вам нужно добавить эту область в вызов EnableTokenAcquisitionToCallDownstreamApi
. Не уверен, что просто https://vault.azure.net/user_impersonation
сработает, но, что еще хуже, попробуйте.
@ Томас Я добавил https://vault.azure.net/user_impersonation
, но у меня все те же проблемы. Он работает локально, но когда я развертываю его как службу приложений Azure, я получаю те же ошибки, что и упомянутые выше, о том, что он не находит никаких токенов с DefaultAzureCredential
При развертывании хранилища ключей и службы приложений вы можете задать политику доступа в хранилище ключей для службы приложений, используя основной идентификатор службы приложений. Таким образом, веб-приложение, размещенное в службе приложений, получит доступ к хранилищу ключей. Вы можете использовать проверку подлинности Azure Ad для проверки подлинности пользователя, входящего в систему, а затем предоставить сведения о хранилище ключей в своем веб-приложении.
Пожалуйста, проверьте и прокомментируйте, работает ли это для вас.
Если вы говорите об использовании «Системы» или «Пользователя», назначенного управляемое удостоверение, я не хочу этого делать. Я хочу использовать права/роли пользователя Azure Active Directory. Именно так наша организация в настоящее время управляет доступом к секретам Azure KeyVault. Если бы я создал управляемое удостоверение, у него были бы другие уровни доступа, чем у пользователя Azure Active Directory (например, [email protected]).
Кажется, что DefaultAzureCredential
не работает в моем случае. Мне пришлось внедрить объект ITokenAcquisition
в мой конструктор и использовать ChainedCredential
вот так, а не просто использовать DefaultAzureCredential
:
var client = new SecretClient(new Uri(this.azureKeyVaultSettings.Value.KeyVaultBaseUrl),
new ChainedTokenCredential(new TokenAcquisitionTokenCredential(this.tokenAcquisition),
new DefaultAzureCredential());
var secrets = client.GetPropertiesOfSecretsAsync();
Мне также пришлось добавить https://vault.azure.net/user_impersonation
к вызову .EnableTokenAcquisitionToCallDownstreamApi()
. См. ниже исправление Startup.cs из моего исходного сообщения:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(this.Configuration,
"AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi(new string[]
{
"https://vault.azure.net/user_impersonation",
"user.read"
})
.AddInMemoryTokenCaches();
.EnableTokenAcquisitionToCallDownstreamApi()
— это то, что позволяет внедрять ITokenAcquisition
в контроллеры. Подробнее см. здесь:
Приятно видеть, что у вас получилось заставить его работать :-0
При регистрации вашего приложения (используется для аутентификации пользователей в вашем приложении) вы делегировали разрешение на хранилище ключей (в разрешениях API)?