From ffed84042c22548bb027df63ca3e70e669121486 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Oct 2025 15:07:50 +0000 Subject: [PATCH 1/6] Initial plan From 30afc349136a94a6c7bfc3af9a9502193ce5082d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Oct 2025 15:13:16 +0000 Subject: [PATCH 2/6] Add certificate trust customization article Co-authored-by: IEvangelist <7679720+IEvangelist@users.noreply.github.com> --- docs/app-host/certificate-trust.md | 254 +++++++++++++++++++++++++++++ docs/toc.yml | 3 + 2 files changed, 257 insertions(+) create mode 100644 docs/app-host/certificate-trust.md diff --git a/docs/app-host/certificate-trust.md b/docs/app-host/certificate-trust.md new file mode 100644 index 0000000000..d4cd9a5c8c --- /dev/null +++ b/docs/app-host/certificate-trust.md @@ -0,0 +1,254 @@ +--- +title: Certificate trust customization in Aspire +description: Learn how to customize trusted certificates for Executable and Container resources in Aspire to enable secure communication. +ms.date: 10/20/2025 +ai-usage: ai-assisted +--- + +# Certificate trust customization in Aspire + +In Aspire, you can customize which certificates resources consider trusted for TLS/HTTPS traffic. This is particularly useful for resources that don't use the system's root trusted certificates by default, such as containerized applications, Python apps, and Node.js apps. By configuring certificate trust, you enable these resources to communicate securely with services that use certificates they wouldn't otherwise trust, including the Aspire dashboard's OTLP endpoint. + +## When to use certificate trust customization + +Certificate trust customization is valuable when: + +- Resources need to trust the ASP.NET Core Development Certificate for local HTTPS communication. +- Containerized services must communicate with the dashboard over HTTPS. +- Python or Node.js applications need to trust custom certificate authorities. +- You're working with services that have specific certificate trust requirements. +- Resources need to establish secure telemetry connections to the Aspire dashboard. + +## Development certificate trust + +By default, Aspire attempts to add trust for the ASP.NET Core Development Certificate to resources that wouldn't otherwise trust it. This enables resources to communicate with the dashboard OTEL collector endpoint over HTTPS and any other HTTPS endpoints secured by the development certificate. + +You can control this behavior at the per-resource level using the `WithDeveloperCertificateTrust` API or through AppHost configuration settings. + +### Configure development certificate trust per resource + +To explicitly enable or disable development certificate trust for a specific resource: + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +// Explicitly enable development certificate trust +var nodeApp = builder.AddNpmApp("frontend", "../frontend") + .WithDeveloperCertificateTrust(enabled: true); + +// Disable development certificate trust +var pythonApp = builder.AddPythonApp("api", "../api", "main.py") + .WithDeveloperCertificateTrust(enabled: false); + +builder.Build().Run(); +``` + +## Certificate authority collections + +Certificate authority collections allow you to bundle custom certificates and make them available to resources. You create a collection using the `AddCertificateAuthorityCollection` method and then reference it from resources that need to trust those certificates. + +### Create and use a certificate authority collection + +```csharp +using System.Security.Cryptography.X509Certificates; + +var builder = DistributedApplication.CreateBuilder(args); + +// Load your custom certificates +var certificates = new X509Certificate2Collection(); +certificates.Import("path/to/certificate.pem"); + +// Create a certificate authority collection +var certBundle = builder.AddCertificateAuthorityCollection("my-bundle") + .WithCertificates(certificates); + +// Apply the certificate bundle to resources +builder.AddNpmApp("my-project", "../myapp") + .WithCertificateAuthorityCollection(certBundle); + +builder.Build().Run(); +``` + +In the preceding example, the certificate bundle is created with custom certificates and then applied to a Node.js application, enabling it to trust those certificates. + +## Certificate trust scopes + +Certificate trust scopes control how custom certificates interact with a resource's default trusted certificates. Different scopes provide flexibility in managing certificate trust based on your application's requirements. + +The `WithCertificateTrustScope` API accepts a value to specify the trust behavior: + +### Append mode + +Attempts to append the configured certificates to the default trusted certificates for a given resource. This mode is useful when you want to add trust for additional certificates while maintaining trust for the system's default certificates. + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +builder.AddNodeApp("api", "../api") + .WithCertificateTrustScope(CertificateTrustScope.Append); + +builder.Build().Run(); +``` + +> [!NOTE] +> Not all languages and runtimes support Append mode. For example, Python doesn't natively support appending certificates to the default trust store. + +### Override mode + +Attempts to override a resource to only trust the configured certificates, replacing the default trusted certificates entirely. This mode is useful when you need strict control over which certificates are trusted. + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +var certBundle = builder.AddCertificateAuthorityCollection("custom-certs") + .WithCertificates(myCertificates); + +builder.AddPythonModule("api", "./api", "uvicorn") + .WithCertificateAuthorityCollection(certBundle) + .WithCertificateTrustScope(CertificateTrustScope.Override); + +builder.Build().Run(); +``` + +### System mode + +Attempts to combine the configured certificates with the default system root certificates and use them to override the default trusted certificates for a resource. This mode is intended to support Python or other languages that don't work well with Append mode. + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +builder.AddPythonApp("worker", "../worker", "main.py") + .WithCertificateTrustScope(CertificateTrustScope.System); + +builder.Build().Run(); +``` + +### None mode + +Disables all custom certificate trust for the resource, causing it to rely solely on its default certificate trust behavior. + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +builder.AddContainer("service", "myimage") + .WithCertificateTrustScope(CertificateTrustScope.None); + +builder.Build().Run(); +``` + +## Custom certificate trust callbacks + +For advanced scenarios, you can specify custom certificate trust behavior using callback APIs. These callbacks allow you to customize how certificates are configured for different resource types. + +### Executable resource certificate trust + +Use `WithExecutableCertificateTrustCallback` to customize certificate trust for executable resources: + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +builder.AddExecutable("custom-app", "myapp", ".") + .WithExecutableCertificateTrustCallback((certificates, args) => + { + // Customize command line arguments + args.Add("--ca-file"); + args.Add("/path/to/ca-bundle.pem"); + + // Set environment variables + // Environment variables can be set through the resource builder + }); + +builder.Build().Run(); +``` + +The callback provides access to the certificate collection and allows you to specify command-line arguments required to configure trusted certificates. + +### Container resource certificate trust + +Use `WithContainerCertificateTrustCallback` to customize certificate trust for container resources: + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +builder.AddContainer("api", "myimage") + .WithContainerCertificateTrustCallback((certificates, containerConfig) => + { + // Customize container certificate paths + containerConfig.CertificatePath = "/custom/certs/path"; + + // Add environment variables for certificate configuration + containerConfig.EnvironmentVariables["SSL_CERT_FILE"] = "/custom/certs/ca-bundle.pem"; + }); + +builder.Build().Run(); +``` + +Default implementations are provided for Node.js, Python, and container resources. Container resources rely on standard OpenSSL configuration options, with default values that support the majority of common Linux distributions. You can override these defaults if necessary. + +## Common scenarios + +### Enable HTTPS telemetry to the dashboard + +By default, Aspire enables development certificate trust for resources, allowing them to send telemetry to the dashboard over HTTPS: + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +// Development certificate trust is enabled by default +var nodeApp = builder.AddNpmApp("frontend", "../frontend"); +var pythonApp = builder.AddPythonApp("api", "../api", "main.py"); + +builder.Build().Run(); +``` + +### Trust custom certificates in containers + +When working with containerized services that need to trust custom certificates: + +```csharp +using System.Security.Cryptography.X509Certificates; + +var builder = DistributedApplication.CreateBuilder(args); + +// Load custom CA certificates +var customCerts = new X509Certificate2Collection(); +customCerts.Import("corporate-ca.pem"); + +var certBundle = builder.AddCertificateAuthorityCollection("corporate-certs") + .WithCertificates(customCerts); + +// Apply to container +builder.AddContainer("service", "myservice:latest") + .WithCertificateAuthorityCollection(certBundle); + +builder.Build().Run(); +``` + +### Configure Python apps with certificate trust + +Python applications require special handling due to their certificate trust model: + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +// Use System mode for Python apps +builder.AddPythonModule("api", "./api", "uvicorn") + .WithCertificateTrustScope(CertificateTrustScope.System); + +builder.Build().Run(); +``` + +## Limitations + +Certificate trust customization has the following limitations: + +- Currently supported only in run mode, not in publish mode. +- Not all languages and runtimes support all trust scope modes. +- Python applications don't natively support Append mode. +- Custom certificate trust requires appropriate runtime support within the resource. + +## See also + +- [Host external executables in Aspire](executable-resources.md) +- [Add Dockerfiles to the app model](withdockerfile.md) +- [AppHost configuration](configuration.md) diff --git a/docs/toc.yml b/docs/toc.yml index ae30c9bd56..a738c02be1 100644 --- a/docs/toc.yml +++ b/docs/toc.yml @@ -57,6 +57,9 @@ items: href: get-started/build-aspire-apps-with-python.md - name: AppHost configuration href: app-host/configuration.md + - name: Certificate trust customization + href: app-host/certificate-trust.md + displayName: certificate trust,TLS,HTTPS,development certificate,certificate authority - name: Customize resources items: - name: Persistent container services From babc66121e3e9b7e129cba38577465b5f5aaf9e0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Oct 2025 15:18:38 +0000 Subject: [PATCH 3/6] Fix cross-reference title to match actual article title Co-authored-by: IEvangelist <7679720+IEvangelist@users.noreply.github.com> --- docs/app-host/certificate-trust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/app-host/certificate-trust.md b/docs/app-host/certificate-trust.md index d4cd9a5c8c..f907550fb7 100644 --- a/docs/app-host/certificate-trust.md +++ b/docs/app-host/certificate-trust.md @@ -250,5 +250,5 @@ Certificate trust customization has the following limitations: ## See also - [Host external executables in Aspire](executable-resources.md) -- [Add Dockerfiles to the app model](withdockerfile.md) +- [Add Dockerfiles to your .NET app model](withdockerfile.md) - [AppHost configuration](configuration.md) From 6f6d732a539d2784224a660346cf147e6a360d4b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Oct 2025 23:51:16 +0000 Subject: [PATCH 4/6] Address PR feedback: update API examples, add runtime callout, document default scopes Co-authored-by: IEvangelist <7679720+IEvangelist@users.noreply.github.com> --- docs/app-host/certificate-trust.md | 59 ++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/docs/app-host/certificate-trust.md b/docs/app-host/certificate-trust.md index f907550fb7..5d9f0ad1ed 100644 --- a/docs/app-host/certificate-trust.md +++ b/docs/app-host/certificate-trust.md @@ -9,6 +9,9 @@ ai-usage: ai-assisted In Aspire, you can customize which certificates resources consider trusted for TLS/HTTPS traffic. This is particularly useful for resources that don't use the system's root trusted certificates by default, such as containerized applications, Python apps, and Node.js apps. By configuring certificate trust, you enable these resources to communicate securely with services that use certificates they wouldn't otherwise trust, including the Aspire dashboard's OTLP endpoint. +> [!IMPORTANT] +> Certificate trust customization only applies at run time. Custom certificates aren't included in publish or deployment artifacts. + ## When to use certificate trust customization Certificate trust customization is valuable when: @@ -34,11 +37,11 @@ var builder = DistributedApplication.CreateBuilder(args); // Explicitly enable development certificate trust var nodeApp = builder.AddNpmApp("frontend", "../frontend") - .WithDeveloperCertificateTrust(enabled: true); + .WithDeveloperCertificateTrust(trust: true); // Disable development certificate trust var pythonApp = builder.AddPythonApp("api", "../api", "main.py") - .WithDeveloperCertificateTrust(enabled: false); + .WithDeveloperCertificateTrust(trust: false); builder.Build().Run(); ``` @@ -56,7 +59,7 @@ var builder = DistributedApplication.CreateBuilder(args); // Load your custom certificates var certificates = new X509Certificate2Collection(); -certificates.Import("path/to/certificate.pem"); +certificates.ImportFromPemFile("path/to/certificate.pem"); // Create a certificate authority collection var certBundle = builder.AddCertificateAuthorityCollection("my-bundle") @@ -75,7 +78,15 @@ In the preceding example, the certificate bundle is created with custom certific Certificate trust scopes control how custom certificates interact with a resource's default trusted certificates. Different scopes provide flexibility in managing certificate trust based on your application's requirements. -The `WithCertificateTrustScope` API accepts a value to specify the trust behavior: +The `WithCertificateTrustScope` API accepts a value to specify the trust behavior. + +### Default trust scopes + +Different resource types have different default trust scopes: + +- **Append**: The default for most resources, appending custom certificates to the default trusted certificates. +- **System**: The default for Python projects, which combines custom certificates with system root certificates because Python doesn't properly support Append mode. +- **None**: The default for .NET projects on Windows, as there's no way to automatically change the default system store source. ### Append mode @@ -148,14 +159,16 @@ Use `WithExecutableCertificateTrustCallback` to customize certificate trust for var builder = DistributedApplication.CreateBuilder(args); builder.AddExecutable("custom-app", "myapp", ".") - .WithExecutableCertificateTrustCallback((certificates, args) => + .WithExecutableCertificateTrustCallback((ctx) => { - // Customize command line arguments - args.Add("--ca-file"); - args.Add("/path/to/ca-bundle.pem"); + // Add a command line argument that must be set to enable custom certificates + ctx.CertificateTrustArguments.Add("--use-custom-ca"); - // Set environment variables - // Environment variables can be set through the resource builder + // Add a command line argument that expects the path to a bundle (single file) of the custom CA certificates + ctx.CertificateBundleArguments.Add("--ca-file"); + + // Add an environment variable that expects the path to a bundle (single file) of the custom CA certificates + ctx.CertificateBundleEnvironment.Add("EXTRA_CA_BUNDLE"); }); builder.Build().Run(); @@ -171,13 +184,21 @@ Use `WithContainerCertificateTrustCallback` to customize certificate trust for c var builder = DistributedApplication.CreateBuilder(args); builder.AddContainer("api", "myimage") - .WithContainerCertificateTrustCallback((certificates, containerConfig) => + .WithContainerCertificateTrustCallback((ctx) => { - // Customize container certificate paths - containerConfig.CertificatePath = "/custom/certs/path"; + // Override the path to default individual certificates in the container (this is a list of common certificate paths for various Linux distros by default) + // This should only need to be updated if your container has certificates in non-standard paths + ctx.DefaultContainerCertificatesDirectoryPaths.Clear(); + ctx.DefaultContainerCertificatesDirectoryPaths.Add("/path/to/custom/certs"); + + // Same as above, by default this is a collection of the default locations of the system certificate authority bundle file for common Linux distros + // You should only need to customize this if your image uses non-standard certificate paths + ctx.DefaultContainerCertificateAuthorityBundlePaths.Clear(); + ctx.DefaultContainerCertificateAuthorityBundlePaths.Add("/path/to/custom/certbundle.pem"); - // Add environment variables for certificate configuration - containerConfig.EnvironmentVariables["SSL_CERT_FILE"] = "/custom/certs/ca-bundle.pem"; + // Add environment variables that should be set with a path to the additional CA certificates as its value + // By default this includes "SSL_CERT_DIR" for OpenSSL compatibility + ctx.CertificatesDirectoryEnvironment.Add("EXTRA_CERTS"); }); builder.Build().Run(); @@ -224,16 +245,16 @@ builder.AddContainer("service", "myservice:latest") builder.Build().Run(); ``` -### Configure Python apps with certificate trust +### Disable certificate trust for Python apps -Python applications require special handling due to their certificate trust model: +Python projects use System mode by default. To disable certificate trust customization for a Python app: ```csharp var builder = DistributedApplication.CreateBuilder(args); -// Use System mode for Python apps +// Disable certificate trust for Python apps builder.AddPythonModule("api", "./api", "uvicorn") - .WithCertificateTrustScope(CertificateTrustScope.System); + .WithCertificateTrustScope(CertificateTrustScope.None); builder.Build().Run(); ``` From 30ab01a476af762d946bcc21732f8c25d643fcb6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Oct 2025 19:29:40 +0000 Subject: [PATCH 5/6] Update callback APIs to use async Task and simplified context objects Co-authored-by: IEvangelist <7679720+IEvangelist@users.noreply.github.com> --- docs/app-host/certificate-trust.md | 52 ++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/docs/app-host/certificate-trust.md b/docs/app-host/certificate-trust.md index 5d9f0ad1ed..e000c394c5 100644 --- a/docs/app-host/certificate-trust.md +++ b/docs/app-host/certificate-trust.md @@ -159,7 +159,7 @@ Use `WithExecutableCertificateTrustCallback` to customize certificate trust for var builder = DistributedApplication.CreateBuilder(args); builder.AddExecutable("custom-app", "myapp", ".") - .WithExecutableCertificateTrustCallback((ctx) => + .WithExecutableCertificateTrustCallback(async (ctx) => { // Add a command line argument that must be set to enable custom certificates ctx.CertificateTrustArguments.Add("--use-custom-ca"); @@ -169,12 +169,24 @@ builder.AddExecutable("custom-app", "myapp", ".") // Add an environment variable that expects the path to a bundle (single file) of the custom CA certificates ctx.CertificateBundleEnvironment.Add("EXTRA_CA_BUNDLE"); + + // Add an environment variable that expects the path to a directory containing CA certificates + ctx.CertificatesDirectoryEnvironment.Add("EXTRA_CERTS_DIR"); + + await Task.CompletedTask; }); builder.Build().Run(); ``` -The callback provides access to the certificate collection and allows you to specify command-line arguments required to configure trusted certificates. +The callback receives an `ExecutableCertificateTrustCallbackAnnotationContext` that provides: + +- `Certificates`: The `X509Certificate2Collection` of certificates for this resource. +- `Scope`: The `CertificateTrustScope` of trust for the resource. +- `CertificateTrustArguments`: Command line arguments required to enable certificate trust. +- `CertificateBundleArguments`: Command line arguments that will be combined with the path to the custom certificates bundle. +- `CertificateBundleEnvironment`: Environment variable names that will be set with the path to the custom certificates bundle. +- `CertificatesDirectoryEnvironment`: Environment variable names that will be set with paths to directories containing CA certificates to trust. ### Container resource certificate trust @@ -184,26 +196,46 @@ Use `WithContainerCertificateTrustCallback` to customize certificate trust for c var builder = DistributedApplication.CreateBuilder(args); builder.AddContainer("api", "myimage") - .WithContainerCertificateTrustCallback((ctx) => + .WithContainerCertificateTrustCallback(async (ctx) => { - // Override the path to default individual certificates in the container (this is a list of common certificate paths for various Linux distros by default) - // This should only need to be updated if your container has certificates in non-standard paths - ctx.DefaultContainerCertificatesDirectoryPaths.Clear(); - ctx.DefaultContainerCertificatesDirectoryPaths.Add("/path/to/custom/certs"); + // Customize the path where custom certificates will be placed in the container + // Defaults to /usr/lib/ssl/aspire + ctx.CustomCertificatesContainerFilePath = "/custom/certs/path"; - // Same as above, by default this is a collection of the default locations of the system certificate authority bundle file for common Linux distros - // You should only need to customize this if your image uses non-standard certificate paths + // Override the default container certificate authority bundle paths + // This is a list of common certificate paths for various Linux distros by default + // You should only need to update this if your container has certificates in non-standard paths ctx.DefaultContainerCertificateAuthorityBundlePaths.Clear(); ctx.DefaultContainerCertificateAuthorityBundlePaths.Add("/path/to/custom/certbundle.pem"); - // Add environment variables that should be set with a path to the additional CA certificates as its value + // Override the default container certificates directory paths + // By default this is a collection of common certificate directory paths for various Linux distros + // You should only need to customize this if your image uses non-standard certificate paths + ctx.DefaultContainerCertificatesDirectoryPaths.Clear(); + ctx.DefaultContainerCertificatesDirectoryPaths.Add("/path/to/custom/certs/dir"); + + // Add environment variables that should be set with a path to the additional CA certificates directory as its value // By default this includes "SSL_CERT_DIR" for OpenSSL compatibility ctx.CertificatesDirectoryEnvironment.Add("EXTRA_CERTS"); + + await Task.CompletedTask; }); builder.Build().Run(); ``` +The callback receives a `ContainerCertificateTrustCallbackAnnotationContext` that provides: + +- `Certificates`: The `X509Certificate2Collection` of certificates for this resource. +- `Scope`: The `CertificateTrustScope` of trust for the resource. +- `CustomCertificatesContainerFilePath`: The path in the container where custom certificates will be placed (defaults to `/usr/lib/ssl/aspire`). +- `DefaultContainerCertificateAuthorityBundlePaths`: List of default certificate bundle files in the container that will be replaced in Override mode. +- `DefaultContainerCertificatesDirectoryPaths`: List of default certificate directories in the container that will be appended to in Append mode. +- `CertificateTrustArguments`: Command line arguments required to enable certificate trust. +- `CertificateBundleArguments`: Command line arguments that will be combined with the path to the custom certificates bundle. +- `CertificateBundleEnvironment`: Environment variable names that will be set with the path to the custom certificates bundle. +- `CertificatesDirectoryEnvironment`: Environment variable names that will be set with paths to directories containing CA certificates (defaults include `SSL_CERT_DIR` for OpenSSL compatibility). + Default implementations are provided for Node.js, Python, and container resources. Container resources rely on standard OpenSSL configuration options, with default values that support the majority of common Linux distributions. You can override these defaults if necessary. ## Common scenarios From 9d886255a94930055a382178d37452f8cfe94223 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Oct 2025 17:53:26 +0000 Subject: [PATCH 6/6] Replace deprecated callback APIs with new simplified APIs Co-authored-by: IEvangelist <7679720+IEvangelist@users.noreply.github.com> --- docs/app-host/certificate-trust.md | 92 +++++++++++------------------- 1 file changed, 33 insertions(+), 59 deletions(-) diff --git a/docs/app-host/certificate-trust.md b/docs/app-host/certificate-trust.md index e000c394c5..a61da6994a 100644 --- a/docs/app-host/certificate-trust.md +++ b/docs/app-host/certificate-trust.md @@ -147,31 +147,29 @@ builder.AddContainer("service", "myimage") builder.Build().Run(); ``` -## Custom certificate trust callbacks +## Custom certificate trust configuration -For advanced scenarios, you can specify custom certificate trust behavior using callback APIs. These callbacks allow you to customize how certificates are configured for different resource types. +For advanced scenarios, you can specify custom certificate trust behavior using a callback API. This callback allows you to customize the command line arguments and environment variables required to configure certificate trust for different resource types. -### Executable resource certificate trust +### Configure certificate trust with a callback -Use `WithExecutableCertificateTrustCallback` to customize certificate trust for executable resources: +Use `WithCertificateTrustConfiguration` to customize how certificate trust is configured for a resource: ```csharp var builder = DistributedApplication.CreateBuilder(args); -builder.AddExecutable("custom-app", "myapp", ".") - .WithExecutableCertificateTrustCallback(async (ctx) => +builder.AddContainer("api", "myimage") + .WithCertificateTrustConfiguration(async (ctx) => { - // Add a command line argument that must be set to enable custom certificates - ctx.CertificateTrustArguments.Add("--use-custom-ca"); - - // Add a command line argument that expects the path to a bundle (single file) of the custom CA certificates - ctx.CertificateBundleArguments.Add("--ca-file"); + // Add a command line argument + ctx.Arguments.Add("--use-system-ca"); - // Add an environment variable that expects the path to a bundle (single file) of the custom CA certificates - ctx.CertificateBundleEnvironment.Add("EXTRA_CA_BUNDLE"); + // Set environment variables with certificate paths + // CertificateBundlePath resolves to the path of the custom certificate bundle file + ctx.EnvironmentVariables["MY_CUSTOM_CERT_VAR"] = ctx.CertificateBundlePath; - // Add an environment variable that expects the path to a directory containing CA certificates - ctx.CertificatesDirectoryEnvironment.Add("EXTRA_CERTS_DIR"); + // CertificateDirectoriesPath resolves to paths containing individual certificates + ctx.EnvironmentVariables["CERTS_DIR"] = ctx.CertificateDirectoriesPath; await Task.CompletedTask; }); @@ -179,64 +177,40 @@ builder.AddExecutable("custom-app", "myapp", ".") builder.Build().Run(); ``` -The callback receives an `ExecutableCertificateTrustCallbackAnnotationContext` that provides: +The callback receives a `CertificateTrustConfigurationCallbackAnnotationContext` that provides: + +- `Scope`: The `CertificateTrustScope` for the resource. +- `Arguments`: Command line arguments for the resource. Values can be strings or path providers like `CertificateBundlePath` or `CertificateDirectoriesPath`. +- `EnvironmentVariables`: Environment variables for configuring certificate trust. The dictionary key is the environment variable name; values can be strings or path providers. By default, includes `SSL_CERT_DIR` and may include `SSL_CERT_FILE` if Override or System scope is configured. +- `CertificateBundlePath`: A value provider that resolves to the path of a custom certificate bundle file. +- `CertificateDirectoriesPath`: A value provider that resolves to paths containing individual certificates. -- `Certificates`: The `X509Certificate2Collection` of certificates for this resource. -- `Scope`: The `CertificateTrustScope` of trust for the resource. -- `CertificateTrustArguments`: Command line arguments required to enable certificate trust. -- `CertificateBundleArguments`: Command line arguments that will be combined with the path to the custom certificates bundle. -- `CertificateBundleEnvironment`: Environment variable names that will be set with the path to the custom certificates bundle. -- `CertificatesDirectoryEnvironment`: Environment variable names that will be set with paths to directories containing CA certificates to trust. +Default implementations are provided for Node.js, Python, and container resources. Container resources rely on standard OpenSSL configuration options, with default values that support the majority of common Linux distributions. -### Container resource certificate trust +### Configure container certificate paths -Use `WithContainerCertificateTrustCallback` to customize certificate trust for container resources: +For container resources, you can customize where certificates are stored and accessed using `WithContainerCertificatePaths`: ```csharp var builder = DistributedApplication.CreateBuilder(args); builder.AddContainer("api", "myimage") - .WithContainerCertificateTrustCallback(async (ctx) => - { - // Customize the path where custom certificates will be placed in the container - // Defaults to /usr/lib/ssl/aspire - ctx.CustomCertificatesContainerFilePath = "/custom/certs/path"; - - // Override the default container certificate authority bundle paths - // This is a list of common certificate paths for various Linux distros by default - // You should only need to update this if your container has certificates in non-standard paths - ctx.DefaultContainerCertificateAuthorityBundlePaths.Clear(); - ctx.DefaultContainerCertificateAuthorityBundlePaths.Add("/path/to/custom/certbundle.pem"); - - // Override the default container certificates directory paths - // By default this is a collection of common certificate directory paths for various Linux distros - // You should only need to customize this if your image uses non-standard certificate paths - ctx.DefaultContainerCertificatesDirectoryPaths.Clear(); - ctx.DefaultContainerCertificatesDirectoryPaths.Add("/path/to/custom/certs/dir"); - - // Add environment variables that should be set with a path to the additional CA certificates directory as its value - // By default this includes "SSL_CERT_DIR" for OpenSSL compatibility - ctx.CertificatesDirectoryEnvironment.Add("EXTRA_CERTS"); - - await Task.CompletedTask; - }); + .WithContainerCertificatePaths( + customCertificatesDestination: "/custom/certs/path", + defaultCertificateBundlePaths: ["/etc/ssl/certs/ca-certificates.crt"], + defaultCertificateDirectoryPaths: ["/etc/ssl/certs"]); builder.Build().Run(); ``` -The callback receives a `ContainerCertificateTrustCallbackAnnotationContext` that provides: +The `WithContainerCertificatePaths` API accepts three optional parameters: -- `Certificates`: The `X509Certificate2Collection` of certificates for this resource. -- `Scope`: The `CertificateTrustScope` of trust for the resource. -- `CustomCertificatesContainerFilePath`: The path in the container where custom certificates will be placed (defaults to `/usr/lib/ssl/aspire`). -- `DefaultContainerCertificateAuthorityBundlePaths`: List of default certificate bundle files in the container that will be replaced in Override mode. -- `DefaultContainerCertificatesDirectoryPaths`: List of default certificate directories in the container that will be appended to in Append mode. -- `CertificateTrustArguments`: Command line arguments required to enable certificate trust. -- `CertificateBundleArguments`: Command line arguments that will be combined with the path to the custom certificates bundle. -- `CertificateBundleEnvironment`: Environment variable names that will be set with the path to the custom certificates bundle. -- `CertificatesDirectoryEnvironment`: Environment variable names that will be set with paths to directories containing CA certificates (defaults include `SSL_CERT_DIR` for OpenSSL compatibility). +- `customCertificatesDestination`: Overrides the base path in the container where custom certificate files are placed. If not set or set to `null`, the default path of `/usr/lib/ssl/aspire` is used. +- `defaultCertificateBundlePaths`: Overrides the path(s) in the container where a default certificate authority bundle file is located. When the `CertificateTrustScope` is Override or System, the custom certificate bundle is additionally written to these paths. If not set or set to `null`, a set of default certificate paths for common Linux distributions is used. +- `defaultCertificateDirectoryPaths`: Overrides the path(s) in the container where individual trusted certificate files are found. When the `CertificateTrustScope` is Append, these paths are concatenated with the path to the uploaded certificate artifacts. If not set or set to `null`, a set of default certificate paths for common Linux distributions is used. -Default implementations are provided for Node.js, Python, and container resources. Container resources rely on standard OpenSSL configuration options, with default values that support the majority of common Linux distributions. You can override these defaults if necessary. +> [!NOTE] +> All desired paths must be configured in a single call to `WithContainerCertificatePaths` as only the most recent call to the API is honored. ## Common scenarios