Skip to content

Commit 9d1b119

Browse files
author
trwalke
committed
merge from main
2 parents d15b71d + 466bceb commit 9d1b119

File tree

12 files changed

+65
-55
lines changed

12 files changed

+65
-55
lines changed

docs/msi_v2/msi_with_credential_design.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ The primary objective is to enable seamless token acquisition in MSI V2 for VM/V
1616

1717
In **MSI V1**, IMDS or any other Managed Identity Resource Provider (MIRP) directly returns an **access token**. However, in **MSI V2**, the process involves few more steps:
1818

19+
Conceptual diagram
20+
1921
```mermaid
2022
sequenceDiagram
2123
participant App as Application
@@ -24,10 +26,31 @@ sequenceDiagram
2426
participant MAA as Azure MAA
2527
participant ESTS as Entra STS (mTLS)
2628
27-
App ->> MSAL: AcquireTokenForManagedIdentity()
29+
App ->> MSAL: AcquireToken
30+
MSAL -> MSAL: Detect that MSIv2 is available, otherwise bail
31+
MSAL -> MSAL: Create the strongest key possible, e.g. in the TPM
32+
MSAL ->> MAA: Acquire an attestation token, which proves the key strength
33+
MSAL ->> IMDS: Certificate Signing Request with (key, attestation token)
34+
IMDS -->> MSAL: Certificate associated with key
35+
MSAL ->> ESTS: Open mTLS connection to ESTS with this certificate and acquire token
36+
ESTS -->> MSAL: token with special claim xms_tb
37+
MSAL -->> App: token and certificate
38+
```
39+
40+
Technical diagram
41+
42+
```mermaid
43+
sequenceDiagram
44+
participant App as Application
45+
participant MSAL
46+
participant IMDS
47+
participant MAA as Azure MAA
48+
participant ESTS as Entra STS (mTLS)
49+
50+
App ->> MSAL: AcquireToken
2851
MSAL ->> IMDS: GET /metadata/identity/getPlatformMetadata
2952
IMDS -->> MSAL: client_id, tenant_id, cuid, maa_endpoint
30-
53+
3154
alt Attestable CU
3255
MSAL ->> MAA: POST /attest/keyguard (attestation info)
3356
MAA -->> MSAL: attestation_token

src/client/Microsoft.Identity.Client/AppConfig/IMsalMtlsHttpClientFactory.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@
77
namespace Microsoft.Identity.Client
88
{
99
/// <summary>
10-
/// Internal factory responsible for creating HttpClient instances configured for mutual TLS (MTLS).
11-
/// This factory is specifically intended for use within the MSAL library for secure communication with Azure AD using MTLS.
12-
/// For more details on HttpClient instancing, see https://learn.microsoft.com/dotnet/api/system.net.http.httpclient?view=net-7.0#instancing.
10+
/// A factory responsible for creating HttpClient instances configured for mutual TLS (mTLS).
11+
/// This factory is intended for use to secure communication with Azure AD using mTLS.
12+
/// For more details on HttpClient instancing, see https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=net-8.0#instancing.
1313
/// </summary>
1414
/// <remarks>
1515
/// Implementations of this interface must be thread-safe.
1616
/// It is important to reuse HttpClient instances to avoid socket exhaustion.
1717
/// Do not create a new HttpClient for each call to <see cref="GetHttpClient(X509Certificate2)"/>.
1818
/// If your application requires Integrated Windows Authentication, set <see cref="HttpClientHandler.UseDefaultCredentials"/> to true.
19-
/// This interface is intended for internal use by MSAL only and is designed to support MTLS scenarios.
19+
/// This interface is designed to support mTLS scenarios.
2020
/// </remarks>
21-
internal interface IMsalMtlsHttpClientFactory : IMsalHttpClientFactory
21+
public interface IMsalMtlsHttpClientFactory : IMsalHttpClientFactory
2222
{
2323
/// <summary>
2424
/// Returns an HttpClient configured with a certificate for mutual TLS authentication.

src/client/Microsoft.Identity.Client/Internal/Requests/RequestBase.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ public async Task<AuthenticationResult> RunAsync(CancellationToken cancellationT
116116

117117
LogFailureTelemetryToOtel(ex.GetType().Name, apiEvent, apiEvent.CacheInfo);
118118
throw;
119-
}
119+
}
120120
}
121121

122122
private void LogSuccessTelemetryToOtel(AuthenticationResult authenticationResult, ApiEvent apiEvent, long durationInUs)
@@ -140,7 +140,7 @@ private void LogFailureTelemetryToOtel(string errorCodeToLog, ApiEvent apiEvent,
140140
ServiceBundle.PlatformProxy.GetProductName(),
141141
errorCodeToLog,
142142
apiEvent.ApiId,
143-
apiEvent.CallerSdkApiId,
143+
apiEvent.CallerSdkApiId,
144144
apiEvent.CallerSdkVersion,
145145
cacheRefreshReason,
146146
apiEvent.TokenType);
@@ -267,12 +267,12 @@ private void UpdateCallerSdkDetails(ApiEvent apiEvent)
267267
if (AuthenticationRequestParameters.ExtraQueryParameters.TryGetValue("caller-sdk-id", out callerSdkId))
268268
{
269269
AuthenticationRequestParameters.ExtraQueryParameters.Remove("caller-sdk-id");
270-
}
270+
}
271271
else
272272
{
273273
callerSdkId = AuthenticationRequestParameters.RequestContext.ServiceBundle.Config.ClientName;
274274
}
275-
275+
276276
if (AuthenticationRequestParameters.ExtraQueryParameters.TryGetValue("caller-sdk-ver", out callerSdkVer))
277277
{
278278
AuthenticationRequestParameters.ExtraQueryParameters.Remove("caller-sdk-ver");

src/client/Microsoft.Identity.Client/PublicApi/net462/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ const Microsoft.Identity.Client.MsalError.CannotSwitchBetweenImdsVersionsForPrev
22
const Microsoft.Identity.Client.MsalError.InvalidCertificate = "invalid_certificate" -> string
33
const Microsoft.Identity.Client.MsalError.MtlsNotSupportedForManagedIdentity = "mtls_not_supported_for_managed_identity" -> string
44
const Microsoft.Identity.Client.MsalError.MtlsPopTokenNotSupportedinImdsV1 = "mtls_pop_token_not_supported_in_imds_v1" -> string
5-
Microsoft.Identity.Client.AuthScheme.ValidateCachedToken(Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData cachedTokenItem) -> bool
6-
Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData
7-
Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData.MsalCacheValidationData() -> void
8-
Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData.PersistedCacheParameters.get -> System.Collections.Generic.IDictionary<string, string>
5+
Microsoft.Identity.Client.IMsalMtlsHttpClientFactory
6+
Microsoft.Identity.Client.IMsalMtlsHttpClientFactory.GetHttpClient(System.Security.Cryptography.X509Certificates.X509Certificate2 x509Certificate2) -> System.Net.Http.HttpClient
97
Microsoft.Identity.Client.ManagedIdentityApplication.GetManagedIdentitySourceAsync() -> System.Threading.Tasks.Task<Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource>
108
Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource.ImdsV2 = 8 -> Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource
119
Microsoft.Identity.Client.ManagedIdentityApplicationBuilder.WithExtraQueryParameters(System.Collections.Generic.IDictionary<string, string> extraQueryParameters) -> Microsoft.Identity.Client.ManagedIdentityApplicationBuilder

src/client/Microsoft.Identity.Client/PublicApi/net472/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ const Microsoft.Identity.Client.MsalError.CannotSwitchBetweenImdsVersionsForPrev
22
const Microsoft.Identity.Client.MsalError.InvalidCertificate = "invalid_certificate" -> string
33
const Microsoft.Identity.Client.MsalError.MtlsNotSupportedForManagedIdentity = "mtls_not_supported_for_managed_identity" -> string
44
const Microsoft.Identity.Client.MsalError.MtlsPopTokenNotSupportedinImdsV1 = "mtls_pop_token_not_supported_in_imds_v1" -> string
5-
Microsoft.Identity.Client.AuthScheme.ValidateCachedToken(Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData cachedTokenItem) -> bool
6-
Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData
7-
Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData.MsalCacheValidationData() -> void
8-
Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData.PersistedCacheParameters.get -> System.Collections.Generic.IDictionary<string, string>
5+
Microsoft.Identity.Client.IMsalMtlsHttpClientFactory
6+
Microsoft.Identity.Client.IMsalMtlsHttpClientFactory.GetHttpClient(System.Security.Cryptography.X509Certificates.X509Certificate2 x509Certificate2) -> System.Net.Http.HttpClient
97
Microsoft.Identity.Client.ManagedIdentityApplication.GetManagedIdentitySourceAsync() -> System.Threading.Tasks.Task<Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource>
108
Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource.ImdsV2 = 8 -> Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource
119
Microsoft.Identity.Client.ManagedIdentityApplicationBuilder.WithExtraQueryParameters(System.Collections.Generic.IDictionary<string, string> extraQueryParameters) -> Microsoft.Identity.Client.ManagedIdentityApplicationBuilder

src/client/Microsoft.Identity.Client/PublicApi/net8.0-android/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ const Microsoft.Identity.Client.MsalError.CannotSwitchBetweenImdsVersionsForPrev
22
const Microsoft.Identity.Client.MsalError.InvalidCertificate = "invalid_certificate" -> string
33
const Microsoft.Identity.Client.MsalError.MtlsNotSupportedForManagedIdentity = "mtls_not_supported_for_managed_identity" -> string
44
const Microsoft.Identity.Client.MsalError.MtlsPopTokenNotSupportedinImdsV1 = "mtls_pop_token_not_supported_in_imds_v1" -> string
5-
Microsoft.Identity.Client.AuthScheme.ValidateCachedToken(Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData cachedTokenItem) -> bool
6-
Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData
7-
Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData.MsalCacheValidationData() -> void
8-
Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData.PersistedCacheParameters.get -> System.Collections.Generic.IDictionary<string, string>
5+
Microsoft.Identity.Client.IMsalMtlsHttpClientFactory
6+
Microsoft.Identity.Client.IMsalMtlsHttpClientFactory.GetHttpClient(System.Security.Cryptography.X509Certificates.X509Certificate2 x509Certificate2) -> System.Net.Http.HttpClient
97
Microsoft.Identity.Client.ManagedIdentityApplication.GetManagedIdentitySourceAsync() -> System.Threading.Tasks.Task<Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource>
108
Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource.ImdsV2 = 8 -> Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource
119
Microsoft.Identity.Client.ManagedIdentityApplicationBuilder.WithExtraQueryParameters(System.Collections.Generic.IDictionary<string, string> extraQueryParameters) -> Microsoft.Identity.Client.ManagedIdentityApplicationBuilder

src/client/Microsoft.Identity.Client/PublicApi/net8.0-ios/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ const Microsoft.Identity.Client.MsalError.CannotSwitchBetweenImdsVersionsForPrev
22
const Microsoft.Identity.Client.MsalError.InvalidCertificate = "invalid_certificate" -> string
33
const Microsoft.Identity.Client.MsalError.MtlsNotSupportedForManagedIdentity = "mtls_not_supported_for_managed_identity" -> string
44
const Microsoft.Identity.Client.MsalError.MtlsPopTokenNotSupportedinImdsV1 = "mtls_pop_token_not_supported_in_imds_v1" -> string
5-
Microsoft.Identity.Client.AuthScheme.ValidateCachedToken(Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData cachedTokenItem) -> bool
6-
Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData
7-
Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData.MsalCacheValidationData() -> void
8-
Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData.PersistedCacheParameters.get -> System.Collections.Generic.IDictionary<string, string>
5+
Microsoft.Identity.Client.IMsalMtlsHttpClientFactory
6+
Microsoft.Identity.Client.IMsalMtlsHttpClientFactory.GetHttpClient(System.Security.Cryptography.X509Certificates.X509Certificate2 x509Certificate2) -> System.Net.Http.HttpClient
97
Microsoft.Identity.Client.ManagedIdentityApplication.GetManagedIdentitySourceAsync() -> System.Threading.Tasks.Task<Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource>
108
Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource.ImdsV2 = 8 -> Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource
119
Microsoft.Identity.Client.ManagedIdentityApplicationBuilder.WithExtraQueryParameters(System.Collections.Generic.IDictionary<string, string> extraQueryParameters) -> Microsoft.Identity.Client.ManagedIdentityApplicationBuilder

src/client/Microsoft.Identity.Client/PublicApi/net8.0/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ const Microsoft.Identity.Client.MsalError.CannotSwitchBetweenImdsVersionsForPrev
22
const Microsoft.Identity.Client.MsalError.InvalidCertificate = "invalid_certificate" -> string
33
const Microsoft.Identity.Client.MsalError.MtlsNotSupportedForManagedIdentity = "mtls_not_supported_for_managed_identity" -> string
44
const Microsoft.Identity.Client.MsalError.MtlsPopTokenNotSupportedinImdsV1 = "mtls_pop_token_not_supported_in_imds_v1" -> string
5-
Microsoft.Identity.Client.AuthScheme.ValidateCachedToken(Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData cachedTokenItem) -> bool
6-
Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData
7-
Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData.MsalCacheValidationData() -> void
8-
Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData.PersistedCacheParameters.get -> System.Collections.Generic.IDictionary<string, string>
5+
Microsoft.Identity.Client.IMsalMtlsHttpClientFactory
6+
Microsoft.Identity.Client.IMsalMtlsHttpClientFactory.GetHttpClient(System.Security.Cryptography.X509Certificates.X509Certificate2 x509Certificate2) -> System.Net.Http.HttpClient
97
Microsoft.Identity.Client.ManagedIdentityApplication.GetManagedIdentitySourceAsync() -> System.Threading.Tasks.Task<Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource>
108
Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource.ImdsV2 = 8 -> Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource
119
Microsoft.Identity.Client.ManagedIdentityApplicationBuilder.WithExtraQueryParameters(System.Collections.Generic.IDictionary<string, string> extraQueryParameters) -> Microsoft.Identity.Client.ManagedIdentityApplicationBuilder

src/client/Microsoft.Identity.Client/PublicApi/netstandard2.0/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ const Microsoft.Identity.Client.MsalError.CannotSwitchBetweenImdsVersionsForPrev
22
const Microsoft.Identity.Client.MsalError.InvalidCertificate = "invalid_certificate" -> string
33
const Microsoft.Identity.Client.MsalError.MtlsNotSupportedForManagedIdentity = "mtls_not_supported_for_managed_identity" -> string
44
const Microsoft.Identity.Client.MsalError.MtlsPopTokenNotSupportedinImdsV1 = "mtls_pop_token_not_supported_in_imds_v1" -> string
5-
Microsoft.Identity.Client.AuthScheme.ValidateCachedToken(Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData cachedTokenItem) -> bool
6-
Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData
7-
Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData.MsalCacheValidationData() -> void
8-
Microsoft.Identity.Client.AuthScheme.MsalCacheValidationData.PersistedCacheParameters.get -> System.Collections.Generic.IDictionary<string, string>
5+
Microsoft.Identity.Client.IMsalMtlsHttpClientFactory
6+
Microsoft.Identity.Client.IMsalMtlsHttpClientFactory.GetHttpClient(System.Security.Cryptography.X509Certificates.X509Certificate2 x509Certificate2) -> System.Net.Http.HttpClient
97
Microsoft.Identity.Client.ManagedIdentityApplication.GetManagedIdentitySourceAsync() -> System.Threading.Tasks.Task<Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource>
108
Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource.ImdsV2 = 8 -> Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource
119
Microsoft.Identity.Client.ManagedIdentityApplicationBuilder.WithExtraQueryParameters(System.Collections.Generic.IDictionary<string, string> extraQueryParameters) -> Microsoft.Identity.Client.ManagedIdentityApplicationBuilder

tests/Microsoft.Identity.Test.E2e/ManagedIdentityImdsTests.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ private static IManagedIdentityApplication BuildMi(
3939
[TestCategory("MI_E2E_Imds")]
4040
[DataTestMethod]
4141
[DataRow(null /*SAMI*/, null, DisplayName = "AcquireToken_OnImds_Succeeds-SAMI")]
42-
[DataRow("4b7a4b0b-ecb2-409e-879a-1e21a15ddaf6", "clientid", DisplayName = "AcquireToken_OnImds_Succeeds-UAMI-ClientId")]
43-
[DataRow("/subscriptions/c1686c51-b717-4fe0-9af3-24a20a41fb0c/resourcegroups/MSAL_MSI/providers/Microsoft.ManagedIdentity/userAssignedIdentities/LabVaultAccess_UAMI",
42+
[DataRow("8ef2ae5a-f349-4d36-bc0e-a567f2cc50f7", "clientid", DisplayName = "AcquireToken_OnImds_Succeeds-UAMI-ClientId")]
43+
[DataRow("/subscriptions/6f52c299-a200-4fe1-8822-a3b61cf1f931/resourcegroups/DevOpsHostedAgents/providers/Microsoft.ManagedIdentity/userAssignedIdentities/ID4SMSIHostedAgent_UAMI",
4444
"resourceid", DisplayName = "AcquireToken_OnImds_Succeeds-UAMI-ResourceId")]
45-
[DataRow("1eee55b7-168a-46be-8d19-30e830ee9611", "objectid", DisplayName = "AcquireToken_OnImds_Succeeds-UAMI-ObjectId")]
45+
[DataRow("0651a6fc-fbf5-4904-9e48-16f63ec1f2b1", "objectid", DisplayName = "AcquireToken_OnImds_Succeeds-UAMI-ObjectId")]
4646
public async Task AcquireToken_OnImds_Succeeds(string id, string idType)
4747
{
4848
var mi = BuildMi(id, idType);
@@ -69,10 +69,10 @@ public async Task AcquireToken_OnImds_Succeeds(string id, string idType)
6969
[TestCategory("MI_E2E_Imds")]
7070
[DataTestMethod]
7171
[DataRow(null /*SAMI*/, null, DisplayName = "AcquireToken_OnImds_Fails_WithMtlsProofOfPossession-SAMI")]
72-
[DataRow("4b7a4b0b-ecb2-409e-879a-1e21a15ddaf6", "clientid", DisplayName = "AcquireToken_OnImds_Fails_WithMtlsProofOfPossession-UAMI-ClientId")]
73-
[DataRow("/subscriptions/c1686c51-b717-4fe0-9af3-24a20a41fb0c/resourcegroups/MSAL_MSI/providers/Microsoft.ManagedIdentity/userAssignedIdentities/LabVaultAccess_UAMI",
72+
[DataRow("8ef2ae5a-f349-4d36-bc0e-a567f2cc50f7", "clientid", DisplayName = "AcquireToken_OnImds_Fails_WithMtlsProofOfPossession-UAMI-ClientId")]
73+
[DataRow("/subscriptions/6f52c299-a200-4fe1-8822-a3b61cf1f931/resourcegroups/DevOpsHostedAgents/providers/Microsoft.ManagedIdentity/userAssignedIdentities/ID4SMSIHostedAgent_UAMI",
7474
"resourceid", DisplayName = "AcquireToken_OnImds_Fails_WithMtlsProofOfPossession-UAMI-ResourceId")]
75-
[DataRow("1eee55b7-168a-46be-8d19-30e830ee9611", "objectid", DisplayName = "AcquireToken_OnImds_Fails_WithMtlsProofOfPossession-UAMI-ObjectId")]
75+
[DataRow("0651a6fc-fbf5-4904-9e48-16f63ec1f2b1", "objectid", DisplayName = "AcquireToken_OnImds_Fails_WithMtlsProofOfPossession-UAMI-ObjectId")]
7676
public async Task AcquireToken_OnImds_Fails_WithMtlsProofOfPossession(string id, string idType)
7777
{
7878
var mi = BuildMi(id, idType);

0 commit comments

Comments
 (0)