using Microsoft.AspNetCore.DataProtection; using Tiku.Infrastructure.Persistence; using Tiku.Infrastructure.Security; namespace Tiku.Api.Configuration; internal static class DataProtectionExtensions { internal static IServiceCollection AddApiDataProtection( this IServiceCollection services, IConfiguration configuration, IHostEnvironment environment) { var requireProtectedKeys = !environment.IsDevelopment(); services.AddOptions() .Bind(configuration.GetSection(DataProtectionKeyRingOptions.SectionName)) .PostConfigure(options => ApplyEnvironmentOverrides(options, configuration)) .Validate( options => DataProtectionKeyRingOptions.BeValid(options, requireProtectedKeys), "Data Protection requires an application name and, outside Development, an X509 certificate path.") .ValidateOnStart(); var keyRingOptions = configuration .GetSection(DataProtectionKeyRingOptions.SectionName) .Get() ?? new DataProtectionKeyRingOptions(); ApplyEnvironmentOverrides(keyRingOptions, configuration); if (!DataProtectionKeyRingOptions.BeValid(keyRingOptions, requireProtectedKeys)) throw new InvalidOperationException( "Data Protection requires an application name and, outside Development, an X509 certificate path."); var dataProtection = services .AddDataProtection() .SetApplicationName(keyRingOptions.ApplicationName.Trim()) .PersistKeysToDbContext(); var certificate = keyRingOptions.LoadCertificate(requireProtectedKeys); if (certificate is not null) dataProtection.ProtectKeysWithCertificate(certificate); return services; } private static void ApplyEnvironmentOverrides( DataProtectionKeyRingOptions options, IConfiguration configuration) { options.ApplicationName = configuration["TIKU_DATA_PROTECTION_APPLICATION_NAME"] ?? options.ApplicationName; options.CertificatePath = configuration["TIKU_DATA_PROTECTION_CERTIFICATE_PATH"] ?? options.CertificatePath; options.CertificatePassword = configuration["TIKU_DATA_PROTECTION_CERTIFICATE_PASSWORD"] ?? options.CertificatePassword; } }