diff --git a/Finch/Configuration/FinchConfigurationModule.cs b/Finch/Configuration/FinchConfigurationModule.cs index 0f3f286d..9d6262b3 100644 --- a/Finch/Configuration/FinchConfigurationModule.cs +++ b/Finch/Configuration/FinchConfigurationModule.cs @@ -15,6 +15,7 @@ internal class FinchConfigurationModule : FinchModule opts.ServiceProvider = svc; opts.Version = "1.0.0-alpha.1"; opts.TokenExpiration = TimeSpan.FromHours(3); + opts.DataProtectionStoragePath = "../cache/dpkeys"; }).Bind(configuration.GetSection("Finch")); services.AddTransient(factory => factory.GetService>().Value); diff --git a/Finch/Configuration/FinchOptions.cs b/Finch/Configuration/FinchOptions.cs index 59445a7c..d8b96382 100644 --- a/Finch/Configuration/FinchOptions.cs +++ b/Finch/Configuration/FinchOptions.cs @@ -18,6 +18,9 @@ public class FinchOptions : IFinchOptions /// public TimeSpan TokenExpiration { get; set; } + /// + public string DataProtectionStoragePath { get; set; } + internal IServiceProvider ServiceProvider { get; set; } @@ -55,7 +58,7 @@ public interface IFinchOptions public string Language { get; set; } /// - /// Name of the app (used in logging and otehr areas) + /// Name of the app (used in logging and other areas) /// public string AppName { get; set; } @@ -64,6 +67,11 @@ public interface IFinchOptions /// TimeSpan TokenExpiration { get; set; } + /// + /// The path to data protection key storage, when the keys are persisted to the filesystem + /// + string DataProtectionStoragePath { get; set; } + /// /// Get typed options (proxy to IOptions) /// diff --git a/Finch/Finch.csproj b/Finch/Finch.csproj index 44a2552b..8e659e17 100644 --- a/Finch/Finch.csproj +++ b/Finch/Finch.csproj @@ -14,10 +14,10 @@ - + - + diff --git a/Finch/Logging/LogLevelOverrides.cs b/Finch/Logging/LogLevelOverrides.cs index 2ff6d4ae..fd632cf1 100644 --- a/Finch/Logging/LogLevelOverrides.cs +++ b/Finch/Logging/LogLevelOverrides.cs @@ -24,6 +24,7 @@ public class LogLevelOverrides : Dictionary this["Quartz"] = LogLevel.Warning; this["Microsoft.AspNetCore"] = LogLevel.Warning; this["System.Net.Http.HttpClient"] = LogLevel.Warning; + this["Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager"] = LogLevel.Error; string executingAssemblyName = Assembly.GetExecutingAssembly().GetName().Name; if (executingAssemblyName != null) diff --git a/Finch/Security/FinchSecurityModule.cs b/Finch/Security/FinchSecurityModule.cs index 23842000..29bd765e 100644 --- a/Finch/Security/FinchSecurityModule.cs +++ b/Finch/Security/FinchSecurityModule.cs @@ -1,8 +1,16 @@ -using Microsoft.AspNetCore.Builder; +using System.IO; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.AspNetCore.DataProtection.Repositories; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; using PowCapServer; using PowCapServer.Abstractions; @@ -19,19 +27,24 @@ internal class FinchSecurityModule : FinchModule services.TryAddTransient(); services.Configure(opts => opts.Default = captchaSection.Get() ?? new CaptchaOptions()); services.AddOptions().Bind(captchaSection); + + services.AddDataProtection(); + services.AddSingleton>(s => + { + ILoggerFactory loggerFactory = s.GetService() ?? NullLoggerFactory.Instance; + FinchOptions finchOptions = s.GetService>().Value; + string contentRootPath = s.GetService().ContentRootPath; + + return new ConfigureOptions(options => + { + string keyPath = Path.GetFullPath(Path.Combine(contentRootPath, finchOptions.DataProtectionStoragePath)); + options.XmlRepository = new FileSystemXmlRepository(new DirectoryInfo(keyPath), loggerFactory); + }); + }); } public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) { - // if (app is WebApplication webApp) - // { - // webApp.MapGet("/teamup/sync", async (ISchedulerFactory scheduler) => - // { - // await SyncTeamUpDataJob.RunNow(scheduler); - // return "done"; - // }); - // } - StaticCaptchaService.Configure(serviceProvider); } } \ No newline at end of file