question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Azure.Identity: support MSI_CLIENT_ID or AZURE_CLIENT_ID env var for User Assigned Identities

See original GitHub issue

Library or service name. Azure.Identity.

Is your feature request related to a problem? Please describe.

This affects App Services and Function Apps with user assigned identity.

The standard method to obtain credential in app service is this:

credentials = new DefaultAzureCredential();

As per docs, this will try to obtain token using this chain: Environment, Managed Identity, Visual Studio, VS Code, Azure CLI.

All good and well, except that does not work with User Assigned Managed Identities, it only works with System Assigned MSIs.

The reason for this is we need to specify client id of User Assigned MSI.

This leads to many undesirable things:

  • Separate code paths just for User Assigned MSI.
  • Figuring out if we run locally on in Azure to support local machine scenarios. E.g. this is the kind of code we need to write:
TokenCredential credentials;
var _isLocal = string.IsNullOrEmpty(Environment.GetEnvironmentVariable("WEBSITE_HOSTNAME"));
if (_isLocal)
{
    Console.WriteLine("Using local DefaultAzureCredential");
    credentials = new DefaultAzureCredential();
}
else
{
    Console.WriteLine("Using MSI credentials");
    credentials = new ManagedIdentityCredential(msiClientId);
}

Proposal

Support MSI_CLIENT_ID env variable or repurpose existing AZURE_CLIENT_ID.

We can set this in App Settings, either during terraform, or during deployment. If MSI_CLIENT_ID is set, the library will use client id specified there when getting MSI token.

For example, add support for env var here: https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/identity/Azure.Identity/src/EnvironmentVariables.cs#L19

internal class EnvironmentVariables
{
    // Either reuse this.
    public static string ClientId => Environment.GetEnvironmentVariable("AZURE_CLIENT_ID");
    // ...
    public static string MsiEndpoint => Environment.GetEnvironmentVariable("MSI_ENDPOINT");
    public static string MsiSecret => Environment.GetEnvironmentVariable("MSI_SECRET");
    // Or add this.
    public static string MsiClientId => Environment.GetEnvironmentVariable("MSI_CLIENT_ID");
}

Here is how the code might look here: https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/identity/Azure.Identity/src/AppServiceV2017ManagedIdentitySource.cs#L54

protected override Request CreateRequest(string[] scopes)
{
    // covert the scopes to a resource string
    string resource = ScopeUtilities.ScopesToResource(scopes);

    Request request = Pipeline.HttpPipeline.CreateRequest();

    request.Method = RequestMethod.Get;
    request.Headers.Add("secret", _secret);
    request.Uri.Reset(_endpoint);
    request.Uri.AppendQuery("api-version", AppServiceMsiApiVersion);
    request.Uri.AppendQuery("resource", resource);

    if (!string.IsNullOrEmpty(_clientId))
    {
        request.Uri.AppendQuery("clientid", _clientId);
    } 
    // Add a couple of extra else ifs.
    else if (!string.IsNullOrEmpty(EnvironmentVariables.MsiClientId))
    {
        // Use client id from env var if present.
        request.Uri.AppendQuery("clientid", EnvironmentVariables.MsiClientId);
    }
    else if (!string.IsNullOrEmpty(EnvironmentVariables.ClientId))
    {
        // Repurpose exisitng AZURE_CLIENT_ID if present.
        request.Uri.AppendQuery("clientid", EnvironmentVariables.ClientId);
    }

    return request;
}

Benefits

  • Uniform workflow regardless of auth method, works both locally and in Azure transparently.
  • Setting MSI_CLIENT_ID or AZURE_CLIENT_ID is easy via App Settings. It is terraformable, or easy to set during deployments. The use of AZURE_CLIENT_ID is already supported and documented, so this change will not be out of line.
  • Other features like Key Vault references may start to work with User Assigned Identities, if they use Azure.Identity library under the hood.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:7
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
mattchendersoncommented, Feb 16, 2021

@ppanyukov Normally for a feature request like this we’d ask for this to be filed on our uservoice, but I actually don’t see that item already filed, strangely. That said, we do have support for it lined up to be available very soon. I can’t give a specific timeline, but it shouldn’t be too much longer.

1reaction
christothescommented, Jan 28, 2021

Thanks for clarifying. To your follow up question:

So if you set just AZURE_CLIENT_ID in app settings to the id of User Assigned Identity, everything works as per this proposal. Thoughts on this? If this is officially supported thing, should we document it? If “unsupported” then why?

This appears to be a documentation oversight. I’ll file an issue to get the docs updated.

Thanks for pointing this out!

Read more comments on GitHub >

github_iconTop Results From Across the Web

EnvironmentCredential Class (Azure.Identity)
Enables authentication to Azure Active Directory using a client secret or certificate, or as a user with a username and password.
Read more >
Azure Identity 202 - Environment Variables - Jon Gallant
Azure Identity allows you to set properties via default environment variables. We have standardized on the AZURE_ prefix for environment names ( ...
Read more >
@azure/identity
Azure Identity client library for JavaScript. This library simplifies authentication against Azure Active Directory for Azure SDK libraries.
Read more >
An Analysis of Azure Managed Identities Within Serverless ...
We examine Azure's Managed Identities service and its security capability in a threat model as developers' go-to feature for managing ...
Read more >
Correctly configure service fabric ARM for Azure managed ...
Running locally in Visual Studio it runs with DefaultAzureCredential using environment variables but on the server it is supposed to used ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found