Skip to content

Commit 16d360f

Browse files
authored
DAC only makes probe requeset on first GetToken (Azure#49159)
1 parent 62b6c26 commit 16d360f

File tree

3 files changed

+38
-22
lines changed

3 files changed

+38
-22
lines changed

sdk/identity/Azure.Identity/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
### Breaking Changes
88

99
### Bugs Fixed
10+
- `DefaultAzureCredential` no longer sends a probe request on each call to `GetToken`. It now only happens on the first call.
1011

1112
### Other Changes
1213

sdk/identity/Azure.Identity/src/ManagedIdentityClient.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ internal class ManagedIdentityClient
2222
private MsalManagedIdentityClient _msalManagedIdentityClient;
2323
private bool _isChainedCredential;
2424
private ManagedIdentityClientOptions _options;
25+
private bool _probeRequestSent;
2526

2627
protected ManagedIdentityClient()
2728
{
@@ -66,9 +67,11 @@ public async ValueTask<AccessToken> AuthenticateAsync(bool async, TokenRequestCo
6667
AzureIdentityEventSource.Singleton.ManagedIdentityCredentialSelected(availableSource.ToString(), _options.ManagedIdentityId.ToString());
6768

6869
// If the source is DefaultToImds and the credential is chained, we should probe the IMDS endpoint first.
69-
if (availableSource == MSAL.ManagedIdentitySource.DefaultToImds && _isChainedCredential)
70+
if (availableSource == MSAL.ManagedIdentitySource.DefaultToImds && _isChainedCredential && !_probeRequestSent)
7071
{
71-
return await AuthenticateCoreAsync(async, context, cancellationToken).ConfigureAwait(false);
72+
var probedFlowTokenResult = await AuthenticateCoreAsync(async, context, cancellationToken).ConfigureAwait(false);
73+
_probeRequestSent = true;
74+
return probedFlowTokenResult;
7275
}
7376

7477
// ServiceFabric does not support specifying user-assigned managed identity by client ID or resource ID. The managed identity selected is based on the resource configuration.

sdk/identity/Azure.Identity/tests/ManagedIdentityCredentialTests.cs

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,26 +34,6 @@ public ManagedIdentityCredentialTests(bool isAsync) : base(isAsync)
3434

3535
private const string ExpectedToken = "mock-msi-access-token";
3636

37-
[Test]
38-
public async Task VerifyExpiringTokenRefresh()
39-
{
40-
int callCount = 0;
41-
42-
var mockClient = new MockManagedIdentityClient(CredentialPipeline.GetInstance(null))
43-
{
44-
TokenFactory = () => { callCount++; return new AccessToken(Guid.NewGuid().ToString(), DateTimeOffset.UtcNow.AddMinutes(2)); }
45-
};
46-
47-
var cred = InstrumentClient(new ManagedIdentityCredential(mockClient));
48-
49-
for (int i = 0; i < 5; i++)
50-
{
51-
await cred.GetTokenAsync(new TokenRequestContext(MockScopes.Default));
52-
}
53-
54-
Assert.AreEqual(5, callCount);
55-
}
56-
5737
[NonParallelizable]
5838
[Test]
5939
public async Task VerifyImdsRequestWithClientIdMockAsync()
@@ -84,6 +64,38 @@ public async Task VerifyImdsRequestWithClientIdMockAsync()
8464
Assert.IsTrue(query.Contains($"{Constants.ManagedIdentityClientId}=mock-client-id"));
8565
}
8666

67+
[NonParallelizable]
68+
[Test]
69+
public async Task VerifyImdsSendsProbeOnlyOnFirstRequest()
70+
{
71+
using var environment = new TestEnvVar(new() { { "MSI_ENDPOINT", null }, { "MSI_SECRET", null }, { "IDENTITY_ENDPOINT", null }, { "IDENTITY_HEADER", null }, { "AZURE_POD_IDENTITY_AUTHORITY_HOST", null } });
72+
73+
int probeCount = 0;
74+
var mockTransport = new MockTransport(req =>
75+
{
76+
if (!req.Headers.TryGetValue("Metadata", out var _))
77+
{
78+
probeCount++;
79+
return CreateErrorMockResponse(400, "mock error");
80+
}
81+
else
82+
{
83+
return CreateMockResponse(200, ExpectedToken);
84+
}
85+
});
86+
var options = new TokenCredentialOptions() { Transport = mockTransport, IsChainedCredential = true };
87+
var pipeline = CredentialPipeline.GetInstance(options);
88+
ManagedIdentityCredential credential = InstrumentClient(new ManagedIdentityCredential(
89+
new ManagedIdentityClient(
90+
new ManagedIdentityClientOptions() { Pipeline = pipeline, ManagedIdentityId = ManagedIdentityId.FromUserAssignedClientId("mock-client-id"), IsForceRefreshEnabled = true, Options = options })));
91+
92+
await credential.GetTokenAsync(new TokenRequestContext(MockScopes.Default));
93+
AccessToken actualToken = await credential.GetTokenAsync(new TokenRequestContext(MockScopes.Default));
94+
95+
Assert.AreEqual(ExpectedToken, actualToken.Token);
96+
Assert.AreEqual(1, probeCount, "Probe was sent more than once.");
97+
}
98+
8799
[NonParallelizable]
88100
[Test]
89101
public async Task ImdsWithEmptyClientIdIsIgnoredMockAsync()

0 commit comments

Comments
 (0)