feat: 🎸 enable dynamic csp rewriting when origin changes

This commit is contained in:
Randall Morey committed 2021-01-08 15:39:27 -05:00
1 parent 46fef75017
commit 900a8bd56c
4 files changed
+63 -15

No files matched your search

@@ -1,3 +1,4 @@
const runtimeSettings = require('./runtime-settings.js');
const isDev = require('electron-is-dev');
const csp = {
@@ -23,10 +24,21 @@ const enableDevCSP = () => {
csp['connect-src'].push("ws://localhost:7020");
};
const generateCSPHeader = () => Object
.keys(csp)
.map(key => `${key} ${csp[key].join(' ')};`)
.join(' ');
const generateCSPHeader = () => {
const policy = Object.assign({}, csp);
// If an origin is specified, add it to the connect-src directive
if (runtimeSettings.origin) {
policy['connect-src'] = policy['connect-src'].slice();
policy['connect-src'].push(runtimeSettings.origin);
console.log(`[content-security-policy] Including user-specified origin "${runtimeSettings.origin}" to connect-src`);
}
return Object
.keys(policy)
.map(key => `${key} ${policy[key].join(' ')};`)
.join(' ');
}
if (isDev) enableDevCSP();
+5 -11
View File
@@ -1,24 +1,18 @@
const handle = require('./ipc-handler');
const boundaryCli = require('./boundary-cli');
let origin = '';
const runtimeSettings = require('./runtime-settings.js');
/**
* Returns the current runtime origin, which is used by the main thread to
* rewrite the CSP to allow requests.
*/
handle('getOrigin', () => origin);
handle('getOrigin', () => runtimeSettings.origin);
/**
* TODO: sets the main process origin to the specified value. This value will
* be used to rewrite the CSP to allow requests to that origin. If the origin
* was not previously set, the main process will set it and restart
* the renderer.
*
* For now, we update the internal origin but do not yet rewrite the CSP.
* Sets the origin to be used in the content security policy and triggers
* a main window reload.
*/
handle('setOrigin', (requestOrigin) => origin = requestOrigin);
handle('setOrigin', (requestOrigin) => runtimeSettings.origin = requestOrigin);
/**
* Check for boundary cli existence
+5
View File
@@ -7,6 +7,7 @@ const {
const { session, app, protocol, BrowserWindow, ipcMain } = require('electron');
require('./handlers.js');
const runtimeSettings = require('./runtime-settings.js');
const { generateCSPHeader } = require('./content-security-policy.js');
const isDev = require('electron-is-dev');
@@ -100,6 +101,10 @@ app.on('ready', async () => {
},
});
// If the user-specified origin changes, reload the page so that
// the CSP can be refreshed with the this source allowed
runtimeSettings.onOriginChange(() => mainWindow.loadURL(emberAppURL));
// If you want to open up dev tools programmatically, call
// mainWindow.openDevTools();
@@ -0,0 +1,37 @@
// Provides a singleton class instance to enable a consistent view of
// runtime settings across the application.
// Runtime settings are any configuration, especially user-specified,
// set up at runtime. For example, the Boundary origin is a runtime setting.
class RuntimeSettings {
// Internal private origin is exposed via getter/setter below.
#origin = undefined;
/**
* The user-specified Boundary origin, which should be allowed by CSP.
* @type {?string}
*/
get origin() { return this.#origin; }
set origin(origin) {
this.#origin = origin;
this.triggerOriginChanged();
}
// Quick and dirty event handler pattern to enable the application to respond
// when the origin is changed.
#originWatchers = [];
onOriginChange(fn) {
this.#originWatchers.push(fn);
}
triggerOriginChanged() {
this.#originWatchers.forEach(fn => fn(this.#origin));
}
}
const runtimeSettings = new RuntimeSettings();
module.exports = runtimeSettings;