Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Security Module (Lombiq Technologies: OCORE-91) #11538

Merged
merged 108 commits into from
May 20, 2022
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
b5bec6a
Add OrchardCore.Security module
hishamco Apr 13, 2022
5fb68e3
Add ReferrerPolicyMiddleware
hishamco Apr 14, 2022
f1b18f9
Split middleware and ApplicationExtension tests
hishamco Apr 14, 2022
4d4b972
Add UseSecurityHeaders() extension methods
hishamco Apr 14, 2022
0d644c5
Use Enum-like class instead
hishamco Apr 14, 2022
a279a51
Simplify UseSecurityHeaders() with SecurityHeadersBuilder
hishamco Apr 14, 2022
2282f58
Add UI to configure ReferrerPolicy
hishamco Apr 14, 2022
e362afd
Fix the build
hishamco Apr 14, 2022
820678e
Merge branch 'main' into hishamco/security-module
hishamco Apr 14, 2022
d08e3e0
Remove unnecessar using
hishamco Apr 14, 2022
99ede53
Fix broken test
hishamco Apr 14, 2022
e9c2c3a
Refactoring
hishamco Apr 14, 2022
530a992
Add SecurityHeadersBuilder extension methods
hishamco Apr 15, 2022
d70cc23
Add X-Frame-Options header
hishamco Apr 15, 2022
3c8f64b
XFrameOptions -> FrameOptions
hishamco Apr 15, 2022
f0a97ec
Introduce options builder for fluent configuration
hishamco Apr 15, 2022
17af2b5
Remove unnecessary ApplicationBuilder extension methods
hishamco Apr 15, 2022
233654d
Move SecurityHeaderNames to OC.Infrastructure.Abstractions
hishamco Apr 15, 2022
37e1308
Add PermissionsPolicy header
hishamco Apr 16, 2022
a167ea9
Add X-Content-Type-Options header
hishamco Apr 16, 2022
1aefe17
Refactoring
hishamco Apr 17, 2022
0dbd2fa
Add origin option for PermissonsPolicy
hishamco Apr 17, 2022
5538387
Add unit tests
hishamco Apr 18, 2022
ffc9f06
Remove ContentTypeOptions settings so it should be added always
hishamco Apr 18, 2022
a6fe830
Change settings hint
hishamco Apr 18, 2022
efc8125
Add Strict-Transport-Security header
hishamco Apr 18, 2022
10a5f1b
Bring UseSecurityHeaders() back
hishamco Apr 18, 2022
36770fb
Add fullscreen in self origin as default permission
hishamco Apr 19, 2022
fffa545
Refactoring
hishamco Apr 21, 2022
267c0d8
Address feedback
hishamco Apr 21, 2022
26f2c0c
Remove Order from startup
hishamco Apr 21, 2022
d98af9d
Add Options namespace
hishamco Apr 21, 2022
4adc16f
Remove unnecessary Values property from PermissionsPolicyOptions
hishamco Apr 21, 2022
307d1a8
Remove the checks from the middleware constructors
hishamco Apr 21, 2022
a94b85e
Use ArgumentNullException.ThrowIfNull()
hishamco Apr 21, 2022
ddf54ac
Remove IsAlwaysEnabled
hishamco Apr 21, 2022
a385a07
Remove HSTS
hishamco Apr 22, 2022
5df89f3
Options should be enum like classes
hishamco Apr 22, 2022
ad68337
Use single middleware
hishamco Apr 22, 2022
b3d1ad5
Address feedback
hishamco Apr 22, 2022
aa791f0
Remove unnecessary property
hishamco Apr 22, 2022
6f8433d
Ability to configure allowed permissions policy with fluent APIs
hishamco Apr 23, 2022
9692ed4
Make options configuration APIs consistent
hishamco Apr 23, 2022
48314d1
Group permissions policy options into a folder
hishamco Apr 23, 2022
9146d99
Add Content-Security-Policy header
hishamco Apr 23, 2022
211dc36
Remove unnecessary extension methods
hishamco Apr 24, 2022
54cb66d
Add fluent APIs for CSP
hishamco Apr 24, 2022
41d1c32
Remove options & options builders
hishamco Apr 24, 2022
4e4cf84
ContentSecurityPolicySourceValue -> ContentSecurityPolicyOriginValue
hishamco Apr 26, 2022
1a376e6
Convert ContentSecurityPolicy to string[]
hishamco Apr 26, 2022
33cbd00
Fix NRE
hishamco Apr 27, 2022
5906f00
Fix UI
hishamco Apr 27, 2022
24d180e
Add UI for CSP header
hishamco Apr 27, 2022
45d3b68
Fix issues in SecuritySettingsDisplayDriver
hishamco Apr 27, 2022
b7eb2ff
Check ContentSecurityPolicy length for simplicity
hishamco Apr 27, 2022
994f44e
Address feedback
hishamco May 7, 2022
fb1e286
Remove unnecessary options
hishamco May 7, 2022
fb69ca4
Refactoring
hishamco May 7, 2022
d8782a2
Add ConfigureSecuritySettings() extension method
hishamco May 7, 2022
92e5032
Fix NRE
hishamco May 7, 2022
2f8f7ce
Change policies separator to comma
hishamco May 7, 2022
fa2aa73
Fix security settings section
hishamco May 10, 2022
d36438c
Fix script issue
hishamco May 10, 2022
b052d20
Set PermissionsPolicy default to empty array of string
hishamco May 10, 2022
34bf774
Fix settings in ConfigureSecuritySettings()
hishamco May 10, 2022
26129c9
Use IOptions<SecuritySettings> to get post configured settings properly
hishamco May 10, 2022
eabf382
Move SecurityHeaderMiddleware to Services namespace
hishamco May 11, 2022
555cc36
Replace SecuritySettings by SecurityHeaderOptions
hishamco May 11, 2022
e5ac7b7
Use IOptionsSnapshot
hishamco May 11, 2022
a712dab
Set permission policy value when its set
hishamco May 11, 2022
4385a4c
Return SiteSettings back
hishamco May 11, 2022
c1e8db4
Fix settings when they come from appsettings
hishamco May 11, 2022
3f5b18e
Use IEquatable
hishamco May 11, 2022
f26aaf6
Display warning alert when the settings comes from appsettings
hishamco May 11, 2022
99659d5
Override FrameOptions by CSP if FrameAncestors exists
hishamco May 11, 2022
b992eb6
Add docs for the Orchard.Security module
hishamco May 11, 2022
3c4a606
Rename unit tests
hishamco May 11, 2022
9822a43
Include all permissons policy directives
hishamco May 11, 2022
a7fbf30
Fix broken tests
hishamco May 11, 2022
9632a29
Add section about ConfigureSecuritySettings()
hishamco May 11, 2022
105e4e7
Enable the module though all recipes
hishamco May 11, 2022
7d4ab3b
Add missing switch cases
hishamco May 11, 2022
cd014f5
Revert SecuritySettings changes bug fix
hishamco May 11, 2022
d7f31c1
Change alert type
hishamco May 11, 2022
ac6a224
Remove Frame Options
hishamco May 12, 2022
398d916
Remove readonly modifier
hishamco May 12, 2022
c98a9a7
Fix typo
hishamco May 13, 2022
b138eec
Link to configuration docs
hishamco May 13, 2022
6493df5
Rename unit tests
hishamco May 13, 2022
ed783df
IOptions<SecurityHeadersOptions> -> SecurityHeadersOptions
hishamco May 13, 2022
6e42b5e
Fix comments
hishamco May 13, 2022
9a6ff60
Add FromConfiguration to SecuritySettings
hishamco May 13, 2022
8ddb49e
No need to add policies with None origin
hishamco May 13, 2022
13836a9
Fix policies localized strings
hishamco May 13, 2022
b1a18de
Add link to mkdocs.ml
hishamco May 13, 2022
35dda92
Fix configuration docs path
hishamco May 14, 2022
e89a245
Rename unit tests
hishamco May 14, 2022
d9b6f57
Use dictionary for permissions policy
hishamco May 15, 2022
2b1ffd8
Apply Jean-Thierry change
hishamco May 16, 2022
26b2580
Fix tests
hishamco May 16, 2022
c51c6c8
Edit view fixes
jtkech May 17, 2022
1f4ff2a
Remove overrideAdminSettings parameter
hishamco May 17, 2022
43b78a9
Fixes Settings merging from both Configuration and Site settings
jtkech May 17, 2022
2d437e7
Fix docs to react to the dictionary changes
hishamco May 17, 2022
5bc5425
Rename unit tests
hishamco May 17, 2022
fa9eed7
Address feedback
hishamco May 17, 2022
9072844
Add docs for InitializePolicy
hishamco May 17, 2022
91dd721
Add missing ouble quotations
hishamco May 17, 2022
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
4 changes: 2 additions & 2 deletions src/OrchardCore.Cms.Web/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@
// "InstancePrefix": "" // Optional prefix allowing a Redis instance to be shared by different applications.
//},
//"OrchardCore_Security": {
hishamco marked this conversation as resolved.
Show resolved Hide resolved
// "ContentSecurityPolicy": [],
// "PermissionsPolicy": [ "fullscreen=self" ],
// "ContentSecurityPolicy": {},
// "PermissionsPolicy": { fullscreen: "self" },
hishamco marked this conversation as resolved.
Show resolved Hide resolved
// "ReferrerPolicy": "no-referrer"
//},
// See https://docs.orchardcore.net/en/latest/docs/reference/core/Shells/#enable-azure-shells-configuration to configure shell and tenant configuration in Azure Blob Storage.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
Expand Down Expand Up @@ -50,19 +49,22 @@ public override async Task<IDisplayResult> EditAsync(SecuritySettings settings,
return Initialize<SecuritySettingsViewModel>("SecurityHeadersSettings_Edit", model =>
{
// Set the settings from configuration when AdminSettings are overriden via ConfigureSecuritySettings()
var currentSettings = settings;
if (_securitySettings.FromConfiguration)
{
settings = _securitySettings;
model.FromAdminSettings = false;
currentSettings = _securitySettings;
}

model.ContentSecurityPolicy = settings.ContentSecurityPolicy;
model.ContentSecurityPolicyValues = SecurityHeaderDefaults.ContentSecurityPolicyNames.ToList();
model.PermissionsPolicy = settings.PermissionsPolicy;
model.PermissionsPolicyValues = SecurityHeaderDefaults.PermissionsPolicyNames.ToList();
model.ReferrerPolicy = settings.ReferrerPolicy;
model.EnableSandbox = model.ContentSecurityPolicy != null && model.ContentSecurityPolicy.Any(p => p.StartsWith(ContentSecurityPolicyValue.Sandbox));
model.UpgradeInsecureRequests = model.ContentSecurityPolicy != null && model.ContentSecurityPolicy.Any(p => p == ContentSecurityPolicyValue.UpgradeInsecureRequests);
model.FromConfiguration = currentSettings.FromConfiguration;
model.ContentSecurityPolicy = currentSettings.ContentSecurityPolicy;
model.PermissionsPolicy = currentSettings.PermissionsPolicy;
model.ReferrerPolicy = currentSettings.ReferrerPolicy;

model.EnableSandbox = currentSettings.ContentSecurityPolicy != null &&
currentSettings.ContentSecurityPolicy.ContainsKey(ContentSecurityPolicyValue.Sandbox);

model.UpgradeInsecureRequests = currentSettings.ContentSecurityPolicy != null &&
currentSettings.ContentSecurityPolicy.ContainsKey(ContentSecurityPolicyValue.UpgradeInsecureRequests);
}).Location("Content:2").OnGroup(SettingsGroupId);
}

Expand All @@ -83,11 +85,9 @@ public override async Task<IDisplayResult> UpdateAsync(SecuritySettings section,

PrepareContentSecurityPolicyValues(model);

model.PermissionsPolicyValues.RemoveAll(p => p.EndsWith(PermissionsPolicyOriginValue.None));

section.ContentTypeOptions = SecurityHeaderDefaults.ContentTypeOptions;
section.ContentSecurityPolicy = model.ContentSecurityPolicyValues.ToArray();
section.PermissionsPolicy = model.PermissionsPolicyValues.ToArray();
section.ContentSecurityPolicy = model.ContentSecurityPolicy;
section.PermissionsPolicy = model.PermissionsPolicy;
section.ReferrerPolicy = model.ReferrerPolicy;

if (context.Updater.ModelState.IsValid)
Expand All @@ -101,30 +101,22 @@ public override async Task<IDisplayResult> UpdateAsync(SecuritySettings section,

private static void PrepareContentSecurityPolicyValues(SecuritySettingsViewModel model)
{
var sandboxPolicy = model.ContentSecurityPolicyValues.SingleOrDefault(p => p.StartsWith(ContentSecurityPolicyValue.Sandbox));
var hasSandboxPolicyWithoutValues = sandboxPolicy == ContentSecurityPolicyValue.Sandbox;
var upgradeInsecureRequestsPolicy = model.ContentSecurityPolicyValues.SingleOrDefault(p => p == ContentSecurityPolicyValue.UpgradeInsecureRequests);

model.ContentSecurityPolicyValues.RemoveAll(p => SecurityHeaderDefaults.ContentSecurityPolicyNames.Contains(p));

if (model.EnableSandbox && hasSandboxPolicyWithoutValues)
if (!model.EnableSandbox)
{
model.ContentSecurityPolicyValues.Add(ContentSecurityPolicyValue.Sandbox);
model.ContentSecurityPolicy.Remove(ContentSecurityPolicyValue.Sandbox);
}

if (!model.EnableSandbox && sandboxPolicy != null)
else if (!model.ContentSecurityPolicy.TryGetValue(ContentSecurityPolicyValue.Sandbox, out _))
{
model.ContentSecurityPolicyValues.Remove(sandboxPolicy);
model.ContentSecurityPolicy[ContentSecurityPolicyValue.Sandbox] = null;
}

if (model.UpgradeInsecureRequests)
if (!model.UpgradeInsecureRequests)
{
model.ContentSecurityPolicyValues.Add(ContentSecurityPolicyValue.UpgradeInsecureRequests);
model.ContentSecurityPolicy.Remove(ContentSecurityPolicyValue.UpgradeInsecureRequests);
}

if (!model.UpgradeInsecureRequests && upgradeInsecureRequestsPolicy != null)
else
{
model.ContentSecurityPolicyValues.Remove(ContentSecurityPolicyValue.UpgradeInsecureRequests);
model.ContentSecurityPolicy[ContentSecurityPolicyValue.UpgradeInsecureRequests] = null;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,21 @@
using Microsoft.Extensions.Configuration;
using OrchardCore.Environment.Shell.Configuration;
using OrchardCore.Security;
using OrchardCore.Security.Settings;

namespace Microsoft.Extensions.DependencyInjection
{
public static class OrchardCoreBuilderExtensions
{
public static OrchardCoreBuilder ConfigureSecuritySettings(this OrchardCoreBuilder builder, bool overrideAdminSettings = true)
public static OrchardCoreBuilder ConfigureSecuritySettings(this OrchardCoreBuilder builder)
{
builder.ConfigureServices((tenantServices, serviceProvider) =>
{
var configurationSection = serviceProvider.GetRequiredService<IShellConfiguration>().GetSection("OrchardCore_Security");

tenantServices.PostConfigure<SecuritySettings>(settings =>
{
if (!overrideAdminSettings)
{
return;
}

// Reset the settings to avoid merging with the current settings values
settings.ContentSecurityPolicy = SecurityHeaderDefaults.ContentSecurityPolicy;
settings.PermissionsPolicy = SecurityHeaderDefaults.PermissionsPolicy;
settings.ContentSecurityPolicy.Clear();
hishamco marked this conversation as resolved.
Show resolved Hide resolved
settings.PermissionsPolicy.Clear();

configurationSection.Bind(settings);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ public class ContentSecurityPolicyValue

public const string FormAction = "form-action";

public const string FrameSource = "frame-src";

public const string FrameAncestors = "frame-ancestors";

public const string FrameSource = "frame-src";

public const string ImageSource = "img-src";

public const string ManifestSource = "manifest-src";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OrchardCore.Security.Services;

namespace OrchardCore.Security.Options
Expand Down Expand Up @@ -27,8 +28,17 @@ public SecurityHeadersOptions()

public IList<IHeaderPolicyProvider> HeaderPolicyProviders { get; set; }

public SecurityHeadersOptions AddContentSecurityPolicy(string policies)
=> AddContentSecurityPolicy(policies.Split(SecurityHeaderDefaults.PoliciesSeparator, StringSplitOptions.RemoveEmptyEntries));
public SecurityHeadersOptions AddContentSecurityPolicy(Dictionary<string, string> policies)
{
ContentSecurityPolicy = policies
.Where(kvp => kvp.Value != null ||
kvp.Key == ContentSecurityPolicyValue.Sandbox ||
kvp.Key == ContentSecurityPolicyValue.UpgradeInsecureRequests)
.Select(kvp => kvp.Key + (kvp.Value != null ? " " + kvp.Value : String.Empty))
.ToArray();

return this;
}

public SecurityHeadersOptions AddContentSecurityPolicy(params string[] policies)
{
Expand All @@ -44,12 +54,12 @@ public SecurityHeadersOptions AddContentTypeOptions()
return this;
}

public SecurityHeadersOptions AddPermissionsPolicy(string policies)
=> AddPermissionsPolicy(policies.Split(SecurityHeaderDefaults.PoliciesSeparator, StringSplitOptions.RemoveEmptyEntries));

public SecurityHeadersOptions AddPermissionsPolicy(params string[] policies)
public SecurityHeadersOptions AddPermissionsPolicy(IDictionary<string, string> policies)
{
PermissionsPolicy = policies;
PermissionsPolicy = policies
.Where(kvp => kvp.Value != PermissionsPolicyOriginValue.None)
.Select(kvp => kvp.Key + "=" + kvp.Value)
.ToArray();

return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,21 @@ namespace OrchardCore.Security.Services
{
public class ContentSecurityPolicyHeaderPolicyProvider : HeaderPolicyProvider
{
public override void ApplyPolicy(HttpContext httpContext)
private string _policy;

public override void InitializePolicy()
{
if (Options.ContentSecurityPolicy.Length > 0)
{
httpContext.Response.Headers[SecurityHeaderNames.ContentSecurityPolicy] = String.Join(SecurityHeaderDefaults.PoliciesSeparator, Options.ContentSecurityPolicy);
_policy = String.Join(SecurityHeaderDefaults.PoliciesSeparator, Options.ContentSecurityPolicy);
}
}

public override void ApplyPolicy(HttpContext httpContext)
{
if (_policy != null)
{
httpContext.Response.Headers[SecurityHeaderNames.ContentSecurityPolicy] = _policy;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ public abstract class HeaderPolicyProvider : IHeaderPolicyProvider
{
public SecurityHeadersOptions Options { get; set; }

public virtual void InitializePolicy()
{

}
hishamco marked this conversation as resolved.
Show resolved Hide resolved

public abstract void ApplyPolicy(HttpContext httpContext);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ namespace OrchardCore.Security.Services
{
public interface IHeaderPolicyProvider
{
void InitializePolicy();

void ApplyPolicy(HttpContext httpContext);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,21 @@ namespace OrchardCore.Security.Services
{
public class PermissionsHeaderPolicyProvider : HeaderPolicyProvider
{
public override void ApplyPolicy(HttpContext httpContext)
private string _policy;

public override void InitializePolicy()
{
if (Options.PermissionsPolicy.Length > 0)
{
httpContext.Response.Headers[SecurityHeaderNames.PermissionsPolicy] = String.Join(SecurityHeaderDefaults.PoliciesSeparator, Options.PermissionsPolicy);
_policy = String.Join(SecurityHeaderDefaults.PoliciesSeparator, Options.PermissionsPolicy);
}
}

public override void ApplyPolicy(HttpContext httpContext)
{
if (_policy != null)
{
httpContext.Response.Headers[SecurityHeaderNames.PermissionsPolicy] = _policy;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ public SecurityHeadersMiddleware(SecurityHeadersOptions options, RequestDelegate
{
_options = options;
_next = next;

foreach (var provider in _options.HeaderPolicyProviders)
{
provider.InitializePolicy();
}
Piedone marked this conversation as resolved.
Show resolved Hide resolved
}
hishamco marked this conversation as resolved.
Show resolved Hide resolved

public Task Invoke(HttpContext context)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,56 @@
using System.Collections.Generic;
using System.Linq;
using OrchardCore.Security.Options;

namespace OrchardCore.Security.Settings
{
public class SecuritySettings
hishamco marked this conversation as resolved.
Show resolved Hide resolved
{
public string[] ContentSecurityPolicy { get; set; } = SecurityHeaderDefaults.ContentSecurityPolicy;
private Dictionary<string, string> _contentSecurityPolicy = new();
private Dictionary<string, string> _permissionsPolicy = new();

public Dictionary<string, string> ContentSecurityPolicy
{
get => _contentSecurityPolicy;
set
{
if (value == null)
{
return;
}

// Exclude null values and clone the dictionary to not be shared by site settings and options instances.
_contentSecurityPolicy = value
.Where(kvp => kvp.Value != null ||
kvp.Key == ContentSecurityPolicyValue.Sandbox ||
kvp.Key == ContentSecurityPolicyValue.UpgradeInsecureRequests)
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

if (_contentSecurityPolicy.TryGetValue(ContentSecurityPolicyValue.UpgradeInsecureRequests, out _))
{
_contentSecurityPolicy[ContentSecurityPolicyValue.UpgradeInsecureRequests] = null;
}
}
}

public string ContentTypeOptions { get; set; } = SecurityHeaderDefaults.ContentTypeOptions;

public string[] PermissionsPolicy { get; set; } = SecurityHeaderDefaults.PermissionsPolicy;
public Dictionary<string, string> PermissionsPolicy
{
get => _permissionsPolicy;
set
{
if (value == null)
{
return;
}

// Exlude 'None' values and clone the dictionary to not be shared by site settings and options instances.
_permissionsPolicy = value
.Where(kvp => kvp.Value != PermissionsPolicyOriginValue.None)
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
}

public string ReferrerPolicy { get; set; } = SecurityHeaderDefaults.ReferrerPolicy;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,50 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using OrchardCore.Security.Options;

namespace OrchardCore.Security.ViewModels
{
public class SecuritySettingsViewModel
{
public string[] ContentSecurityPolicy { get; set; }

public List<string> ContentSecurityPolicyValues { get; set; }
private Dictionary<string, string> _contentSecurityPolicy = new();
private Dictionary<string, string> _permissionsPolicy = new();

public Dictionary<string, string> ContentSecurityPolicy
{
get => _contentSecurityPolicy;
set
{
// Populate all policy values for the editor (null if not provided).
_contentSecurityPolicy = SecurityHeaderDefaults.ContentSecurityPolicyNames
.ToDictionary(name => name, name =>
value?.ContainsKey(name) ?? false
? value[name]
: null);
}
}

public bool EnableSandbox { get; set; }
hishamco marked this conversation as resolved.
Show resolved Hide resolved

public bool UpgradeInsecureRequests { get; set; }

public string[] PermissionsPolicy { get; set; }

public List<string> PermissionsPolicyValues { get; set; }
public Dictionary<string, string> PermissionsPolicy
{
get => _permissionsPolicy;
set
{
// Populate all policy values for the editor ('None' if not provided).
_permissionsPolicy = SecurityHeaderDefaults.PermissionsPolicyNames
.ToDictionary(name => name, name =>
value?.ContainsKey(name) ?? false
? value[name]
: PermissionsPolicyOriginValue.None);
}
}

public string ReferrerPolicy { get; set; }

[BindNever]
public bool FromAdminSettings { get; set; } = true;
public bool FromConfiguration { get; set; }
}
}
Loading