Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions scenarios/tls.benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ jobs:
tlsRenegotiation: false # enables client cert validation
# debug settings
certValidationConsoleEnabled: false
httpSysLogs: false
statsEnabled: false
logRequestDetails: false
arguments: "--urls https://{{serverAddress}}:{{serverPort}} --mTLS {{mTLS}} --certValidationConsoleEnabled {{certValidationConsoleEnabled}} --statsEnabled {{statsEnabled}} --tlsRenegotiation {{tlsRenegotiation}} --httpSysLogs {{httpSysLogs}} --logRequestDetails {{logRequestDetails}}"
arguments: "--urls https://{{serverAddress}}:{{serverPort}} --mTLS {{mTLS}} --certValidationConsoleEnabled {{certValidationConsoleEnabled}} --statsEnabled {{statsEnabled}} --tlsRenegotiation {{tlsRenegotiation}} --logRequestDetails {{logRequestDetails}}"

kestrelServer:
source:
Expand Down Expand Up @@ -81,7 +80,6 @@ scenarios:
variables:
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
serverPort: 8080 # IMPORTANT: not to intersect with other tests in case http.sys configuration impacts other benchmarks
load:
Expand All @@ -102,7 +100,6 @@ scenarios:
variables:
mTLS: false
tlsRenegotiation: true
httpSysLogs: false # only for debug purposes
certValidationConsoleEnabled: false # only for debug purposes
load:
job: httpclient
Expand Down
68 changes: 55 additions & 13 deletions src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
using System.Diagnostics;
using System.Security.Cryptography.X509Certificates;
using System.Text.RegularExpressions;

namespace HttpSys
{
public static class NetShWrapper
{
public static void DisableHttpSysMutualTlsIfExists(string ipPort)
public static void DeleteBindingIfExists(string ipPort)
{
try
{
DisableHttpSysMutualTls(ipPort);
DeleteBinding(ipPort);
}
catch
{
// ignore
}
}

public static void DisableHttpSysMutualTls(string ipPort)
public static void DeleteBinding(string ipPort)
{
Console.WriteLine("Disabling mTLS for http.sys");

Expand All @@ -27,14 +28,42 @@
Console.WriteLine("Disabled http.sys settings for mTLS");
}

public static bool BindingExists(string ipPort, out string certThumbprint, out string appId)
{
certThumbprint = string.Empty;
appId = string.Empty;

var bindings = ExecuteNetShCommand("http show sslcert");
if (string.IsNullOrEmpty(bindings) || !bindings.Contains(ipPort))
{
return false;
}

// Extract the certificate thumbprint
var thumbprintMatch = Regex.Match(bindings, @"Certificate Hash\s+:\s+([a-fA-F0-9]+)");
if (thumbprintMatch.Success)
{
certThumbprint = thumbprintMatch.Groups[1].Value;
}

// Extract the application ID
var appIdMatch = Regex.Match(bindings, @"Application ID\s+:\s+{([a-fA-F0-9-]+)}");
if (appIdMatch.Success)
{
appId = appIdMatch.Groups[1].Value;
}

return true;
}

public static void Show()
{
ExecuteNetShCommand("http show sslcert", alwaysLogOutput: true);
}

public static void EnableHttpSysMutualTls(string ipPort)
public static void SetTestCertBinding(string ipPort, bool enableClientCertNegotiation)
{
Console.WriteLine("Setting up mTLS for http.sys");
Console.WriteLine("Setting up binding for testCert for http.sys");

var certificate = LoadCertificate();
Console.WriteLine("Loaded `testCert.pfx` from local file system");
Expand All @@ -47,25 +76,36 @@
}

string certThumbprint = certificate.Thumbprint;
string appId = Guid.NewGuid().ToString();
SetCertBinding(ipPort, certThumbprint, enableClientCertNegotiation: enableClientCertNegotiation);

string command = $"http add sslcert ipport={ipPort} certstorename=MY certhash={certThumbprint} appid={{{appId}}} clientcertnegotiation=enable";
ExecuteNetShCommand(command);
Console.WriteLine("Configured binding for testCert for http.sys");
}

Console.WriteLine("Configured http.sys settings for mTLS");
public static void SetCertBinding(string ipPort, string certThumbprint, string appId = null, bool enableClientCertNegotiation = false)

Check warning on line 84 in src/BenchmarksApps/TLS/HttpSys/NetShWrapper.cs

View workflow job for this annotation

GitHub Actions / Build & Test (ubuntu-latest)

Cannot convert null literal to non-nullable reference type.
{
var negotiateClientCert = enableClientCertNegotiation ? "enable" : "disable";
if (string.IsNullOrEmpty(appId))
{
appId = "00000000-0000-0000-0000-000000000000";
}
string command = $"http add sslcert ipport={ipPort} certstorename=MY certhash={certThumbprint} appid={{{appId}}} clientcertnegotiation={negotiateClientCert}";
ExecuteNetShCommand(command);
}

private static void ExecuteNetShCommand(string command, bool alwaysLogOutput = false)
private static string ExecuteNetShCommand(string command, bool alwaysLogOutput = false)
=> ExecuteCommand("netsh", command, alwaysLogOutput);

private static string ExecuteCommand(string fileName, string command, bool alwaysLogOutput = false)
{
ProcessStartInfo processInfo = new ProcessStartInfo("netsh", command)
ProcessStartInfo processInfo = new ProcessStartInfo(fileName, command)
{
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};

Console.WriteLine($"Executing command: `netsh {command}`");
Console.WriteLine($"Executing command: `{fileName} {command}`");
using Process process = Process.Start(processInfo)!;
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
Expand All @@ -77,8 +117,10 @@

if (process.ExitCode != 0)
{
throw new InvalidOperationException($"netsh command execution failure: {output}");
throw new InvalidOperationException($"{fileName} command execution failure: {output}");
}

return output;
}

private static X509Certificate2 LoadCertificate()
Expand Down
22 changes: 13 additions & 9 deletions src/BenchmarksApps/TLS/HttpSys/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
builder.Logging.ClearProviders();

// behavioral
var httpSysLoggingEnabled = bool.TryParse(builder.Configuration["httpSysLogs"], out var httpSysLogsEnabled) && httpSysLogsEnabled;
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/";
Expand All @@ -18,6 +17,13 @@
var statsEnabled = bool.TryParse(builder.Configuration["statsEnabled"], out var connectionStatsEnabledConfig) && connectionStatsEnabledConfig;
var logRequestDetails = bool.TryParse(builder.Configuration["logRequestDetails"], out var logRequestDetailsConfig) && logRequestDetailsConfig;

// existing netsh bindings to restore after the benchmark run
if (!NetShWrapper.BindingExists(httpsIpPort, out var originalCertThumbprint, out var originalAppId))
{
Console.WriteLine("WARNING: no binding existed...");
throw new ApplicationException($"SslCert binding should exist for '{httpsIpPort}' before. Infrastructure error.");
}

#pragma warning disable CA1416 // Can be launched only on Windows (HttpSys)
builder.WebHost.UseHttpSys(options =>
{
Expand Down Expand Up @@ -81,7 +87,9 @@ void OnShutdown()

try
{
NetShWrapper.DisableHttpSysMutualTls(ipPort: httpsIpPort);
NetShWrapper.DeleteBinding(ipPort: httpsIpPort);
NetShWrapper.SetCertBinding(ipPort: httpsIpPort, certThumbprint: originalCertThumbprint, appId: originalAppId);
NetShWrapper.Show();
}
catch
{
Expand All @@ -93,9 +101,8 @@ 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);
NetShWrapper.DeleteBindingIfExists(ipPort: httpsIpPort);
NetShWrapper.SetTestCertBinding(ipPort: httpsIpPort, enableClientCertNegotiation: true);
}
catch
{
Expand Down Expand Up @@ -138,10 +145,7 @@ void OnShutdown()

await app.StartAsync();

if (httpSysLoggingEnabled)
{
NetShWrapper.Show();
}
NetShWrapper.Show();

Console.WriteLine("Application Info:");
if (mTlsEnabled)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "hello-world",
"applicationUrl": "https://localhost:5000;http://localhost:5001",
"applicationUrl": "https://127.0.0.1:5000;http://localhost:5001",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
Expand Down
Loading