mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-03-27 19:41:08 +01:00
[Feature] Add support for client certificate password and test with real services that require client certificate auth (#32)
* Add support for client certificate password and test with some real services that require client certificates. Also update so when proxying, the path and query will be passed to the proxied api. * Add correct param * Update to read certificate from store instead of file * Add support for client certificate password and test with some real services that require client certificates. Also update so when proxying, the path and query will be passed to the proxied api. * Add correct param * Fixup PR issues * Add support for client certificate password and test with some real services that require client certificates. Also update so when proxying, the path and query will be passed to the proxied api. * Add correct param * Fixup PR issues
This commit is contained in:
committed by
Stef Heyenrath
parent
c29b88eb43
commit
49ce2f0dfb
44
src/WireMock.Net/Http/CertificateUtil.cs
Normal file
44
src/WireMock.Net/Http/CertificateUtil.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace WireMock.Http
|
||||
{
|
||||
internal static class CertificateUtil
|
||||
{
|
||||
public static X509Certificate2 GetCertificate(string thumbprintOrSubjectName)
|
||||
{
|
||||
X509Store certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
|
||||
try
|
||||
{
|
||||
//Certificate must be in the local machine store
|
||||
certStore.Open(OpenFlags.ReadOnly);
|
||||
|
||||
//Attempt to find by thumbprint first
|
||||
var matchingCertificates = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprintOrSubjectName, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
//Fallback to subject name
|
||||
matchingCertificates = certStore.Certificates.Find(X509FindType.FindBySubjectName, thumbprintOrSubjectName, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// No certificates matched the search criteria.
|
||||
throw new Exception($"No certificate found with Thumbprint or SubjectName '{thumbprintOrSubjectName}'");
|
||||
}
|
||||
}
|
||||
// Use the first matching certificate.
|
||||
return matchingCertificates[0];
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (certStore != null)
|
||||
{
|
||||
#if NETSTANDARD || NET46
|
||||
certStore.Dispose();
|
||||
#else
|
||||
certStore.Close();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,19 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WireMock.Http
|
||||
{
|
||||
internal static class HttpClientHelper
|
||||
{
|
||||
private static HttpClient CreateHttpClient(string clientX509Certificate2Filename = null)
|
||||
|
||||
private static HttpClient CreateHttpClient(string clientX509Certificate2ThumbprintOrSubjectName = null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(clientX509Certificate2Filename))
|
||||
if (!string.IsNullOrEmpty(clientX509Certificate2ThumbprintOrSubjectName))
|
||||
{
|
||||
#if NETSTANDARD || NET46
|
||||
var handler = new HttpClientHandler
|
||||
@@ -19,16 +23,20 @@ namespace WireMock.Http
|
||||
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
|
||||
};
|
||||
|
||||
handler.ClientCertificates.Add(new System.Security.Cryptography.X509Certificates.X509Certificate2(clientX509Certificate2Filename));
|
||||
return new HttpClient(handler);
|
||||
var x509Certificate2 = CertificateUtil.GetCertificate(clientX509Certificate2ThumbprintOrSubjectName);
|
||||
handler.ClientCertificates.Add(x509Certificate2);
|
||||
|
||||
|
||||
#else
|
||||
var handler = new WebRequestHandler
|
||||
{
|
||||
ClientCertificateOptions = ClientCertificateOption.Manual,
|
||||
ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true
|
||||
ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true,
|
||||
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
|
||||
};
|
||||
|
||||
handler.ClientCertificates.Add(new System.Security.Cryptography.X509Certificates.X509Certificate2(clientX509Certificate2Filename));
|
||||
var x509Certificate2 = CertificateUtil.GetCertificate(clientX509Certificate2ThumbprintOrSubjectName);
|
||||
handler.ClientCertificates.Add(x509Certificate2);
|
||||
return new HttpClient(handler);
|
||||
#endif
|
||||
}
|
||||
@@ -36,9 +44,9 @@ namespace WireMock.Http
|
||||
return new HttpClient();
|
||||
}
|
||||
|
||||
public static async Task<ResponseMessage> SendAsync(RequestMessage requestMessage, string url, string clientX509Certificate2Filename = null)
|
||||
public static async Task<ResponseMessage> SendAsync(RequestMessage requestMessage, string url, string clientX509Certificate2ThumbprintOrSubjectName = null)
|
||||
{
|
||||
var client = CreateHttpClient(clientX509Certificate2Filename);
|
||||
var client = CreateHttpClient(clientX509Certificate2ThumbprintOrSubjectName);
|
||||
|
||||
var httpRequestMessage = new HttpRequestMessage(new HttpMethod(requestMessage.Method), url);
|
||||
|
||||
@@ -61,21 +69,29 @@ namespace WireMock.Http
|
||||
}
|
||||
|
||||
// Call the URL
|
||||
var httpResponseMessage = await client.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseContentRead);
|
||||
|
||||
// Transform response
|
||||
var responseMessage = new ResponseMessage
|
||||
try
|
||||
{
|
||||
StatusCode = (int)httpResponseMessage.StatusCode,
|
||||
Body = await httpResponseMessage.Content.ReadAsStringAsync()
|
||||
};
|
||||
var httpResponseMessage = await client.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseContentRead);
|
||||
|
||||
foreach (var header in httpResponseMessage.Headers)
|
||||
{
|
||||
responseMessage.AddHeader(header.Key, header.Value.FirstOrDefault());
|
||||
|
||||
// Transform response
|
||||
var responseMessage = new ResponseMessage
|
||||
{
|
||||
StatusCode = (int)httpResponseMessage.StatusCode,
|
||||
Body = await httpResponseMessage.Content.ReadAsStringAsync()
|
||||
};
|
||||
|
||||
foreach (var header in httpResponseMessage.Headers)
|
||||
{
|
||||
responseMessage.AddHeader(header.Key, header.Value.FirstOrDefault());
|
||||
}
|
||||
|
||||
return responseMessage;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
|
||||
return responseMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user