diff --git a/IssuerDrivingLicense/IssuerDrivingLicense.csproj b/IssuerDrivingLicense/IssuerDrivingLicense.csproj index de0e688..8892c69 100644 --- a/IssuerDrivingLicense/IssuerDrivingLicense.csproj +++ b/IssuerDrivingLicense/IssuerDrivingLicense.csproj @@ -21,8 +21,8 @@ - - + + diff --git a/IssuerDrivingLicense/Program.cs b/IssuerDrivingLicense/Program.cs index 0bc8621..1f488ae 100644 --- a/IssuerDrivingLicense/Program.cs +++ b/IssuerDrivingLicense/Program.cs @@ -1,18 +1,78 @@ -namespace IssuerDrivingLicense; +using System.Configuration; +using IssuerDrivingLicense; +using IssuerDrivingLicense.Persistence; +using Microsoft.AspNetCore.Authentication.OpenIdConnect; +using Microsoft.AspNetCore.Server.Kestrel.Core; +using Microsoft.EntityFrameworkCore; +using Microsoft.Identity.Web.UI; +using Microsoft.Identity.Web; -public class Program +var builder = WebApplication.CreateBuilder(args); + +builder.WebHost.ConfigureKestrel(serverOptions => +{ + serverOptions.AddServerHeader = false; +}); + +var services = builder.Services; +var configuration = builder.Configuration; + +services.Configure(options => +{ + options.AllowSynchronousIO = true; +}); + +services.AddSecurityHeaderPolicies() + .SetPolicySelector(ctx => SecurityHeadersDefinitions + .GetHeaderPolicyCollection(builder.Environment.IsDevelopment())); + +services.Configure(configuration.GetSection("CredentialSettings")); +services.AddScoped(); +services.AddScoped(); + +services.AddDatabaseDeveloperPageExceptionFilter(); +services.AddDbContext(options => + options.UseSqlServer( + configuration.GetConnectionString("DefaultConnection"))); + +services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) + .AddMicrosoftIdentityWebApp(configuration.GetSection("AzureAd")); + +services.AddAuthorization(options => +{ + options.FallbackPolicy = options.DefaultPolicy; +}); + +services.AddDistributedMemoryCache(); + +services.AddRazorPages() + .AddMvcOptions(options => { }) + .AddMicrosoftIdentityUI(); + +services.AddRazorPages(); + +var app = builder.Build(); + +app.UseSecurityHeaders(); + +if (app.Environment.IsDevelopment()) +{ + app.UseDeveloperExceptionPage(); +} +else { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } - - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder - .ConfigureKestrel(options => options.AddServerHeader = false) - .UseStartup(); - }); + app.UseExceptionHandler("/Error"); } + +app.UseHttpsRedirection(); +app.UseStaticFiles(); + +app.UseRouting(); + +app.UseAuthentication(); +app.UseAuthorization(); + +app.MapRazorPages(); +app.MapControllers(); + +app.Run(); diff --git a/IssuerDrivingLicense/SecurityHeadersDefinitions.cs b/IssuerDrivingLicense/SecurityHeadersDefinitions.cs index d5ffdeb..99ee508 100644 --- a/IssuerDrivingLicense/SecurityHeadersDefinitions.cs +++ b/IssuerDrivingLicense/SecurityHeadersDefinitions.cs @@ -2,13 +2,22 @@ namespace IssuerDrivingLicense; public static class SecurityHeadersDefinitions { + private static HeaderPolicyCollection? policy; + public static HeaderPolicyCollection GetHeaderPolicyCollection(bool isDev) { - var policy = new HeaderPolicyCollection() + // Avoid building a new HeaderPolicyCollection on every request for performance reasons. + // Where possible, cache and reuse HeaderPolicyCollection instances. + if (policy != null) + { + return policy; + } + + policy = new HeaderPolicyCollection() .AddFrameOptionsDeny() - .AddXssProtectionBlock() .AddContentTypeOptionsNoSniff() .AddReferrerPolicyStrictOriginWhenCrossOrigin() + .RemoveServerHeader() .AddCrossOriginOpenerPolicy(builder => builder.SameOrigin()) .AddCrossOriginEmbedderPolicy(builder => builder.RequireCorp()) .AddCrossOriginResourcePolicy(builder => builder.SameOrigin()) @@ -17,32 +26,14 @@ public static HeaderPolicyCollection GetHeaderPolicyCollection(bool isDev) builder.AddObjectSrc().None(); builder.AddBlockAllMixedContent(); builder.AddImgSrc().Self().From("data:"); - builder.AddFormAction().Self(); builder.AddFontSrc().Self(); + builder.AddFormAction().Self(); builder.AddStyleSrc().Self().UnsafeInline(); builder.AddBaseUri().Self(); - builder.AddScriptSrc().Self().UnsafeInline().WithNonce(); + builder.AddScriptSrc().UnsafeInline().WithNonce(); builder.AddFrameAncestors().None(); - //builder.AddCustomDirective("require-trusted-types-for", "'script'"); }) - .RemoveServerHeader() - .AddPermissionsPolicy(builder => - { - builder.AddAccelerometer().None(); - builder.AddAutoplay().None(); - builder.AddCamera().None(); - builder.AddEncryptedMedia().None(); - builder.AddFullscreen().All(); - builder.AddGeolocation().None(); - builder.AddGyroscope().None(); - builder.AddMagnetometer().None(); - builder.AddMicrophone().None(); - builder.AddMidi().None(); - builder.AddPayment().None(); - builder.AddPictureInPicture().None(); - builder.AddSyncXHR().None(); - builder.AddUsb().None(); - }); + .AddPermissionsPolicyWithDefaultSecureDirectives(); if (!isDev) { @@ -50,8 +41,6 @@ public static HeaderPolicyCollection GetHeaderPolicyCollection(bool isDev) policy.AddStrictTransportSecurityMaxAgeIncludeSubDomains(maxAgeInSeconds: 60 * 60 * 24 * 365); } - policy.ApplyDocumentHeadersToAllResponses(); - return policy; } } diff --git a/IssuerDrivingLicense/Startup.cs b/IssuerDrivingLicense/Startup.cs deleted file mode 100644 index 06f47c1..0000000 --- a/IssuerDrivingLicense/Startup.cs +++ /dev/null @@ -1,78 +0,0 @@ -using IssuerDrivingLicense.Persistence; -using Microsoft.AspNetCore.Authentication.OpenIdConnect; -using Microsoft.AspNetCore.Server.Kestrel.Core; -using Microsoft.EntityFrameworkCore; -using Microsoft.Identity.Web; -using Microsoft.Identity.Web.UI; - -namespace IssuerDrivingLicense; - -public class Startup -{ - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - public void ConfigureServices(IServiceCollection services) - { - services.Configure(options => - { - options.AllowSynchronousIO = true; - }); - - services.Configure(Configuration.GetSection("CredentialSettings")); - services.AddScoped(); - services.AddScoped(); - - services.AddDatabaseDeveloperPageExceptionFilter(); - services.AddDbContext(options => - options.UseSqlServer( - Configuration.GetConnectionString("DefaultConnection"))); - - services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")); - - services.AddAuthorization(options => - { - options.FallbackPolicy = options.DefaultPolicy; - }); - - services.AddDistributedMemoryCache(); - - services.AddRazorPages() - .AddMvcOptions(options => { }) - .AddMicrosoftIdentityUI(); - } - - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - app.UseSecurityHeaders(SecurityHeadersDefinitions - .GetHeaderPolicyCollection(env.IsDevelopment())); - - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - app.UseExceptionHandler("/Error"); - } - - app.UseHttpsRedirection(); - app.UseStaticFiles(); - - app.UseRouting(); - - app.UseAuthentication(); - app.UseAuthorization(); - - app.UseEndpoints(endpoints => - { - endpoints.MapRazorPages(); - endpoints.MapControllers(); - }); - } -} diff --git a/VerifierInsuranceCompany/Program.cs b/VerifierInsuranceCompany/Program.cs index 2877105..8a6ecaa 100644 --- a/VerifierInsuranceCompany/Program.cs +++ b/VerifierInsuranceCompany/Program.cs @@ -1,16 +1,59 @@ -namespace VerifierInsuranceCompany; +using System.Configuration; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authentication.OpenIdConnect; +using Microsoft.AspNetCore.Server.Kestrel.Core; +using VerifierInsuranceCompany; -public class Program +var builder = WebApplication.CreateBuilder(args); + +builder.WebHost.ConfigureKestrel(serverOptions => +{ + serverOptions.AddServerHeader = false; +}); + +var services = builder.Services; +var configuration = builder.Configuration; + +services.Configure(options => +{ + options.AllowSynchronousIO = true; +}); + +services.AddSecurityHeaderPolicies() + .SetPolicySelector(ctx => SecurityHeadersDefinitions + .GetHeaderPolicyCollection(builder.Environment.IsDevelopment())); + +services.AddScoped(); +services.Configure(options => +{ + options.AllowSynchronousIO = true; +}); + +services.Configure(configuration.GetSection("CredentialSettings")); +services.AddHttpClient(); +services.AddDistributedMemoryCache(); + +services.AddRazorPages(); + +var app = builder.Build(); + +app.UseSecurityHeaders(); + +if (app.Environment.IsDevelopment()) { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } - - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); + app.UseDeveloperExceptionPage(); } +else +{ + app.UseExceptionHandler("/Error"); + app.UseHsts(); +} + +app.UseHttpsRedirection(); +app.UseStaticFiles(); +app.UseRouting(); + +app.MapControllers(); +app.MapRazorPages(); + +app.Run(); diff --git a/VerifierInsuranceCompany/SecurityHeadersDefinitions.cs b/VerifierInsuranceCompany/SecurityHeadersDefinitions.cs index 72b589a..efc2d8a 100644 --- a/VerifierInsuranceCompany/SecurityHeadersDefinitions.cs +++ b/VerifierInsuranceCompany/SecurityHeadersDefinitions.cs @@ -1,14 +1,23 @@ -namespace IssuerDrivingLicense; +namespace VerifierInsuranceCompany; public static class SecurityHeadersDefinitions { + private static HeaderPolicyCollection? policy; + public static HeaderPolicyCollection GetHeaderPolicyCollection(bool isDev) { - var policy = new HeaderPolicyCollection() + // Avoid building a new HeaderPolicyCollection on every request for performance reasons. + // Where possible, cache and reuse HeaderPolicyCollection instances. + if (policy != null) + { + return policy; + } + + policy = new HeaderPolicyCollection() .AddFrameOptionsDeny() - .AddXssProtectionBlock() .AddContentTypeOptionsNoSniff() .AddReferrerPolicyStrictOriginWhenCrossOrigin() + .RemoveServerHeader() .AddCrossOriginOpenerPolicy(builder => builder.SameOrigin()) .AddCrossOriginEmbedderPolicy(builder => builder.RequireCorp()) .AddCrossOriginResourcePolicy(builder => builder.SameOrigin()) @@ -17,32 +26,13 @@ public static HeaderPolicyCollection GetHeaderPolicyCollection(bool isDev) builder.AddObjectSrc().None(); builder.AddBlockAllMixedContent(); builder.AddImgSrc().Self().From("data:"); - builder.AddFormAction().Self(); builder.AddFontSrc().Self(); - builder.AddBaseUri().Self(); builder.AddStyleSrc().Self().UnsafeInline(); - builder.AddScriptSrc().Self().UnsafeInline().WithNonce(); + builder.AddBaseUri().Self(); + builder.AddScriptSrc().UnsafeInline().WithNonce(); builder.AddFrameAncestors().None(); - //builder.AddCustomDirective("require-trusted-types-for", "'script'"); }) - .RemoveServerHeader() - .AddPermissionsPolicy(builder => - { - builder.AddAccelerometer().None(); - builder.AddAutoplay().None(); - builder.AddCamera().None(); - builder.AddEncryptedMedia().None(); - builder.AddFullscreen().All(); - builder.AddGeolocation().None(); - builder.AddGyroscope().None(); - builder.AddMagnetometer().None(); - builder.AddMicrophone().None(); - builder.AddMidi().None(); - builder.AddPayment().None(); - builder.AddPictureInPicture().None(); - builder.AddSyncXHR().None(); - builder.AddUsb().None(); - }); + .AddPermissionsPolicyWithDefaultSecureDirectives(); if (!isDev) { @@ -50,8 +40,6 @@ public static HeaderPolicyCollection GetHeaderPolicyCollection(bool isDev) policy.AddStrictTransportSecurityMaxAgeIncludeSubDomains(maxAgeInSeconds: 60 * 60 * 24 * 365); } - policy.ApplyDocumentHeadersToAllResponses(); - return policy; } } diff --git a/VerifierInsuranceCompany/Startup.cs b/VerifierInsuranceCompany/Startup.cs deleted file mode 100644 index 3c12bda..0000000 --- a/VerifierInsuranceCompany/Startup.cs +++ /dev/null @@ -1,56 +0,0 @@ -using IssuerDrivingLicense; -using Microsoft.AspNetCore.Server.Kestrel.Core; - -namespace VerifierInsuranceCompany; - -public class Startup -{ - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) - { - services.AddScoped(); - services.Configure(options => - { - options.AllowSynchronousIO = true; - }); - - services.Configure(Configuration.GetSection("CredentialSettings")); - services.AddHttpClient(); - services.AddDistributedMemoryCache(); - - services.AddRazorPages(); - } - - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - app.UseSecurityHeaders(SecurityHeadersDefinitions - .GetHeaderPolicyCollection(env.IsDevelopment())); - - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - app.UseExceptionHandler("/Error"); - app.UseHsts(); - } - - app.UseHttpsRedirection(); - app.UseStaticFiles(); - app.UseRouting(); - - app.UseEndpoints(endpoints => - { - endpoints.MapControllers(); - endpoints.MapRazorPages(); - }); - } -} diff --git a/VerifierInsuranceCompany/VerifierInsuranceCompany.csproj b/VerifierInsuranceCompany/VerifierInsuranceCompany.csproj index 76dbd12..3ae48f7 100644 --- a/VerifierInsuranceCompany/VerifierInsuranceCompany.csproj +++ b/VerifierInsuranceCompany/VerifierInsuranceCompany.csproj @@ -14,8 +14,8 @@ - - + +