From 67231c86afb3090cff448948c40ce7a6a0661a22 Mon Sep 17 00:00:00 2001 From: Oliver Booth Date: Sat, 12 Aug 2023 18:35:57 +0100 Subject: [PATCH] refactor: delegate ssl cert read to common lib --- OliverBooth.Common/.gitignore | 1 + .../Extensions/WebHostBuilderExtensions.cs | 41 +++++++++++++++++++ OliverBooth.Common/OliverBooth.Common.csproj | 20 +++++++++ OliverBooth.sln | 8 +++- OliverBooth/OliverBooth.csproj | 5 ++- OliverBooth/Program.cs | 34 ++------------- 6 files changed, 76 insertions(+), 33 deletions(-) create mode 100644 OliverBooth.Common/.gitignore create mode 100644 OliverBooth.Common/Extensions/WebHostBuilderExtensions.cs create mode 100644 OliverBooth.Common/OliverBooth.Common.csproj diff --git a/OliverBooth.Common/.gitignore b/OliverBooth.Common/.gitignore new file mode 100644 index 0000000..701678b --- /dev/null +++ b/OliverBooth.Common/.gitignore @@ -0,0 +1 @@ +wwwroot diff --git a/OliverBooth.Common/Extensions/WebHostBuilderExtensions.cs b/OliverBooth.Common/Extensions/WebHostBuilderExtensions.cs new file mode 100644 index 0000000..3443e9a --- /dev/null +++ b/OliverBooth.Common/Extensions/WebHostBuilderExtensions.cs @@ -0,0 +1,41 @@ +using System.Runtime.InteropServices; +using System.Security.Cryptography.X509Certificates; +using Microsoft.AspNetCore.Hosting; + +namespace OliverBooth.Common.Extensions; + +public static class WebHostBuilderExtensions +{ + public static IWebHostBuilder AddCertificateFromEnvironment(this IWebHostBuilder builder) + { + return builder.UseKestrel(options => + { + string certPath = Environment.GetEnvironmentVariable("SSL_CERT_PATH")!; + if (!File.Exists(certPath)) + { + options.ListenAnyIP(5049); + return; + } + + string? keyPath = Environment.GetEnvironmentVariable("SSL_KEY_PATH"); + if (string.IsNullOrWhiteSpace(keyPath) || !File.Exists(keyPath)) keyPath = null; + + options.ListenAnyIP(2845, options => + { + X509Certificate2 cert = CreateCertFromPemFile(certPath, keyPath); + options.UseHttps(cert); + }); + return; + + static X509Certificate2 CreateCertFromPemFile(string certPath, string? keyPath) + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return X509Certificate2.CreateFromPemFile(certPath, keyPath); + + //workaround for windows issue https://github.com/dotnet/runtime/issues/23749#issuecomment-388231655 + using var cert = X509Certificate2.CreateFromPemFile(certPath, keyPath); + return new X509Certificate2(cert.Export(X509ContentType.Pkcs12)); + } + }); + } +} diff --git a/OliverBooth.Common/OliverBooth.Common.csproj b/OliverBooth.Common/OliverBooth.Common.csproj new file mode 100644 index 0000000..dc46373 --- /dev/null +++ b/OliverBooth.Common/OliverBooth.Common.csproj @@ -0,0 +1,20 @@ + + + + net7.0 + enable + enable + true + + + + + + + + + + + + + diff --git a/OliverBooth.sln b/OliverBooth.sln index 4484d78..1895954 100644 --- a/OliverBooth.sln +++ b/OliverBooth.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OliverBooth", "OliverBooth\OliverBooth.csproj", "{A58A6FA3-480C-400B-822A-3786741BF39C}" EndProject @@ -31,6 +31,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ts", "ts", "{BB9F76AC-292A- src\ts\Input.ts = src\ts\Input.ts EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OliverBooth.Common", "OliverBooth.Common\OliverBooth.Common.csproj", "{38DEB2FA-3DF4-4D37-A12D-22CAEEA3A8AB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -41,6 +43,10 @@ Global {A58A6FA3-480C-400B-822A-3786741BF39C}.Debug|Any CPU.Build.0 = Debug|Any CPU {A58A6FA3-480C-400B-822A-3786741BF39C}.Release|Any CPU.ActiveCfg = Release|Any CPU {A58A6FA3-480C-400B-822A-3786741BF39C}.Release|Any CPU.Build.0 = Release|Any CPU + {38DEB2FA-3DF4-4D37-A12D-22CAEEA3A8AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {38DEB2FA-3DF4-4D37-A12D-22CAEEA3A8AB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {38DEB2FA-3DF4-4D37-A12D-22CAEEA3A8AB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {38DEB2FA-3DF4-4D37-A12D-22CAEEA3A8AB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {822F528E-3CA7-4B7D-9250-BD248ADA7BAE} = {8A323E64-E41E-4780-99FD-17BF58961FB5} diff --git a/OliverBooth/OliverBooth.csproj b/OliverBooth/OliverBooth.csproj index 8f79f91..27f8dbe 100644 --- a/OliverBooth/OliverBooth.csproj +++ b/OliverBooth/OliverBooth.csproj @@ -17,7 +17,6 @@ - @@ -26,4 +25,8 @@ + + + + diff --git a/OliverBooth/Program.cs b/OliverBooth/Program.cs index 4f79459..2b6b6b7 100644 --- a/OliverBooth/Program.cs +++ b/OliverBooth/Program.cs @@ -1,8 +1,7 @@ -using System.Runtime.InteropServices; -using System.Security.Cryptography.X509Certificates; using Markdig; using NLog; using NLog.Extensions.Logging; +using OliverBooth.Common.Extensions; using OliverBooth.Data; using OliverBooth.Markdown.Template; using OliverBooth.Markdown.Timestamp; @@ -18,6 +17,7 @@ builder.Logging.AddNLog(); builder.Services.AddHostedSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); +builder.Services.AddHostedSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(provider => new MarkdownPipelineBuilder() @@ -41,35 +41,7 @@ builder.Services.AddCors(options => options.AddPolicy("BlogApi", policy => (buil .AllowAnyHeader())); builder.Services.AddRouting(options => options.LowercaseUrls = true); -builder.WebHost.UseKestrel(kestrel => -{ - string certPath = Environment.GetEnvironmentVariable("SSL_CERT_PATH")!; - if (!File.Exists(certPath)) - { - kestrel.ListenAnyIP(5049); - return; - } - - string? keyPath = Environment.GetEnvironmentVariable("SSL_KEY_PATH"); - if (string.IsNullOrWhiteSpace(keyPath) || !File.Exists(keyPath)) keyPath = null; - - kestrel.ListenAnyIP(2845, options => - { - X509Certificate2 cert = CreateCertFromPemFile(certPath, keyPath); - options.UseHttps(cert); - }); - return; - - static X509Certificate2 CreateCertFromPemFile(string certPath, string? keyPath) - { - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - return X509Certificate2.CreateFromPemFile(certPath, keyPath); - - //workaround for windows issue https://github.com/dotnet/runtime/issues/23749#issuecomment-388231655 - using var cert = X509Certificate2.CreateFromPemFile(certPath, keyPath); - return new X509Certificate2(cert.Export(X509ContentType.Pkcs12)); - } -}); +builder.WebHost.AddCertificateFromEnvironment(); WebApplication app = builder.Build();