From 9d774bf5e3df98a91a8c44685d12192a93cc9eb4 Mon Sep 17 00:00:00 2001 From: Dmitrii Korolev Date: Tue, 14 Jan 2025 13:36:11 +0100 Subject: [PATCH 01/18] init scripts --- scenarios/tls.benchmarks.yml | 19 +++++++++++++++++++ src/BenchmarksApps/TLS/HttpSys/HttpSys.csproj | 9 +++++++++ .../TLS/HttpSys/scripts/setup-httpsys.ps1 | 1 + .../TLS/HttpSys/scripts/shutdown-httpsys.ps1 | 1 + 4 files changed, 30 insertions(+) create mode 100644 src/BenchmarksApps/TLS/HttpSys/scripts/setup-httpsys.ps1 create mode 100644 src/BenchmarksApps/TLS/HttpSys/scripts/shutdown-httpsys.ps1 diff --git a/scenarios/tls.benchmarks.yml b/scenarios/tls.benchmarks.yml index 16e359625..0aafe3897 100644 --- a/scenarios/tls.benchmarks.yml +++ b/scenarios/tls.benchmarks.yml @@ -49,6 +49,25 @@ scenarios: serverScheme: https mTls-handshakes-httpsys: + application: + job: httpSysServer + variables: + mTLS: true + certValidationConsoleEnabled: false # only for debug purposes + options: + beforeScript: ".\setup-httpsys.ps1" + afterScript: ".\shutdown-httpsys.ps1" + load: + job: httpclient + variables: + path: /hello-world + presetHeaders: connectionclose + connections: 32 + serverScheme: https + certPath: https://raw.githubusercontent.com/aspnet/Benchmarks/refs/heads/main/src/BenchmarksApps/TLS/HttpSys/testCert.pfx + certPwd: testPassword + + tls-renegotiation-httpsys: application: job: httpSysServer variables: diff --git a/src/BenchmarksApps/TLS/HttpSys/HttpSys.csproj b/src/BenchmarksApps/TLS/HttpSys/HttpSys.csproj index 6568b3dcf..41f6d3cc8 100644 --- a/src/BenchmarksApps/TLS/HttpSys/HttpSys.csproj +++ b/src/BenchmarksApps/TLS/HttpSys/HttpSys.csproj @@ -6,4 +6,13 @@ enable + + + PreserveNewest + + + PreserveNewest + + + diff --git a/src/BenchmarksApps/TLS/HttpSys/scripts/setup-httpsys.ps1 b/src/BenchmarksApps/TLS/HttpSys/scripts/setup-httpsys.ps1 new file mode 100644 index 000000000..e9c16633a --- /dev/null +++ b/src/BenchmarksApps/TLS/HttpSys/scripts/setup-httpsys.ps1 @@ -0,0 +1 @@ +Write-Output "hello world setup" \ No newline at end of file diff --git a/src/BenchmarksApps/TLS/HttpSys/scripts/shutdown-httpsys.ps1 b/src/BenchmarksApps/TLS/HttpSys/scripts/shutdown-httpsys.ps1 new file mode 100644 index 000000000..1decd92b6 --- /dev/null +++ b/src/BenchmarksApps/TLS/HttpSys/scripts/shutdown-httpsys.ps1 @@ -0,0 +1 @@ +Write-Output "hello world shutdown" \ No newline at end of file From 5bb7a655b40639fe582bb4cd3d7e9bb0867da745 Mon Sep 17 00:00:00 2001 From: Dmitrii Korolev Date: Tue, 14 Jan 2025 13:40:08 +0100 Subject: [PATCH 02/18] upd --- scenarios/tls.benchmarks.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scenarios/tls.benchmarks.yml b/scenarios/tls.benchmarks.yml index 0aafe3897..ab9f7b780 100644 --- a/scenarios/tls.benchmarks.yml +++ b/scenarios/tls.benchmarks.yml @@ -55,8 +55,8 @@ scenarios: mTLS: true certValidationConsoleEnabled: false # only for debug purposes options: - beforeScript: ".\setup-httpsys.ps1" - afterScript: ".\shutdown-httpsys.ps1" + beforeScript: "powershell -File .\\setup-httpsys.ps1" + afterScript: "powershell -File .\\shutdown-httpsys.ps1" load: job: httpclient variables: From d7fdb1c0657615f5f3a4320e6cd2e1d8c70d973f Mon Sep 17 00:00:00 2001 From: Dmitrii Korolev Date: Tue, 14 Jan 2025 16:34:35 +0100 Subject: [PATCH 03/18] add http.sys setup --- src/BenchmarksApps/TLS/HttpSys/Program.cs | 46 ++++++++++++++++++- .../TLS/HttpSys/appsettings.Development.json | 1 + 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/BenchmarksApps/TLS/HttpSys/Program.cs b/src/BenchmarksApps/TLS/HttpSys/Program.cs index b3d56516b..cbede16ee 100644 --- a/src/BenchmarksApps/TLS/HttpSys/Program.cs +++ b/src/BenchmarksApps/TLS/HttpSys/Program.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Mvc; +using System.Diagnostics; +using System.Security.Cryptography.X509Certificates; using Microsoft.AspNetCore.Server.HttpSys; var builder = WebApplication.CreateBuilder(args); @@ -7,6 +8,7 @@ var writeCertValidationEventsToConsole = bool.TryParse(builder.Configuration["certValidationConsoleEnabled"], out var certValidationConsoleEnabled) && certValidationConsoleEnabled; var statsEnabled = bool.TryParse(builder.Configuration["statsEnabled"], out var connectionStatsEnabledConfig) && connectionStatsEnabledConfig; var mTlsEnabled = bool.TryParse(builder.Configuration["mTLS"], out var mTlsEnabledConfig) && mTlsEnabledConfig; +var tlsRenegotiationEnabled = bool.TryParse(builder.Configuration["tlsRenegotiation"], out var tlsRenegotiationEnabledConfig) && tlsRenegotiationEnabledConfig; var listeningEndpoints = builder.Configuration["urls"] ?? "https://localhost:5000/"; #pragma warning disable CA1416 // Can be launched only on Windows (HttpSys) @@ -40,6 +42,11 @@ } if (mTlsEnabled) +{ + ConfigureHttpSysForMutualTls(); +} + +if (tlsRenegotiationEnabled) { // this is an http.sys middleware to get a cert Console.WriteLine("Registered client cert validation middleware"); @@ -89,4 +96,39 @@ Console.WriteLine("--------------------------------"); Console.WriteLine("Application started."); -await app.WaitForShutdownAsync(); \ No newline at end of file +await app.WaitForShutdownAsync(); + +void ConfigureHttpSysForMutualTls() +{ + var certificate = new X509Certificate2("testCert.pfx", "testPassword", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable); + using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine)) + { + store.Open(OpenFlags.ReadWrite); + store.Add(certificate); + store.Close(); + } + + string certThumbprint = certificate.Thumbprint; + string appId = Guid.NewGuid().ToString(); + + string command = $"http add sslcert ipport=0.0.0.0:5000 certhash={certThumbprint} appid={{{appId}}} clientcertnegotiation=enable"; + ProcessStartInfo processInfo = new ProcessStartInfo("netsh", command) + { + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + }; + + using Process process = Process.Start(processInfo)!; + string output = process.StandardOutput.ReadToEnd(); + string error = process.StandardError.ReadToEnd(); + process.WaitForExit(); + + if (process.ExitCode != 0) + { + throw new InvalidOperationException($"Failed to configure http.sys: {error}"); + } + + Console.WriteLine("Configured http.sys settings for mTLS"); +} \ No newline at end of file diff --git a/src/BenchmarksApps/TLS/HttpSys/appsettings.Development.json b/src/BenchmarksApps/TLS/HttpSys/appsettings.Development.json index 9a6e8fd75..9bbb0fbcb 100644 --- a/src/BenchmarksApps/TLS/HttpSys/appsettings.Development.json +++ b/src/BenchmarksApps/TLS/HttpSys/appsettings.Development.json @@ -6,5 +6,6 @@ } }, "mTLS": "true", + "tlsRenegotiation": "true", "certValidationConsoleEnabled": "true" } From 86f2ec8f8279642a5933d1d25450b3e64bcb6ae5 Mon Sep 17 00:00:00 2001 From: Dmitrii Korolev Date: Tue, 14 Jan 2025 18:25:59 +0100 Subject: [PATCH 04/18] add debug info --- src/BenchmarksApps/TLS/HttpSys/Program.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/BenchmarksApps/TLS/HttpSys/Program.cs b/src/BenchmarksApps/TLS/HttpSys/Program.cs index cbede16ee..827c9870d 100644 --- a/src/BenchmarksApps/TLS/HttpSys/Program.cs +++ b/src/BenchmarksApps/TLS/HttpSys/Program.cs @@ -43,7 +43,14 @@ if (mTlsEnabled) { - ConfigureHttpSysForMutualTls(); + try + { + ConfigureHttpSysForMutualTls(); + } + catch (Exception ex) + { + throw new Exception($"Http.Sys configuration for mTLS failed. Current dir: {Directory.GetCurrentDirectory()}", innerException: ex); + } } if (tlsRenegotiationEnabled) @@ -100,6 +107,8 @@ void ConfigureHttpSysForMutualTls() { + Console.WriteLine("Setting up mTLS for http.sys"); + var certificate = new X509Certificate2("testCert.pfx", "testPassword", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable); using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine)) { From 7adced18896d79bb635b3eb3e3325b50185b042f Mon Sep 17 00:00:00 2001 From: Dmitrii Korolev Date: Tue, 14 Jan 2025 18:29:19 +0100 Subject: [PATCH 05/18] path to cert? --- src/BenchmarksApps/TLS/HttpSys/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BenchmarksApps/TLS/HttpSys/Program.cs b/src/BenchmarksApps/TLS/HttpSys/Program.cs index 827c9870d..6be5cf53a 100644 --- a/src/BenchmarksApps/TLS/HttpSys/Program.cs +++ b/src/BenchmarksApps/TLS/HttpSys/Program.cs @@ -109,7 +109,7 @@ void ConfigureHttpSysForMutualTls() { Console.WriteLine("Setting up mTLS for http.sys"); - var certificate = new X509Certificate2("testCert.pfx", "testPassword", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable); + var certificate = new X509Certificate2("../testCert.pfx", "testPassword", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable); using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine)) { store.Open(OpenFlags.ReadWrite); From deedf400d2abde27bf75b145b1fc2ed7a2990571 Mon Sep 17 00:00:00 2001 From: Dmitrii Korolev Date: Tue, 14 Jan 2025 20:59:54 +0100 Subject: [PATCH 06/18] add tlsRenegotiation param --- scenarios/tls.benchmarks.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/scenarios/tls.benchmarks.yml b/scenarios/tls.benchmarks.yml index ab9f7b780..8a81fbe0d 100644 --- a/scenarios/tls.benchmarks.yml +++ b/scenarios/tls.benchmarks.yml @@ -53,6 +53,7 @@ scenarios: job: httpSysServer variables: mTLS: true + tlsRenegotiation: true certValidationConsoleEnabled: false # only for debug purposes options: beforeScript: "powershell -File .\\setup-httpsys.ps1" From 546753b7fe22b411071fd267f465400a8942fccf Mon Sep 17 00:00:00 2001 From: Dmitrii Korolev Date: Tue, 14 Jan 2025 21:07:33 +0100 Subject: [PATCH 07/18] dont use scripts --- scenarios/tls.benchmarks.yml | 3 - src/BenchmarksApps/TLS/HttpSys/HttpSys.csproj | 3 - .../TLS/HttpSys/NetShWrapper.cs | 73 +++++++++++++++++++ src/BenchmarksApps/TLS/HttpSys/Program.cs | 68 +++++++---------- .../TLS/HttpSys/scripts/setup-httpsys.ps1 | 1 - .../TLS/HttpSys/scripts/shutdown-httpsys.ps1 | 1 - 6 files changed, 99 insertions(+), 50 deletions(-) create mode 100644 src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs delete mode 100644 src/BenchmarksApps/TLS/HttpSys/scripts/setup-httpsys.ps1 delete mode 100644 src/BenchmarksApps/TLS/HttpSys/scripts/shutdown-httpsys.ps1 diff --git a/scenarios/tls.benchmarks.yml b/scenarios/tls.benchmarks.yml index 8a81fbe0d..92b60bce6 100644 --- a/scenarios/tls.benchmarks.yml +++ b/scenarios/tls.benchmarks.yml @@ -55,9 +55,6 @@ scenarios: mTLS: true tlsRenegotiation: true certValidationConsoleEnabled: false # only for debug purposes - options: - beforeScript: "powershell -File .\\setup-httpsys.ps1" - afterScript: "powershell -File .\\shutdown-httpsys.ps1" load: job: httpclient variables: diff --git a/src/BenchmarksApps/TLS/HttpSys/HttpSys.csproj b/src/BenchmarksApps/TLS/HttpSys/HttpSys.csproj index 41f6d3cc8..ffda0c4f9 100644 --- a/src/BenchmarksApps/TLS/HttpSys/HttpSys.csproj +++ b/src/BenchmarksApps/TLS/HttpSys/HttpSys.csproj @@ -7,9 +7,6 @@ - - PreserveNewest - PreserveNewest diff --git a/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs b/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs new file mode 100644 index 000000000..f54aea798 --- /dev/null +++ b/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs @@ -0,0 +1,73 @@ +using System.Diagnostics; +using System.Security.Cryptography.X509Certificates; + +namespace HttpSys +{ + public static class NetShWrapper + { + public static void DisableHttpSysMutualTls(string ipPort) + { + Console.WriteLine("Disabling mTLS for http.sys"); + + string command = $"http delete sslcert ipport={ipPort}"; + ExecuteNetShCommand(command); + + Console.WriteLine("Disabled http.sys settings for mTLS"); + } + + public static bool HttpSysCertBindingExists(string ipPort) + { + return true; + } + + public static void EnableHttpSysMutualTls(string ipPort) + { + Console.WriteLine("Setting up mTLS for http.sys"); + + var certificate = LoadCertificate(); + Console.WriteLine("Loaded `testCert.pfx` from local file system"); + using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine)) + { + store.Open(OpenFlags.ReadWrite); + store.Add(certificate); + Console.WriteLine("Added `testCert.pfx` to localMachine cert store"); + store.Close(); + } + + string certThumbprint = certificate.Thumbprint; + string appId = Guid.NewGuid().ToString(); + + string command = $"http add sslcert ipport={ipPort} certstorename=MY certhash={certThumbprint} appid={{{appId}}} clientcertnegotiation=enable"; + ExecuteNetShCommand(command); + + Console.WriteLine("Configured http.sys settings for mTLS"); + } + + private static void ExecuteNetShCommand(string command) + { + ProcessStartInfo processInfo = new ProcessStartInfo("netsh", command) + { + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + }; + + Console.WriteLine($"Executing command: `netsh {command}`"); + using Process process = Process.Start(processInfo)!; + string output = process.StandardOutput.ReadToEnd(); + process.WaitForExit(); + + if (process.ExitCode != 0) + { + throw new InvalidOperationException($"netsh command execution failure: {output}"); + } + } + +#pragma warning disable SYSLIB0057 // Type or member is obsolete + private static X509Certificate2 LoadCertificate() => File.Exists("testCert.pfx") + ? new X509Certificate2("testCert.pfx", "testPassword", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable) + : new X509Certificate2("../testCert.pfx", "testPassword", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable); +#pragma warning restore SYSLIB0057 // Type or member is obsolete + } +} diff --git a/src/BenchmarksApps/TLS/HttpSys/Program.cs b/src/BenchmarksApps/TLS/HttpSys/Program.cs index 6be5cf53a..d026969c4 100644 --- a/src/BenchmarksApps/TLS/HttpSys/Program.cs +++ b/src/BenchmarksApps/TLS/HttpSys/Program.cs @@ -1,15 +1,18 @@ -using System.Diagnostics; -using System.Security.Cryptography.X509Certificates; +using HttpSys; using Microsoft.AspNetCore.Server.HttpSys; var builder = WebApplication.CreateBuilder(args); builder.Logging.ClearProviders(); +Console.WriteLine($"args: {string.Join(" ", args)}"); +Console.WriteLine(); + var writeCertValidationEventsToConsole = bool.TryParse(builder.Configuration["certValidationConsoleEnabled"], out var certValidationConsoleEnabled) && certValidationConsoleEnabled; var statsEnabled = bool.TryParse(builder.Configuration["statsEnabled"], out var connectionStatsEnabledConfig) && connectionStatsEnabledConfig; var mTlsEnabled = bool.TryParse(builder.Configuration["mTLS"], out var mTlsEnabledConfig) && mTlsEnabledConfig; var tlsRenegotiationEnabled = bool.TryParse(builder.Configuration["tlsRenegotiation"], out var tlsRenegotiationEnabledConfig) && tlsRenegotiationEnabledConfig; var listeningEndpoints = builder.Configuration["urls"] ?? "https://localhost:5000/"; +var httpsIpPort = listeningEndpoints.Split(";").First(x => x.Contains("https")).Replace("https://", ""); #pragma warning disable CA1416 // Can be launched only on Windows (HttpSys) builder.WebHost.UseHttpSys(options => @@ -19,7 +22,7 @@ }); #pragma warning restore CA1416 // Can be launched only on Windows (HttpSys) -var app = builder.Build(); +var app = builder.Build(); app.MapGet("/hello-world", () => { @@ -43,13 +46,30 @@ if (mTlsEnabled) { + var hostAppLifetime = app.Services.GetService(); + hostAppLifetime!.ApplicationStopping.Register(OnShutdown); + + void OnShutdown() + { + try + { + NetShWrapper.DisableHttpSysMutualTls(ipPort: httpsIpPort); + } + catch + { + Console.WriteLine("Failed to disable HTTP.SYS mTLS settings"); + throw; + } + } + try { - ConfigureHttpSysForMutualTls(); + NetShWrapper.EnableHttpSysMutualTls(ipPort: httpsIpPort); } - catch (Exception ex) + catch { - throw new Exception($"Http.Sys configuration for mTLS failed. Current dir: {Directory.GetCurrentDirectory()}", innerException: ex); + Console.WriteLine($"Http.Sys configuration for mTLS failed"); + throw; } } @@ -105,39 +125,3 @@ Console.WriteLine("Application started."); await app.WaitForShutdownAsync(); -void ConfigureHttpSysForMutualTls() -{ - Console.WriteLine("Setting up mTLS for http.sys"); - - var certificate = new X509Certificate2("../testCert.pfx", "testPassword", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable); - using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine)) - { - store.Open(OpenFlags.ReadWrite); - store.Add(certificate); - store.Close(); - } - - string certThumbprint = certificate.Thumbprint; - string appId = Guid.NewGuid().ToString(); - - string command = $"http add sslcert ipport=0.0.0.0:5000 certhash={certThumbprint} appid={{{appId}}} clientcertnegotiation=enable"; - ProcessStartInfo processInfo = new ProcessStartInfo("netsh", command) - { - RedirectStandardOutput = true, - RedirectStandardError = true, - UseShellExecute = false, - CreateNoWindow = true - }; - - using Process process = Process.Start(processInfo)!; - string output = process.StandardOutput.ReadToEnd(); - string error = process.StandardError.ReadToEnd(); - process.WaitForExit(); - - if (process.ExitCode != 0) - { - throw new InvalidOperationException($"Failed to configure http.sys: {error}"); - } - - Console.WriteLine("Configured http.sys settings for mTLS"); -} \ No newline at end of file diff --git a/src/BenchmarksApps/TLS/HttpSys/scripts/setup-httpsys.ps1 b/src/BenchmarksApps/TLS/HttpSys/scripts/setup-httpsys.ps1 deleted file mode 100644 index e9c16633a..000000000 --- a/src/BenchmarksApps/TLS/HttpSys/scripts/setup-httpsys.ps1 +++ /dev/null @@ -1 +0,0 @@ -Write-Output "hello world setup" \ No newline at end of file diff --git a/src/BenchmarksApps/TLS/HttpSys/scripts/shutdown-httpsys.ps1 b/src/BenchmarksApps/TLS/HttpSys/scripts/shutdown-httpsys.ps1 deleted file mode 100644 index 1decd92b6..000000000 --- a/src/BenchmarksApps/TLS/HttpSys/scripts/shutdown-httpsys.ps1 +++ /dev/null @@ -1 +0,0 @@ -Write-Output "hello world shutdown" \ No newline at end of file From efa9d8f4a82a4fac352f1b3106ccd889bf4087ad Mon Sep 17 00:00:00 2001 From: Dmitrii Korolev Date: Tue, 14 Jan 2025 21:23:19 +0100 Subject: [PATCH 08/18] pass tls renego param --- scenarios/tls.benchmarks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenarios/tls.benchmarks.yml b/scenarios/tls.benchmarks.yml index 92b60bce6..8c54d1476 100644 --- a/scenarios/tls.benchmarks.yml +++ b/scenarios/tls.benchmarks.yml @@ -18,7 +18,7 @@ jobs: mTLS: false certValidationConsoleEnabled: false statsEnabled: false - arguments: "--urls https://{{serverAddress}}:{{serverPort}} --mTLS {{mTLS}} --certValidationConsoleEnabled {{certValidationConsoleEnabled}} --statsEnabled {{statsEnabled}}" + arguments: "--urls https://{{serverAddress}}:{{serverPort}} --mTLS {{mTLS}} --certValidationConsoleEnabled {{certValidationConsoleEnabled}} --statsEnabled {{statsEnabled}} --tlsRenegotiation {{tlsRenegotiation}}" kestrelServer: source: From 6332df91fd6882b4dd140749435b0c39d86fa731 Mon Sep 17 00:00:00 2001 From: Dmitrii Korolev Date: Tue, 14 Jan 2025 21:40:54 +0100 Subject: [PATCH 09/18] httpsys logs --- scenarios/tls.benchmarks.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scenarios/tls.benchmarks.yml b/scenarios/tls.benchmarks.yml index 8c54d1476..85c2c0f5c 100644 --- a/scenarios/tls.benchmarks.yml +++ b/scenarios/tls.benchmarks.yml @@ -17,8 +17,10 @@ jobs: variables: mTLS: false certValidationConsoleEnabled: false + tlsRenegotiation: false + httpSysLogs: false statsEnabled: false - arguments: "--urls https://{{serverAddress}}:{{serverPort}} --mTLS {{mTLS}} --certValidationConsoleEnabled {{certValidationConsoleEnabled}} --statsEnabled {{statsEnabled}} --tlsRenegotiation {{tlsRenegotiation}}" + arguments: "--urls https://{{serverAddress}}:{{serverPort}} --mTLS {{mTLS}} --certValidationConsoleEnabled {{certValidationConsoleEnabled}} --statsEnabled {{statsEnabled}} --tlsRenegotiation {{tlsRenegotiation}} --httpSysLogs {{httpSysLogs}}" kestrelServer: source: @@ -54,6 +56,7 @@ scenarios: variables: mTLS: true tlsRenegotiation: true + httpSysLogs: false # only for debug purposes certValidationConsoleEnabled: false # only for debug purposes load: job: httpclient From 12acd3e48becd56621ff895a41a3d36d97ab4e4c Mon Sep 17 00:00:00 2001 From: Dmitrii Korolev Date: Tue, 14 Jan 2025 22:00:05 +0100 Subject: [PATCH 10/18] netsh wrap --- src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs | 11 ++++++++--- src/BenchmarksApps/TLS/HttpSys/Program.cs | 12 +++++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs b/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs index f54aea798..8cced738a 100644 --- a/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs +++ b/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs @@ -15,9 +15,9 @@ public static void DisableHttpSysMutualTls(string ipPort) Console.WriteLine("Disabled http.sys settings for mTLS"); } - public static bool HttpSysCertBindingExists(string ipPort) + public static void Show() { - return true; + ExecuteNetShCommand("http show sslcert", alwaysLogOutput: true); } public static void EnableHttpSysMutualTls(string ipPort) @@ -43,7 +43,7 @@ public static void EnableHttpSysMutualTls(string ipPort) Console.WriteLine("Configured http.sys settings for mTLS"); } - private static void ExecuteNetShCommand(string command) + private static void ExecuteNetShCommand(string command, bool alwaysLogOutput = false) { ProcessStartInfo processInfo = new ProcessStartInfo("netsh", command) { @@ -58,6 +58,11 @@ private static void ExecuteNetShCommand(string command) string output = process.StandardOutput.ReadToEnd(); process.WaitForExit(); + if (alwaysLogOutput) + { + Console.WriteLine(output); + } + if (process.ExitCode != 0) { throw new InvalidOperationException($"netsh command execution failure: {output}"); diff --git a/src/BenchmarksApps/TLS/HttpSys/Program.cs b/src/BenchmarksApps/TLS/HttpSys/Program.cs index d026969c4..31043be07 100644 --- a/src/BenchmarksApps/TLS/HttpSys/Program.cs +++ b/src/BenchmarksApps/TLS/HttpSys/Program.cs @@ -4,10 +4,8 @@ var builder = WebApplication.CreateBuilder(args); builder.Logging.ClearProviders(); -Console.WriteLine($"args: {string.Join(" ", args)}"); -Console.WriteLine(); - var writeCertValidationEventsToConsole = bool.TryParse(builder.Configuration["certValidationConsoleEnabled"], out var certValidationConsoleEnabled) && certValidationConsoleEnabled; +var httpSysLoggingEnabled = bool.TryParse(builder.Configuration["httpSysLogs"], out var httpSysLogsEnabled) && httpSysLogsEnabled; var statsEnabled = bool.TryParse(builder.Configuration["statsEnabled"], out var connectionStatsEnabledConfig) && connectionStatsEnabledConfig; var mTlsEnabled = bool.TryParse(builder.Configuration["mTLS"], out var mTlsEnabledConfig) && mTlsEnabledConfig; var tlsRenegotiationEnabled = bool.TryParse(builder.Configuration["tlsRenegotiation"], out var tlsRenegotiationEnabledConfig) && tlsRenegotiationEnabledConfig; @@ -51,6 +49,8 @@ void OnShutdown() { + Console.WriteLine("Application shutdown started."); + try { NetShWrapper.DisableHttpSysMutualTls(ipPort: httpsIpPort); @@ -106,6 +106,12 @@ void OnShutdown() } await app.StartAsync(); + +if (httpSysLoggingEnabled) +{ + NetShWrapper.Show(); +} + Console.WriteLine("Application Info:"); if (mTlsEnabled) { From 5d64e38fe52ddaa0102c021edb27d96352810eca Mon Sep 17 00:00:00 2001 From: Dmitrii Korolev Date: Tue, 14 Jan 2025 22:02:59 +0100 Subject: [PATCH 11/18] adjust CI configs --- build/trend-scenarios.yml | 3 +++ scenarios/tls.benchmarks.yml | 12 +++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/build/trend-scenarios.yml b/build/trend-scenarios.yml index a56479934..98d4e899d 100644 --- a/build/trend-scenarios.yml +++ b/build/trend-scenarios.yml @@ -108,6 +108,9 @@ parameters: - displayName: "HttpSys Windows: mTLS Handshakes" arguments: --scenario mTls-handshakes-httpsys $(tlsJobs) --property scenario=HttpSysMutualTLSHandshakes --application.options.requiredOperatingSystem windows + - displayName: "HttpSys Windows: TLS Renegotiation" + arguments: --scenario tls-renegotiation-httpsys $(tlsJobs) --property scenario=HttpSysTLSRenegotiation --application.options.requiredOperatingSystem windows + - displayName: "Kestrel Linux: TLS Handshakes" arguments: --scenario tls-handshakes-kestrel $(tlsJobs) --property scenario=KestrelTLSHandshakes --application.options.requiredOperatingSystem linux diff --git a/scenarios/tls.benchmarks.yml b/scenarios/tls.benchmarks.yml index 85c2c0f5c..bb50a2925 100644 --- a/scenarios/tls.benchmarks.yml +++ b/scenarios/tls.benchmarks.yml @@ -15,9 +15,9 @@ jobs: project: src/BenchmarksApps/TLS/HttpSys/HttpSys.csproj readyStateText: Application started. variables: - mTLS: false + mTLS: false # enables settings on http.sys to negotiate client cert on connections + tlsRenegotiation: false # enables client cert validation certValidationConsoleEnabled: false - tlsRenegotiation: false httpSysLogs: false statsEnabled: false arguments: "--urls https://{{serverAddress}}:{{serverPort}} --mTLS {{mTLS}} --certValidationConsoleEnabled {{certValidationConsoleEnabled}} --statsEnabled {{statsEnabled}} --tlsRenegotiation {{tlsRenegotiation}} --httpSysLogs {{httpSysLogs}}" @@ -54,8 +54,8 @@ scenarios: application: job: httpSysServer variables: - mTLS: true - tlsRenegotiation: true + mTLS: true # enables settings on http.sys to negotiate client cert on connections + tlsRenegotiation: true # enables client cert validation httpSysLogs: false # only for debug purposes certValidationConsoleEnabled: false # only for debug purposes load: @@ -72,7 +72,9 @@ scenarios: application: job: httpSysServer variables: - mTLS: true + mTLS: false + tlsRenegotiation: true + httpSysLogs: false # only for debug purposes certValidationConsoleEnabled: false # only for debug purposes load: job: httpclient From adbba73ee1fd904ea4c63debda59db4a08364de8 Mon Sep 17 00:00:00 2001 From: Dmitrii Korolev Date: Tue, 14 Jan 2025 22:05:29 +0100 Subject: [PATCH 12/18] minor --- src/BenchmarksApps/TLS/HttpSys/Program.cs | 3 +-- src/BenchmarksApps/TLS/HttpSys/appsettings.Development.json | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/BenchmarksApps/TLS/HttpSys/Program.cs b/src/BenchmarksApps/TLS/HttpSys/Program.cs index 31043be07..2bcd51b9b 100644 --- a/src/BenchmarksApps/TLS/HttpSys/Program.cs +++ b/src/BenchmarksApps/TLS/HttpSys/Program.cs @@ -129,5 +129,4 @@ void OnShutdown() Console.WriteLine("--------------------------------"); Console.WriteLine("Application started."); -await app.WaitForShutdownAsync(); - +await app.WaitForShutdownAsync(); \ No newline at end of file diff --git a/src/BenchmarksApps/TLS/HttpSys/appsettings.Development.json b/src/BenchmarksApps/TLS/HttpSys/appsettings.Development.json index 9bbb0fbcb..116355112 100644 --- a/src/BenchmarksApps/TLS/HttpSys/appsettings.Development.json +++ b/src/BenchmarksApps/TLS/HttpSys/appsettings.Development.json @@ -5,7 +5,8 @@ "Microsoft.AspNetCore": "Warning" } }, - "mTLS": "true", + "mTLS": "false", + "httpSysLogs": "true", "tlsRenegotiation": "true", "certValidationConsoleEnabled": "true" } From 2f5437e18846bdaa5f79851aeeba2493b6ab6667 Mon Sep 17 00:00:00 2001 From: Dmitrii Korolev Date: Wed, 15 Jan 2025 12:00:23 +0100 Subject: [PATCH 13/18] address PR comment --- src/BenchmarksApps/TLS/HttpSys/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BenchmarksApps/TLS/HttpSys/Program.cs b/src/BenchmarksApps/TLS/HttpSys/Program.cs index 2bcd51b9b..630e58317 100644 --- a/src/BenchmarksApps/TLS/HttpSys/Program.cs +++ b/src/BenchmarksApps/TLS/HttpSys/Program.cs @@ -44,7 +44,7 @@ if (mTlsEnabled) { - var hostAppLifetime = app.Services.GetService(); + var hostAppLifetime = app.Services.GetRequiredService(); hostAppLifetime!.ApplicationStopping.Register(OnShutdown); void OnShutdown() From 754adeea8af7f4adcaf900881bebb60ae3c68340 Mon Sep 17 00:00:00 2001 From: Dmitrii Korolev Date: Wed, 15 Jan 2025 19:47:27 +0100 Subject: [PATCH 14/18] address PR comments + change port to high-value (no intersection with other tests) --- scenarios/tls.benchmarks.yml | 1 + .../TLS/HttpSys/NetShWrapper.cs | 19 ++++++++++++++++--- src/BenchmarksApps/TLS/HttpSys/Program.cs | 3 +++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/scenarios/tls.benchmarks.yml b/scenarios/tls.benchmarks.yml index bb50a2925..c6da21477 100644 --- a/scenarios/tls.benchmarks.yml +++ b/scenarios/tls.benchmarks.yml @@ -58,6 +58,7 @@ scenarios: tlsRenegotiation: true # enables client cert validation httpSysLogs: false # only for debug purposes certValidationConsoleEnabled: false # only for debug purposes + serverPort: 30000 # IMPORTANT: not to intersect with other tests load: job: httpclient variables: diff --git a/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs b/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs index 8cced738a..2894d76a8 100644 --- a/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs +++ b/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs @@ -5,6 +5,18 @@ namespace HttpSys { public static class NetShWrapper { + public static void DisableHttpSysMutualTlsIfExists(string ipPort) + { + try + { + DisableHttpSysMutualTls(ipPort); + } + catch + { + // ignore + } + } + public static void DisableHttpSysMutualTls(string ipPort) { Console.WriteLine("Disabling mTLS for http.sys"); @@ -70,9 +82,10 @@ private static void ExecuteNetShCommand(string command, bool alwaysLogOutput = f } #pragma warning disable SYSLIB0057 // Type or member is obsolete - private static X509Certificate2 LoadCertificate() => File.Exists("testCert.pfx") - ? new X509Certificate2("testCert.pfx", "testPassword", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable) - : new X509Certificate2("../testCert.pfx", "testPassword", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable); + private static X509Certificate2 LoadCertificate() + => File.Exists("testCert.pfx") + ? X509CertificateLoader.LoadPkcs12FromFile("testCert.pfx", "testPassword", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable) + : X509CertificateLoader.LoadPkcs12FromFile("../testCert.pfx", "testPassword", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable) #pragma warning restore SYSLIB0057 // Type or member is obsolete } } diff --git a/src/BenchmarksApps/TLS/HttpSys/Program.cs b/src/BenchmarksApps/TLS/HttpSys/Program.cs index 630e58317..2ab338cb1 100644 --- a/src/BenchmarksApps/TLS/HttpSys/Program.cs +++ b/src/BenchmarksApps/TLS/HttpSys/Program.cs @@ -64,6 +64,9 @@ void OnShutdown() try { + // if not executed, following command (enable http.sys mutual tls) will fail because binding exists + NetShWrapper.DisableHttpSysMutualTlsIfExists(ipPort: httpsIpPort); + NetShWrapper.EnableHttpSysMutualTls(ipPort: httpsIpPort); } catch From fad204121e1dbe36e4fd8466865fd3d4008d8d16 Mon Sep 17 00:00:00 2001 From: Dmitrii Korolev Date: Wed, 15 Jan 2025 19:59:51 +0100 Subject: [PATCH 15/18] typo --- src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs b/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs index 2894d76a8..13f8bbf1d 100644 --- a/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs +++ b/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs @@ -85,7 +85,7 @@ private static void ExecuteNetShCommand(string command, bool alwaysLogOutput = f private static X509Certificate2 LoadCertificate() => File.Exists("testCert.pfx") ? X509CertificateLoader.LoadPkcs12FromFile("testCert.pfx", "testPassword", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable) - : X509CertificateLoader.LoadPkcs12FromFile("../testCert.pfx", "testPassword", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable) + : X509CertificateLoader.LoadPkcs12FromFile("../testCert.pfx", "testPassword", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable); #pragma warning restore SYSLIB0057 // Type or member is obsolete } } From 2b5c4d9be5e93c0525684e9b19973984c0b8be1b Mon Sep 17 00:00:00 2001 From: Dmitrii Korolev Date: Wed, 15 Jan 2025 20:01:40 +0100 Subject: [PATCH 16/18] remove pragmas --- src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs b/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs index 13f8bbf1d..f7ef2410b 100644 --- a/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs +++ b/src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs @@ -81,11 +81,9 @@ private static void ExecuteNetShCommand(string command, bool alwaysLogOutput = f } } -#pragma warning disable SYSLIB0057 // Type or member is obsolete private static X509Certificate2 LoadCertificate() => File.Exists("testCert.pfx") ? X509CertificateLoader.LoadPkcs12FromFile("testCert.pfx", "testPassword", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable) : X509CertificateLoader.LoadPkcs12FromFile("../testCert.pfx", "testPassword", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable); -#pragma warning restore SYSLIB0057 // Type or member is obsolete } } From 1503f746af6af06a06ec22396f137357d2882ece Mon Sep 17 00:00:00 2001 From: Dmitrii Korolev Date: Wed, 15 Jan 2025 20:39:40 +0100 Subject: [PATCH 17/18] sync client port and server port --- scenarios/tls.benchmarks.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/scenarios/tls.benchmarks.yml b/scenarios/tls.benchmarks.yml index c6da21477..bd8654aed 100644 --- a/scenarios/tls.benchmarks.yml +++ b/scenarios/tls.benchmarks.yml @@ -62,6 +62,7 @@ scenarios: load: job: httpclient variables: + serverPort: 30000 # in sync with server path: /hello-world presetHeaders: connectionclose connections: 32 From c69e2ce9b97242a62b9bf44fa6edfbfa497b3d77 Mon Sep 17 00:00:00 2001 From: Dmitrii Korolev Date: Wed, 15 Jan 2025 21:22:51 +0100 Subject: [PATCH 18/18] port 8080 --- scenarios/tls.benchmarks.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scenarios/tls.benchmarks.yml b/scenarios/tls.benchmarks.yml index bd8654aed..276976b14 100644 --- a/scenarios/tls.benchmarks.yml +++ b/scenarios/tls.benchmarks.yml @@ -58,11 +58,11 @@ scenarios: tlsRenegotiation: true # enables client cert validation httpSysLogs: false # only for debug purposes certValidationConsoleEnabled: false # only for debug purposes - serverPort: 30000 # IMPORTANT: not to intersect with other tests + serverPort: 8080 # IMPORTANT: not to intersect with other tests in case http.sys configuration impacts other benchmarks load: job: httpclient variables: - serverPort: 30000 # in sync with server + serverPort: 8080 # in sync with server path: /hello-world presetHeaders: connectionclose connections: 32