New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FEATURE REQ] ManagedIdentityCredential should fail fast when running outside of Azure #29471
Comments
Thank you for your feedback. Tagging and routing to the team member best able to assist. |
Hi @jonpayne |
I'm using Windows 11 22H2 with .NET 6. I see the following times:
This is the code I used for timing: using Azure.Core;
using Azure.Core.Diagnostics;
using Azure.Identity;
using System.Diagnostics.Tracing;
var tokenTimer = new TokenTimer();
new AzureEventSourceListener(
(args, message) =>
{
if (args.EventName == "GetToken") tokenTimer.StartGetToken((string)(args.Payload![0])!);
if (args.EventName == "GetTokenSucceeded" || args.EventName == "GetTokenFailed") tokenTimer.EndGetToken((string)(args.Payload![0])!);
},
EventLevel.Informational);
var credential = new DefaultAzureCredential();
await credential.GetTokenAsync(new TokenRequestContext(new[] { "https://management.core.windows.net/.default" }, null));
tokenTimer.Print();
class TokenTimer
{
private readonly Dictionary<string, long> _startTimes = new();
private readonly Dictionary<string, long> _endTimes = new();
public void StartGetToken(string method) => _startTimes[method] = DateTime.UtcNow.Ticks;
public void EndGetToken(string method) => _endTimes[method] = DateTime.UtcNow.Ticks;
public void Print()
{
foreach (var t in _startTimes)
{
var ms = (_endTimes[t.Key] - t.Value) / 10000.0;
Console.WriteLine($"{t.Key,-50}{ms,10:0.00} ms");
}
}
} |
related #24767 |
@christothes I ran the code provided by @jonpayne and you can see the results below.
Running from Visual Studio 2022
Running from the command line while Visual Studio 2022 was opened)
Running from the command line (Visual Studio 2022 was closed)
Local environment
|
What would be the most ideal solution to this issue with regards to using Authentication=Active Directory Default in a Azure SQL connection string? Using this eliminates the need for an interceptor, so we do not currently have a place to set the DefaultAzureCredential properties to disable the various Identities that we don't need. I can confirm that the DefaultAzureCredential.GetToken dependency call is taking 10 seconds most of the time, yet still intermittently. Certainly seems that caching is not working as well. |
this really sucks in azure functions because there's no way to override the DefaultAzureCredentialOptions() that AzureComponentFactory leverages to create credentals for a whole slew of various extensions (eventhubs, blobs) so every time it takes liek 10-20 seconds to auth to these services when it should take momennts. cf azure-sdk-for-net/sdk/extensions/Microsoft.Extensions.Azure/src/Internal/ClientFactory.cs Line 185 in af08a03
I miss the previous libraries ability to put VS credential ahead of managed identity credential. most devs on my teams are really confused by this delay and do really odd cache wrapper code that ends up being worthless, or they specify environment variables with clientid secret to get client credentials flow ahead of their local identities which is NOT what i want them to be doing. if we can't fix this at the DefaultAzureCredential level can we at least fix it at the AzureComponentFactory level which has a handle to IServiceProvider so that it could look for a DefaultAzureCredentialsOptions outta the container? |
I have a similar problem. Using Steps to reproduce:
The calls take five minutes for uploading to two different Service Bus and Storage accounts. If it runs on our AKS, it is fast. Using connection string for local development is not an option for us. There is also no caching or something like this, the next call takes again five minutes. |
You should be able to customize the client construction via the ConfigureServices method. |
@christothes not sure if you're suggesting HOW it should work, or suggesting it's already possible. If it's the latter, look at the code i linked, nothing is coming from DI, the library is just new()ing up the DefaultAzureCredentialOptions in it's execution stack thus no chance to work with injection on it. also this is being leveraged inside function app, not mvc. |
This is how it works today. Sorry, here is a better link that describes the functions integration: https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference?tabs=blob#configure-an-identity-based-connection . Essentially you should be able to configure any of the credential options via the functions config. |
Im not seeing a way to opt out of the managed identity credential without having to specify the client id/secret to use client credentials flow..which is NOT what i want. is there a __skip_managed_identity option that is not documented? |
azure-sdk-for-net/sdk/identity/Azure.Identity/src/Credentials/DefaultAzureCredentialOptions.cs Line 224 in 4b8a362
|
yes for sure, but look at my linked code, it new's that up in the method...the question is if there's a config / appsetting host.json setting that assigns to that property to false? correct me if i'm wrong, but the linked code does NOT retrieve the DefaultAzureCredentialOptions from a DI container, so i have no opportunity to customize it. |
You should be able to do this via the UseCredential method: services.AddAzureClients(builder => builder.UseCredential(new DefaultAzureCredential(options)) |
have you actually tried this and achieved success? you keep pointing me to DI, but the code clearly does NOT get anything from a DI container. |
I'm not sure which code you are referring to - but yes, your functions code would need to use DI to do this. |
The code i linked that u originally replied to. Its not MY code its the code used in azure functions azure-sdk-for-net/sdk/extensions/Microsoft.Extensions.Azure/src/Internal/ClientFactory.cs Line 185 in af08a03
I had a feeling i was being jerked around here.. :( |
Hi guys, I have also hit this issue when using webjobs locally. What drdamour pointed out does seem like an issue, as webjobs extensions does use a DefaultAzureCredentialOptoins when if you don't set the web job specific configuration in your appsettings.json (or environment vars). This seems like a miss to me as they already are checking with their settings if a customer wants to use a managed identity but fail to remove those from the default check later. What Chirstothes is saying does work around this issue. If you add the azure client directly with the DI builder (outside of the webjobs builder), web jobs will honor that client instead of creating a new one with the DefaultAzureCredentialsOptions. I think that is the disconnect here in this conversation. |
hey guys, Also ran into this issue with my customers recently. These customers use our tools outside of Azure and we are soon planning to upgrade to Public Preview, it could be a bit cumbersome to ask our onboarding customers outside of their azure environments to remember to configure this prior of usage, especially because most of our customers will be using transient build machines to run our service. Is there any way of knowing when a permanent fix will be implemented on the library? Cheers, |
I've added the below snippet to our services, which makes the ManagedIdentityCredential fail much faster. Obviously you'll lose the retry functionality. We haven't had any issues because of that (yet? ;) ) DefaultAzureCredentialOptions.Default.Retry.MaxRetries = 0;
DefaultAzureCredentialOptions.Default.Retry.Delay = TimeSpan.Zero; The VisualStudio provider is also very slow, to disable that completely you can remove the TokenProvider in |
@bacobart thanks, in my scenario that doesn't work because I want retries for our clients. For now, I'm using an exclusion of the MI validation for the customers who dont credentialize using MI via the DefaultAzureCredentialOptions prop, but like I mentioned before, its cumbersome to explain to hundreds of customers these specific types of scenarios. |
I wasn't even able to use the workaround. We configured something like this:
services.AddAzureClients(builder =>
{
builder.UseCredential(new DefaultAzureCredential(
new DefaultAzureCredentialOptions {
ExcludeEnvironmentCredential = true,
ExcludeWorkloadIdentityCredential = true,
ExcludeManagedIdentityCredential = true,
ExcludeSharedTokenCacheCredential = true,
ExcludeVisualStudioCredential = false,
ExcludeVisualStudioCodeCredential = true,
ExcludeAzureCliCredential = false,
ExcludeAzurePowerShellCredential = true,
ExcludeAzureDeveloperCliCredential = true,
ExcludeInteractiveBrowserCredential = true,
}
));
builder.AddBlobServiceClient(new Uri(storageUri));
});
and it would still try to use Managed Identities and takes ~10 seconds (VS 2022, Windows 11), Nevermind, I did not use |
In my scenario it took 30 seconds for the |
This issue was already impacting my team about a year ago and shockingly I found it is still an issue today as I tried DefaultAzureCredential in a new project. To unblock my local VS Code dev experience I'm doing something like this: public static IServiceCollection AddBlobClient(
this IServiceCollection services,
IConfiguration configuration,
IHostEnvironment environment)
{
var blobServiceUrl = configuration["GameStore:BlobServiceUrl"] ?? throw new Exception("Blob storage connection string is not set");
TokenCredential credential = environment.IsDevelopment() ? new AzureCliCredential() : new ManagedIdentityCredential();
services.AddSingleton(new BlobServiceClient(new Uri(blobServiceUrl), credential));
return services;
} Hope a proper fix is coming soon! |
What about the speed of /msi/token inside of Azure? It takes over a second, oftentimes, to return a successful result |
Library name
Azure.Identity
Please describe the feature.
When using
DefaultAzureCredential
outside of Azure, theManagedIdentityCredential
class retries four times before failing. This adds 8 to 10 seconds to token requests.ManagedIdentityCredential
should use a heuristic to determine when the code is not running in Azure (e.g., environment variables, network errors, ...), and fail fast.It is possible to work around this by disabling Managed Identity authentication:
I do not like this solution as:
a) It is hard to discover -- many users may just assume that token requests are slow
b) It makes code less portable to Azure
c) It is boilerplate code that has to be repeated in each application
The text was updated successfully, but these errors were encountered: