Add support for PEM certificates (#787)

* Support PEM

* net5

* 31

* txt

* FILE

* new

* Fixed

* .

* .

* RSA
This commit is contained in:
Stef Heyenrath
2022-08-16 13:26:00 +02:00
committed by GitHub
parent e2bd56531d
commit 330559b9fd
17 changed files with 354 additions and 131 deletions

View File

@@ -103,6 +103,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.Proxy.
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.xUnit", "src\WireMock.Net.xUnit\WireMock.Net.xUnit.csproj", "{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.xUnit", "src\WireMock.Net.xUnit\WireMock.Net.xUnit.csproj", "{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.NET6.WithCertificate", "examples\WireMock.Net.Console.NET6.WithCertificate\WireMock.Net.Console.NET6.WithCertificate.csproj", "{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -245,6 +247,10 @@ Global
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Debug|Any CPU.Build.0 = Debug|Any CPU {0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Release|Any CPU.ActiveCfg = Release|Any CPU {0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Release|Any CPU.Build.0 = Release|Any CPU {0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Release|Any CPU.Build.0 = Release|Any CPU
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -286,6 +292,7 @@ Global
{3F7AA023-6833-4856-A08A-4B5717B592B8} = {985E0ADB-D4B4-473A-AA40-567E279B7946} {3F7AA023-6833-4856-A08A-4B5717B592B8} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{670C7562-C154-442E-A249-7D26849BCD13} = {985E0ADB-D4B4-473A-AA40-567E279B7946} {670C7562-C154-442E-A249-7D26849BCD13} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2} {0DE0954F-8C00-4E8D-B94A-4361FC1CBE44} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458} SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}

View File

@@ -1,9 +1,11 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AD/@EntryIndexedValue">AD</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AD/@EntryIndexedValue">AD</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CS/@EntryIndexedValue">CS</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CS/@EntryIndexedValue">CS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=EC/@EntryIndexedValue">EC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IP/@EntryIndexedValue">IP</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IP/@EntryIndexedValue">IP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MD/@EntryIndexedValue">MD5</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MD/@EntryIndexedValue">MD5</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RSA/@EntryIndexedValue">RSA</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SSL/@EntryIndexedValue">SSL</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SSL/@EntryIndexedValue">SSL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TE/@EntryIndexedValue">TE</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TE/@EntryIndexedValue">TE</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TSV/@EntryIndexedValue">TSV</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TSV/@EntryIndexedValue">TSV</s:String>

View File

@@ -0,0 +1,16 @@
https://www.scottbrady91.com/openssl/creating-elliptical-curve-keys-using-openssl
# find your curve
openssl ecparam -list_curves
# generate a private key for a curve
openssl ecparam -name prime256v1 -genkey -noout -out private-key.pem
# generate corresponding public key
openssl ec -in private-key.pem -pubout -out public-key.pem
# optional: create a self-signed certificate
openssl req -new -x509 -key private-key.pem -out cert.pem -days 360
# optional: convert pem to pfx
openssl pkcs12 -export -inkey private-key.pem -in cert.pem -out cert.pfx

View File

@@ -0,0 +1,52 @@
using System.IO;
using WireMock.Logging;
using WireMock.Server;
using WireMock.Settings;
namespace WireMock.Net.Console.NET6.WithCertificate;
class Program
{
static void Main(string[] args)
{
var serverEC = WireMockServer.Start(new WireMockServerSettings
{
Urls = new[] { "https://localhost:8433/" },
StartAdminInterface = true,
Logger = new WireMockConsoleLogger(),
CertificateSettings = new WireMockCertificateSettings
{
// https://www.scottbrady91.com/c-sharp/pem-loading-in-dotnet-core-and-dotnet
// https://www.scottbrady91.com/openssl/creating-elliptical-curve-keys-using-openssl
X509CertificateFilePath = "cert.pem",
X509CertificatePassword = @"
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIJZTv6ujGrEwxW+ab1+CtZouRd8PK7PsklVMvJwm1uDmoAoGCCqGSM49
AwEHoUQDQgAE39VoI268uDuIeKmRzr9e9jgMSGeuJTvTG7+cSXmeDymrVgIGXQgm
qKA8TDXpJNrRhWMd/fpsnWu1JwJUjBmspQ==
-----END EC PRIVATE KEY-----"
}
});
System.Console.WriteLine("WireMockServer listening at {0}", serverEC.Url);
var serverRSA = WireMockServer.Start(new WireMockServerSettings
{
Urls = new[] { "https://localhost:8434/" },
StartAdminInterface = true,
Logger = new WireMockConsoleLogger(),
CertificateSettings = new WireMockCertificateSettings
{
// https://www.scottbrady91.com/c-sharp/pem-loading-in-dotnet-core-and-dotnet
// https://www.scottbrady91.com/openssl/creating-rsa-keys-using-openssl
X509CertificateFilePath = "cert-rsa.pem",
X509CertificatePassword = File.ReadAllText("private-key-rsa.pem")
}
});
System.Console.WriteLine("WireMockServer listening at {0}", serverRSA.Url);
System.Console.WriteLine("Press any key to stop the server(s)");
System.Console.ReadKey();
serverEC.Stop();
serverRSA.Stop();
}
}

View File

@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<None Update="*.pem">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="*.pfx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="nlog.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,28 @@
-----BEGIN CERTIFICATE-----
MIIErzCCAxegAwIBAgIUeVJ5l3LJPakcwhBGXNfa7UawgPcwDQYJKoZIhvcNAQEL
BQAwZzELMAkGA1UEBhMCTkwxEzARBgNVBAgMClNvbWUtU3RhdGUxFTATBgNVBAoM
DFdpcmVNb2NrLk5ldDEVMBMGA1UECwwMV2lyZU1vY2suTmV0MRUwEwYDVQQDDAxX
aXJlTW9jay5OZXQwHhcNMjIwODEyMTQzMjUxWhcNMzIwNjIwMTQzMjUxWjBnMQsw
CQYDVQQGEwJOTDETMBEGA1UECAwKU29tZS1TdGF0ZTEVMBMGA1UECgwMV2lyZU1v
Y2suTmV0MRUwEwYDVQQLDAxXaXJlTW9jay5OZXQxFTATBgNVBAMMDFdpcmVNb2Nr
Lk5ldDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALyF2sKsueDaZ78r
fQ5IyqWJLYXnYRT94xVfiPoRQNex7JMYwdIt+xEPcfhIlyODxYRxzYTSuXi/cBOM
/svTewIdBmDDyyCDboZ+P8THlzdwCLNHUPONQqJtc0msLVfwPuvDeZIwhIn9CDwC
1EXstWLEePxu1i2/PAfUudYeQunjrP10DE06fyW+ZH7sMSPOSyY4BO4Rt0dk3Cws
U/CEl+bSN5Kx2WkyPxbOvZLa66JmQEaeSZ4ypkhujWE1LuIIQE94P28BzFpHtDWO
1+42K8mqjdnO8eH1/IfAMmOE/o3rKoI4C5aUPyJpDOaz5KFCqdCSBHlb2uo3lqgd
yYOCrVOLIsljp8H4ncfs1AUo+tExNW/5jWYegAZGXLArrWktHEbwa4f+9ZMa7+VS
lKpx6hLI7eMSHBCsQJ7yH8QyLhr0HMjoDw38isGV+mK/N1u47s4oaTQyG+HXH+e/
Shj5OSKnLWBV/eX7YSAJ1hqHgmAbwl/BnuGI3SBXSK4mcjcNvQIDAQABo1MwUTAd
BgNVHQ4EFgQUYhrgWXNdcFpnyz0mifPqYM+kyK4wHwYDVR0jBBgwFoAUYhrgWXNd
cFpnyz0mifPqYM+kyK4wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC
AYEAmfJZJ019pO7ZXDQ85nEC99+x9+MUnSZ6UuMIiy2VMcS/oea8ugQ4NBYVPpQS
O/xiYENpw36+H4+ctv1tdAbZELGGLBahkkzZedLyiFObxDALu0PP7jQYr4nUjfQj
B/fWuTcCrVmuH3yiutw/sALd1su63VjjZiOCwxMB8LV4T0ojBTHA2D4rqLTiSRgs
sP3CRoWDI2JIr2afM/K8SMczRbo/5ovv0YF9kFcwG9WDEa/oQ67Yu05GFBnItYmT
QP+Br5WiPTLOON9TKm1ZgxLwrhJNHfD2+u9uudkVF5uWyg9ZvB8sYmIw5wSvUFl5
SDj1Pxy4olim54BL5wIwlMMQu+fKp6T89iShgN/NEot3JKW3zDpa/t93IjJXGOlh
O4ECoUzXCtDTnc6aais2SoYjbveP2wduS9MHAQinjTiepzYbhJbySURKqCBu1mN2
EFsU9Pzd1+MA3ZbRfhvl8Jvwdp5GqaFyCqgqmP5oPOcd9ncJowyfobfdqzYMXPGl
bu9i
-----END CERTIFICATE-----

View File

@@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB9TCCAZugAwIBAgIUYH7UM/DAXzosxsT+ea2jdYvhqqMwCgYIKoZIzj0EAwIw
UDELMAkGA1UEBhMCTkwxEzARBgNVBAgMClNvbWUtU3RhdGUxFTATBgNVBAoMDFdp
cmVNb2NrLk5ldDEVMBMGA1UEAwwMV2lyZU1vY2suTmV0MB4XDTIyMDgxMTE2MjE0
NFoXDTMyMDYxOTE2MjE0NFowUDELMAkGA1UEBhMCTkwxEzARBgNVBAgMClNvbWUt
U3RhdGUxFTATBgNVBAoMDFdpcmVNb2NrLk5ldDEVMBMGA1UEAwwMV2lyZU1vY2su
TmV0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE39VoI268uDuIeKmRzr9e9jgM
SGeuJTvTG7+cSXmeDymrVgIGXQgmqKA8TDXpJNrRhWMd/fpsnWu1JwJUjBmspaNT
MFEwHQYDVR0OBBYEFILL8V+fAtMnccWKGAdkx2Dh/v/TMB8GA1UdIwQYMBaAFILL
8V+fAtMnccWKGAdkx2Dh/v/TMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwID
SAAwRQIgKDLAG8OWK6GF5HV4kmWz3kp2V3yVsNK2V9Lw3dSE+YsCIQCK1EEBvuqc
0ncZV4ETVnOY23PWFOMk1VwN2aoTi5n++Q==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,39 @@
-----BEGIN RSA PRIVATE KEY-----
MIIG5AIBAAKCAYEAvIXawqy54Npnvyt9DkjKpYkthedhFP3jFV+I+hFA17HskxjB
0i37EQ9x+EiXI4PFhHHNhNK5eL9wE4z+y9N7Ah0GYMPLIINuhn4/xMeXN3AIs0dQ
841Com1zSawtV/A+68N5kjCEif0IPALURey1YsR4/G7WLb88B9S51h5C6eOs/XQM
TTp/Jb5kfuwxI85LJjgE7hG3R2TcLCxT8ISX5tI3krHZaTI/Fs69ktrromZARp5J
njKmSG6NYTUu4ghAT3g/bwHMWke0NY7X7jYryaqN2c7x4fX8h8AyY4T+jesqgjgL
lpQ/ImkM5rPkoUKp0JIEeVva6jeWqB3Jg4KtU4siyWOnwfidx+zUBSj60TE1b/mN
Zh6ABkZcsCutaS0cRvBrh/71kxrv5VKUqnHqEsjt4xIcEKxAnvIfxDIuGvQcyOgP
DfyKwZX6Yr83W7juzihpNDIb4dcf579KGPk5IqctYFX95fthIAnWGoeCYBvCX8Ge
4YjdIFdIriZyNw29AgMBAAECggGBAJcMsNDWUECG/iVAFP0C+ctUdDMbxr9pBS+0
0i168XdhSeo6JeHfkZCDzY9fqil8hR+vhznrFUxYJtajW+u4UJDK7LdPaUttw3rj
YPir6s8yZuYuOABMqJ04EO1wlQwmpGOGxbuKQEfHg3eB1M8J7/No9H9d1yHkXZbw
rM2QhZCdKZgSCWE/g2ycdizz1hOYUMIYlGqjqzP67iY+hirqMkNxH7Hb6hTNe5ss
ntwxqCcAwnNSlC2661yRp5nBYQUeEfgXAx/cZZ6cILjX6JanDsML/PRY1hOm5hCZ
8/8satOGtd37rgr1cP/kvNMf7uLI8hIeC4JSCymUh6lU6ERpWRoQV8DUE60ztFbi
bQbGU/rseznBN8O1cM6fjduno/n8d4q5wGLjAbIai+xxxTSksbnlvkthRAUfK9/Y
rUdMxqgkDnecCAHof8UPz/Vg3n9J9wl6waFrKa+Kseda1wEB/jf51fb/t0sJP2Dq
n2kcp239zwalUr2XnXfENfeL9IDBiQKBwQDsogaTFy7E5P+66B1ZRDP2X6WgFedH
tjMCVXG4K4VOWp6xMfhieq2d+amMoYi/J3cxS8qDIM64q55caTaB3KTodGrzmvax
avqG58Mpyv9VdEDzMI29D7Xtx5ykoAAWOmQaByH/4J+3IBX6efRDGmSvmoqPoa0V
ChMO0Gw6O9GsH/kVEy2nRaj9dJpOqo05jhh9LLye2stPycCHzYybYqjs0Nt1uboY
3mbiCJBWJ8jZk9KeFhrqCkYB1zZJIJVybJ8CgcEAy/PRm0NZDUx6IJKnwDXBriE0
Qih1ZcvdVi907nhYAlBpAPWisGls6EghBQsfvQ4ZPwHAFBlDu/72JrqGJhkP61mP
D/xT9d59xSU5N90doiInrTHAOoyZEdpul9QvCXxKuFFl3RZnxn0RwPgc23sZUcny
aM4DIWk1541Z84Lxv3tFLXoG5uvqpCkSwEBd9iu0EMHlmoPFkEkY41Q3/zTs46FY
fnWLSdRahKDFHrZTgyu4i/3clbbp9m1cpWLwzUwjAoHAVpSWCT2jPCF5vD5vdpjw
1kV6yU8aV2+/zCvNNxCdbuTTSYw6EHZIjhOqSK1V5nMfNmc/yqi3WnRYtgE9E1jS
8cae11Es0A+PaMrl6qW+tNqbZR+vzKwx6bVuiAGO5pMoyyku9HuQlKVlxUbX67F9
g47tAc6rEJamEHaMEuaOOgdc0Kw6uQhQ46PFTeEzWQq3xR0YSptNZn0wN8AqoTQB
ENz+X128TJsbU7rEbPGTmKBwoKz/3gAySzwePbVxWPOLAoHAAsqehtKAKIdwcHux
YhcaRIjdzz4AhVkp+WEC57Sr97QkC8hQ5rs6q185XHlPgOXtgIhEmcHSxILz2Yna
BjF3n1AFfkGE4Kuf6w/cXaBgJHT1OBCjQenkunLT6q4TyrxxxV4P19vTpcrWcF60
/mgL66uo7rhLIKzw+O9dWNDlACruwnWWHJkECCUrxYfcAV+NwmD1BI1jKdtmRM5F
Se/ughsWO/zd4C/Q4VnV+Nqj//qcNwZNe5saTq4mg3j8NMMjAoHBANRR+WLpgr3f
Kh9vNA+v1gnBUFImheWrJ+Eu75q1sGKrz3gZ8glhewf37YbJVuSKFMEBAg1qobWG
/2B26beXia/NprVuV5vqJNuts29W1/WuDKE7BsNya/quDA1WxTQAzhSA54DYtWXw
UgVTPtEQXL9Wbk2wF98tWiUio4VjV++geVql4qKQUet1IMo1RgRgbQL5hn/rDH0g
ZOX552VdK1xivWQRVA4486eKHlW/lbKJjX0Os6qhNIF57qVquIRQPw==
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIJZTv6ujGrEwxW+ab1+CtZouRd8PK7PsklVMvJwm1uDmoAoGCCqGSM49
AwEHoUQDQgAE39VoI268uDuIeKmRzr9e9jgMSGeuJTvTG7+cSXmeDymrVgIGXQgm
qKA8TDXpJNrRhWMd/fpsnWu1JwJUjBmspQ==
-----END EC PRIVATE KEY-----

View File

@@ -0,0 +1,11 @@
-----BEGIN PUBLIC KEY-----
MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAvIXawqy54Npnvyt9DkjK
pYkthedhFP3jFV+I+hFA17HskxjB0i37EQ9x+EiXI4PFhHHNhNK5eL9wE4z+y9N7
Ah0GYMPLIINuhn4/xMeXN3AIs0dQ841Com1zSawtV/A+68N5kjCEif0IPALURey1
YsR4/G7WLb88B9S51h5C6eOs/XQMTTp/Jb5kfuwxI85LJjgE7hG3R2TcLCxT8ISX
5tI3krHZaTI/Fs69ktrromZARp5JnjKmSG6NYTUu4ghAT3g/bwHMWke0NY7X7jYr
yaqN2c7x4fX8h8AyY4T+jesqgjgLlpQ/ImkM5rPkoUKp0JIEeVva6jeWqB3Jg4Kt
U4siyWOnwfidx+zUBSj60TE1b/mNZh6ABkZcsCutaS0cRvBrh/71kxrv5VKUqnHq
Esjt4xIcEKxAnvIfxDIuGvQcyOgPDfyKwZX6Yr83W7juzihpNDIb4dcf579KGPk5
IqctYFX95fthIAnWGoeCYBvCX8Ge4YjdIFdIriZyNw29AgMBAAE=
-----END PUBLIC KEY-----

View File

@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE39VoI268uDuIeKmRzr9e9jgMSGeu
JTvTG7+cSXmeDymrVgIGXQgmqKA8TDXpJNrRhWMd/fpsnWu1JwJUjBmspQ==
-----END PUBLIC KEY-----

View File

@@ -6,15 +6,17 @@ namespace WireMock.HttpsCertificate;
internal static class CertificateLoader internal static class CertificateLoader
{ {
private const string ExtensionPem = ".PEM";
/// <summary> /// <summary>
/// Used by the WireMock.Net server /// Used by the WireMock.Net server
/// </summary> /// </summary>
public static X509Certificate2 LoadCertificate( public static X509Certificate2 LoadCertificate(
string storeName, string? storeName,
string storeLocation, string? storeLocation,
string thumbprintOrSubjectName, string? thumbprintOrSubjectName,
string filePath, string? filePath,
string password, string? passwordOrKey,
string host) string host)
{ {
if (!string.IsNullOrEmpty(storeName) && !string.IsNullOrEmpty(storeLocation)) if (!string.IsNullOrEmpty(storeName) && !string.IsNullOrEmpty(storeLocation))
@@ -47,19 +49,41 @@ internal static class CertificateLoader
#if NETSTANDARD || NET46 #if NETSTANDARD || NET46
certStore.Dispose(); certStore.Dispose();
#else #else
certStore.Close(); certStore.Close();
#endif #endif
} }
} }
if (!string.IsNullOrEmpty(filePath) && !string.IsNullOrEmpty(password))
{
return new X509Certificate2(filePath, password);
}
if (!string.IsNullOrEmpty(filePath)) if (!string.IsNullOrEmpty(filePath))
{ {
return new X509Certificate2(filePath); if (filePath!.EndsWith(ExtensionPem, StringComparison.OrdinalIgnoreCase))
{
// PEM logic based on: https://www.scottbrady91.com/c-sharp/pem-loading-in-dotnet-core-and-dotnet
#if NET5_0_OR_GREATER
if (!string.IsNullOrEmpty(passwordOrKey))
{
var certPem = File.ReadAllText(filePath);
var cert = X509Certificate2.CreateFromPem(certPem, passwordOrKey);
const string defaultPasswordPem = "WireMock.Net";
return new X509Certificate2(cert.Export(X509ContentType.Pfx, defaultPasswordPem), defaultPasswordPem);
}
return X509Certificate2.CreateFromPemFile(filePath);
#elif NETCOREAPP3_1
var cert = new X509Certificate2(filePath);
if (!string.IsNullOrEmpty(passwordOrKey))
{
var key = System.Security.Cryptography.ECDsa.Create()!;
key.ImportECPrivateKey(System.Text.Encoding.UTF8.GetBytes(passwordOrKey), out _);
return cert.CopyWithPrivateKey(key);
}
return cert;
#else
throw new InvalidOperationException("Loading a PEM Certificate is only supported for .NET Core App 3.1, .NET 5.0 and higher.");
#endif
}
return !string.IsNullOrEmpty(passwordOrKey) ? new X509Certificate2(filePath, passwordOrKey) : new X509Certificate2(filePath);
} }
throw new InvalidOperationException("X509StoreName and X509StoreLocation OR X509CertificateFilePath are mandatory. Note that X509CertificatePassword is optional."); throw new InvalidOperationException("X509StoreName and X509StoreLocation OR X509CertificateFilePath are mandatory. Note that X509CertificatePassword is optional.");
@@ -97,7 +121,7 @@ internal static class CertificateLoader
#if NETSTANDARD || NET46 #if NETSTANDARD || NET46
certStore.Dispose(); certStore.Dispose();
#else #else
certStore.Close(); certStore.Close();
#endif #endif
} }
} }

View File

@@ -5,7 +5,6 @@ using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using WireMock.HttpsCertificate; using WireMock.HttpsCertificate;
using WireMock.Types;
namespace WireMock.Owin namespace WireMock.Owin
{ {

View File

@@ -1,4 +1,4 @@
#if USE_ASPNETCORE && NETSTANDARD1_3 #if USE_ASPNETCORE && NETSTANDARD1_3
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel; using Microsoft.AspNetCore.Server.Kestrel;
@@ -6,58 +6,58 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using WireMock.HttpsCertificate; using WireMock.HttpsCertificate;
namespace WireMock.Owin namespace WireMock.Owin;
{
internal partial class AspNetCoreSelfHost
{
private static void SetKestrelOptionsLimits(KestrelServerOptions options)
{
options.Limits.MaxRequestBufferSize = null;
options.Limits.MaxRequestHeaderCount = 100;
options.Limits.MaxResponseBufferSize = null;
}
private static void SetHttpsAndUrls(KestrelServerOptions options, IWireMockMiddlewareOptions wireMockMiddlewareOptions, IEnumerable<HostUrlDetails> urlDetails) internal partial class AspNetCoreSelfHost
{
private static void SetKestrelOptionsLimits(KestrelServerOptions options)
{
options.Limits.MaxRequestBufferSize = null;
options.Limits.MaxRequestHeaderCount = 100;
options.Limits.MaxResponseBufferSize = null;
}
private static void SetHttpsAndUrls(KestrelServerOptions options, IWireMockMiddlewareOptions wireMockMiddlewareOptions, IEnumerable<HostUrlDetails> urlDetails)
{
foreach (var urlDetail in urlDetails)
{ {
foreach (var urlDetail in urlDetails) if (urlDetail.IsHttps)
{ {
if (urlDetail.IsHttps) if (wireMockMiddlewareOptions.CustomCertificateDefined)
{ {
if (wireMockMiddlewareOptions.CustomCertificateDefined) options.UseHttps(CertificateLoader.LoadCertificate(
{ wireMockMiddlewareOptions.X509StoreName,
options.UseHttps(CertificateLoader.LoadCertificate( wireMockMiddlewareOptions.X509StoreLocation,
wireMockMiddlewareOptions.X509StoreName, wireMockMiddlewareOptions.X509ThumbprintOrSubjectName,
wireMockMiddlewareOptions.X509StoreLocation, wireMockMiddlewareOptions.X509CertificateFilePath,
wireMockMiddlewareOptions.X509ThumbprintOrSubjectName, wireMockMiddlewareOptions.X509CertificatePassword,
wireMockMiddlewareOptions.X509CertificateFilePath, urlDetail.Host)
wireMockMiddlewareOptions.X509CertificatePassword, );
urlDetail.Host) }
); else
} {
else options.UseHttps(PublicCertificateHelper.GetX509Certificate2());
{
options.UseHttps(PublicCertificateHelper.GetX509Certificate2());
}
} }
} }
} }
} }
}
internal static class IWebHostBuilderExtensions internal static class IWebHostBuilderExtensions
{
internal static IWebHostBuilder ConfigureAppConfigurationUsingEnvironmentVariables(this IWebHostBuilder builder) => builder;
internal static IWebHostBuilder ConfigureKestrelServerOptions(this IWebHostBuilder builder)
{ {
internal static IWebHostBuilder ConfigureAppConfigurationUsingEnvironmentVariables(this IWebHostBuilder builder) => builder; var configuration = new ConfigurationBuilder()
.AddEnvironmentVariables()
.Build();
internal static IWebHostBuilder ConfigureKestrelServerOptions(this IWebHostBuilder builder) return builder.ConfigureServices(services =>
{ {
var configuration = new ConfigurationBuilder() services.Configure<KestrelServerOptions>(configuration.GetSection("Kestrel"));
.AddEnvironmentVariables() });
.Build();
return builder.ConfigureServices(services =>
{
services.Configure<KestrelServerOptions>(configuration.GetSection("Kestrel"));
});
}
} }
} }
#endif #endif

View File

@@ -132,7 +132,7 @@ namespace WireMock.Owin
#elif NETSTANDARD2_1 #elif NETSTANDARD2_1
_logger.Info("Server using netstandard2.1"); _logger.Info("Server using netstandard2.1");
#elif NETCOREAPP3_1 #elif NETCOREAPP3_1
_logger.Info("Server using .NET Core 3.1"); _logger.Info("Server using .NET Core App 3.1");
#elif NET5_0 #elif NET5_0
_logger.Info("Server using .NET 5.0"); _logger.Info("Server using .NET 5.0");
#elif NET6_0 #elif NET6_0

View File

@@ -12,62 +12,61 @@ using IAppBuilder = Microsoft.AspNetCore.Builder.IApplicationBuilder;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
#endif #endif
namespace WireMock.Owin namespace WireMock.Owin;
internal interface IWireMockMiddlewareOptions
{ {
internal interface IWireMockMiddlewareOptions IWireMockLogger Logger { get; set; }
{
IWireMockLogger Logger { get; set; }
TimeSpan? RequestProcessingDelay { get; set; } TimeSpan? RequestProcessingDelay { get; set; }
IStringMatcher? AuthenticationMatcher { get; set; } IStringMatcher? AuthenticationMatcher { get; set; }
bool? AllowPartialMapping { get; set; } bool? AllowPartialMapping { get; set; }
ConcurrentDictionary<Guid, IMapping> Mappings { get; } ConcurrentDictionary<Guid, IMapping> Mappings { get; }
ConcurrentDictionary<string, ScenarioState> Scenarios { get; } ConcurrentDictionary<string, ScenarioState> Scenarios { get; }
ConcurrentObservableCollection<LogEntry> LogEntries { get; } ConcurrentObservableCollection<LogEntry> LogEntries { get; }
int? RequestLogExpirationDuration { get; set; } int? RequestLogExpirationDuration { get; set; }
int? MaxRequestLogCount { get; set; } int? MaxRequestLogCount { get; set; }
Action<IAppBuilder>? PreWireMockMiddlewareInit { get; set; } Action<IAppBuilder>? PreWireMockMiddlewareInit { get; set; }
Action<IAppBuilder>? PostWireMockMiddlewareInit { get; set; } Action<IAppBuilder>? PostWireMockMiddlewareInit { get; set; }
#if USE_ASPNETCORE #if USE_ASPNETCORE
Action<IServiceCollection>? AdditionalServiceRegistration { get; set; } Action<IServiceCollection>? AdditionalServiceRegistration { get; set; }
CorsPolicyOptions? CorsPolicyOptions { get; set; } CorsPolicyOptions? CorsPolicyOptions { get; set; }
#endif #endif
IFileSystemHandler? FileSystemHandler { get; set; } IFileSystemHandler? FileSystemHandler { get; set; }
bool? AllowBodyForAllHttpMethods { get; set; } bool? AllowBodyForAllHttpMethods { get; set; }
bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; } bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; }
bool? DisableJsonBodyParsing { get; set; } bool? DisableJsonBodyParsing { get; set; }
bool? DisableRequestBodyDecompressing { get; set; } bool? DisableRequestBodyDecompressing { get; set; }
bool? HandleRequestsSynchronously { get; set; } bool? HandleRequestsSynchronously { get; set; }
string? X509StoreName { get; set; } string? X509StoreName { get; set; }
string? X509StoreLocation { get; set; } string? X509StoreLocation { get; set; }
string? X509ThumbprintOrSubjectName { get; set; } string? X509ThumbprintOrSubjectName { get; set; }
string? X509CertificateFilePath { get; set; } string? X509CertificateFilePath { get; set; }
string? X509CertificatePassword { get; set; } string? X509CertificatePassword { get; set; }
bool CustomCertificateDefined { get; } bool CustomCertificateDefined { get; }
bool? SaveUnmatchedRequests { get; set; } bool? SaveUnmatchedRequests { get; set; }
}
} }

View File

@@ -12,77 +12,76 @@ using IAppBuilder = Microsoft.AspNetCore.Builder.IApplicationBuilder;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
#endif #endif
namespace WireMock.Owin namespace WireMock.Owin;
internal class WireMockMiddlewareOptions : IWireMockMiddlewareOptions
{ {
internal class WireMockMiddlewareOptions : IWireMockMiddlewareOptions public IWireMockLogger Logger { get; set; }
{
public IWireMockLogger Logger { get; set; }
public TimeSpan? RequestProcessingDelay { get; set; } public TimeSpan? RequestProcessingDelay { get; set; }
public IStringMatcher AuthenticationMatcher { get; set; } public IStringMatcher AuthenticationMatcher { get; set; }
public bool? AllowPartialMapping { get; set; } public bool? AllowPartialMapping { get; set; }
public ConcurrentDictionary<Guid, IMapping> Mappings { get; } = new ConcurrentDictionary<Guid, IMapping>(); public ConcurrentDictionary<Guid, IMapping> Mappings { get; } = new ConcurrentDictionary<Guid, IMapping>();
public ConcurrentDictionary<string, ScenarioState> Scenarios { get; } = new ConcurrentDictionary<string, ScenarioState>(); public ConcurrentDictionary<string, ScenarioState> Scenarios { get; } = new();
public ConcurrentObservableCollection<LogEntry> LogEntries { get; } = new ConcurrentObservableCollection<LogEntry>(); public ConcurrentObservableCollection<LogEntry> LogEntries { get; } = new();
public int? RequestLogExpirationDuration { get; set; } public int? RequestLogExpirationDuration { get; set; }
public int? MaxRequestLogCount { get; set; } public int? MaxRequestLogCount { get; set; }
public Action<IAppBuilder> PreWireMockMiddlewareInit { get; set; } public Action<IAppBuilder>? PreWireMockMiddlewareInit { get; set; }
public Action<IAppBuilder> PostWireMockMiddlewareInit { get; set; } public Action<IAppBuilder>? PostWireMockMiddlewareInit { get; set; }
#if USE_ASPNETCORE #if USE_ASPNETCORE
public Action<IServiceCollection> AdditionalServiceRegistration { get; set; } public Action<IServiceCollection>? AdditionalServiceRegistration { get; set; }
public CorsPolicyOptions? CorsPolicyOptions { get; set; } public CorsPolicyOptions? CorsPolicyOptions { get; set; }
#endif #endif
/// <inheritdoc cref="IWireMockMiddlewareOptions.FileSystemHandler"/> /// <inheritdoc cref="IWireMockMiddlewareOptions.FileSystemHandler"/>
public IFileSystemHandler FileSystemHandler { get; set; } public IFileSystemHandler FileSystemHandler { get; set; }
/// <inheritdoc cref="IWireMockMiddlewareOptions.AllowBodyForAllHttpMethods"/> /// <inheritdoc cref="IWireMockMiddlewareOptions.AllowBodyForAllHttpMethods"/>
public bool? AllowBodyForAllHttpMethods { get; set; } public bool? AllowBodyForAllHttpMethods { get; set; }
/// <inheritdoc cref="IWireMockMiddlewareOptions.AllowOnlyDefinedHttpStatusCodeInResponse"/> /// <inheritdoc cref="IWireMockMiddlewareOptions.AllowOnlyDefinedHttpStatusCodeInResponse"/>
public bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; } public bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; }
/// <inheritdoc cref="IWireMockMiddlewareOptions.DisableJsonBodyParsing"/> /// <inheritdoc cref="IWireMockMiddlewareOptions.DisableJsonBodyParsing"/>
public bool? DisableJsonBodyParsing { get; set; } public bool? DisableJsonBodyParsing { get; set; }
/// <inheritdoc cref="IWireMockMiddlewareOptions.DisableRequestBodyDecompressing"/> /// <inheritdoc cref="IWireMockMiddlewareOptions.DisableRequestBodyDecompressing"/>
public bool? DisableRequestBodyDecompressing { get; set; } public bool? DisableRequestBodyDecompressing { get; set; }
/// <inheritdoc cref="IWireMockMiddlewareOptions.HandleRequestsSynchronously"/> /// <inheritdoc cref="IWireMockMiddlewareOptions.HandleRequestsSynchronously"/>
public bool? HandleRequestsSynchronously { get; set; } public bool? HandleRequestsSynchronously { get; set; }
/// <inheritdoc cref="IWireMockMiddlewareOptions.X509StoreName"/> /// <inheritdoc cref="IWireMockMiddlewareOptions.X509StoreName"/>
public string X509StoreName { get; set; } public string? X509StoreName { get; set; }
/// <inheritdoc cref="IWireMockMiddlewareOptions.X509StoreLocation"/> /// <inheritdoc cref="IWireMockMiddlewareOptions.X509StoreLocation"/>
public string X509StoreLocation { get; set; } public string? X509StoreLocation { get; set; }
/// <inheritdoc cref="IWireMockMiddlewareOptions.X509ThumbprintOrSubjectName"/> /// <inheritdoc cref="IWireMockMiddlewareOptions.X509ThumbprintOrSubjectName"/>
public string X509ThumbprintOrSubjectName { get; set; } public string? X509ThumbprintOrSubjectName { get; set; }
/// <inheritdoc cref="IWireMockMiddlewareOptions.X509CertificateFilePath"/> /// <inheritdoc cref="IWireMockMiddlewareOptions.X509CertificateFilePath"/>
public string X509CertificateFilePath { get; set; } public string? X509CertificateFilePath { get; set; }
/// <inheritdoc cref="IWireMockMiddlewareOptions.X509CertificatePassword"/> /// <inheritdoc cref="IWireMockMiddlewareOptions.X509CertificatePassword"/>
public string X509CertificatePassword { get; set; } public string? X509CertificatePassword { get; set; }
/// <inheritdoc cref="IWireMockMiddlewareOptions.CustomCertificateDefined"/> /// <inheritdoc cref="IWireMockMiddlewareOptions.CustomCertificateDefined"/>
public bool CustomCertificateDefined => public bool CustomCertificateDefined =>
!string.IsNullOrEmpty(X509StoreName) && !string.IsNullOrEmpty(X509StoreLocation) || !string.IsNullOrEmpty(X509StoreName) && !string.IsNullOrEmpty(X509StoreLocation) ||
!string.IsNullOrEmpty(X509CertificateFilePath); !string.IsNullOrEmpty(X509CertificateFilePath);
/// <inheritdoc cref="IWireMockMiddlewareOptions.SaveUnmatchedRequests"/> /// <inheritdoc cref="IWireMockMiddlewareOptions.SaveUnmatchedRequests"/>
public bool? SaveUnmatchedRequests { get; set; } public bool? SaveUnmatchedRequests { get; set; }
}
} }