diff --git a/WireMock.Net Solution.sln b/WireMock.Net Solution.sln index 76244631..0aa4bf57 100644 --- a/WireMock.Net Solution.sln +++ b/WireMock.Net Solution.sln @@ -103,6 +103,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.Proxy. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.xUnit", "src\WireMock.Net.xUnit\WireMock.Net.xUnit.csproj", "{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}" 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 GlobalSection(SolutionConfigurationPlatforms) = preSolution 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}.Release|Any CPU.ActiveCfg = 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 GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -286,6 +292,7 @@ Global {3F7AA023-6833-4856-A08A-4B5717B592B8} = {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} + {7C2A9DE8-C89F-4841-9058-6B9BF81E5E34} = {985E0ADB-D4B4-473A-AA40-567E279B7946} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458} diff --git a/WireMock.Net Solution.sln.DotSettings b/WireMock.Net Solution.sln.DotSettings index a4b9b087..6c092492 100644 --- a/WireMock.Net Solution.sln.DotSettings +++ b/WireMock.Net Solution.sln.DotSettings @@ -1,9 +1,11 @@  AD CS + EC ID IP MD5 + RSA SSL TE TSV diff --git a/examples/WireMock.Net.Console.NET6.WithCertificate/HowTo.txt b/examples/WireMock.Net.Console.NET6.WithCertificate/HowTo.txt new file mode 100644 index 00000000..24dbdc52 --- /dev/null +++ b/examples/WireMock.Net.Console.NET6.WithCertificate/HowTo.txt @@ -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 \ No newline at end of file diff --git a/examples/WireMock.Net.Console.NET6.WithCertificate/Program.cs b/examples/WireMock.Net.Console.NET6.WithCertificate/Program.cs new file mode 100644 index 00000000..7b571d98 --- /dev/null +++ b/examples/WireMock.Net.Console.NET6.WithCertificate/Program.cs @@ -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(); + } +} \ No newline at end of file diff --git a/examples/WireMock.Net.Console.NET6.WithCertificate/WireMock.Net.Console.NET6.WithCertificate.csproj b/examples/WireMock.Net.Console.NET6.WithCertificate/WireMock.Net.Console.NET6.WithCertificate.csproj new file mode 100644 index 00000000..1415e9ac --- /dev/null +++ b/examples/WireMock.Net.Console.NET6.WithCertificate/WireMock.Net.Console.NET6.WithCertificate.csproj @@ -0,0 +1,25 @@ + + + + Exe + net6.0 + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + \ No newline at end of file diff --git a/examples/WireMock.Net.Console.NET6.WithCertificate/cert-rsa.pem b/examples/WireMock.Net.Console.NET6.WithCertificate/cert-rsa.pem new file mode 100644 index 00000000..d71759cd --- /dev/null +++ b/examples/WireMock.Net.Console.NET6.WithCertificate/cert-rsa.pem @@ -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----- diff --git a/examples/WireMock.Net.Console.NET6.WithCertificate/cert.pem b/examples/WireMock.Net.Console.NET6.WithCertificate/cert.pem new file mode 100644 index 00000000..8f6ecc06 --- /dev/null +++ b/examples/WireMock.Net.Console.NET6.WithCertificate/cert.pem @@ -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----- diff --git a/examples/WireMock.Net.Console.NET6.WithCertificate/private-key-rsa.pem b/examples/WireMock.Net.Console.NET6.WithCertificate/private-key-rsa.pem new file mode 100644 index 00000000..55d572b8 --- /dev/null +++ b/examples/WireMock.Net.Console.NET6.WithCertificate/private-key-rsa.pem @@ -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----- diff --git a/examples/WireMock.Net.Console.NET6.WithCertificate/private-key.pem b/examples/WireMock.Net.Console.NET6.WithCertificate/private-key.pem new file mode 100644 index 00000000..80b3f1b2 --- /dev/null +++ b/examples/WireMock.Net.Console.NET6.WithCertificate/private-key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIJZTv6ujGrEwxW+ab1+CtZouRd8PK7PsklVMvJwm1uDmoAoGCCqGSM49 +AwEHoUQDQgAE39VoI268uDuIeKmRzr9e9jgMSGeuJTvTG7+cSXmeDymrVgIGXQgm +qKA8TDXpJNrRhWMd/fpsnWu1JwJUjBmspQ== +-----END EC PRIVATE KEY----- diff --git a/examples/WireMock.Net.Console.NET6.WithCertificate/public-key-rsa.pem b/examples/WireMock.Net.Console.NET6.WithCertificate/public-key-rsa.pem new file mode 100644 index 00000000..eddf7d05 --- /dev/null +++ b/examples/WireMock.Net.Console.NET6.WithCertificate/public-key-rsa.pem @@ -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----- diff --git a/examples/WireMock.Net.Console.NET6.WithCertificate/public-key.pem b/examples/WireMock.Net.Console.NET6.WithCertificate/public-key.pem new file mode 100644 index 00000000..a8f89494 --- /dev/null +++ b/examples/WireMock.Net.Console.NET6.WithCertificate/public-key.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE39VoI268uDuIeKmRzr9e9jgMSGeu +JTvTG7+cSXmeDymrVgIGXQgmqKA8TDXpJNrRhWMd/fpsnWu1JwJUjBmspQ== +-----END PUBLIC KEY----- diff --git a/src/WireMock.Net/HttpsCertificate/CertificateLoader.cs b/src/WireMock.Net/HttpsCertificate/CertificateLoader.cs index 5fe48664..7fef03f3 100644 --- a/src/WireMock.Net/HttpsCertificate/CertificateLoader.cs +++ b/src/WireMock.Net/HttpsCertificate/CertificateLoader.cs @@ -6,15 +6,17 @@ namespace WireMock.HttpsCertificate; internal static class CertificateLoader { + private const string ExtensionPem = ".PEM"; + /// /// Used by the WireMock.Net server /// public static X509Certificate2 LoadCertificate( - string storeName, - string storeLocation, - string thumbprintOrSubjectName, - string filePath, - string password, + string? storeName, + string? storeLocation, + string? thumbprintOrSubjectName, + string? filePath, + string? passwordOrKey, string host) { if (!string.IsNullOrEmpty(storeName) && !string.IsNullOrEmpty(storeLocation)) @@ -47,19 +49,41 @@ internal static class CertificateLoader #if NETSTANDARD || NET46 certStore.Dispose(); #else - certStore.Close(); + certStore.Close(); #endif } } - if (!string.IsNullOrEmpty(filePath) && !string.IsNullOrEmpty(password)) - { - return new X509Certificate2(filePath, password); - } - 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."); @@ -97,7 +121,7 @@ internal static class CertificateLoader #if NETSTANDARD || NET46 certStore.Dispose(); #else - certStore.Close(); + certStore.Close(); #endif } } diff --git a/src/WireMock.Net/Owin/AspNetCoreSelfHost.NETStandard.cs b/src/WireMock.Net/Owin/AspNetCoreSelfHost.NETStandard.cs index 616514a5..df71f1fa 100644 --- a/src/WireMock.Net/Owin/AspNetCoreSelfHost.NETStandard.cs +++ b/src/WireMock.Net/Owin/AspNetCoreSelfHost.NETStandard.cs @@ -5,7 +5,6 @@ using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using WireMock.HttpsCertificate; -using WireMock.Types; namespace WireMock.Owin { diff --git a/src/WireMock.Net/Owin/AspNetCoreSelfHost.NETStandard13.cs b/src/WireMock.Net/Owin/AspNetCoreSelfHost.NETStandard13.cs index 0d2bf351..90b741fd 100644 --- a/src/WireMock.Net/Owin/AspNetCoreSelfHost.NETStandard13.cs +++ b/src/WireMock.Net/Owin/AspNetCoreSelfHost.NETStandard13.cs @@ -1,4 +1,4 @@ -#if USE_ASPNETCORE && NETSTANDARD1_3 +#if USE_ASPNETCORE && NETSTANDARD1_3 using System.Collections.Generic; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Server.Kestrel; @@ -6,58 +6,58 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using WireMock.HttpsCertificate; -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; - } +namespace WireMock.Owin; - private static void SetHttpsAndUrls(KestrelServerOptions options, IWireMockMiddlewareOptions wireMockMiddlewareOptions, IEnumerable 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 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, - wireMockMiddlewareOptions.X509StoreLocation, - wireMockMiddlewareOptions.X509ThumbprintOrSubjectName, - wireMockMiddlewareOptions.X509CertificateFilePath, - wireMockMiddlewareOptions.X509CertificatePassword, - urlDetail.Host) - ); - } - else - { - options.UseHttps(PublicCertificateHelper.GetX509Certificate2()); - } + options.UseHttps(CertificateLoader.LoadCertificate( + wireMockMiddlewareOptions.X509StoreName, + wireMockMiddlewareOptions.X509StoreLocation, + wireMockMiddlewareOptions.X509ThumbprintOrSubjectName, + wireMockMiddlewareOptions.X509CertificateFilePath, + wireMockMiddlewareOptions.X509CertificatePassword, + urlDetail.Host) + ); + } + else + { + 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() - .AddEnvironmentVariables() - .Build(); - - return builder.ConfigureServices(services => - { - services.Configure(configuration.GetSection("Kestrel")); - }); - } + services.Configure(configuration.GetSection("Kestrel")); + }); } } + #endif \ No newline at end of file diff --git a/src/WireMock.Net/Owin/AspNetCoreSelfHost.cs b/src/WireMock.Net/Owin/AspNetCoreSelfHost.cs index 7a016ab5..45b7cdd1 100644 --- a/src/WireMock.Net/Owin/AspNetCoreSelfHost.cs +++ b/src/WireMock.Net/Owin/AspNetCoreSelfHost.cs @@ -132,7 +132,7 @@ namespace WireMock.Owin #elif NETSTANDARD2_1 _logger.Info("Server using netstandard2.1"); #elif NETCOREAPP3_1 - _logger.Info("Server using .NET Core 3.1"); + _logger.Info("Server using .NET Core App 3.1"); #elif NET5_0 _logger.Info("Server using .NET 5.0"); #elif NET6_0 diff --git a/src/WireMock.Net/Owin/IWireMockMiddlewareOptions.cs b/src/WireMock.Net/Owin/IWireMockMiddlewareOptions.cs index 92e7c847..2c8e97b4 100644 --- a/src/WireMock.Net/Owin/IWireMockMiddlewareOptions.cs +++ b/src/WireMock.Net/Owin/IWireMockMiddlewareOptions.cs @@ -12,62 +12,61 @@ using IAppBuilder = Microsoft.AspNetCore.Builder.IApplicationBuilder; using Microsoft.Extensions.DependencyInjection; #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 Mappings { get; } + ConcurrentDictionary Mappings { get; } - ConcurrentDictionary Scenarios { get; } + ConcurrentDictionary Scenarios { get; } - ConcurrentObservableCollection LogEntries { get; } + ConcurrentObservableCollection LogEntries { get; } - int? RequestLogExpirationDuration { get; set; } + int? RequestLogExpirationDuration { get; set; } - int? MaxRequestLogCount { get; set; } + int? MaxRequestLogCount { get; set; } - Action? PreWireMockMiddlewareInit { get; set; } + Action? PreWireMockMiddlewareInit { get; set; } - Action? PostWireMockMiddlewareInit { get; set; } + Action? PostWireMockMiddlewareInit { get; set; } #if USE_ASPNETCORE - Action? AdditionalServiceRegistration { get; set; } + Action? AdditionalServiceRegistration { get; set; } - CorsPolicyOptions? CorsPolicyOptions { get; set; } + CorsPolicyOptions? CorsPolicyOptions { get; set; } #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; } } \ No newline at end of file diff --git a/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs b/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs index 1486fd2d..fffdfde9 100644 --- a/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs +++ b/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs @@ -12,77 +12,76 @@ using IAppBuilder = Microsoft.AspNetCore.Builder.IApplicationBuilder; using Microsoft.Extensions.DependencyInjection; #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 Mappings { get; } = new ConcurrentDictionary(); + public ConcurrentDictionary Mappings { get; } = new ConcurrentDictionary(); - public ConcurrentDictionary Scenarios { get; } = new ConcurrentDictionary(); + public ConcurrentDictionary Scenarios { get; } = new(); - public ConcurrentObservableCollection LogEntries { get; } = new ConcurrentObservableCollection(); + public ConcurrentObservableCollection 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 PreWireMockMiddlewareInit { get; set; } + public Action? PreWireMockMiddlewareInit { get; set; } - public Action PostWireMockMiddlewareInit { get; set; } + public Action? PostWireMockMiddlewareInit { get; set; } #if USE_ASPNETCORE - public Action AdditionalServiceRegistration { get; set; } + public Action? AdditionalServiceRegistration { get; set; } - public CorsPolicyOptions? CorsPolicyOptions { get; set; } + public CorsPolicyOptions? CorsPolicyOptions { get; set; } #endif - /// - public IFileSystemHandler FileSystemHandler { get; set; } + /// + public IFileSystemHandler FileSystemHandler { get; set; } - /// - public bool? AllowBodyForAllHttpMethods { get; set; } + /// + public bool? AllowBodyForAllHttpMethods { get; set; } - /// - public bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; } + /// + public bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; } - /// - public bool? DisableJsonBodyParsing { get; set; } + /// + public bool? DisableJsonBodyParsing { get; set; } - /// - public bool? DisableRequestBodyDecompressing { get; set; } + /// + public bool? DisableRequestBodyDecompressing { get; set; } - /// - public bool? HandleRequestsSynchronously { get; set; } + /// + public bool? HandleRequestsSynchronously { get; set; } - /// - public string X509StoreName { get; set; } + /// + public string? X509StoreName { get; set; } - /// - public string X509StoreLocation { get; set; } + /// + public string? X509StoreLocation { get; set; } - /// - public string X509ThumbprintOrSubjectName { get; set; } + /// + public string? X509ThumbprintOrSubjectName { get; set; } - /// - public string X509CertificateFilePath { get; set; } + /// + public string? X509CertificateFilePath { get; set; } - /// - public string X509CertificatePassword { get; set; } + /// + public string? X509CertificatePassword { get; set; } - /// - public bool CustomCertificateDefined => - !string.IsNullOrEmpty(X509StoreName) && !string.IsNullOrEmpty(X509StoreLocation) || - !string.IsNullOrEmpty(X509CertificateFilePath); + /// + public bool CustomCertificateDefined => + !string.IsNullOrEmpty(X509StoreName) && !string.IsNullOrEmpty(X509StoreLocation) || + !string.IsNullOrEmpty(X509CertificateFilePath); - /// - public bool? SaveUnmatchedRequests { get; set; } - } + /// + public bool? SaveUnmatchedRequests { get; set; } } \ No newline at end of file