-
Notifications
You must be signed in to change notification settings - Fork 381
MSI POP Attestation #5612
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
base: main
Are you sure you want to change the base?
MSI POP Attestation #5612
Changes from all commits
cf72c38
56889d7
ba29c76
595aaa8
7acfbed
f9324df
fac7299
9db5690
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,7 +9,6 @@ | |
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="Microsoft.Identity.Client" /> | ||
| <PackageReference Include="Microsoft.Identity.Client.MtlsPop" /> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need to add the new project reference? |
||
| </ItemGroup> | ||
|
|
||
| </Project> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,17 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| using System; | ||
| using System.Runtime.InteropServices; | ||
| using Microsoft.Win32.SafeHandles; | ||
|
|
||
| namespace Microsoft.Identity.Client.MtlsPop.Attestation | ||
| namespace Microsoft.Identity.Client.KeyAttestation | ||
| { | ||
| /// <summary> | ||
| /// Managed façade for <c>AttestationClientLib.dll</c>. Holds initialization state, | ||
| /// does ref-count hygiene on <see cref="SafeNCryptKeyHandle"/>, and returns a JWT. | ||
| /// </summary> | ||
| internal sealed class AttestationClient : IDisposable | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should not be part of the public API |
||
| public sealed class AttestationClient : IDisposable | ||
| { | ||
| private bool _initialized; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| namespace Microsoft.Identity.Client.MtlsPop.Attestation | ||
| namespace Microsoft.Identity.Client.KeyAttestation | ||
| { | ||
| /// <summary> | ||
| /// AttestationResult is the result of an attestation operation. | ||
|
|
@@ -20,7 +20,7 @@ namespace Microsoft.Identity.Client.MtlsPop.Attestation | |
| /// expression, e.g.: var updated = result with { Jwt = newJwt }; | ||
| /// The netstandard2.0 target relies on the IsExternalInit shim (see IsExternalInit.cs) to enable 'init'. | ||
| /// </remarks> | ||
| internal sealed record AttestationResult( | ||
| public sealed record AttestationResult( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does this need to be public? think the safest way it to just rename the project and not recreate a new project. seems like there are many changes that are not necessary |
||
| AttestationStatus Status, | ||
| string Jwt, | ||
| int NativeErrorCode, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,16 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Text; | ||
|
|
||
| namespace Microsoft.Identity.Client.MtlsPop.Attestation | ||
| namespace Microsoft.Identity.Client.KeyAttestation | ||
| { | ||
| /// <summary> | ||
| /// High-level outcome categories returned by <see cref="AttestationClient.Attest"/>. | ||
| /// </summary> | ||
| internal enum AttestationStatus | ||
| public enum AttestationStatus | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should not be part of the public API |
||
| { | ||
| /// <summary>Everything succeeded; <see cref="AttestationResult.Jwt"/> is populated.</summary> | ||
| Success = 0, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| using System; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
| using Microsoft.Identity.Client; | ||
| using Microsoft.Identity.Client.ManagedIdentity; | ||
|
|
||
| namespace Microsoft.Identity.Client.KeyAttestation | ||
| { | ||
| /// <summary> | ||
| /// Extension methods for enabling KeyGuard attestation support in managed identity mTLS PoP flows. | ||
| /// </summary> | ||
| public static class ManagedIdentityAttestationExtensions | ||
| { | ||
| /// <summary> | ||
| /// Enables KeyGuard attestation support for managed identity mTLS Proof-of-Possession flows. | ||
| /// This method should be called after <see cref="ManagedIdentityPopExtensions.WithMtlsProofOfPossession"/>. | ||
| /// </summary> | ||
| /// <param name="builder">The AcquireTokenForManagedIdentityParameterBuilder instance.</param> | ||
| /// <returns>The builder to chain .With methods.</returns> | ||
| public static AcquireTokenForManagedIdentityParameterBuilder WithAttestationSupport( | ||
| this AcquireTokenForManagedIdentityParameterBuilder builder) | ||
| { | ||
| if (builder == null) | ||
| { | ||
| throw new ArgumentNullException(nameof(builder)); | ||
| } | ||
|
|
||
| // Register the attestation token provider | ||
| return builder.WithAttestationProviderForTests(async (req, ct) => | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is builder method suffixed with "ForTests" ? It is production code. |
||
| { | ||
| // Get the caller-provided KeyGuard/CNG handle | ||
| var keyHandle = req.KeyHandle; | ||
|
|
||
| if (keyHandle == null) | ||
| { | ||
| throw new MsalClientException( | ||
| "attestation_key_handle_missing", | ||
| "KeyHandle is required for attestation but was not provided."); | ||
| } | ||
|
|
||
| // Call the native interop via PopKeyAttestor | ||
| AttestationResult attestationResult = await PopKeyAttestor.AttestKeyGuardAsync( | ||
| req.AttestationEndpoint.AbsoluteUri, | ||
| keyHandle, | ||
| req.ClientId ?? string.Empty, | ||
| ct).ConfigureAwait(false); | ||
|
|
||
| // Map to MSAL's internal response | ||
| if (attestationResult != null && | ||
| attestationResult.Status == AttestationStatus.Success && | ||
| !string.IsNullOrWhiteSpace(attestationResult.Jwt)) | ||
| { | ||
| return new AttestationTokenResponse { AttestationToken = attestationResult.Jwt }; | ||
| } | ||
|
|
||
| throw new MsalClientException( | ||
| "attestation_failure", | ||
| $"Key Attestation failed " + | ||
| $"(status={attestationResult?.Status}, " + | ||
| $"code={attestationResult?.NativeErrorCode}). {attestationResult?.ErrorMessage}"); | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
Robbie-Microsoft marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| <!-- ─── Target frameworks ─────────────────────────────────────────────── --> | ||
| <PropertyGroup> | ||
|
|
@@ -19,20 +19,14 @@ | |
| <!--This will generate AssemblyVersion, AssemblyFileVersion and AssemblyInformationVersion--> | ||
| <Version>$(MicrosoftIdentityClientVersion)-preview</Version> | ||
| <!-- Copyright needs to be in the form of © not (c) to be compliant --> | ||
| <Title>MSAL.NET extension for managed identity proof-of-possession flows</Title> | ||
| <Title>MSAL.NET extension for KeyGuard attestation support</Title> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the feature GA'd under this name - https://learn.microsoft.com/en-us/windows/security/identity-protection/credential-guard/ |
||
| <Description> | ||
| This package contains binaries needed to use managed identity proof-of-possession (MTLS PoP) flows in applications using MSAL.NET. | ||
| This package contains binaries needed to enable KeyGuard attestation in managed identity proof-of-possession (mTLS PoP) flows using MSAL.NET. | ||
| </Description> | ||
| <PackageTags>Microsoft Authentication Library Managed Identity MSAL Proof-of-Possession</PackageTags> | ||
| <PackageTags>Microsoft Authentication Library Managed Identity MSAL KeyGuard Attestation Proof-of-Possession</PackageTags> | ||
| <Product>Microsoft Authentication Library</Product> | ||
| </PropertyGroup> | ||
|
|
||
| <!-- ─── File inclusions ───────────────────────────────────────────────── --> | ||
| <ItemGroup> | ||
| <Compile Include="..\Microsoft.Identity.Client\Properties\InternalsVisibleTo.cs" | ||
| Link="Properties\InternalsVisibleTo.cs" /> | ||
| </ItemGroup> | ||
|
|
||
| <!-- ─── References ────────────────────────────────────────────────────── --> | ||
| <ItemGroup> | ||
| <ProjectReference Include="..\Microsoft.Identity.Client\Microsoft.Identity.Client.csproj" /> | ||
|
|
@@ -42,6 +36,11 @@ | |
| <PackageReference Include="System.Security.Cryptography.Cng" /> | ||
| </ItemGroup> | ||
|
|
||
| <PropertyGroup> | ||
| <!-- Temporarily disable PublicAPI analyzer to generate correct signatures --> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need these? |
||
| <NoWarn>$(NoWarn);RS0016;RS0017;RS0036;RS0041</NoWarn> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup Label="For public api analyzer support"> | ||
| <AdditionalFiles Include="PublicAPI/$(TargetFramework)/PublicAPI.Shipped.txt" /> | ||
| <AdditionalFiles Include="PublicAPI/$(TargetFramework)/PublicAPI.Unshipped.txt" /> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,20 +1,19 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| using System; | ||
| using System.Runtime.InteropServices; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
| using Microsoft.Identity.Client.MtlsPop.Attestation; | ||
| using Microsoft.Win32.SafeHandles; | ||
|
|
||
| namespace Microsoft.Identity.Client.MtlsPop | ||
| namespace Microsoft.Identity.Client.KeyAttestation | ||
| { | ||
| /// <summary> | ||
| /// Static facade for attesting a KeyGuard/CNG key and getting a JWT back. | ||
| /// Key discovery / rotation is the caller's responsibility. | ||
| /// </summary> | ||
| internal static class PopKeyAttestor | ||
| public static class PopKeyAttestor | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this be public? |
||
| { | ||
| /// <summary> | ||
| /// Asynchronously attests a KeyGuard/CNG key with the remote attestation service and returns a JWT. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The solution file does not add the new project, only deletes the old one.