Gaurav Mantri
Gaurav Mantri

Reputation: 136394

Trying to make some sense out of all variants of token credentials while getting tokens for Azure Key Vault

I'm building a Web API using .Net 5. The Web API is protected by Azure AD and is accessible by a single tenant. The Web API will connect to other Azure resources (Storage, Cosmos DB etc.), the connection strings of those are stored in Azure Key Vault as secrets.

My objective is to fetch these connection strings (secrets) from Azure Key Vault on API startup and use those to connect to these resources. When the Web API will get deployed to production, it will use managed identity to connect to the Key Vault and get the secrets. During development, I would like to use some other mechanisms to connect and get the secrets. I do not want to create a Service Principal and use client id/client secret for that purpose.

I wondered how I would accomplish the connectivity during development and that's when I found out about different mechanisms to get tokens. However when I used them, I ran into a number of issues and now I am confused about using them.

1. ChainedTokenCredential

While researching, I ran into Secretless Development from Local to Cloud with the New Azure SDKs, Project Tye, and Kubernetes video and subsequently memealyzer project where I came to know about ChainedTokenCredential. Based on my understanding, you can chain multiple token credentials and the SDK will try to connect to each one of the token credentials until it succeeds. This sounded perfect to me and I ended up implementing code similar to below:

ChainedTokenCredential chainedTokenCredential = new ChainedTokenCredential(
    new ManagedIdentityCredential(),
    new VisualStudioCredential()
    );
SecretClient client = new SecretClient(new Uri("https://mykv.vault.azure.net"), chainedTokenCredential);
KeyVaultSecret secret = await secretClient.GetSecretAsync("mysecretkeyname");

As per my understanding, if I run the code above in Visual Studio the code should first try to make use of ManagedIdentityCredential() (which will fail) and then VisualStudioCredential() (which should succeed because I am signed in into Visual Studio with an account that has access to the Key Vault secrets.

However to my surprise the code threw the following exception:

    Azure.Identity.CredentialUnavailableException: The ChainedTokenCredential failed to retrieve a token from the included credentials. 
    - ManagedIdentityCredential authentication unavailable. No Managed Identity endpoint found. 

The exception makes sense as I am running the code locally. However it is my understanding that the SDK will automatically try the next credential provider in the chain if there's an exception. In my case, I was expecting the code to try VisualStudioCredential automatically if getting token via ManagedIdentityCredential failed. However that is not happening.

2. VisualStudioCredential

Next I commented out ManagedIdentityCredential() and just used VisualStudioCredential thinking that it would work considering I am signed in into Visual Studio using correct credentials.

enter image description here

ChainedTokenCredential chainedTokenCredential = new ChainedTokenCredential(
    //new ManagedIdentityCredential(),
    new VisualStudioCredential()
    );
SecretClient client = new SecretClient(new Uri("https://mykv.vault.azure.net"), chainedTokenCredential);
KeyVaultSecret secret = await secretClient.GetSecretAsync("mysecretkeyname");

However that also failed with the following error:

Azure.Identity.CredentialUnavailableException: Operating system Darwin 20.3.0 Darwin Kernel Version 20.3.0: Thu Jan 21 00:06:51 PST 2021; root:xnu-7195.81.3~1/RELEASE_ARM64_T8101 isn't supported.

3. AzureCliCredential

Baffled, I replaced VisualStudioCredential with AzureCliCredential and tried again. I have installed the latest version of Azure CLI (2.21.0) and I logged in into Azure CLI using az login command both in an external terminal and terminal inside Visual Studio.

enter image description here

ChainedTokenCredential chainedTokenCredential = new ChainedTokenCredential(
    //new ManagedIdentityCredential(),
    new AzureCliCredential()
    );
SecretClient client = new SecretClient(new Uri("https://mykv.vault.azure.net"), chainedTokenCredential);
KeyVaultSecret secret = await secretClient.GetSecretAsync("mysecretkeyname");

However that also failed with the following error:

Azure.Identity.CredentialUnavailableException: Azure CLI not installed 

Which does not make any sense considering Azure CLI is installed and I am logged in there.

4. DefaultAzureCredential

Supremely confused and frustrated, I finally decided to use DefaultAzureCredential thinking that it is my last resort. However I did not create any app registration in Azure AD etc. and simply executed the following code:

SecretClient client = new SecretClient(new Uri(keyVaultConfiguration.VaultUri), new DefaultAzureCredential());
KeyVaultSecret secret = await secretClient.GetSecretAsync("mysecretkeyname");

Now here I was expecting the code to fail but to my surprise the code worked (mysteries of Azure Identity, I guess :)) and I was able to get secrets. I am wondering why the above code worked and which token credential did it pick (considering I am both signed in into Visual Studio and Azure CLI using same credentials).

Development Environment

Questions

Thank you for reading so far (it turned out to be a really long post). To summarize, here are my questions:

  1. What am I doing wrong in the 1st 3 cases?
  2. Why did the ChainedTokenCredential implementation failed on ManagedIdentityCredential and did not continue to the next one? Did I misunderstand the implementation of ChainedTokenCredential?
  3. Why did the VisualStudioCredential implementation failed with not supported platform error?
  4. Why did the AzureCliCredential implementation failed with Azure CLI not installed error when it is definitely installed and I am signed in into it.
  5. Lastly, without doing anything special, why did DefaultAzureCredential implementation worked? Also, which credentials did it pick?

Any insights into this will be highly appreciated.

Upvotes: 0

Views: 1685

Answers (2)

Gaurav Mantri
Gaurav Mantri

Reputation: 136394

Partial Answer

I will start putting answers to some of the questions. I had raised an issue on Github (https://github.com/Azure/azure-sdk-for-net/issues/20210) regarding the same and my answers will be based on what I get from there.

Why did the VisualStudioCredential implementation failed with not supported platform error?

Essentially VisualStudioCredential is currently not supported for Visual Studio on Mac as it does not currently have support for logging in to Azure AD (besides for licensing). There's an issue tracking this: https://github.com/Azure/azure-sdk-for-net/issues/20283.

Upvotes: 0

Christopher Scott
Christopher Scott

Reputation: 3156

See GitHub issue https://github.com/Azure/azure-sdk-for-net/issues/20210 for a discussion of these issues.

Upvotes: 1

Related Questions