File: CertGenerator.cs
Web Access
Project: ..\..\..\test\Microsoft.WebTools.AspireService.Tests\Microsoft.WebTools.AspireService.Tests.csproj (Microsoft.WebTools.AspireService.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
#nullable enable
 
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
 
namespace Aspire.Tools.Service;
 
internal static class CertGenerator
{
    public static X509Certificate2 GenerateCert()
    {
        const int rsaKeySize = 2048;
        var rsa = RSA.Create(rsaKeySize); // Create asymmetric RSA key pair.
        var req = new CertificateRequest(
            "cn=debug-session.visualstudio.microsoft.com",
            rsa,
            HashAlgorithmName.SHA256,
            RSASignaturePadding.Pss
        );
 
        var sanBuilder = new SubjectAlternativeNameBuilder();
        sanBuilder.AddDnsName("localhost");
        req.CertificateExtensions.Add(sanBuilder.Build());
 
        var cert = req.CreateSelfSigned(
            DateTimeOffset.UtcNow.AddSeconds(-5),
            DateTimeOffset.UtcNow.AddDays(7)
        );
 
        if (OperatingSystem.IsWindows())
        {
            // Workaround for Windows S/Channel requirement for storing private for the certificate on disk.
            // The file will be automatically generated by the following call and disposed when the returned cert is disposed.
            using (cert)
            {
#if NET9_0_OR_GREATER
                return X509CertificateLoader.LoadPkcs12(cert.Export(X509ContentType.Pfx), password: null, X509KeyStorageFlags.UserKeySet);
#else
                return new X509Certificate2(cert.Export(X509ContentType.Pfx), "", X509KeyStorageFlags.UserKeySet);
#endif
            }
        }
        else
        {
            return cert;
        }
    }
}