Add WithProxy(string proxyUrl, X509Certificate2 certificate) (#880)

This commit is contained in:
Stef Heyenrath
2023-02-01 10:42:35 +01:00
committed by GitHub
parent 1000f4409f
commit 6839b11d35
6 changed files with 93 additions and 56 deletions

View File

@@ -35,9 +35,14 @@ internal static class HttpClientBuilder
{ {
handler.ClientCertificateOptions = ClientCertificateOption.Manual; handler.ClientCertificateOptions = ClientCertificateOption.Manual;
var x509Certificate2 = CertificateLoader.LoadCertificate(settings.ClientX509Certificate2ThumbprintOrSubjectName); var x509Certificate2 = CertificateLoader.LoadCertificate(settings.ClientX509Certificate2ThumbprintOrSubjectName!);
handler.ClientCertificates.Add(x509Certificate2); handler.ClientCertificates.Add(x509Certificate2);
} }
else if (settings.Certificate != null)
{
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ClientCertificates.Add(settings.Certificate);
}
handler.AllowAutoRedirect = settings.AllowAutoRedirect == true; handler.AllowAutoRedirect = settings.AllowAutoRedirect == true;

View File

@@ -1,4 +1,4 @@
using JetBrains.Annotations; using System.Security.Cryptography.X509Certificates;
using WireMock.Settings; using WireMock.Settings;
namespace WireMock.ResponseBuilders; namespace WireMock.ResponseBuilders;
@@ -17,9 +17,17 @@ public interface IProxyResponseBuilder : IStatusCodeResponseBuilder
IResponseBuilder WithProxy(string proxyUrl, string? clientX509Certificate2ThumbprintOrSubjectName = null); IResponseBuilder WithProxy(string proxyUrl, string? clientX509Certificate2ThumbprintOrSubjectName = null);
/// <summary> /// <summary>
/// WithProxy using IProxyAndRecordSettings. /// WithProxy using <see cref="ProxyAndRecordSettings"/>.
/// </summary> /// </summary>
/// <param name="settings">The IProxyAndRecordSettings.</param> /// <param name="settings">The ProxyAndRecordSettings.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns> /// <returns>A <see cref="IResponseBuilder"/>.</returns>
IResponseBuilder WithProxy([NotNull] ProxyAndRecordSettings settings); IResponseBuilder WithProxy(ProxyAndRecordSettings settings);
/// <summary>
/// WithProxy using <see cref="X509Certificate2"/>.
/// </summary>
/// <param name="proxyUrl">The proxy url.</param>
/// <param name="certificate"">The X509Certificate2.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
IResponseBuilder WithProxy(string proxyUrl, X509Certificate2 certificate);
} }

View File

@@ -2,6 +2,7 @@ using System.Net.Http;
using WireMock.Http; using WireMock.Http;
using WireMock.Settings; using WireMock.Settings;
using Stef.Validation; using Stef.Validation;
using System.Security.Cryptography.X509Certificates;
namespace WireMock.ResponseBuilders; namespace WireMock.ResponseBuilders;
@@ -38,4 +39,19 @@ public partial class Response
_httpClientForProxy = HttpClientBuilder.Build(settings); _httpClientForProxy = HttpClientBuilder.Build(settings);
return this; return this;
} }
/// <inheritdoc />
public IResponseBuilder WithProxy(string proxyUrl, X509Certificate2 certificate)
{
Guard.NotNullOrEmpty(proxyUrl);
Guard.NotNull(certificate);
var settings = new ProxyAndRecordSettings
{
Url = proxyUrl,
Certificate = certificate
};
return WithProxy(settings);
}
} }

View File

@@ -1,9 +1,11 @@
using System.Security.Cryptography.X509Certificates;
namespace WireMock.Settings; namespace WireMock.Settings;
/// <summary> /// <summary>
/// HttpClientSettings /// HttpClientSettings
/// </summary> /// </summary>
public class HttpClientSettings public abstract class HttpClientSettings
{ {
/// <summary> /// <summary>
/// The clientCertificate thumbprint or subject name fragment to use. /// The clientCertificate thumbprint or subject name fragment to use.
@@ -20,4 +22,9 @@ public class HttpClientSettings
/// Proxy requests should follow redirection (30x). /// Proxy requests should follow redirection (30x).
/// </summary> /// </summary>
public bool? AllowAutoRedirect { get; set; } public bool? AllowAutoRedirect { get; set; }
/// <summary>
/// The <see cref="X509Certificate2"/> to use.
/// </summary>
public X509Certificate2? Certificate { get; set; }
} }

View File

@@ -1,54 +1,53 @@
using JetBrains.Annotations; using JetBrains.Annotations;
namespace WireMock.Settings namespace WireMock.Settings;
/// <summary>
/// If https is used, these settings can be used to configure the CertificateSettings in case a custom certificate instead the default .NET certificate should be used.
///
/// X509StoreName and X509StoreLocation should be defined
/// OR
/// X509CertificateFilePath and X509CertificatePassword should be defined
/// </summary>
public class WireMockCertificateSettings
{ {
/// <summary> /// <summary>
/// If https is used, these settings can be used to configure the CertificateSettings in case a custom certificate instead the default .NET certificate should be used. /// X509 StoreName (AddressBook, AuthRoot, CertificateAuthority, My, Root, TrustedPeople or TrustedPublisher)
/// /// </summary>
[PublicAPI]
public string? X509StoreName { get; set; }
/// <summary>
/// X509 StoreLocation (CurrentUser or LocalMachine)
/// </summary>
[PublicAPI]
public string? X509StoreLocation { get; set; }
/// <summary>
/// X509 Thumbprint or SubjectName (if not defined, the 'host' is used)
/// </summary>
[PublicAPI]
public string? X509StoreThumbprintOrSubjectName { get; set; }
/// <summary>
/// X509Certificate FilePath
/// </summary>
[PublicAPI]
public string? X509CertificateFilePath { get; set; }
/// <summary>
/// X509Certificate Password
/// </summary>
[PublicAPI]
public string? X509CertificatePassword { get; set; }
/// <summary>
/// X509StoreName and X509StoreLocation should be defined /// X509StoreName and X509StoreLocation should be defined
/// OR /// OR
/// X509CertificateFilePath and X509CertificatePassword should be defined /// X509CertificateFilePath and X509CertificatePassword should be defined
/// </summary> /// </summary>
public class WireMockCertificateSettings [PublicAPI]
{ public bool IsDefined =>
/// <summary> !string.IsNullOrEmpty(X509StoreName) && !string.IsNullOrEmpty(X509StoreLocation) ||
/// X509 StoreName (AddressBook, AuthRoot, CertificateAuthority, My, Root, TrustedPeople or TrustedPublisher) !string.IsNullOrEmpty(X509CertificateFilePath);
/// </summary>
[PublicAPI]
public string? X509StoreName { get; set; }
/// <summary>
/// X509 StoreLocation (CurrentUser or LocalMachine)
/// </summary>
[PublicAPI]
public string? X509StoreLocation { get; set; }
/// <summary>
/// X509 Thumbprint or SubjectName (if not defined, the 'host' is used)
/// </summary>
[PublicAPI]
public string? X509StoreThumbprintOrSubjectName { get; set; }
/// <summary>
/// X509Certificate FilePath
/// </summary>
[PublicAPI]
public string? X509CertificateFilePath { get; set; }
/// <summary>
/// X509Certificate Password
/// </summary>
[PublicAPI]
public string? X509CertificatePassword { get; set; }
/// <summary>
/// X509StoreName and X509StoreLocation should be defined
/// OR
/// X509CertificateFilePath and X509CertificatePassword should be defined
/// </summary>
[PublicAPI]
public bool IsDefined =>
!string.IsNullOrEmpty(X509StoreName) && !string.IsNullOrEmpty(X509StoreLocation) ||
!string.IsNullOrEmpty(X509CertificateFilePath);
}
} }

View File

@@ -1,6 +1,3 @@
using FluentAssertions;
using Moq;
using NFluent;
using System; using System;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
@@ -8,6 +5,9 @@ using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using FluentAssertions;
using Moq;
using NFluent;
using WireMock.Constants; using WireMock.Constants;
using WireMock.Handlers; using WireMock.Handlers;
using WireMock.Matchers; using WireMock.Matchers;
@@ -144,9 +144,11 @@ public class WireMockServerProxyTests
}; };
var server = WireMockServer.Start(settings); var server = WireMockServer.Start(settings);
server.Given(Request.Create() server
.Given(Request.Create()
.WithPath("/*") .WithPath("/*")
.WithBody(new RegexMatcher(stringBody))) .WithBody(new RegexMatcher(stringBody))
)
.WithTitle(title) .WithTitle(title)
.WithDescription(description) .WithDescription(description)
.AtPriority(WireMockConstants.ProxyPriority) .AtPriority(WireMockConstants.ProxyPriority)