Stott.Security.Optimizely
0.5.0-beta
See the version list below for details.
dotnet add package Stott.Security.Optimizely --version 0.5.0-beta
NuGet\Install-Package Stott.Security.Optimizely -Version 0.5.0-beta
<PackageReference Include="Stott.Security.Optimizely" Version="0.5.0-beta" />
paket add Stott.Security.Optimizely --version 0.5.0-beta
#r "nuget: Stott.Security.Optimizely, 0.5.0-beta"
// Install Stott.Security.Optimizely as a Cake Addin
#addin nuget:?package=Stott.Security.Optimizely&version=0.5.0-beta&prerelease
// Install Stott.Security.Optimizely as a Cake Tool
#tool nuget:?package=Stott.Security.Optimizely&version=0.5.0-beta&prerelease
Stott.Optimizely.Csp
Stott.Optimizely.Csp is a CSP editor for Optimizely CMS 12 that provides the user with the ability to define the CSP. Users are presented with the ability to define a source and to select what CSP directives that can be used with that source.
Please note that this is currently under active development and is not yet ready for a version 1.0 release.
Configuration
After pulling in a reference to the Stott.Optimizely.Csp project, you only need to ensure the following lines are added to the startup class of your solution:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddCspManager();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseAuthentication();
app.UseAuthorization();
app.UseCspManager();
app.UseEndpoints(endpoints =>
{
endpoints.MapContent();
endpoints.MapRazorPages();
});
}
The call to services.AddRazorPages()
is a standard .NET 6.0 call to ensure razor pages are included in your solution.
The call to services.AddCspManager()
in the ConfigureServices(IServiceCollection services)
sets up the dependency injection requirements for the CSP solution and is required to ensure the solution works as intended. This works by following the Services Extensions pattern defined by microsoft.
The call to app.UseCspManager()
in the Configure(IApplicationBuilder app, IWebHostEnvironment env)
method sets up the CSP middleware. This should be declared immediately before the app.UseEndpoints(...)
method to ensure that the headers are added to content pages.
This solution also includes an implementation of IMenuProvider
which ensures that the CSP administration pages are included in the CMS Admin menu under the title of "CSP". You do not have to do anything to make this work as Optimizely CMS will scan and action all implementations of IMenuProvider
.
Additional Configuration Customisation
The configuration of the module has some scope for modification by providing configuration in the service extension methods. Both the provision of cspSetupOptions
and authorizationOptions
are optional in the following example.
Example:
services.AddCspManager(cspSetupOptions =>
{
cspSetupOptions.ConnectionStringName = "EPiServerDB";
},
authorizationOptions =>
{
authorizationOptions.AddPolicy(CspConstants.AuthorizationPolicy, policy =>
{
policy.RequireRole("WebAdmins");
});
});
Default Configuration Options
Configuration | Default Values | Notes |
---|---|---|
Allowed Roles | WebAdmins or CmsAdmins or Administrator | Defines the roles required in order to access the Admin interface. |
Connection String Name | EPiServerDB | Defines which connection string to use for modules data storage. Must be a SQL Server connection string. |
CSP Reporting
A Content Security Policy can be set to report violations to a given end point. An API endpoint has been added to the solution which allows for CSP reports to be sent to the CMS. Browsers can batch up these reports and send them at a later point in time. This can lead to monitoring violations to be non-responsive. By adding the following ViewComponent to your layout files, violations will be posted to the CMS as they occur.
@await Component.InvokeAsync("CspReporting")
This works by adding an event listener for the security violation and are raised by the browser by adding a listener to the security policy violation event.
Agency Whitelisting
SEO and Data teams within Digital Agencies, may have many sites which they have to maintain collectively as a team. Approving a new tool to be injected via GTM may be made once, but may need applying to dozens of websites, each of which may have it's own CSP whitelist.
If you have applied the CSP Reporting component (see above), then this plugin can automatically extend the whitelist for the site based on centralized approved list.
Central Whitelist Structure
The structure of the central whitelist must exist as a JSON object reachable by a GET method for the specified Whitelist Url. The JSON returned should be an array with each entry having a sourceUrl
and an array of directives
. All of these should be valid strings.
[
{
"sourceUrl": "https://*.google.com",
"directives": [ "default-src" ]
},
{
"sourceUrl": "https://*.twitter.com",
"directives": [ "script-src", "style-src" ]
},
{
"sourceUrl": "https://pbs.twimg.com",
"directives": [ "img-src" ]
}
]
Contributing
I am open to contributions to the code base. The following rules should be followed:
- Contributions should be made by Pull Requests.
- All commits should have a meaningful messages.
- All commits should have a reference to your GitHub user.
- Ideally all new changes should include appropriate unit test coverage.
Technologies Used
- .NET 6.0
- Optimizely CMS 12.7
- MVC
- Razor Class Libraries
- React
- Bootstrap for React
- NUnit & Moq
Default CSP Settings
In order to prevent a CSP from preventing Optimizely CMS from functioning optimally, the following sources and directives are automatically merged into the user defined CSP:
Source | Default Directives |
---|---|
'self' | child-src, connect-src, default-src, font-src, frame-src, img-src, script-src, style-src |
'unsafe-inline' | script-src, style-src |
'unsafe-eval' | script-src |
https://dc.services.visualstudio.com |
connect-src, script-src |
https://*.msecnd.net |
script-src |
Common Issues
A 404 error response is returned for static javascript and style assets.
The Stott.Optimizely.Csp is built as a Razor Class Library, this produces a manifest that tells the application about the static assets that are included within the Razor Class Library. This is solved by adding webBuilder.UseStaticWebAssets();
to the ConfigureWebHostDefaults
method in Program.cs
. Please see the configuration section above.
Projects that do not use Razor MVC lead to missing assets
Stott.Optimizely.Csp has been built as a Razor Class Library, this is predicated on a build being compatible with Razor MVC. If your build does not use Razor MVC and the build pipeline does not inclue the output of such, then this can cause the admin interface not to work. In this scenario this will require you to update your build pipeline to include these assets.
The following is a YAML example cloned from a screenshot where this problem was resolved:
- task: CopyFiles@2
inputs:
SourceFolder: '$(projectName)/obj/$(BuildConfiguration)/net6.0/PubTmp/Out/wwwrooot'
Contents: '**'
CleanTargetFolder: false
TargetFolder: '$(Agent.TempDirectory)/$(today)/wwwroot/wwwroot/'
A big thank you goes to Praveen Soni who helped identify this as an issue.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net6.0
- EPiServer.CMS.UI.Core (>= 12.9.0)
- Microsoft.EntityFrameworkCore.SqlServer (>= 6.0.6)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Fifth beta release of the Stott.Security.Optimizely package. Whitelist management moved to settings UI, Added audit trail for changes made to the security settings.