Add option to provide X509Certificate (#1303)

* Add option to provide X509CertificateRawData

* X509Certificate

* remove X509CertificateRawData
This commit is contained in:
Stef Heyenrath
2025-05-28 07:15:46 +02:00
committed by GitHub
parent 3438539138
commit 86d4717216
8 changed files with 138 additions and 123 deletions

View File

@@ -11,113 +11,105 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using CertificateLoader = WireMock.HttpsCertificate.CertificateLoader;
namespace WireMock.Owin
namespace WireMock.Owin;
internal partial class AspNetCoreSelfHost
{
internal partial class AspNetCoreSelfHost
private static void SetKestrelOptionsLimits(KestrelServerOptions options)
{
private static void SetKestrelOptionsLimits(KestrelServerOptions options)
{
options.Limits.MaxRequestBodySize = null; // https://stackoverflow.com/questions/46738364/increase-upload-request-length-limit-in-kestrel
options.Limits.MaxRequestBufferSize = null;
options.Limits.MaxRequestHeaderCount = 100;
options.Limits.MaxResponseBufferSize = null;
}
options.Limits.MaxRequestBodySize = null; // https://stackoverflow.com/questions/46738364/increase-upload-request-length-limit-in-kestrel
options.Limits.MaxRequestBufferSize = null;
options.Limits.MaxRequestHeaderCount = 100;
options.Limits.MaxResponseBufferSize = null;
}
private static void SetHttpsAndUrls(KestrelServerOptions kestrelOptions, IWireMockMiddlewareOptions wireMockMiddlewareOptions, IEnumerable<HostUrlDetails> urlDetails)
private static void SetHttpsAndUrls(KestrelServerOptions kestrelOptions, IWireMockMiddlewareOptions wireMockMiddlewareOptions, IEnumerable<HostUrlDetails> urlDetails)
{
foreach (var urlDetail in urlDetails)
{
foreach (var urlDetail in urlDetails)
if (urlDetail.IsHttps)
{
if (urlDetail.IsHttps)
Listen(kestrelOptions, urlDetail, listenOptions =>
{
Listen(kestrelOptions, urlDetail, listenOptions =>
listenOptions.UseHttps(options =>
{
listenOptions.UseHttps(options =>
if (wireMockMiddlewareOptions.CustomCertificateDefined)
{
if (wireMockMiddlewareOptions.CustomCertificateDefined)
{
options.ServerCertificate = CertificateLoader.LoadCertificate(
wireMockMiddlewareOptions.X509StoreName,
wireMockMiddlewareOptions.X509StoreLocation,
wireMockMiddlewareOptions.X509ThumbprintOrSubjectName,
wireMockMiddlewareOptions.X509CertificateFilePath,
wireMockMiddlewareOptions.X509CertificatePassword,
urlDetail.Host
);
}
options.ServerCertificate = CertificateLoader.LoadCertificate(wireMockMiddlewareOptions, urlDetail.Host);
}
options.ClientCertificateMode = (ClientCertificateMode)wireMockMiddlewareOptions.ClientCertificateMode;
if (wireMockMiddlewareOptions.AcceptAnyClientCertificate)
{
options.ClientCertificateValidation = (_, _, _) => true;
}
});
if (urlDetail.IsHttp2)
options.ClientCertificateMode = (ClientCertificateMode)wireMockMiddlewareOptions.ClientCertificateMode;
if (wireMockMiddlewareOptions.AcceptAnyClientCertificate)
{
listenOptions.Protocols = HttpProtocols.Http2;
options.ClientCertificateValidation = (_, _, _) => true;
}
});
continue;
}
if (urlDetail.IsHttp2)
{
Listen(kestrelOptions, urlDetail, listenOptions =>
if (urlDetail.IsHttp2)
{
listenOptions.Protocols = HttpProtocols.Http2;
});
continue;
}
Listen(kestrelOptions, urlDetail, _ => { });
}
});
continue;
}
}
private static void Listen(KestrelServerOptions kestrelOptions, HostUrlDetails urlDetail, Action<ListenOptions> configure)
{
// Listens on any IP with the given port.
if (urlDetail is { Port: > 0, Host: "0.0.0.0" })
if (urlDetail.IsHttp2)
{
kestrelOptions.ListenAnyIP(urlDetail.Port, configure);
return;
}
// Listens on ::1 and 127.0.0.1 with the given port.
if (urlDetail is { Port: > 0, Host: "localhost" or "127.0.0.1" or "::1" })
{
kestrelOptions.ListenLocalhost(urlDetail.Port, configure);
return;
Listen(kestrelOptions, urlDetail, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http2;
});
continue;
}
// Try to parse the host as a valid IP address and bind to the given IP address and port.
if (IPAddress.TryParse(urlDetail.Host, out var ipAddress))
{
kestrelOptions.Listen(ipAddress, urlDetail.Port, configure);
return;
}
// Otherwise, listen on all IPs.
kestrelOptions.ListenAnyIP(urlDetail.Port, configure);
Listen(kestrelOptions, urlDetail, _ => { });
}
}
internal static class IWebHostBuilderExtensions
private static void Listen(KestrelServerOptions kestrelOptions, HostUrlDetails urlDetail, Action<ListenOptions> configure)
{
internal static IWebHostBuilder ConfigureAppConfigurationUsingEnvironmentVariables(this IWebHostBuilder builder)
// Listens on any IP with the given port.
if (urlDetail is { Port: > 0, Host: "0.0.0.0" })
{
return builder.ConfigureAppConfiguration(config =>
{
config.AddEnvironmentVariables();
});
kestrelOptions.ListenAnyIP(urlDetail.Port, configure);
return;
}
internal static IWebHostBuilder ConfigureKestrelServerOptions(this IWebHostBuilder builder)
// Listens on ::1 and 127.0.0.1 with the given port.
if (urlDetail is { Port: > 0, Host: "localhost" or "127.0.0.1" or "::1" })
{
return builder.ConfigureServices((context, services) =>
{
services.Configure<KestrelServerOptions>(context.Configuration.GetSection("Kestrel"));
});
kestrelOptions.ListenLocalhost(urlDetail.Port, configure);
return;
}
// Try to parse the host as a valid IP address and bind to the given IP address and port.
if (IPAddress.TryParse(urlDetail.Host, out var ipAddress))
{
kestrelOptions.Listen(ipAddress, urlDetail.Port, configure);
return;
}
// Otherwise, listen on all IPs.
kestrelOptions.ListenAnyIP(urlDetail.Port, configure);
}
}
#endif
internal static class IWebHostBuilderExtensions
{
internal static IWebHostBuilder ConfigureAppConfigurationUsingEnvironmentVariables(this IWebHostBuilder builder)
{
return builder.ConfigureAppConfiguration(config =>
{
config.AddEnvironmentVariables();
});
}
internal static IWebHostBuilder ConfigureKestrelServerOptions(this IWebHostBuilder builder)
{
return builder.ConfigureServices((context, services) =>
{
services.Configure<KestrelServerOptions>(context.Configuration.GetSection("Kestrel"));
});
}
}
#endif

View File

@@ -28,19 +28,9 @@ internal partial class AspNetCoreSelfHost
{
options.UseHttps(new HttpsConnectionFilterOptions
{
ServerCertificate = wireMockMiddlewareOptions.CustomCertificateDefined
? CertificateLoader.LoadCertificate(
wireMockMiddlewareOptions.X509StoreName,
wireMockMiddlewareOptions.X509StoreLocation,
wireMockMiddlewareOptions.X509ThumbprintOrSubjectName,
wireMockMiddlewareOptions.X509CertificateFilePath,
wireMockMiddlewareOptions.X509CertificatePassword,
urlDetail.Host)
: PublicCertificateHelper.GetX509Certificate2(),
ServerCertificate = wireMockMiddlewareOptions.CustomCertificateDefined ? CertificateLoader.LoadCertificate(wireMockMiddlewareOptions, urlDetail.Host) : PublicCertificateHelper.GetX509Certificate2(),
ClientCertificateMode = (ClientCertificateMode) wireMockMiddlewareOptions.ClientCertificateMode,
ClientCertificateValidation = wireMockMiddlewareOptions.AcceptAnyClientCertificate
? (_, _, _) => true
: null,
ClientCertificateValidation = wireMockMiddlewareOptions.AcceptAnyClientCertificate ? (_, _, _) => true : null
});
}
}

View File

@@ -7,6 +7,10 @@ using WireMock.Logging;
using WireMock.Matchers;
using WireMock.Types;
using WireMock.Util;
using System.Security.Cryptography.X509Certificates;
using JetBrains.Annotations;
#if !USE_ASPNETCORE
using Owin;
#else
@@ -70,6 +74,11 @@ internal interface IWireMockMiddlewareOptions
string? X509CertificateFilePath { get; set; }
/// <summary>
/// A X.509 certificate instance.
/// </summary>
public X509Certificate2? X509Certificate { get; set; }
string? X509CertificatePassword { get; set; }
bool CustomCertificateDefined { get; }

View File

@@ -7,6 +7,8 @@ using WireMock.Logging;
using WireMock.Matchers;
using WireMock.Types;
using WireMock.Util;
using System.Security.Cryptography.X509Certificates;
#if !USE_ASPNETCORE
using Owin;
#else
@@ -81,13 +83,17 @@ internal class WireMockMiddlewareOptions : IWireMockMiddlewareOptions
/// <inheritdoc cref="IWireMockMiddlewareOptions.X509CertificateFilePath"/>
public string? X509CertificateFilePath { get; set; }
/// <inheritdoc />
public X509Certificate2? X509Certificate { get; set; }
/// <inheritdoc cref="IWireMockMiddlewareOptions.X509CertificatePassword"/>
public string? X509CertificatePassword { get; set; }
/// <inheritdoc cref="IWireMockMiddlewareOptions.CustomCertificateDefined"/>
public bool CustomCertificateDefined =>
!string.IsNullOrEmpty(X509StoreName) && !string.IsNullOrEmpty(X509StoreLocation) ||
!string.IsNullOrEmpty(X509CertificateFilePath);
!string.IsNullOrEmpty(X509CertificateFilePath) ||
X509Certificate != null;
/// <inheritdoc cref="IWireMockMiddlewareOptions.SaveUnmatchedRequests"/>
public bool? SaveUnmatchedRequests { get; set; }

View File

@@ -39,6 +39,7 @@ internal static class WireMockMiddlewareOptionsHelper
options.X509StoreName = settings.CertificateSettings!.X509StoreName;
options.X509StoreLocation = settings.CertificateSettings.X509StoreLocation;
options.X509ThumbprintOrSubjectName = settings.CertificateSettings.X509StoreThumbprintOrSubjectName;
options.X509Certificate = settings.CertificateSettings.X509Certificate;
options.X509CertificateFilePath = settings.CertificateSettings.X509CertificateFilePath;
options.X509CertificatePassword = settings.CertificateSettings.X509CertificatePassword;
}