I'm trying to create a web app where a user can explore Azure Keyvault secret information that their azure ad account explicitly has access to. It's an Azure Keyvault dashboard essentially. I'm using Azure Active Directory authentication when the user signs in to the app. This app is being hosted as an azure app service.
The Azure Active Directory authentication itself is working fine but when I try to connect to Azure Keyvault using the SecretClient
and DefaultAzureCredential
from within Azure, it's not working.
Here is the code I'm using to gather secret information:
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)
{
...
}
Below is the code I have in Startup.cs
. I feel like the part I'm missing is the storing of the token I'm getting back after signin via oidc and leveraging that in the SecretClient
somehow. I at first thought that's what EnableTokenAcquisitionToCallDownstreamApi
and AddInMemoryTokenCaches
were doing below and somehow DefaultAzureCredential
would leverage that but that is obviously not working.
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": "*"
}
The errors I'm getting in my azure app service are:
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))
All of this functionality appears to work fine when testing locally.
I'm using
- .net 6
- Azure.Identity - 1.5
- Azure.Security.KeyVault.Secrets - 4.2
CodePudding user response:
It seems as though the DefaultAzureCredential
doesn't really work in my case. I had to inject an ITokenAcquisition
object into my constructor and use a ChainedCredential
like this instead of just using DefaultAzureCredential
:
var client = new SecretClient(new Uri(this.azureKeyVaultSettings.Value.KeyVaultBaseUrl),
new ChainedTokenCredential(new TokenAcquisitionTokenCredential(this.tokenAcquisition),
new DefaultAzureCredential());
var secrets = client.GetPropertiesOfSecretsAsync();
I also had to add the https://vault.azure.net/user_impersonation
to the .EnableTokenAcquisitionToCallDownstreamApi()
call. See below Startup.cs correction from my original post:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(this.Configuration,
"AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi(new string[]
{
"https://vault.azure.net/user_impersonation",
"user.read"
})
.AddInMemoryTokenCaches();
The .EnableTokenAcquisitionToCallDownstreamApi()
is what allows the ITokenAcquisition
to be injected in controllers. See here for more detail:
CodePudding user response:
On deployment of keyvault and app service, you can set the access policy at keyvault for app service using principal ID of app service. In this way, the web app hosted under app service will get the access to keyvault. You can use azure ad authentication to authenticate the user logging in and then provide the key vault detail on your web application.
Please check and comment whether it works for you.