diff --git a/Gruntfile.js b/Gruntfile.js index 6ac462c6..721788df 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -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; diff --git a/build/tasks/grunt-sign-exe.js b/build/tasks/grunt-sign-exe.js index 316d59b8..df81f776 100644 --- a/build/tasks/grunt-sign-exe.js +++ b/build/tasks/grunt-sign-exe.js @@ -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}`); } }; diff --git a/package-lock.json b/package-lock.json index 19ab3bfd..4b169e3b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index fa9b0af3..1db7b86d 100644 --- a/package.json +++ b/package.json @@ -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",