Skip to content

Commit

Permalink
Issue #386 [Enhancement][WIP] Use "this" instead of targetConfig wher…
Browse files Browse the repository at this point in the history
…e possible
  • Loading branch information
t2ym committed Sep 9, 2020
1 parent 7967945 commit 7294511
Show file tree
Hide file tree
Showing 13 changed files with 166 additions and 183 deletions.
74 changes: 63 additions & 11 deletions demo-config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class TargetConfig extends GulpDefaultRegistry {
throw new Error(`task("${pluginName}"): plugin.name === ${plugin.name} does not match`);
}
if (typeof plugin.init === 'function') {
plugin.init(targetConfig);
plugin.init.call(targetConfig, targetConfig);
}
return this.gulp.task(pluginName,
this.gulp.series(
Expand All @@ -104,7 +104,8 @@ class TargetConfig extends GulpDefaultRegistry {
}
done();
}, { displayName: `${pluginName} check dependencies` }),
Object.assign(plugin.configurator(targetConfig), { displayName: `${pluginName} configurator` }),
// Note: task function is bound to targetConfig since gulp.series() bypasses registry.set(name, fn)
Object.assign(plugin.configurator.call(targetConfig, targetConfig).bind(targetConfig), { displayName: `${pluginName} configurator` }),
Object.assign((done) => {
targetConfig[pluginName] = targetConfig[pluginName] || {};
targetConfig[pluginName].done = true;
Expand Down Expand Up @@ -163,6 +164,43 @@ class TargetConfig extends GulpDefaultRegistry {
let args = names.map(command => `"${commands[command]}"`);
return `--names "${names.join(',')}" ${args.join(' ')}`;
}
// reverse [ fullPath, urlPath ] mappings
reverseMappings(mappings) {
// [ urlPath, fullPath ] in directory path names
let _mappings = JSON.parse(JSON.stringify(mappings)); // clone
_mappings.sort((a, b) => {
let _a = a[1] + (a[1].endsWith('/') ? '' : '/');
let _b = b[1] + (b[1].endsWith('/') ? '' : '/');
if (_a.length < _b.length) {
if (_b.startsWith(_a)) {
// a > b
return 1;
}
}
else if (_a.length > _b.length) {
if (_a.startsWith(_b)) {
// a < b
return -1;
}
}
return _a.localeCompare(_b);
});
return _mappings.map(([ fullPath, urlPath ]) => [ urlPath, fullPath ]);
}
// map a path with provided mappings
mapper(mappings, _path) {
let result;
for (let [ original, mapped ] of mappings) {
if (_path.startsWith(original + '/')) {
result = path.join(mapped, _path.substring(original.length + '/'.length));
break;
}
}
if (!result) {
throw new Error(`targetConfig.mapper(): "${_path}" cannot be mapped`);
}
return result;
}
// configure itself step by step
_configure() {
this.path = {
Expand All @@ -172,6 +210,7 @@ class TargetConfig extends GulpDefaultRegistry {
backend: 'demo-backend',
frontend: 'demo-frontend',
keys: 'demo-keys',
components: 'bower_components',
encodedIndexHtml: 'index.html',
decodedIndexHtml: 'original-index.html',
hook: TargetConfig.hookPath,
Expand All @@ -183,12 +222,19 @@ class TargetConfig extends GulpDefaultRegistry {
pluginScope: '@thin-hook',
},
url: {
mappings: [
// [ fullPath, urlPath ] in directory path names
[path.resolve(this.path.base, 'bower_components'), '/components'], // highest priority in mapping
[path.resolve(this.path.base, 'demo'), '/components/thin-hook/demo'], // path.resolve(targetConfig.path.base, targetConfig.path.root) is interpreted as root
[this.path.hook, '/components/thin-hook'], // for hook.min.js
],
[TargetConfig.needResolution]: true,
root: '/components/thin-hook/demo', // usually root path should be in an upper directory like '/'; this root is in a deep directory since it is a demo in a component
components: '/components',
mappings: () => {
let mappings = [
// [ fullPath, urlPath ] in directory path names
[path.resolve(this.path.base, this.path.components), this.url.components], // highest priority in mapping
[path.resolve(this.path.base, this.path.root), this.url.root],
[this.path.hook, path.resolve(this.url.components, this.path.hook.split('/').pop())], // for hook.min.js
];
this.url.reverseMappings = this.reverseMappings(mappings); // [ urlPath, fullPath ] in directory path names
return mappings;
},
},
server: {
serverJs: 'demoServer.js',
Expand All @@ -204,7 +250,7 @@ class TargetConfig extends GulpDefaultRegistry {
},
certificates: {
generateCertSh: 'generate_cert.sh',
CA: 'demoCA',
CA: 'demoCA', // default value for openssl
},
mode: {
enableDebugging: false,
Expand Down Expand Up @@ -249,8 +295,14 @@ class TargetConfig extends GulpDefaultRegistry {
"test:attack": () => `concurrently -k -s all -c cyan,magentaBright,yellowBright \\
${this.getConcurrentlyArguments(this.commands, 'buildServer', 'cacheBundleUploadService', 'puppeteerAttackTest')}`,
"puppeteerAttackTest": `node ${path.resolve(this.path.base, 'test/puppeteerAttackTest.js')}`,
"demo-frontend-modules": `cd ${path.resolve(this.path.base, this.path.root)} && npm install`,
"demo-frontend-modules-locked": `cd ${path.resolve(this.path.base, this.path.root)} && npm ci`,
"frontend-modules": `cd ${path.resolve(this.path.base, this.path.root)} && npm install`,
"frontend-modules-locked": `cd ${path.resolve(this.path.base, this.path.root)} && npm ci`,
},
keys: {
noUpdate: true,
},
'automation-secret': {
serverSecret: /*null*/'DummyServerSecretOnlyForDebugging',
},
});
Object.assign(this, { // scoped plugins
Expand Down
18 changes: 9 additions & 9 deletions demo-config/integrity-json/targets.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,25 @@ Copyright (c) 2020, Tetsuya Mori <t2y3141592@gmail.com>. All rights reserved.
const path = require('path');

// return globs for target entries in integrity.json
const targets = (targetConfig) => {
const destPath = path.resolve(targetConfig.path.base, targetConfig.path.root);
const targets = function (targetConfig) {
const destPath = path.resolve(this.path.base, this.path.root);
return [
path.resolve(targetConfig.path.hook, 'hook.min.js'),
path.resolve(this.path.hook, 'hook.min.js'),
path.resolve(destPath, '**/*'),
path.resolve(targetConfig.path.base, 'bower_components/**/*'),
path.resolve(this.path.base, this.path.components, '**/*'),
// integrity.json itself
'!' + path.resolve(destPath, 'integrity.json'),
'!' + path.resolve(destPath, '**/*.gz'),
'!' + path.resolve(destPath, 'errorReport.json'),
// decoded index.html
'!' + path.resolve(destPath, targetConfig.path.decodedIndexHtml),
'!' + path.resolve(destPath, this.path.decodedIndexHtml),
// encoded index.html
'!' + path.resolve(destPath, targetConfig.path.encodedIndexHtml),
'!' + path.resolve(targetConfig.path.base, 'bower_components/**/test/**/*'),
'!' + path.resolve(targetConfig.path.base, 'bower_components/**/demo/**/*'),
'!' + path.resolve(destPath, this.path.encodedIndexHtml),
'!' + path.resolve(this.path.base, this.path.components, '**/test/**/*'),
'!' + path.resolve(this.path.base, this.path.components, '**/demo/**/*'),
];
}

module.exports = {
targets: targets,
targets,
};
24 changes: 12 additions & 12 deletions plugins/automation-secret/configurator.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ const readline = require('readline');

const pluginName = 'automation-secret';

const configurator = (targetConfig) => {
const configPath = path.resolve(targetConfig.path.base, targetConfig.path.config, pluginName);
const destPath = path.resolve(targetConfig.path.base, targetConfig.path.root);
const configurator = function (targetConfig) {
const configPath = path.resolve(this.path.base, this.path.config, pluginName);
const destPath = path.resolve(this.path.base, this.path.root);
const pluginDirname = __dirname;
const sourceFile = targetConfig[pluginName] && targetConfig[pluginName].sourceFile
? targetConfig[pluginName].sourceFile
const sourceFile = this[pluginName] && this[pluginName].sourceFile
? this[pluginName].sourceFile
: 'cache-automation.js';
return (done) => gulp.src([path.resolve(destPath, sourceFile)])
.pipe(through.obj((file, enc, callback) => {
// server secret for cache-automation.js
(async () => {
let usePreconfiguredServerSecret = false;
if (targetConfig[pluginName] && targetConfig[pluginName].serverSecret) {
if (this[pluginName] && this[pluginName].serverSecret) {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
Expand All @@ -37,7 +37,7 @@ const configurator = (targetConfig) => {
plugin: ${pluginName}
targetConfig["${pluginName}"].serverSecret is set as "${targetConfig[pluginName].serverSecret}"
targetConfig["${pluginName}"].serverSecret is set as "${this[pluginName].serverSecret}"
The current configuration must be solely for debugging purposes and must never be applied for production.
If serverSecret should be known to attackers, the web application would have a severe vulnerability through a crafted automation script.
Expand All @@ -58,16 +58,16 @@ Can you confirm this vulnerable configuration for serverSecret? (y/N) `, (answer
});
});
}
const serverSecret = usePreconfiguredServerSecret ? targetConfig[pluginName].serverSecret : crypto.randomFillSync(Buffer.alloc(32)).toString('hex');
const serverSecret = usePreconfiguredServerSecret ? this[pluginName].serverSecret : crypto.randomFillSync(Buffer.alloc(32)).toString('hex');
const cacheAutomationScript = String(file.contents);
let authorization; // sha256(serverSecret + cacheAutomationScript)
let hash = createHash('sha256');
hash.update(serverSecret + cacheAutomationScript);
authorization = hash.digest('hex');
targetConfig[pluginName] = targetConfig[pluginName] || {};
targetConfig[pluginName].serverSecret = serverSecret;
targetConfig[pluginName].cacheAutomationScriptPath = file.path;
targetConfig[pluginName].authorization = authorization;
this[pluginName] = this[pluginName] || {};
this[pluginName].serverSecret = serverSecret;
this[pluginName].cacheAutomationScriptPath = file.path;
this[pluginName].authorization = authorization;
//console.log(targetConfig);
done();
})();
Expand Down
18 changes: 7 additions & 11 deletions plugins/cache-bundle-automation-json/configurator.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,23 @@
Copyright (c) 2020, Tetsuya Mori <t2y3141592@gmail.com>. All rights reserved.
*/
const path = require('path');
const { preprocess } = require('preprocess');
const through = require('through2');
const gulp = require('gulp');
const fs = require('fs');

const pluginName = 'cache-bundle-automation-json';

const configurator = (targetConfig) => {
const configPath = path.resolve(targetConfig.path.base, targetConfig.path.config, pluginName);
const destPath = path.resolve(targetConfig.path.base, targetConfig.path.root);
const configurator = function (targetConfig) {
const destPath = path.resolve(this.path.base, this.path.root);
const pluginDirname = __dirname;
const sourceFile = targetConfig[pluginName] && targetConfig[pluginName].sourceFile
? targetConfig[pluginName].sourceFile
const sourceFile = this[pluginName] && this[pluginName].sourceFile
? this[pluginName].sourceFile
: 'cache-bundle.json';
return (done) => {
const cacheAutomationScript = fs.readFileSync(targetConfig['automation-secret'].cacheAutomationScriptPath, 'utf-8');
const cacheAutomationScript = fs.readFileSync(this['automation-secret'].cacheAutomationScriptPath, 'utf-8');
fs.writeFileSync(path.resolve(destPath, sourceFile), JSON.stringify({
"version": targetConfig['get-version'].version,
"version": this['get-version'].version,
"https://thin-hook.localhost.localdomain/automation.json": JSON.stringify({
"state": "init", // update state in the script to perform operations including reloading
"serverSecret": targetConfig['automation-secret'].serverSecret,
"serverSecret": this['automation-secret'].serverSecret,
"script": cacheAutomationScript,
}, null, 0)
}, null, 2));
Expand Down
37 changes: 8 additions & 29 deletions plugins/disable-devtools/configurator.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,18 @@ Copyright (c) 2020, Tetsuya Mori <t2y3141592@gmail.com>. All rights reserved.
const path = require('path');
const { preprocess } = require('preprocess');
const through = require('through2');
const gulp = require('gulp');

const pluginName = 'disable-devtools';

const configurator = (targetConfig) => {
const configPath = path.resolve(targetConfig.path.base, targetConfig.path.config, pluginName);
const destPath = path.resolve(targetConfig.path.base, targetConfig.path.root);
const devtoolsDisabled = targetConfig.mode.devtoolsDisabled;
const configurator = function (targetConfig) {
const configPath = path.resolve(this.path.base, this.path.config, pluginName);
const destPath = path.resolve(this.path.base, this.path.root);
const devtoolsDisabled = this.mode.devtoolsDisabled;
const pluginDirname = __dirname;
const sourceFile = targetConfig[pluginName] && targetConfig[pluginName].sourceFile
? targetConfig[pluginName].sourceFile
const sourceFile = this[pluginName] && this[pluginName].sourceFile
? this[pluginName].sourceFile
: 'disable-devtools.js';
return () => gulp.src([ path.resolve(pluginDirname, sourceFile) ])
// 1st pass
return () => this.gulp.src([ path.resolve(pluginDirname, sourceFile) ])
.pipe(through.obj((file, enc, callback) => {
let script = String(file.contents);
script = preprocess(script,
Expand All @@ -37,26 +35,7 @@ const configurator = (targetConfig) => {
file.contents = Buffer.from(script);
callback(null, file);
}))
/*
// 2nd pass
.pipe(through.obj((file, enc, callback) => {
let script = String(file.contents);
script = preprocess(script,
{
SPACE: ' ',
EQUAL: '=',
SEMICOLON: ';',
},
{
type: 'js',
srcDir: configPath, // in demo-config/policy/
}
);
file.contents = Buffer.from(script);
callback(null, file);
}))
*/
.pipe(gulp.dest(destPath));
.pipe(this.gulp.dest(destPath));
}

module.exports = {
Expand Down
18 changes: 7 additions & 11 deletions plugins/dummy-integrity/configurator.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,24 @@
Copyright (c) 2020, Tetsuya Mori <t2y3141592@gmail.com>. All rights reserved.
*/
const path = require('path');
const { preprocess } = require('preprocess');
const through = require('through2');
const gulp = require('gulp');
const fs = require('fs');

const pluginName = 'dummy-integrity';

const configurator = (targetConfig) => {
const configPath = path.resolve(targetConfig.path.base, targetConfig.path.config, pluginName);
const destPath = path.resolve(targetConfig.path.base, targetConfig.path.root);
const configurator = function (targetConfig) {
const destPath = path.resolve(this.path.base, this.path.root);
const pluginDirname = __dirname;
const sourceFile = targetConfig[pluginName] && targetConfig[pluginName].sourceFile
? targetConfig[pluginName].sourceFile
const sourceFile = this[pluginName] && this[pluginName].sourceFile
? this[pluginName].sourceFile
: 'integrity.json';
return (done) => {
// generate a dummy demo/integrity.json for cache-bundle generation
const cacheAutomationScript = fs.readFileSync(targetConfig['automation-secret'].cacheAutomationScriptPath, 'utf-8');
const cacheAutomationScript = fs.readFileSync(this['automation-secret'].cacheAutomationScriptPath, 'utf-8');
fs.writeFileSync(path.resolve(destPath, sourceFile), JSON.stringify({
"version": targetConfig['get-version'].version,
"version": this['get-version'].version,
"https://thin-hook.localhost.localdomain/automation.json": JSON.stringify({
"state": "init", // update state in the script to perform operations including reloading
"serverSecret": targetConfig['automation-secret'].serverSecret,
"serverSecret": this['automation-secret'].serverSecret,
"script": cacheAutomationScript,
}, null, 0)
}, null, 2));
Expand Down
16 changes: 6 additions & 10 deletions plugins/get-version/configurator.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,16 @@
Copyright (c) 2020, Tetsuya Mori <t2y3141592@gmail.com>. All rights reserved.
*/
const path = require('path');
const { preprocess } = require('preprocess');
const through = require('through2');
const gulp = require('gulp');

const pluginName = 'get-version';

const configurator = (targetConfig) => {
const configPath = path.resolve(targetConfig.path.base, targetConfig.path.config, pluginName);
const destPath = path.resolve(targetConfig.path.base, targetConfig.path.root);
const configurator = function (targetConfig) {
const destPath = path.resolve(this.path.base, this.path.root);
const pluginDirname = __dirname;
const sourceFile = targetConfig.path.decodedIndexHtml || 'original-index.html';
const sourceFile = this.path.decodedIndexHtml || 'original-index.html';
let version = 'version_1';
return (done) => gulp.src([path.resolve(destPath, sourceFile)])
return (done) => this.gulp.src([path.resolve(destPath, sourceFile)])
.pipe(through.obj((file, enc, callback) => {
let html = String(file.contents);
let versionIndex = html.indexOf('/hook.min.js?version=') + '/hook.min.js?version='.length;
Expand All @@ -24,9 +21,8 @@ const configurator = (targetConfig) => {
callback(null, file);
}))
.pipe(through.obj((file, enc, callback) => {
targetConfig[pluginName] = targetConfig[pluginName] || {};
targetConfig[pluginName].version = version;
//console.log('targetConfig', targetConfig);
this[pluginName] = this[pluginName] || {};
this[pluginName].version = version;
done();
}));
}
Expand Down

0 comments on commit 7294511

Please sign in to comment.