Stott.Security.Optimizely 0.5.0-beta

This is a prerelease version of Stott.Security.Optimizely.
There is a newer version of this package available.
See the version list below for details.
The owner has unlisted this package. This could mean that the package is deprecated, has security vulnerabilities or shouldn't be used anymore.
dotnet add package Stott.Security.Optimizely --version 0.5.0-beta
NuGet\Install-Package Stott.Security.Optimizely -Version 0.5.0-beta
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Stott.Security.Optimizely" Version="0.5.0-beta" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Stott.Security.Optimizely --version 0.5.0-beta
#r "nuget: Stott.Security.Optimizely, 0.5.0-beta"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// 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

Platform Platform GitHub GitHub Workflow Status Nuget

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:

  1. Contributions should be made by Pull Requests.
  2. All commits should have a meaningful messages.
  3. All commits should have a reference to your GitHub user.
  4. 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
2.6.0 260 4/7/2024
2.5.0 427 3/12/2024
2.4.2 276 2/23/2024
2.4.1 181 2/21/2024
2.4.0 826 2/7/2024
2.3.0 199 2/5/2024
2.2.0 907 12/30/2023
2.1.0 337 12/5/2023
1.2.2 1,441 7/14/2023
1.2.1 550 5/23/2023
1.2.0 491 5/3/2023
1.1.0 871 4/10/2023
1.0.0 552 3/26/2023

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.