unable to access azure secret once i publish

Nick Mabe 1 Reputation point
2022-04-01T12:16:34.1+00:00

I have an aspnetcore web app and am using Azure Vault Secrets to store an MSSQL connection string. I have set up the key and can retrieve and the connection string is executed when on localhost. Once I publish to the web I get a 502 error and the following is found in the logs:

Unhandled exception. 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

The code I am using to access the vault ket is in my program.cs

builder.Configuration.AddAzureKeyVault(
new Uri($"https://MYVAULTs.vault.azure.net/"),
new DefaultAzureCredential(new DefaultAzureCredentialOptions
{

    ManagedIdentityClientId = builder.Configuration["MYApplication (client) ID"]
}));
Not Monitored
Not Monitored
Tag not monitored by Microsoft.
38,712 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Nick Mabe 1 Reputation point
    2022-04-02T06:51:32.757+00:00

    Hi James, thank you for your comment and your mail.

    In answer to your question, I am not following anyone document as I can't find a single document that solves the issue. I have read hundreds of documents and watched many videos. Nothing I have been able to find address retrieving an Azure Secret from a non-Azure hosted environment.

    What I have been able to achieve is as follows:

    1. Set up the Azure account
    2. Create a Resource Group
    3. Create a Vault
    4. Create a Secret
    5. Go into Active Directory / App Services and create an App
    6. Go back to the Vault, create Access Policy with the App as the Selected principle, applying Get and List permissions.

    In Visual Studio 2022 I am using dotnet6.
    All the documentation I have followed only takes me so far because it either assumes the web app is hosted in Azure or that I am using an older version of VS that uses the program.cs and startup.cs. In all the examples I see, the program.cs is structured totally different to the version i am working with.

    Now here's the thing though, take for example, I am using an Azure Vault Secret to store an SQL Connection String, If I comment out the connection string in appsettings.json, with the very simple code above I am able to access the Azure Key Vault, the database launches and the site works in a LocalHost environment. As you will see above, I have only declared the URI and Application ID; This is giving me access to the secret.

    I have not declared the TenantID, or the SecretID, only the vault URI and the ApplicationId. I have considered that it would be worth trying to declare these properties but do not understand how:

    My code so far is:

    builder.Configuration.AddAzureKeyVault(
    new Uri($"https://"MYVAULTNAME".vault.azure.net/"),
    new DefaultAzureCredential(new DefaultAzureCredentialOptions
    {
    ManagedIdentityClientId = builder.Configuration["MYCLIENTID"],

    }));
    

    Having searched around I cannot find anyway to insert the TenantID, or the SecretID, the closest I have been able to find is: InteractiveBrowserTenantId by adding the following line below ManagedIdentityClientId

    InteractiveBrowserTenantId = builder.Configuration["MYTENNANTID"],

    ClientID and SecretID are not DefaultAzureCredentialOptions as I look at the DefaultAzureCredentialOptions there is nothing that makes me think I can inject the required variables in this object.

    I have of course declared them in appsettings.json but how to use them inside the program.cs is an issue I have not been able to overcome, as of yet.

    When I look at examples from previous versions of dotnet they were declaring these inside a public class inside the program.cs in ways such as follows:

    namespace ?????????
    {

    public class Program
    {

    public static void Main(string[] args)
        {
        CreateHostBuilder(args).Build().Run();
        }
    
    public static IhostBuilder CreateHostBuilder(string[] args)=>
        Host.createDefaultBuilder(args)
        .ConfigureAppConfiguration ((context, config) =>
        {
            var builtConfiguration = config.Build();
    
            string kvURL = builtConfiguration["keyVaultConfig:KVUrl"];
            string tenantId = builtConfiguration["keyVaultConfig:TenantId"];
            string clientId = builtConfiguration["keyVaultConfig:ClientId"];
            string clientSecret = builtConfiguration["keyVaultConfig:ClientSecretId"];
    
            var credential = new ClientSecretCredential(tenantId, clientid, clientSecret);
    
            var client = new SecretClient(new Uri(kvURL), credential);
            config.AddAzureKeyVault(client, new AzureKeyVaultConfiguratioinOptions());
        })
        .ConfigureWebHostDefaults( webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });
    }
    

    }

    Well my Program.cs doesn't look anything like this program.cs, I don't have a namespace, i don't have public classes, I can see the variables are being passed in this method, whether it works I don't know but applying the same logic in todays version of program.cs seems to be the most logical thing to try, but if i try to declare variables inside the code I have I get red squiggly lines and the message is the for example is:

    "DefaultAzureCredentialOptions does not contain a definition for clientid"

    So back to the issue I have.

    I can access the vault key from my LocalHost environment, I assume this is using the credentials of either the logon pc, the logged-in VS Studio or the logged in Azure Portal.

    But there lies another quandary, the pc and VS Studio have a different logon emails to Azure Portal.
    I am not providing any Azure login credentials when I run it in the localhost environment, why it's working is also a bit of a puzzle, one I can live without solving....

    The issue is that once I publish the web app to its hosting with the secret in the Azure Vault, it falls over.

    When I look at the logs, they steer me towards thinking I am either not passing the credentials required to authorise OR the application is not authorised to access the secret. But as I say, I have added an access policy.

    Any help you can give me to solve this issue is greatly appreciated.


  2. Nick Mabe 1 Reputation point
    2022-04-02T10:26:29.983+00:00

    Set up the Azure account

    Create a Resource Group

    Create a Vault, copy the Vault URI (referred to below as VAULTURI)

    Create a Secret

    Go into Active Directory / App Services and create an App, copy the value of the Application (client) ID (referred to below as MYAPPLICATIONID)

    in the App you have created, create a Client Secret, copy the value of the ClientSecret (referred to below as MYAPPLICATIONCLIENTSECRET.VALUE)

    Go back to the Vault, create an Access Policy for the App fou have created, select the AppName from the selection, if it's not there just start typing it. as the Selected principle, and allow Get and List Secret permissions.

    Add the following line inside program.cs:

    builder.Configuration.AddAzureKeyVault("VAULTURI", "MYAPPLICATIONID", "MYAPPLICATIONCLIENTSECRET.VALUE");

    The Secret Keys are now available for use.

    For example lets say I have a Secret inside the Vault for Facebook Authentification called SOMEKEY to refer to it, I use the following:

    builder.Services.AddAuthentication().AddFacebook(options =>
    {
    options.AppId = "MIFACEBOOKAPPID";
    options.AppSecret = builder.Configuration.GetSection("SOMEKEY").Get<string>();
    });

    It is the part:
    builder.Configuration.GetSection("SOMEKEY").Get<string>()
    that applies the Secret

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.