Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 12 additions & 2 deletions files/nginx/odk.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,7 @@ server {
}
# To read single submission cookies
location = /-/single/check-submitted {
alias /usr/share/nginx/html/blank.html;
default_type text/html;
try_files $uri @blank.html;
}

# For that iframe to work, we'll need another path prefix (enketo-passthrough) under which we can
Expand Down Expand Up @@ -166,6 +165,17 @@ server {
proxy_read_timeout 2m;
}

location @blank.html {
root /usr/share/nginx/html;
try_files /blank.html =404;

add_header Content-Security-Policy-Report-Only "default-src 'none'";
include /usr/share/odk/nginx/common-headers.conf;
}
location = /blank.html {
try_files $uri @blank.html;
}

location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
Expand Down
36 changes: 23 additions & 13 deletions test/nginx/test-nginx.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const none = `'none'`;
const self = `'self'`;
const unsafeInline = `'unsafe-inline'`;
const contentSecurityPolicies = {
'restrictive': {
'backend-default': {
'default-src': none,
'connect-src': [
'https://translate.google.com',
Expand Down Expand Up @@ -37,6 +37,9 @@ const contentSecurityPolicies = {
'worker-src': 'data:',
'report-uri': '/csp-report',
},
'disallow-all': {
'default-src': none,
},
enketo: {
'default-src': none,
'connect-src': [
Expand Down Expand Up @@ -183,7 +186,6 @@ describe('nginx config', () => {
[
[ '/index.html', /<div id="app"><\/div>/ ],
[ '/version.txt', /^versions:/ ],
[ '/blank.html', /^\n$/ ],
[ '/favicon.ico', /^\n$/ ],
].forEach(([ path, expectedContent ]) => {
it(`${path} file should serve expected content`, async () => {
Expand Down Expand Up @@ -317,15 +319,23 @@ describe('nginx config', () => {
});
});

it('should serve blank page on /-/single/check-submitted', async () => {
// when
const res = await fetchHttps('/-/single/check-submitted');
describe('blank.html', () => {
[
'/blank.html',
'/-/single/check-submitted',
].forEach(path => {
it(`should serve blank page on ${path}`, async () => {
// when
const res = await fetchHttps(path);

// then
assert.equal(res.status, 200);
assert.isEmpty((await res.text()).trim());
assertSecurityHeaders(res, { csp:'restrictive' });
await assertEnketoReceivedNoRequests();
// then
assert.equal(res.status, 200);
assert.isEmpty((await res.text()).trim());
assert.equal(res.headers.get('Content-Type'), 'text/html');
assertSecurityHeaders(res, { csp:'disallow-all' });
await assertEnketoReceivedNoRequests();
});
});
});

it('/v1/... should forward to backend', async () => {
Expand All @@ -335,7 +345,7 @@ describe('nginx config', () => {
// then
assert.equal(res.status, 200);
assert.equal(await res.text(), 'OK');
assertSecurityHeaders(res, { csp:'restrictive' });
assertSecurityHeaders(res, { csp:'backend-default' });
// and
await assertBackendReceived(
{ method:'GET', path:'/v1/some/central-backend/path' },
Expand All @@ -347,7 +357,7 @@ describe('nginx config', () => {
const res = await fetchHttps('/v1/reflect-headers');
// then
assert.equal(res.status, 200);
assertSecurityHeaders(res, { csp:'restrictive' });
assertSecurityHeaders(res, { csp:'backend-default' });

// when
const body = await res.json();
Expand All @@ -365,7 +375,7 @@ describe('nginx config', () => {
// then
assert.equal(res.status, 200);
// and
assertSecurityHeaders(res, { csp:'restrictive' });
assertSecurityHeaders(res, { csp:'backend-default' });

// when
const body = await res.json();
Expand Down