-
Notifications
You must be signed in to change notification settings - Fork 704
Add initial support for custom certificate trust #11889
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
Merged
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
4b73479
Add initial support for custom certificate trust
danegsta efe6a96
Update src/Aspire.Hosting/Dcp/DcpExecutor.cs
danegsta a42e923
Update src/Aspire.Hosting/Dcp/DcpExecutor.cs
danegsta 0886e9e
Update src/Aspire.Hosting/Utils/X509Certificate2Extensions.cs
danegsta 88c2eed
Fix failing DCP tests
danegsta 92467b2
Merge remote-tracking branch 'upstream/main' into danegsta/trustCerts
danegsta c6a94a2
Fix tests that don't expect custom certificates in output
danegsta 4ab71a5
Set as string
danegsta 987b977
Skip automatic config on conflict with manual config
danegsta aa61232
Update yarp tests
danegsta 91c924e
Fix another failing test after change
danegsta 5a07be9
Add test cases for default container cert behavior
danegsta 757c69a
Use a list
danegsta 51f2648
Fix last failing test
danegsta 8a1651e
Add examples to new API and additional helper method
danegsta c7c9e7b
Respond to PR feedback and ensure nodejs config works
danegsta 54ef7fb
Fix DcpExecutor test
danegsta bc1c117
Enable python https instrumentation
danegsta d42ed49
Remove extra using
danegsta dd1ba27
Add container certificate trust config
danegsta 4d34591
Merge remote-tracking branch 'upstream/main' into danegsta/trustCerts
danegsta 0434472
Fix failing tests due to options change
danegsta 16d7867
Respond to PR comments
danegsta c2b7a58
Add helper for loading certificates from an X509Store
danegsta 87c3baa
Add some additional examples
danegsta 3501ac2
Merge branch 'main' into danegsta/trustCerts
danegsta 8e9e267
Exclude dev certs from test
danegsta File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
12 changes: 12 additions & 0 deletions
12
playground/AspireWithPython/AspireWithPython.AppHost/Properties/launchSettings.json
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
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
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
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
41 changes: 41 additions & 0 deletions
41
src/Aspire.Hosting/ApplicationModel/CertificateAuthorityCollectionAnnotation.cs
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
namespace Aspire.Hosting.ApplicationModel; | ||
|
||
/// <summary> | ||
/// Defines the scope of custom certificate authorities for a resource. The default is <see cref="Append"/>. | ||
/// </summary> | ||
public enum CustomCertificateAuthoritiesScope | ||
{ | ||
/// <summary> | ||
/// Append the specified certificate authorities to the default set of trusted CAs for a resource. | ||
/// </summary> | ||
Append, | ||
/// <summary> | ||
/// Replace the default set of trusted CAs for a resource with the specified certificate authorities. | ||
/// </summary> | ||
Override, | ||
} | ||
|
||
/// <summary> | ||
/// An annotation that indicates a resource is referencing a certificate authority collection. | ||
/// </summary> | ||
public sealed class CertificateAuthorityCollectionAnnotation : IResourceAnnotation | ||
{ | ||
/// <summary> | ||
/// Gets the <see cref="global::CertificateAuthorityCollection"/> that is being referenced. | ||
/// </summary> | ||
public List<CertificateAuthorityCollection> CertificateAuthorityCollections { get; internal set; } = new List<CertificateAuthorityCollection>(); | ||
|
||
/// <summary> | ||
/// Gets a value indicating whether platform developer certificates should be considered trusted. | ||
/// </summary> | ||
public bool? TrustDeveloperCertificates { get; internal set; } | ||
|
||
/// <summary> | ||
/// Gets a value indicating whether the resource should attempt to override its default CA trust behavior in | ||
/// favor of the provided certificates (not all resources will support this). | ||
/// </summary> | ||
public CustomCertificateAuthoritiesScope? Scope { get; internal set; } | ||
} |
29 changes: 29 additions & 0 deletions
29
src/Aspire.Hosting/ApplicationModel/CertificateAuthorityCollectionResource.cs
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Security.Cryptography.X509Certificates; | ||
using Aspire.Hosting.ApplicationModel; | ||
|
||
/// <summary> | ||
/// Represents a collection of certificate authorities within the application model. | ||
/// </summary> | ||
/// <remarks> | ||
/// This class implements <see cref="IResourceWithoutLifetime"/> and provides access to | ||
/// the name and annotations associated with the certificate authority collection. | ||
/// </remarks> | ||
public class CertificateAuthorityCollection : Resource | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of the <see cref="CertificateAuthorityCollection"/> class with the specified name. | ||
/// </summary> | ||
/// <param name="name">The name of the certificate authority collection resource.</param> | ||
public CertificateAuthorityCollection(string name) : base(name) | ||
{ | ||
ArgumentNullException.ThrowIfNull(name); | ||
} | ||
|
||
/// <summary> | ||
/// Gets the <see cref="X509Certificate2Collection"/> of certificates for this resource. | ||
/// </summary> | ||
public X509Certificate2Collection Certificates { get; } = new(); | ||
} |
153 changes: 153 additions & 0 deletions
153
src/Aspire.Hosting/ApplicationModel/CertificateAuthorityCollectionResourceExtensions.cs
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Security.Cryptography.X509Certificates; | ||
|
||
namespace Aspire.Hosting.ApplicationModel; | ||
|
||
/// <summary> | ||
/// Provides extension methods for <see cref="CertificateAuthorityCollection"/>. | ||
/// </summary> | ||
public static class CertificateAuthorityCollectionResourceExtensions | ||
{ | ||
/// <summary> | ||
/// Adds a new <see cref="CertificateAuthorityCollection"/> to the application model. | ||
/// </summary> | ||
/// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param> | ||
/// <param name="name">The name of the certificate authority collection resource.</param> | ||
/// <returns>An <see cref="IResourceBuilder{CertificateAuthorityCollectionResource}"/> instance.</returns> | ||
public static IResourceBuilder<CertificateAuthorityCollection> AddCertificateAuthorityCollection(this IDistributedApplicationBuilder builder, [ResourceName] string name) | ||
{ | ||
ArgumentNullException.ThrowIfNull(builder); | ||
ArgumentNullException.ThrowIfNull(name); | ||
|
||
var resource = new CertificateAuthorityCollection(name); | ||
return builder.AddResource(resource); | ||
} | ||
|
||
/// <summary> | ||
/// Adds a certificate to the <see cref="CertificateAuthorityCollection.Certificates"/> collection. | ||
/// </summary> | ||
/// <param name="builder">The <see cref="IResourceBuilder{CertificateAuthorityCollectionResource}"/>.</param> | ||
/// <param name="certificate">The certificate to add.</param> | ||
/// <returns>The updated <see cref="IResourceBuilder{CertificateAuthorityCollectionResource}"/>.</returns> | ||
public static IResourceBuilder<CertificateAuthorityCollection> WithCertificate(this IResourceBuilder<CertificateAuthorityCollection> builder, X509Certificate2 certificate) | ||
{ | ||
ArgumentNullException.ThrowIfNull(builder); | ||
ArgumentNullException.ThrowIfNull(certificate); | ||
|
||
builder.Resource.Certificates.Add(certificate); | ||
return builder; | ||
} | ||
|
||
/// <summary> | ||
/// Adds a collection of certificates to the <see cref="CertificateAuthorityCollection.Certificates"/> collection. | ||
/// </summary> | ||
/// <param name="builder">The <see cref="IResourceBuilder{CertificateAuthorityCollectionResource}"/>.</param> | ||
/// <param name="certificates">The collection of certificates to add.</param> | ||
/// <returns>The updated <see cref="IResourceBuilder{CertificateAuthorityCollectionResource}"/>.</returns> | ||
public static IResourceBuilder<CertificateAuthorityCollection> WithCertificates(this IResourceBuilder<CertificateAuthorityCollection> builder, X509Certificate2Collection certificates) | ||
{ | ||
ArgumentNullException.ThrowIfNull(builder); | ||
ArgumentNullException.ThrowIfNull(certificates); | ||
|
||
builder.Resource.Certificates.AddRange(certificates); | ||
return builder; | ||
} | ||
|
||
/// <summary> | ||
/// Adds a collection of certificates to the <see cref="CertificateAuthorityCollection.Certificates"/> collection. | ||
/// </summary> | ||
/// <param name="builder">The <see cref="IResourceBuilder{CertificateAuthorityCollectionResource}"/>.</param> | ||
/// <param name="certificates">The collection of certificates to add.</param> | ||
/// <returns>The updated <see cref="IResourceBuilder{CertificateAuthorityCollectionResource}"/>.</returns> | ||
public static IResourceBuilder<CertificateAuthorityCollection> WithCertificates(this IResourceBuilder<CertificateAuthorityCollection> builder, IEnumerable<X509Certificate2> certificates) | ||
{ | ||
ArgumentNullException.ThrowIfNull(builder); | ||
ArgumentNullException.ThrowIfNull(certificates); | ||
|
||
builder.Resource.Certificates.AddRange(certificates.ToArray()); | ||
return builder; | ||
} | ||
|
||
/// <summary> | ||
/// Adds certificates from a certificate store to the <see cref="CertificateAuthorityCollection.Certificates"/> collection. | ||
/// </summary> | ||
/// <param name="builder">The <see cref="IResourceBuilder{CertificateAuthorityCollectionResource}"/>.</param> | ||
/// <param name="storeName">The name of the certificate store.</param> | ||
/// <param name="storeLocation">The location of the certificate store.</param> | ||
/// <param name="filter">An optional filter to apply to the certificates.</param> | ||
/// <returns>The updated <see cref="IResourceBuilder{CertificateAuthorityCollectionResource}"/>.</returns> | ||
/// <remarks> | ||
/// <example> | ||
/// This example adds all certificates from the "Root" store in the "LocalMachine" location. | ||
/// <code language="csharp"> | ||
/// builder.AddCertificateAuthorityCollection("my-ca") | ||
/// .WithCertificatesFromStore(StoreName.Root, StoreLocation.LocalMachine); | ||
/// </code> | ||
/// </example> | ||
/// <example> | ||
/// This example adds only certificates that are not expired from the "My" store in the "CurrentUser" location. | ||
/// <code language="csharp"> | ||
/// builder.AddCertificateAuthorityCollection("my-ca") | ||
/// .WithCertificatesFromStore(StoreName.My, StoreLocation.CurrentUser, c => c.NotAfter > DateTime.UtcNow); | ||
/// </code> | ||
/// </example> | ||
/// </remarks> | ||
public static IResourceBuilder<CertificateAuthorityCollection> WithCertificatesFromStore(this IResourceBuilder<CertificateAuthorityCollection> builder, StoreName storeName, StoreLocation storeLocation, Func<X509Certificate2, bool>? filter = null) | ||
{ | ||
ArgumentNullException.ThrowIfNull(builder); | ||
|
||
using var store = new X509Store(storeName, storeLocation); | ||
store.Open(OpenFlags.ReadOnly); | ||
var certificates = store.Certificates as IEnumerable<X509Certificate2>; | ||
if (filter != null) | ||
{ | ||
certificates = certificates.Where(filter); | ||
} | ||
builder.Resource.Certificates.AddRange(certificates.ToArray()); | ||
return builder; | ||
} | ||
|
||
/// <summary> | ||
/// Adds certificates from a PEM file to the <see cref="CertificateAuthorityCollection.Certificates"/> collection. | ||
/// </summary> | ||
/// <param name="builder">The <see cref="IResourceBuilder{CertificateAuthorityCollection}"/>.</param> | ||
/// <param name="pemFilePath">The path to the PEM file.</param> | ||
/// <param name="filter">An optional filter to apply to the loaded certificates before they are added to the collection.</param> | ||
/// <returns>The updated <see cref="IResourceBuilder{CertificateAuthorityCollection}"/>.</returns> | ||
/// <remarks> | ||
/// <example> | ||
/// This example adds certificates from a PEM file located at "../path/to/certificates.pem". | ||
/// <code language="csharp"> | ||
/// builder.AddCertificateAuthorityCollection("my-ca") | ||
/// .WithCertificatesFromFile("../path/to/certificates.pem"); | ||
/// </code> | ||
/// </example> | ||
/// <example> | ||
/// This example adds only certificates that are not expired from a PEM file located at "../path/to/certificates.pem". | ||
/// <code language="csharp"> | ||
/// builder.AddCertificateAuthorityCollection("my-ca") | ||
/// .WithCertificatesFromFile("../path/to/certificates.pem", c => c.NotAfter > DateTime.UtcNow); | ||
/// </code> | ||
/// </example> | ||
/// </remarks> | ||
public static IResourceBuilder<CertificateAuthorityCollection> WithCertificatesFromFile(this IResourceBuilder<CertificateAuthorityCollection> builder, string pemFilePath, Func<X509Certificate2, bool>? filter = null) | ||
{ | ||
ArgumentNullException.ThrowIfNull(builder); | ||
ArgumentNullException.ThrowIfNull(pemFilePath); | ||
|
||
var certificates = new X509Certificate2Collection(); | ||
certificates.ImportFromPemFile(pemFilePath); | ||
if (filter != null) | ||
{ | ||
builder.WithCertificates(certificates.Where(filter).ToArray()); | ||
} | ||
else | ||
{ | ||
builder.WithCertificates(certificates); | ||
} | ||
|
||
return builder; | ||
} | ||
} |
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.