diff --git a/deploy/app.js b/deploy/app.js index f233a07c66eefbc560bac96d259524d450f4c7b6..657514945f390cfe45affd9604c97bbc53f3a424 100644 --- a/deploy/app.js +++ b/deploy/app.js @@ -45,6 +45,11 @@ app.use(session({ store })) +/** + * configure CSP + */ +require('./csp')(app) + /** * configure Auth * async function, but can start server without diff --git a/deploy/csp/index.js b/deploy/csp/index.js new file mode 100644 index 0000000000000000000000000000000000000000..2a7a7d91ecee0909f1708a656e80839218a510f8 --- /dev/null +++ b/deploy/csp/index.js @@ -0,0 +1,67 @@ +const csp = require('helmet-csp') +const bodyParser = require('body-parser') + +let ALLOWED_DEFAULT_SRC, DATA_SRC + +try { + ALLOWED_DEFAULT_SRC = JSON.parse(process.env.ALLOWED_DEFAULT_SRC || '[]') +} catch (e) { + console.warn(`parsing ALLOWED_DEFAULT_SRC error ${process.env.ALLOWED_DEFAULT_SRC}`, e) + ALLOWED_DEFAULT_SRC = [] +} + +try { + DATA_SRC = JSON.parse(process.env.DATA_SRC || '[]') +} catch (e) { + console.warn(`parsing DATA_SRC error ${process.env.DATA_SRC}`, e) + DATA_SRC = [] +} + +const defaultAllowedSites = [ + "'self'", + '*.apps.hbp.eu', + '*.apps-dev.hbp.eu', + ...ALLOWED_DEFAULT_SRC +] + +const dataSource = [ + "'self'", + '*.humanbrainproject.org', + '*.humanbrainproject.eu', + '*.fz-juelich.de', + ...DATA_SRC +] + +module.exports = (app) => { + app.use(csp({ + directives: { + defaultSrc: [ + ...defaultAllowedSites + ], + styleSrc: [ + ...defaultAllowedSites, + '*.bootstrapcdn.com', + '*.fontawesome.com', + "'unsafe-inline'" // required for angular [style.xxx] bindings + ], + fontSrc: [ '*.fontawesome.com' ], + connectSrc: [ + ...defaultAllowedSites, + ...dataSource + ], + reportUri: '/report-violation' + }, + reportOnly: true + })) + + app.post('/report-violation', bodyParser.json({ + type: ['json', 'application/csp-report'] + }), (req, res) => { + if (req.body) { + console.warn(`CSP Violation: `, req.body) + } else { + console.warn(`CSP Violation: no data received!`) + } + res.status(204).end() + }) +} \ No newline at end of file diff --git a/deploy/package.json b/deploy/package.json index a1d2f4121597df333198cedf3a0be87749356fa2..2d33823ef6a544b335a6a6edfc2096456b09419c 100644 --- a/deploy/package.json +++ b/deploy/package.json @@ -17,6 +17,7 @@ "body-parser": "^1.19.0", "express": "^4.16.4", "express-session": "^1.15.6", + "helmet-csp": "^2.8.0", "jszip": "^3.2.1", "jwt-decode": "^2.2.0", "memorystore": "^1.6.1", diff --git a/src/index.html b/src/index.html index 467e979f0b14b8f6bbaedae248b488a4f72745d6..5daabaa09f3c303607e068bf5ac29107cf3a5761 100644 --- a/src/index.html +++ b/src/index.html @@ -6,49 +6,22 @@ <meta http-equiv="X-UA-Compatible" content="ie=edge"> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous"> - <link rel = "stylesheet" href = "extra_styles.css"> - <link rel = "stylesheet" href = "plugin_styles.css"> - <link rel = "stylesheet" href = "indigo-pink.css"> + <link rel="stylesheet" href="extra_styles.css"> + <link rel="stylesheet" href="plugin_styles.css"> + <link rel="stylesheet" href="indigo-pink.css"> <title>Interactive Atlas Viewer</title> </head> <body> <atlas-viewer> - <h1 style = "text-align:center;"> - <span class = "homeAnimationDots loadingAnimationDots">•</span> - <span class = "homeAnimationDots loadingAnimationDots">•</span> - <span class = "homeAnimationDots loadingAnimationDots">•</span> + <h1 class="text-center"> + <span class="homeAnimationDots loadingAnimationDots">•</span> + <span class="homeAnimationDots loadingAnimationDots">•</span> + <span class="homeAnimationDots loadingAnimationDots">•</span> </h1> </atlas-viewer> - <script> - /** - * Catching Safari 10 bug: - * - * https://bugs.webkit.org/show_bug.cgi?id=171041 - * - */ - try{ - eval('(()=>{\ - let e = e => {\ - console.log(e);\ - for(let e of [1,2,3]){\ - console.log(e);\ - }\ - }\ - })()') - }catch(e){ - console.log(e) - const warning = 'Your browser cannot display the interactive viewer. Please use either Chrome >= 56 and/or Firefox >= 51' - console.log(warning) - const warningEl = document.createElement('h4') - warningEl.innerHTML = warning - const el = document.getElementsByTagName('atlas-viewer') - if(el.length > 0){ - document.body.removeChild(el[0]) - } - document.body.appendChild(warningEl) - } + <script src="testSafari.js"> </script> </body> </html> diff --git a/src/main-aot.ts b/src/main-aot.ts index 171bd6ce7beb8ae5a35e9d43553fdc134235d0e1..deb5b01964c9a760c2d8d40bf23a6d859a6555e3 100644 --- a/src/main-aot.ts +++ b/src/main-aot.ts @@ -1,5 +1,7 @@ import 'zone.js' +import 'third_party/testSafari.js' + import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' import { MainModule } from './main.module'; import { enableProdMode } from '@angular/core'; diff --git a/src/main.ts b/src/main.ts index 5eec78190f22de8b0a62e4d71eb812efc3a842ab..479dbb34491927cd7ed00952948534c70cdc698f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,5 +1,8 @@ import 'zone.js' import 'reflect-metadata' + +import 'third_party/testSafari.js' + import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' import { MainModule } from './main.module'; diff --git a/third_party/testSafari.js b/third_party/testSafari.js new file mode 100644 index 0000000000000000000000000000000000000000..b56fa557b4dabeba4f993200723d8bb5bb21673e --- /dev/null +++ b/third_party/testSafari.js @@ -0,0 +1,31 @@ + +/** +* Catching Safari 10 bug: +* +* https://bugs.webkit.org/show_bug.cgi?id=171041 +* +*/ + +(function(){ + try{ + eval('(()=>{\ + let e = e => {\ + console.log(e);\ + for(let e of [1,2,3]){\ + console.log(e);\ + }\ + }\ + })()') + } catch (e) { + console.log(e) + const warning = 'Your browser cannot display the interactive viewer. Please use either Chrome >= 56 and/or Firefox >= 51' + console.log(warning) + const warningEl = document.createElement('h4') + warningEl.innerHTML = warning + const el = document.getElementsByTagName('atlas-viewer') + if(el.length > 0){ + document.body.removeChild(el[0]) + } + document.body.appendChild(warningEl) + } +})() \ No newline at end of file diff --git a/webpack.aot.js b/webpack.aot.js index 0b8ac221109bc3d7a1868e4779576f6190b71b1c..8c815798d118033bf6a7662bbf4e32980cbd74d1 100644 --- a/webpack.aot.js +++ b/webpack.aot.js @@ -19,7 +19,7 @@ module.exports = merge(staticAssets, { module: { rules: [ { - test : /export_nehuba.*?\.js$|worker\.js/, + test : /third_party.*?\.js$|worker\.js/, use : { loader : 'file-loader', options: { @@ -30,7 +30,7 @@ module.exports = merge(staticAssets, { { test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/, loader: '@ngtools/webpack', - exclude : /export_nehuba|plugin_example/ + exclude : /third_party|plugin_example/ }, { test : /\.(html|css)$/, diff --git a/webpack.common.js b/webpack.common.js index aafad55efaecb04b6f4684048c5fc6e91479d946..9f680d8ef445b10c2a672197ea510f1dba6033c8 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -10,7 +10,7 @@ module.exports = { exclude : /node_modules|[Ss]pec\.ts$/ }, { - test : /export_nehuba|.*?worker.*?\.js$/, + test : /third_party|.*?worker.*?\.js$/, use : { loader : 'file-loader', options: { diff --git a/webpack.export.aot.js b/webpack.export.aot.js index 8421c23bfbf643fbf0926c5e4d6e689d0a984200..fda5c27b38cc2f8a9208ea0db0b72110359510ab 100644 --- a/webpack.export.aot.js +++ b/webpack.export.aot.js @@ -18,7 +18,7 @@ module.exports = { test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/, // test : /\.ts$/, loader: '@ngtools/webpack', - exclude : /export_nehuba/ + exclude : /third_party/ }, { test : /\.(html|css)$/,