feat: 🎸 enable dynamic csp rewriting when origin changes
This commit is contained in:
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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
Reference in new issue
Block a user