Add GetManagedIdentityCapabilitiesAsync host capability discovery API (Phase 1)#6049
Merged
Robbie-Microsoft merged 7 commits intoJun 4, 2026
Merged
Conversation
Builds on #6026's compute-metadata detection to ship the capability-discovery API agreed in the #6040 proposal: - Add GetManagedIdentityCapabilitiesAsync(CancellationToken) on ManagedIdentityApplication returning ManagedIdentityCapabilities (Source, MaxSupportedBindingStrength, derived IsMtlsPopSupportedByHost); remove GetManagedIdentitySourceAsync/ManagedIdentitySourceResult. - Add public MtlsBindingStrength enum (Bearer/Software/KeyGuard) in AppConfig. - Port ComputeMetadataResponse + ImdsComputeMetadataManager from #6026; register JSON types. - Fold public ManagedIdentitySource.ImdsV2 into Imds while preserving internal v1/v2 routing; gate MSIv1 claims validation behind RequiresMsiV1ClaimsValidation. - Discovery maps IMDSv2 success to Software and IMDSv1 success to compute-metadata-derived strength (TVM/CVM Windows to Software, else Bearer). - Update all 6 TFM PublicAPI files, tests, and changelog. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The IMDSv2-success path now probes the platform managed-identity key provider and advertises the attested KeyGuard tier when a VBS-isolated KeyGuard key is obtainable, mirroring what the v2 PoP token flow itself requires. It floors at Software (never downgrades a confirmed v2 host) and reports Bearer on net462. The IMDSv1-only compute-based path is unchanged and renamed for clarity. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
GetManagedIdentityCapabilitiesAsync may provision and persist a binding key while detecting the strongest available binding strength on capable hosts, pre-warming the cache reused by a later token request. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR implements Phase 1 of managed identity host capability discovery by introducing a new public discovery API (GetManagedIdentityCapabilitiesAsync) that reports the detected managed identity source plus the host’s maximum supported mTLS binding strength (via the new MtlsBindingStrength enum). It also folds the public ManagedIdentitySource.ImdsV2 enum value back into Imds and updates tests and public API baselines accordingly.
Changes:
- Added
ManagedIdentityApplication.GetManagedIdentityCapabilitiesAsync(CancellationToken)returningManagedIdentityCapabilities(Source,ErrorReason,MaxSupportedBindingStrength, derivedIsMtlsPopSupportedByHost). - Added
Microsoft.Identity.Client.AppConfig.MtlsBindingStrengthand IMDS compute-metadata fetching to infer binding strength (IMDSv1 via/compute, IMDSv2 via key provider probing). - Removed the legacy
GetManagedIdentitySourceAsync/ManagedIdentitySourceResultAPI surface and updated PublicAPI baselines across TFMs; updated unit tests to match the new discovery flow.
Reviewed changes
Copilot reviewed 32 out of 32 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/Microsoft.Identity.Test.Unit/ManagedIdentityTests/ManagedIdentityTests.cs | Updates discovery tests to use GetManagedIdentityCapabilitiesAsync and adds binding-strength assertions for IMDS scenarios. |
| tests/Microsoft.Identity.Test.Unit/ManagedIdentityTests/ImdsV2Tests.cs | Reworks IMDSv2 tests to validate the new discovery API and to inject deterministic key providers before capability discovery. |
| tests/Microsoft.Identity.Test.Unit/ManagedIdentityTests/AppServiceTests.cs | Switches App Service upgrade test to the new discovery API. |
| src/client/Microsoft.Identity.Lab.Api/Http/MockHelpers.cs | Adds mock handlers for IMDS compute metadata (/metadata/instance/compute) including 200 and 404 responses. |
| src/client/Microsoft.Identity.Lab.Api/Helpers/ManagedIdentityTestUtil.cs | Removes ImdsV2 from test environment-variable routing (now folded into Imds). |
| src/client/Microsoft.Identity.Client/PublicApi/netstandard2.0/PublicAPI.Unshipped.txt | Adds new public types/members (MtlsBindingStrength, ManagedIdentityCapabilities, GetManagedIdentityCapabilitiesAsync). |
| src/client/Microsoft.Identity.Client/PublicApi/netstandard2.0/PublicAPI.Shipped.txt | Removes ManagedIdentitySource.ImdsV2 and the legacy ManagedIdentitySourceResult/GetManagedIdentitySourceAsync API surface. |
| src/client/Microsoft.Identity.Client/PublicApi/net8.0/PublicAPI.Unshipped.txt | Same PublicAPI additions for net8.0. |
| src/client/Microsoft.Identity.Client/PublicApi/net8.0/PublicAPI.Shipped.txt | Same PublicAPI removals for net8.0. |
| src/client/Microsoft.Identity.Client/PublicApi/net8.0-ios/PublicAPI.Unshipped.txt | Same PublicAPI additions for net8.0-ios. |
| src/client/Microsoft.Identity.Client/PublicApi/net8.0-ios/PublicAPI.Shipped.txt | Same PublicAPI removals for net8.0-ios. |
| src/client/Microsoft.Identity.Client/PublicApi/net8.0-android/PublicAPI.Unshipped.txt | Same PublicAPI additions for net8.0-android. |
| src/client/Microsoft.Identity.Client/PublicApi/net8.0-android/PublicAPI.Shipped.txt | Same PublicAPI removals for net8.0-android. |
| src/client/Microsoft.Identity.Client/PublicApi/net472/PublicAPI.Unshipped.txt | Same PublicAPI additions for net472. |
| src/client/Microsoft.Identity.Client/PublicApi/net472/PublicAPI.Shipped.txt | Same PublicAPI removals for net472. |
| src/client/Microsoft.Identity.Client/PublicApi/net462/PublicAPI.Unshipped.txt | Same PublicAPI additions for net462. |
| src/client/Microsoft.Identity.Client/PublicApi/net462/PublicAPI.Shipped.txt | Same PublicAPI removals for net462. |
| src/client/Microsoft.Identity.Client/Platforms/net/MsalJsonSerializerContext.cs | Registers new IMDS compute metadata DTOs for System.Text.Json source generation. |
| src/client/Microsoft.Identity.Client/ManagedIdentityApplication.cs | Replaces GetManagedIdentitySourceAsync with GetManagedIdentityCapabilitiesAsync and wires it to the new internal discovery result. |
| src/client/Microsoft.Identity.Client/ManagedIdentity/V2/ImdsV2ManagedIdentitySource.cs | Updates IMDSv2 source reporting to ManagedIdentitySource.Imds (public v1/v2 fold). |
| src/client/Microsoft.Identity.Client/ManagedIdentity/V2/CertificateRequestResponse.cs | Updates managed identity source attribution in error construction (v1/v2 fold). |
| src/client/Microsoft.Identity.Client/ManagedIdentity/ManagedIdentitySourceResult.cs | Removes the legacy public result type for source discovery. |
| src/client/Microsoft.Identity.Client/ManagedIdentity/ManagedIdentitySource.cs | Removes the public ImdsV2 enum member and updates the obsolete message for DefaultToImds. |
| src/client/Microsoft.Identity.Client/ManagedIdentity/ManagedIdentityDiscoveryResult.cs | Adds internal discovery result carrying public source + internal IMDS protocol version + binding strength + probe failure reasons. |
| src/client/Microsoft.Identity.Client/ManagedIdentity/ManagedIdentityClient.cs | Implements new discovery flow, caches discovery result, and adds IMDSv1/v2 binding-strength detection. |
| src/client/Microsoft.Identity.Client/ManagedIdentity/ManagedIdentityCapabilities.cs | Adds the new public capabilities DTO (source, error reason, max binding strength, derived PoP support flag). |
| src/client/Microsoft.Identity.Client/ManagedIdentity/ImdsManagedIdentitySource.cs | Introduces IMDSv1-specific claims validation flag to preserve behavior after folding IMDS v1/v2 into a single public source label. |
| src/client/Microsoft.Identity.Client/ManagedIdentity/ImdsComputeMetadataManager.cs | Adds /metadata/instance/compute call and helper to infer host PoP capability from OS/security profile. |
| src/client/Microsoft.Identity.Client/ManagedIdentity/ComputeMetadataResponse.cs | Adds DTOs for compute metadata response (osType, securityProfile.securityType). |
| src/client/Microsoft.Identity.Client/ManagedIdentity/AbstractManagedIdentity.cs | Preserves IMDSv1-only claim validation via a new virtual flag, now that IMDS v1/v2 share the same public source label. |
| src/client/Microsoft.Identity.Client/AppConfig/MtlsBindingStrength.cs | Adds new public enum describing binding strength tiers (Bearer, Software, KeyGuard). |
| CHANGELOG.md | Documents the new discovery API and the folding/removal of the legacy discovery surface. |
gladjohn
reviewed
Jun 3, 2026
gladjohn
reviewed
Jun 3, 2026
gladjohn
reviewed
Jun 3, 2026
gladjohn
reviewed
Jun 3, 2026
gladjohn
reviewed
Jun 3, 2026
gladjohn
reviewed
Jun 3, 2026
gladjohn
reviewed
Jun 3, 2026
gladjohn
reviewed
Jun 3, 2026
…gelog link - Serialize GetManagedIdentityCapabilitiesAsync with a static SemaphoreSlim so concurrent first calls don't issue redundant IMDS probes or provision the binding key more than once (non-blocking fast-path acquire preserves the existing HTTP-probe cancellation point). - Remove 'MSAL' from the IMDS-unavailable error message. - Enrich the mtls_pop_requires_keyguard message with actionable VBS/KeyGuard guidance (error code unchanged). - Fix CHANGELOG entry to link this PR (#6049) instead of the proposal (#6040). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
bgavrilMS
reviewed
Jun 3, 2026
bgavrilMS
reviewed
Jun 3, 2026
bgavrilMS
reviewed
Jun 3, 2026
bgavrilMS
reviewed
Jun 3, 2026
bgavrilMS
approved these changes
Jun 3, 2026
gladjohn
approved these changes
Jun 3, 2026
…cancellation handling Addresses review feedback on PR #6049: - MtlsBindingStrength floor renamed Bearer -> None (strength tier, not a token type); reworded XML docs and updated PublicAPI.Unshipped baselines. - Collapsed the explicit OperationCanceledException rethrow into an exception filter on the broad catch in ImdsComputeMetadataManager. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Addresses Copilot review feedback on PR #6049: - Remove issue6046_check.txt, a design scratch note accidentally committed. - Update CHANGELOG to reference the renamed MtlsBindingStrength.None value (was Bearer) so the documented API surface matches the code. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
gladjohn
approved these changes
Jun 4, 2026
This was referenced Jun 4, 2026
This was referenced Jun 5, 2026
Open
Open
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements Phase 1 of the
GetManagedIdentityCapabilitiesAsyncproposal (spec: PR #6040) to unblock the AKV SDK. Builds on Bogdan's #6026 (/metadata/instance/computehost detection, validated on a real VM) rather than starting fresh.This is the discovery API only. The
WithMtlsProofOfPossession(PoPOptions { MinStrength })enforcement knob is Phase 2 / follow-up and is intentionally out of scope.What changed
ManagedIdentityApplication.GetManagedIdentityCapabilitiesAsync(CancellationToken)returningManagedIdentityCapabilities(Source,ErrorReason,MaxSupportedBindingStrength, derivedIsMtlsPopSupportedByHost).MtlsBindingStrengthenum inMicrosoft.Identity.Client.AppConfig(Bearer=0,Software=1,KeyGuard=3;2reserved for a future TPM tier), shared by MI and confidential-client mTLS PoP.KeyGuardtier, otherwise theSoftwarefloor (mirrors what the v2 PoP token flow requires)./computesecurity profile (TVM/CVM →Software, elseBearer).Beareron .NET Framework 4.6.2 (no PoP).ManagedIdentitySource.ImdsV2back intoImds— the v1/v2 distinction is now internal routing only; callers branch on the capability signal.GetManagedIdentitySourceAsync+ManagedIdentitySourceResult; updatedPublicAPI.Shipped.txt/PublicAPI.Unshipped.txtacross all TFMs.Semantics (per the approved spec)
IsMtlsPopSupportedByHostis derived (MaxSupportedBindingStrength > Bearer) and means "the host can bind a token to a key" — NOT "attested." Attestation must be read from theKeyGuardtier specifically. Documented in the XML docs.Capability discovery may provision/persist a binding key on capable hosts as a side effect, pre-warming the cache reused by a later token request (documented on the API).
Safety for AKS / high-density hosts
AKS nodes are Linux with no TVM/CVM profile, so
IsMtlsPopSupportedByHostcomes backfalse; Azure SDK also gates onFEDERATED_TOKEN_FILEbefore calling MSAL's MI path.Tests
Covers AKS/Linux →
IsMtlsPopSupportedByHost = false, Windows TVM/CVM IMDSv2 →KeyGuardtier, IMDSv2 software-key →Software, and existing token flows unchanged. Builds clean across all TFMs (TreatWarningsAsErrors); ManagedIdentity / ImdsV2 / AppService unit suites green.Out of scope (Phase 2 follow-up)
PoPOptions+WithMtlsProofOfPossession(PoPOptions)minimum-strength enforcement, andMsalError.MinStrengthNotMet. Not needed for the AKV unblock.