diff --git a/task/codesigning.ts b/task/codesigning.ts index 7640c54..909c573 100644 --- a/task/codesigning.ts +++ b/task/codesigning.ts @@ -3,7 +3,7 @@ import tl = require("azure-pipelines-task-lib/task"); import { ToolRunner } from "azure-pipelines-task-lib/toolrunner"; import fs = require("fs"); -async function sign(signToolPath: string, filePath: string, hashingAlgorithm: string, timeServer: string, signCertPassword: string, description: string): Promise { +async function sign(signToolPath: string, filePath: string, hashingAlgorithm: string, timeServer: string, signCertPassword: string, description: string, enableDebugSwitch: boolean): Promise { const signToolRunner: ToolRunner = tl.tool(signToolPath); let secureFilePath: string = tl.getTaskVariable("SECURE_FILE_PATH"); console.log("Signing file: " + filePath); @@ -13,6 +13,10 @@ async function sign(signToolPath: string, filePath: string, hashingAlgorithm: st signToolRunner.arg(["/t", timeServer]); signToolRunner.arg(["/f", secureFilePath]); signToolRunner.arg(["/p", signCertPassword]); + if(enableDebugSwitch){ + signToolRunner.arg(["/debug"]); + signToolRunner.arg(["/v"]); + } if(description) { signToolRunner.arg(["/d", description]); } @@ -27,6 +31,7 @@ async function run(): Promise { let signCertPassword: string = tl.getInput("signCertPassword", true); let timeServer: string = tl.getInput("timeServer", true); + let enableDebugSwitch: boolean = tl.getBoolInput("enableDebugSwitch", true); let hashingAlgorithm: string = tl.getInput("hashingAlgorithm", true); let filesPattern: string = tl.getInput("files", true); let signToolLocationMethod: string = tl.getInput("signToolLocationMethod", false); @@ -53,7 +58,7 @@ async function run(): Promise { throw new Error(tl.loc("NoMatchingFiles", filesPattern)); } for (let filePath of filesToSign) { - await sign(signToolPath, filePath, hashingAlgorithm, timeServer, signCertPassword, description); + await sign(signToolPath, filePath, hashingAlgorithm, timeServer, signCertPassword, description, enableDebugSwitch); console.log("Job Finished: Successfully signed file " + filePath + " with given certificate."); } } catch (err) { @@ -96,4 +101,4 @@ function findFilesInDir(startPath: string, filter: string): string[] { return results; } -run(); \ No newline at end of file +run(); diff --git a/task/task.json b/task/task.json index 28e4cfe..bdfe92c 100644 --- a/task/task.json +++ b/task/task.json @@ -67,6 +67,14 @@ "defaultValue": "", "helpMarkDown": "UAC will display this description when installing the signed file" }, + { + "name": "enableDebugSwitch", + "type": "boolean", + "label": "Enable debug output from signtool.exe", + "required": false, + "defaultValue": false, + "helpMarkDown": "Enable debug output from signtool.exe" + }, { "name": "signToolLocationMethod", "type": "radio", @@ -110,4 +118,4 @@ "NoMatchingFiles": "No matching files were found with search pattern: %s", "DeleteSecureFileFailed": "Failed to delete secure file downloaded from the server: %s" } -} \ No newline at end of file +} diff --git a/tests/L0CodeSigningSingleFileWithDebugSwitch.ts b/tests/L0CodeSigningSingleFileWithDebugSwitch.ts new file mode 100644 index 0000000..b9e2060 --- /dev/null +++ b/tests/L0CodeSigningSingleFileWithDebugSwitch.ts @@ -0,0 +1,38 @@ +import mockanswer = require("azure-pipelines-task-lib/mock-answer"); +import tmrm = require("azure-pipelines-task-lib/mock-run"); +import path = require("path"); + +let taskPath: string = path.join(__dirname, "../task", "codesigning.js"); +let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); + +const secureFileId: string = "THESECUREFILEID"; +const signCertPassword: string = "PASSWORD"; +const timeServer: string = "http://timestamp.digicert.com"; +const hashingAlgorithm: string = "SHA256"; +const fileToSign: string = "DllToSign.dll"; + +const signToolPath: string = path.normalize(path.join(__dirname, "../task", "signtool.exe")); +const certificatePath: string = path.join(__dirname, "./test-files", "TestCertificate.pfx"); +const filePaths: string = "DllToSign.dll"; +tmr.setInput("secureFileId", secureFileId); +tmr.setInput("signCertPassword", signCertPassword); +tmr.setInput("timeServer", timeServer); +tmr.setInput("hashingAlgorithm", hashingAlgorithm); +tmr.setInput("files", filePaths); +tmr.setVariableName("SECURE_FILE_PATH", certificatePath); + +let answers: mockanswer.TaskLibAnswers = { + findMatch: { + "DllToSign.dll": [ + "DllToSign.dll" + ] + }, + exec: {} +}; +answers.exec[`${signToolPath} sign /fd ${hashingAlgorithm} /t ${timeServer} /f ${certificatePath} /p ${signCertPassword} ${fileToSign}`] = { + code: 0, + stdout: `Successfully signed ${fileToSign}` +}; + +tmr.setAnswers(answers); +tmr.run();