Azure managed identities are great. You just turn it on and your Azure Resource can request a token for other resources that support it in your tenant. This way each resource in Azure can get it’s own “identity” and Microsoft will manage the credentials for you. You’ll no longer have to store credentials in the configuration as this is all part of the managed services.
This post will give you an in-depth view of how Azure allows several client apps to requests tokens for Azure Resources.
Using a Managed Identity in dotnet core
Using a managed identity in dotnet core, is really easy.
- Install
Azure.Identity
- Use the DefaultAzureCredential in the resource sdk you like.
A lot for resource have support for these managed identities.
The Azure.Identity package provides an instance of the TokenCredential abstract class. This instance can be used in all Azure SDK libraries that require authentication.
Default Credentials order
If you use the new DefaultAzureCredential()
you’ll get the default order of authentication methods, first environment then Managed Identity and then the rest.
You can exclude all these methods of authentication by setting the options. Or for the advanced users, you can create your own ChainedTokenCredential.
Use cases for EnvironmentCredential
Some use-cases for not using managed identities, but using the environment variables are:
- During development in containers
- Using managed identity in resources that don’t support managed identity just yet
- Running tests that require some sort of access token
- Pipeline access to Key Vault
- SQL migrations from pipeline
- Running a copy of you code on a non-azure resource
The EnvironmentCredential
is loaded first by default. You can use then to (temporary) override the ManagedIdentityCredential
. By setting the 3 required environment variables to something else you can trigger a Failed authentication error.
We mainly use these environment variables during development, most of our applications run in containers. And we could not find an easy way to use the managed identities during development. So for now we just set the required environment variables in the containers. This way we didn’t have to change any code to test our application.
EnvironmentCredential explained
As said the DefaultAzureCredential
first checks if it can request a token with the EnvironmentCredential, this will check the existence of some environment variables and tries to used those to get an access token.
AZURE_TENANT_ID
Always needed for the EnvironmentCredentialAZURE_CLIENT_ID
Always needed for the EnvironmentCredentialAZURE_CLIENT_SECRET
orAZURE_CLIENT_CERTIFICATE_PATH
needed for Client Credentials FlowAZURE_USERNAME
andAZURE_PASSWORD
for old fashioned resource-owner flow with User/Password authentication, MFA is not supported.
ManagedIdentityCredential explained
The ManagedIdentityCredential tries to create a ManagedIdentityClient which in turn tries to create several ManagedIdentitySources
They all work slightly different but in the end they all have a http endpoint where they send a request.
For the CloudShellManagedIdentitySource
the endpoint is stored in the MSI_ENDPOINT
environment variable .
Display all environment variables in powershell Get-ChildItem -Path Env:\
and take the endpoint which was http://localhost:50xxx/oauth2/token
in that cloud shell session. Once you have this endpoint, you can request an access token for any resource by specifying the resource
parameter with the resource uri you want a token for.
To get an access token for the Azure Key Vault (resource uri https://vault.azure.net
), you just run the following code in your cloud shell session:
$token_uri = $env:MSI_ENDPOINT + '?resource=https%3A%2F%2Fvault.azure.net'
$token_response = Invoke-RestMethod -Uri $token_uri -Method GET -Headers @{Metadata="true"}
write-output $token_response
The last source checked is the ImdsManagedIdentitySource which doesn’t depend on any environment variables, but just tries to get a token from a constant token endpoint. Any resource that supports managed identities has access to the endpoint at 169.254.169.254
. This last ManagedIdentitySource just tries to see if it can create a TCP connection to this IP at port 80, within 1 second.
As you can see there is no additional information about the client or user requesting the token being send to this endpoint. That is all managed in the background.
Performance improvements
Since the DefaultAzureCredential tries several methods to get a token, it might help to disable the once you will not be using (during development). The ManagedIdentityCredential adds at least a second during initialization of the DefaultIdentityCredential, if none of the previous methods resulted in valid credentials.
Services with support for managed identities
Just to name a few.