Disable CSP for development purposes
Change-Id: Iff20edb302f9f03e524b7bd8bcb4ce3a9690d3be
diff --git a/Changes b/Changes
index 4b16d51..b7bcfac 100755
--- a/Changes
+++ b/Changes
@@ -1,4 +1,4 @@
-0.43 2021-10-13
+0.43 2021-10-28
- New menu class that has an entry at the very end,
similar to the input text prefix,
that is always available. (lerepp)
@@ -36,6 +36,8 @@
- Turn "upgradeTo" into an object prototype.
- Fix QueryParam response to work with Chrome (#149).
- Added DemoServer plugin.
+ - Support CSP disabling.
+ - Update intro.js (#109; hebasta)
0.42 2021-06-18
- Added GitHub based CI for perl.
diff --git a/lib/Kalamar/Plugin/CSP.pm b/lib/Kalamar/Plugin/CSP.pm
index c9768aa..59c6c58 100644
--- a/lib/Kalamar/Plugin/CSP.pm
+++ b/lib/Kalamar/Plugin/CSP.pm
@@ -16,6 +16,11 @@
};
my $with_nonce = delete $param->{-with_nonce};
+ my $disabled = delete $param->{-disable};
+
+ if ($disabled) {
+ $app->log->warn('CSP DISABLED!','NEVER USE IN PRODUCTION!');
+ };
$app->plugin('Util::RandomString' => {
nonce => {
@@ -44,19 +49,21 @@
my $csp = \( generate(%directives) );
# Add csp header
- $app->hook(
- before_dispatch => sub {
- my $c = shift;
- if ($$csp) {
- my $line = $$csp;
- if ($with_nonce) {
- $c->stash('csp.nonce' => my $nonce = $c->random_string('nonce'));
- $line =~ s/\'nonce-\{\{nonce_js\}\}\'/\'nonce-$nonce\'/;
+ unless ($disabled) {
+ $app->hook(
+ before_dispatch => sub {
+ my $c = shift;
+ if ($$csp) {
+ my $line = $$csp;
+ if ($with_nonce) {
+ $c->stash('csp.nonce' => my $nonce = $c->random_string('nonce'));
+ $line =~ s/\'nonce-\{\{nonce_js\}\}\'/\'nonce-$nonce\'/;
+ };
+ $c->res->headers->header('Content-Security-Policy' => $line);
};
- $c->res->headers->header('Content-Security-Policy' => $line);
- };
- }
- );
+ }
+ );
+ };
# Add csp directives
$app->helper(
@@ -86,7 +93,7 @@
$app->helper(
csp_nonce_tag => sub {
my $c = shift;
- unless ($c->content_block_ok('nonce_js')) {
+ if ($disabled || !$c->content_block_ok('nonce_js')) {
return '';
};
@@ -120,3 +127,117 @@
};
1;
+
+
+__END__
+
+=pod
+
+=encoding utf8
+
+=head1 NAME
+
+Kalamar::Plugin::CSP - Define CSP rules per config
+
+=head1 DESCRIPTION
+
+This Mojolicious plugin allows to define CSP directives in
+a configuration file and programmatically. It will add CSP to all
+responses using the C<before_dispatch> hook.
+
+
+=head2 register
+
+ # Mojolicious
+ $app->plugin('Kalamar::Plugin::CSP' => {
+ 'script-src' => '*',
+ 'img-src' => ['self', 'data:']
+ });
+
+ # Or in the config file
+ {
+ CSP => {
+ 'script-src' => '*',
+ 'img-src' => ['self', 'data:']
+ }
+ }
+
+Called when registering the plugin.
+
+All L<parameters|/PARAMETERS> can be set either as part of the configuration
+file with the key C<CSP> or on registration
+(that can be overwritten by configuration).
+
+
+=head1 PARAMETERS
+
+L<Kalamar::Plugin::CSP> supports all valid CSP directives as parameters.
+Multiple values can be defined as arrays.
+
+In addition, the following special parameters for
+the C<CSP> configuration section in the Kalamar configuration are supported.
+
+=over 2
+
+=item B<-disable>
+
+Disables all CSP. It's strongly recommended to not use this option
+in a production environment.
+
+=item B<-with_nonce>
+
+Adds I<nonce> support, i.e. inline-support, for JavaScript.
+Allows the use of the L</csp_nonce_tag>.
+
+=back
+
+All parameters can be set as part of the configuration
+file with the key C<CSP> or on registration
+(that can be overwritten by configuration).
+
+
+=head1 HELPERS
+
+=head2 csp_nonce_tag
+
+ # Configure inline JavaScript as a content block:
+ $mojo->content_block(
+ 'nonce_js' => {
+ inline => 'console.log("Hallo")'
+ }
+ );
+
+ # Embed inline JavaScript in templates:
+ %= csp_nonce_tag
+
+The nonce tag allows to embed inline JavaScript despite CSP rules.
+It requires the C<-with_nonce> configuration flag.
+The inline JavaScript can be formulated as a
+L<Mojolicious::Plugin::TagHelpers::ContentBlock> with the block name
+C<nonce_js>.
+
+
+=head2 csp.add
+
+ # Mojolicious:
+ $app->csp->add('script-src', '*');
+
+Adds a CSP rule to the configuration. This is B<no> controller helper
+and should be used only before dispatch.
+
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2021, L<IDS Mannheim|http://www.ids-mannheim.de/>
+Author: L<Nils Diewald|https://www.nils-diewald.de/>
+
+Kalamar is developed as part of the L<KorAP|https://korap.ids-mannheim.de/>
+Corpus Analysis Platform at the
+L<Leibniz Institute for the German Language (IDS)|https://ids-mannheim.de/>,
+member of the
+L<Leibniz-Gemeinschaft|http://www.leibniz-gemeinschaft.de>.
+
+Kalamar is free software published under the
+L<BSD-2 License|https://raw.githubusercontent.com/KorAP/Kalamar/master/LICENSE>.
+
+=cut
diff --git a/t/plugin/csp.t b/t/plugin/csp.t
index 1031450..aa6cd70 100644
--- a/t/plugin/csp.t
+++ b/t/plugin/csp.t
@@ -149,6 +149,24 @@
like($content, qr/nonce-\Q$1\E/);
+# Disable csp
+$t = Test::Mojo->new(Mojolicious::Lite->new);
+$t->app->plugin('Kalamar::Plugin::CSP' => {
+ '-disable' => 1
+});
+
+$t->app->routes->get('/' => sub {
+ shift->render(text => 'hello world');
+});
+
+$t->app->csp->add('script-src', '*');
+is($t->app->csp_nonce_tag,'');
+
+$t->get_ok('/')
+ ->status_is(200)
+ ->content_is('hello world')
+ ->header_is($csp, undef)
+ ;
done_testing;
__END__