View | Details | Raw Unified | Return to bug 38365
Collapse All | Expand All

(-)a/Koha/Middleware/ContentSecurityPolicy.pm (-2 / +28 lines)
Lines 47-57 sub call { Link Here
47
    return Plack::Util::response_cb(
47
    return Plack::Util::response_cb(
48
        $res,
48
        $res,
49
        sub {
49
        sub {
50
            my $res     = shift;
50
            my $res                     = shift;
51
            my $headers = $res->[1];
51
            my $headers                 = $res->[1];
52
            my $add_reporting_endpoints = 1;
53
            for ( my $i = 0 ; $i < @$headers ; $i++ ) {
54
55
                # if reporting-endpoints already exists, append it
56
                if ( lc( $headers->[$i] ) eq 'reporting-endpoints' ) {
57
                    $headers->[ $i + 1 ] = _add_csp_to_reporting_endpoints( $headers->[ $i + 1 ] );
58
                    $add_reporting_endpoints = 0;
59
                    last;
60
                }
61
            }
62
63
            # reporting-endpoints is not yet defined, so let's define it
64
            if ($add_reporting_endpoints) {
65
                push @$headers, ( 'Reporting-Endpoints' => _add_csp_to_reporting_endpoints() );
66
            }
52
            push @$headers, ( $csp->header_name => $csp->header_value );
67
            push @$headers, ( $csp->header_name => $csp->header_value );
53
        }
68
        }
54
    );
69
    );
55
}
70
}
56
71
72
sub _add_csp_to_reporting_endpoints {
73
    my ($value) = @_;
74
    if ( $value && $value =~ /^\w+/ ) {
75
        $value = $value . ', ';
76
    } else {
77
        $value = '';
78
    }
79
    $value = $value . 'csp-violations="/api/v1/public/csp-reports"';
80
81
    return $value;
82
}
57
1;
83
1;
(-)a/debian/templates/koha-conf-site.xml.in (-3 / +3 lines)
Lines 519-527 __END_SRU_PUBLICSERVER__ Link Here
519
     2. Review logs and fix any legitimate violations
519
     2. Review logs and fix any legitimate violations
520
     3. Switch to enabled mode once violations are resolved
520
     3. Switch to enabled mode once violations are resolved
521
521
522
   To enable violation reporting, add report-uri to your policy pointing to Koha's
522
   To enable violation reporting, add report-to to your policy pointing to csp-violations.
523
   built-in CSP report endpoint. Example with reporting:
523
   Example with reporting:
524
     <csp_header_value>default-src 'self'; script-src 'self' 'nonce-_CSP_NONCE_'; style-src 'self' 'nonce-_CSP_NONCE_'; style-src-attr 'unsafe-inline'; img-src 'self' data:; font-src 'self'; object-src 'none'; report-uri /api/v1/public/csp-reports</csp_header_value>
524
     <csp_header_value>default-src 'self'; script-src 'self' 'nonce-_CSP_NONCE_'; style-src 'self' 'nonce-_CSP_NONCE_'; style-src-attr 'unsafe-inline'; img-src 'self' data:; font-src 'self'; object-src 'none'; report-uri /api/v1/public/csp-reports; report-to csp-violations</csp_header_value>
525
525
526
   Reports are logged via Koha's logging system. Configure log4perl to capture them:
526
   Reports are logged via Koha's logging system. Configure log4perl to capture them:
527
     log4perl.logger.api.csp = WARN, CSP
527
     log4perl.logger.api.csp = WARN, CSP
(-)a/etc/koha-conf.xml (-3 / +3 lines)
Lines 330-338 Link Here
330
     2. Review logs and fix any legitimate violations
330
     2. Review logs and fix any legitimate violations
331
     3. Switch to enabled mode once violations are resolved
331
     3. Switch to enabled mode once violations are resolved
332
332
333
   To enable violation reporting, add report-uri to your policy pointing to Koha's
333
   To enable violation reporting, add report-to to your policy pointing csp-violations.
334
   built-in CSP report endpoint. Example with reporting:
334
   Example with reporting:
335
     <csp_header_value>default-src 'self'; script-src 'self' 'nonce-_CSP_NONCE_'; style-src 'self' 'nonce-_CSP_NONCE_'; style-src-attr 'unsafe-inline'; img-src 'self' data:; font-src 'self'; object-src 'none'; report-uri /api/v1/public/csp-reports</csp_header_value>
335
     <csp_header_value>default-src 'self'; script-src 'self' 'nonce-_CSP_NONCE_'; style-src 'self' 'nonce-_CSP_NONCE_'; style-src-attr 'unsafe-inline'; img-src 'self' data:; font-src 'self'; object-src 'none'; report-uri /api/v1/public/csp-reports; report-to csp-violations</csp_header_value>
336
336
337
   Reports are logged via Koha's logging system. Configure log4perl to capture them:
337
   Reports are logged via Koha's logging system. Configure log4perl to capture them:
338
     log4perl.logger.api.csp = WARN, CSP
338
     log4perl.logger.api.csp = WARN, CSP
(-)a/t/db_dependent/Koha/Middleware/ContentSecurityPolicy.t (-2 / +48 lines)
Lines 21-39 Link Here
21
use strict;
21
use strict;
22
use warnings;
22
use warnings;
23
use Test::NoWarnings;
23
use Test::NoWarnings;
24
use Test::More tests => 4;
24
use Test::More tests => 5;
25
25
26
use HTTP::Request::Common;
26
use HTTP::Request::Common;
27
use Plack::App::CGIBin;
27
use Plack::App::CGIBin;
28
use Plack::Builder;
28
use Plack::Builder;
29
use Plack::Test;
29
use Plack::Test;
30
30
31
use Koha::Database;
32
31
use t::lib::Mocks;
33
use t::lib::Mocks;
32
34
33
use_ok("Koha::Middleware::ContentSecurityPolicy");
35
use_ok("Koha::Middleware::ContentSecurityPolicy");
34
36
35
my $conf_csp_section = 'content_security_policy';
37
my $conf_csp_section = 'content_security_policy';
36
38
39
my $schema = Koha::Database->schema;
40
37
subtest 'test CSP in OPAC' => sub {
41
subtest 'test CSP in OPAC' => sub {
38
    plan tests => 5;
42
    plan tests => 5;
39
43
Lines 159-161 subtest 'test CSP in staff client' => sub { Link Here
159
163
160
    like( $res->content, qr/<body id="main_auth"/, 'mainpage.pl looks okay' );
164
    like( $res->content, qr/<body id="main_auth"/, 'mainpage.pl looks okay' );
161
};
165
};
162
- 
166
167
subtest 'test Reporting-Endpoints for CSP violation reports' => sub {
168
    plan tests => 1;
169
170
    my $test_nonce = 'TEST_NONCE';
171
    my $csp_header_value =
172
        "default-src 'self'; script-src 'self' 'nonce-_CSP_NONCE_'; style-src 'self' 'nonce-_CSP_NONCE_'; img-src 'self' data:; font-src 'self'; object-src 'none'";
173
174
    t::lib::Mocks::mock_preference( 'SessionStorage', 'tmp' );
175
176
    $schema->storage->txn_begin;
177
178
    t::lib::Mocks::mock_preference( 'OpacPublic', 1 );
179
    t::lib::Mocks::mock_config(
180
        $conf_csp_section,
181
        { opac => { csp_mode => 'enabled', csp_header_value => $csp_header_value } }
182
    );
183
184
    # Set nonce
185
    Koha::ContentSecurityPolicy->new->set_nonce($test_nonce);
186
187
    my $env  = {};
188
    my $home = $ENV{KOHA_HOME};
189
    my $app  = Plack::App::CGIBin->new( root => $ENV{GIT_INSTALL} ? "$home/opac" : "$home/opac/cgi-bin/opac" )->to_app;
190
191
    $app = builder {
192
        mount '/opac' => builder {
193
            enable "+Koha::Middleware::ContentSecurityPolicy";
194
            $app;
195
        };
196
    };
197
198
    my $test                      = Plack::Test->create($app);
199
    my $res                       = $test->request( GET "/opac/opac-main.pl" );
200
    my $expected_csp_header_value = $csp_header_value;
201
    $expected_csp_header_value =~ s/_CSP_NONCE_/$test_nonce/g;
202
    like(
203
        $res->header('reporting-endpoints'), qr/^csp-violations="\/api\/v1\/public\/csp-reports"$/,
204
        "Response contains Reporting-Endpoints header with the expected value"
205
    );
206
207
    $schema->storage->txn_rollback;
208
};

Return to bug 38365