Skip to content

Instantly share code, notes, and snippets.

@davidfowl
Created August 12, 2025 12:21
Show Gist options
  • Save davidfowl/12adb8ae6c44e0df924476e8e966b5bf to your computer and use it in GitHub Desktop.
Save davidfowl/12adb8ae6c44e0df924476e8e966b5bf to your computer and use it in GitHub Desktop.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.IO;
namespace Aspire.Hosting;
public static class DevCertHostingExtensions
{
/// <summary>
/// Injects the ASP.NET Core HTTPS developer certificate into the resource via the specified environment variables when
/// <paramref name="builder"/>.<see cref="IResourceBuilder{T}.ApplicationBuilder">ApplicationBuilder</see>.<see cref="IDistributedApplicationBuilder.ExecutionContext">ExecutionContext</see>.<see cref="DistributedApplicationExecutionContext.IsRunMode">IsRunMode</see><c> == true</c>.<br/>
/// If the resource is a <see cref="ContainerResource"/>, the certificate files will be provided via WithContainerFiles.
/// </summary>
/// <remarks>
/// This method <strong>does not</strong> configure an HTTPS endpoint on the resource.
/// Use <see cref="ResourceBuilderExtensions.WithHttpsEndpoint{TResource}"/> to configure an HTTPS endpoint.
/// </remarks>
public static IResourceBuilder<TResource> RunWithHttpsDevCertificate<TResource>(
this IResourceBuilder<TResource> builder, string certFileEnv, string certKeyFileEnv)
where TResource : IResourceWithEnvironment, IResourceWithWaitSupport
{
if (!builder.ApplicationBuilder.ExecutionContext.IsRunMode)
{
return builder;
}
// Create temp directory for certificate export
var tempDir = Directory.CreateTempSubdirectory("aspire-dev-certs");
var certExportPath = Path.Combine(tempDir.FullName, "dev-cert.pem");
var certKeyExportPath = Path.Combine(tempDir.FullName, "dev-cert.key");
// Create a unique resource name for the certificate export
var exportResourceName = $"dev-cert-export";
// Check if we already have a certificate export resource
var existingResource = builder.ApplicationBuilder.Resources.FirstOrDefault(r => r.Name == exportResourceName);
IResourceBuilder<ExecutableResource> exportExecutable;
if (existingResource == null)
{
// Create the executable resource to export the certificate
exportExecutable = builder.ApplicationBuilder
.AddExecutable(exportResourceName, "dotnet", tempDir.FullName)
.WithEnvironment("DOTNET_CLI_UI_LANGUAGE", "en") // Ensure consistent output language
.WithArgs(context =>
{
context.Args.Add("dev-certs");
context.Args.Add("https");
context.Args.Add("--export-path");
context.Args.Add(certExportPath);
context.Args.Add("--format");
context.Args.Add("Pem");
context.Args.Add("--no-password");
});
}
else
{
exportExecutable = builder.ApplicationBuilder.CreateResourceBuilder((ExecutableResource)existingResource);
}
builder.WaitForCompletion(exportExecutable);
// Configure the current resource with the certificate paths
if (builder.Resource is ContainerResource containerResource)
{
// Use WithContainerFiles to provide the certificate files to the container
const string DEV_CERT_BIND_MOUNT_DEST_DIR = "/dev-certs";
const string CERT_FILE_NAME = "dev-cert.pem";
const string CERT_KEY_FILE_NAME = "dev-cert.key";
var certFileDest = $"{DEV_CERT_BIND_MOUNT_DEST_DIR}/{CERT_FILE_NAME}";
var certKeyFileDest = $"{DEV_CERT_BIND_MOUNT_DEST_DIR}/{CERT_KEY_FILE_NAME}";
builder.ApplicationBuilder.CreateResourceBuilder(containerResource)
.WithContainerFiles(DEV_CERT_BIND_MOUNT_DEST_DIR, (context, cancellationToken) =>
{
var files = new List<ContainerFile>();
// Check if certificate files exist before adding them
if (File.Exists(certExportPath))
{
files.Add(new ContainerFile
{
Name = CERT_FILE_NAME,
SourcePath = certExportPath
});
}
if (File.Exists(certKeyExportPath))
{
files.Add(new ContainerFile
{
Name = CERT_KEY_FILE_NAME,
SourcePath = certKeyExportPath
});
}
return Task.FromResult(files.AsEnumerable<ContainerFileSystemItem>());
})
.WithEnvironment(certFileEnv, certFileDest)
.WithEnvironment(certKeyFileEnv, certKeyFileDest);
}
else
{
// For non-container resources, set the file paths directly
builder
.WithEnvironment(certFileEnv, certExportPath)
.WithEnvironment(certKeyFileEnv, certKeyExportPath);
}
return builder;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment