Skip to content

Introduce ListenOptions.GetServerCertificate #48055

@amcasey

Description

@amcasey

Background and Motivation

The original fix for #45801 had to be rolled back because it broke an internal partner that depended on UseHttps failing fast in the absence of a certificate. Rather than having them continue to rely on the behavior (which we want to change), we should introduce an API that allows them to check for certificates explicitly (originally requested in #28120).

Proposed API

See #48054

namespace Microsoft.AspNetCore.Hosting;

public static class ListenOptionsHttpsExtensions
{
+    /// <summary>
+    /// Retrieve the server certificate, if any, for an endpoint; otherwise, throw.
+    /// Should not be called before the configuration is loaded, if there is one.
+    /// </summary>
+    /// <param name="listenOptions">The <see cref="ListenOptions"/> to configure.</param>
+    /// <returns>The server certificate for this endpoint.</returns>
+    /// <exception cref="InvalidOperationException">If there is no server certificate for this endpoint.</exception>
+    /// <exception cref="InvalidOperationException">If there is a configuration and it has not been loaded.</exception>
+    public static X509Certificate2 GetServerCertificate(this ListenOptions listenOptions)
}

Usage Examples

webHostBuilder
    .UseKestrel(options =>
    {
        options.Configure(/* ... */);
        options.ConfigurationLoader.Load();

        options.Listen(IPAddress.Loopback, 5000, listenOptions =>
        {
                // No HTTPS
        });

        try
        {
            options.Listen(IPAddress.Loopback, 5001, listenOptions =>
            {
                listenOptions.GetServerCertificate();
                listenOptions.UseHttps();
            });
        }
        catch
        {
            Console.WriteLine("No https");
        }
    })

Alternative Designs

We could have gone with TryGet but our partner expressed a preference for getting an explanatory exception message.
We could have made UseHttps fail eagerly, but that would have introduced a lot of complexity, chiefly around handling configuration changes between UseHttps and bind-time.

Risks

It's a little wonky that you have to explicitly load the configuration yourself, but this is a very niche scenario.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-networkingIncludes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions