mirror of https://github.com/keeweb/keeweb
remote code signing
parent
52045ad2a6
commit
79ca627e7c
|
@ -579,8 +579,8 @@ module.exports = function(grunt) {
|
|||
'sign-exe': {
|
||||
options: {
|
||||
url: pkg.homepage,
|
||||
get vm() {
|
||||
return getCodeSingConfig().windowsVM;
|
||||
get windows() {
|
||||
return getCodeSingConfig().windows;
|
||||
},
|
||||
get certHash() {
|
||||
return getCodeSingConfig().microsoftCertHash;
|
||||
|
|
|
@ -1,51 +1,60 @@
|
|||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { spawnSync } = require('child_process');
|
||||
const AdmZip = require('adm-zip');
|
||||
const { runRemoteTask } = require('run-remote-task');
|
||||
|
||||
module.exports = function(grunt) {
|
||||
grunt.registerMultiTask('sign-exe', 'Signs exe file with authenticode certificate', function() {
|
||||
const opt = this.options();
|
||||
for (const [file, name] of Object.entries(opt.files)) {
|
||||
signFile(file, name, opt);
|
||||
}
|
||||
});
|
||||
grunt.registerMultiTask(
|
||||
'sign-exe',
|
||||
'Signs exe file with authenticode certificate',
|
||||
async function() {
|
||||
const done = this.async();
|
||||
const opt = this.options();
|
||||
|
||||
function signFile(file, name, opt) {
|
||||
const fileNameWithoutFolder = path.basename(file);
|
||||
const sharePath = `${process.env.HOME}/VMShare/${fileNameWithoutFolder}`;
|
||||
fs.copyFileSync(file, sharePath);
|
||||
|
||||
const timeServer = 'http://timestamp.verisign.com/scripts/timstamp.dll';
|
||||
|
||||
const cmd = 'VBoxManage';
|
||||
const args = [
|
||||
'guestcontrol',
|
||||
opt.vm.name,
|
||||
'--username',
|
||||
opt.vm.user,
|
||||
'--password',
|
||||
opt.vm.pass,
|
||||
'run',
|
||||
opt.vm.exec,
|
||||
`sign /t ${timeServer} /d "${name}" /du ${opt.url} ${opt.vm.share}${fileNameWithoutFolder}`
|
||||
];
|
||||
// the algo is not working: "/fd ${opt.algo}"
|
||||
let res = spawnSync(cmd, args);
|
||||
if (res.status) {
|
||||
args[5] = '*';
|
||||
const cmdStr = cmd + ' ' + args.join(' ');
|
||||
grunt.warn(`Sign error ${file}: exit code ${res.status}.\nCommand: ${cmdStr}`);
|
||||
}
|
||||
res = spawnSync('osslsigncode', ['verify', sharePath]);
|
||||
if (res.status) {
|
||||
const hasCertHash = res.stdout.includes(`Serial : ${opt.certHash}`);
|
||||
if (!hasCertHash) {
|
||||
grunt.warn(
|
||||
`Verify error ${file}: exit code ${res.status}.\n${res.stdout.toString()}`
|
||||
);
|
||||
for (const [file, name] of Object.entries(opt.files)) {
|
||||
await signFile(file, name, opt);
|
||||
}
|
||||
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
async function signFile(file, name, opt) {
|
||||
grunt.log.writeln(`Signing ${file}...`);
|
||||
|
||||
const fileNameWithoutFolder = path.basename(file);
|
||||
|
||||
const actionConfig = {
|
||||
exe: fileNameWithoutFolder,
|
||||
name: name || fileNameWithoutFolder,
|
||||
url: opt.url
|
||||
};
|
||||
|
||||
const zip = new AdmZip();
|
||||
zip.addFile('action.json', Buffer.from(JSON.stringify(actionConfig)));
|
||||
zip.addLocalFile(file);
|
||||
const zipContents = zip.toBuffer();
|
||||
|
||||
fs.writeFileSync('data.zip', zipContents);
|
||||
|
||||
try {
|
||||
const taskResult = await runRemoteTask(opt.windows, zipContents);
|
||||
const signedFile = taskResult.file;
|
||||
|
||||
const res = spawnSync('osslsigncode', ['verify', signedFile]);
|
||||
if (res.status) {
|
||||
const hasCertHash = res.stdout.includes(`Serial : ${opt.certHash}`);
|
||||
if (!hasCertHash) {
|
||||
grunt.warn(
|
||||
`Verify error ${file}: exit code ${res.status}.\n${res.stdout.toString()}`
|
||||
);
|
||||
}
|
||||
}
|
||||
fs.renameSync(signedFile, file);
|
||||
grunt.log.writeln(`Signed ${file}: ${name}`);
|
||||
} catch (e) {
|
||||
grunt.warn(`Sign error ${file}: ${e}`);
|
||||
}
|
||||
fs.renameSync(sharePath, file);
|
||||
grunt.log.writeln(`Signed ${file}: ${name}`);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1555,6 +1555,11 @@
|
|||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.1.1.tgz",
|
||||
"integrity": "sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ=="
|
||||
},
|
||||
"adm-zip": {
|
||||
"version": "0.4.14",
|
||||
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.14.tgz",
|
||||
"integrity": "sha512-/9aQCnQHF+0IiCl0qhXoK7qs//SwYE7zX8lsr/DNk1BRAHYxeLZPL4pguwK29gUEqasYQjqPtEpDRSWEkdHn9g=="
|
||||
},
|
||||
"agent-base": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz",
|
||||
|
@ -12380,6 +12385,21 @@
|
|||
"aproba": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"run-remote-task": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/run-remote-task/-/run-remote-task-0.1.0.tgz",
|
||||
"integrity": "sha512-FiEaJDoRxCaPnYh73niWlFq96poLBQzR8gRkfWzKr1MoChwiGMe1+JBoY3xojxzjA4ESGwrsaxSfzvJ339rxjg==",
|
||||
"requires": {
|
||||
"minimist": "^1.2.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "6.5.4",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz",
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
"@babel/plugin-external-helpers": "^7.8.3",
|
||||
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
||||
"@babel/preset-env": "^7.9.0",
|
||||
"adm-zip": "^0.4.14",
|
||||
"argon2-browser": "1.13.0",
|
||||
"autoprefixer": "^9.7.5",
|
||||
"babel-cli": "^6.26.0",
|
||||
|
@ -77,6 +78,7 @@
|
|||
"prettier": "^1.19.1",
|
||||
"puppeteer": "^2.1.1",
|
||||
"raw-loader": "^4.0.0",
|
||||
"run-remote-task": "^0.1.0",
|
||||
"sass-loader": "^8.0.2",
|
||||
"stats-webpack-plugin": "0.7.0",
|
||||
"string-replace-webpack-plugin": "0.1.3",
|
||||
|
|
Loading…
Reference in New Issue