scaffolder-backend: add initial SecureTemplater implementation

Co-authored-by: Johan Haals <johan.haals@gmail.com>
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2021-11-19 17:50:25 +01:00
parent d6da7d706d
commit 21b54689c6
3 changed files with 78 additions and 1 deletions
+2 -1
View File
@@ -69,7 +69,8 @@
"octokit-plugin-create-pull-request": "^3.10.0",
"uuid": "^8.2.0",
"winston": "^3.2.1",
"yaml": "^1.10.0"
"yaml": "^1.10.0",
"vm2": "^3.9.5"
},
"devDependencies": {
"@backstage/cli": "^0.9.0",
@@ -0,0 +1,71 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { VM } from 'vm2';
import { resolvePackagePath } from '@backstage/backend-common';
import fs from 'fs-extra';
const mkScript = (nunjucksSource: string) => `
const render = (() => {
const module = {};
const require = (pkg) => { if (pkg === 'events') { return function (){}; }};
${nunjucksSource}
const env = module.exports.configure({
autoescape: false,
tags: {
variableStart: '\${{',
variableEnd: '}}',
},
});
return function render(str, values) {
return env.renderString(str, JSON.parse(values));
}
})();
`;
export class SecureTemplater {
#vm?: VM;
async render(template: string, values: unknown) {
const vm = await this.getVm();
vm.setGlobal('templateStr', template);
vm.setGlobal('templateValues', JSON.stringify(values));
const result = vm.run(`render(templateStr, templateValues)`);
return result;
}
private async getVm() {
if (!this.#vm) {
this.#vm = new VM({
timeout: 1000,
});
const nunjucksSource = await fs.readFile(
resolvePackagePath(
'@backstage/plugin-scaffolder-backend',
'assets/nunjucks.js.txt',
),
'utf-8',
);
this.#vm.run(mkScript(nunjucksSource));
}
return this.#vm;
}
}