[sysadmin/ci-notary-service] /: Add support for JSign which will be used for signing Windows artifacts (exe, dll, appx) on Linux systems
Ben Cooksley <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 7e8743b5e0a5c02506aec81bf5e3df2624fd5b67 by Ben Cooksley.
Committed on 29/07/2026 at 10:41.
Pushed by bcooksley into branch 'master'.
Add support for JSign which will be used for signing Windows artifacts (exe, dll, appx) on Linux systems
M +7 -0 doc/windowsbinariessigner.sample.ini
M +53 -1 sftpnotary/windowsbinariessigner.py
https://invent.kde.org/sysadmin/ci-notary-service/-/commit/7e8743b5e0a5c02506aec81bf5e3df2624fd5b67
diff --git a/doc/windowsbinariessigner.sample.ini b/doc/windowsbinariessigner.sample.ini
index 66f0eb2..0eb6899 100644
--- a/doc/windowsbinariessigner.sample.ini
+++ b/doc/windowsbinariessigner.sample.ini
@@ -6,8 +6,15 @@ Enabled = true
GitLabAPIv4Url = https://gitlab.example.net/api/v4
[CodeSigning]
+## Utility to use when signing
+# For Windows using Windows SDK Sign Tool
+Utility = codesign
+# For all other systems
+# Utility = jsign
## Path of SignTool
SignTool = C:/windowsbinariessigner/signtool.exe
+## Path of JSign
+JSignPath = /usr/bin/jsign
## Path of Certificate
# Certificate = C:\windowsbinariessigner\mycert.pfx
## Password to unlock the certificate
diff --git a/sftpnotary/windowsbinariessigner.py b/sftpnotary/windowsbinariessigner.py
index 5677941..a2d67a5 100644
--- a/sftpnotary/windowsbinariessigner.py
+++ b/sftpnotary/windowsbinariessigner.py
@@ -7,7 +7,7 @@ import os
import re
import shutil
from pathlib import Path
-from tempfile import TemporaryDirectory
+from tempfile import NamedTemporaryFile, TemporaryDirectory
from typing import Dict, List, Optional
from zipfile import ZipFile
@@ -230,6 +230,58 @@ class SignWindowsBinariesProcessor(TaskProcessor):
log.info("No files to sign")
return
+ signingUtility = config.settings.get("CodeSigning", "Utility", "codesign")
+
+ if signingUtility == "jsign":
+ self.signFilesWithJSign(fileNames, path)
+ elif signingUtility == "codesign":
+ self.signFilesWithCodesign(fileNames, path)
+ else:
+ raise Error(
+ "System configuration error - only jsign (ebourg.github.io/jsign/) and "
+ "codesign (Microsoft Windows SDK) are supported"
+ )
+
+ def signFilesWithJSign(self, fileNames: List[str], path: Path):
+ log.info(f"Signing files: {', '.join(fileNames)}")
+ workingDirectory = path
+
+ jsignPath = Path(config.settings.get("CodeSigning", "JSignPath"))
+ certFile = config.settings.get("CodeSigning", "Certificate", "")
+ password = config.settings.get("CodeSigning", "Password", "")
+ subjectName = config.settings.get("CodeSigning", "CommonName", "")
+ command = [
+ jsignPath,
+ "sign",
+ "--verbose",
+ "--storetype PKCS11",
+ "--tsaurl",
+ "http://timestamp.digicert.com",
+ "--alg",
+ "SHA-256",
+ ]
+ if certFile:
+ command += ["--keystore", certFile]
+ if password:
+ command += ["--storepass", password]
+ if subjectName:
+ command += ["--alias", subjectName]
+
+ # To avoid issues with command line length we pass the list of files to sign to JSign by way of a file
+ with NamedTemporaryFile(mode="w", delete=False) as filesToSign:
+ # Write that list and ensure it is flushed
+ filesToSign.write("\n".join(fileNames))
+ filesToSign.close()
+
+ commandToRun = command + [f"@{filesToSign.name}"]
+ commandToLog = sftpnotary.log.maskFollowingItem(commandToRun, "--storepass")
+ util.runCommand(commandToRun, commandToLog=commandToLog, cwd=workingDirectory)
+
+ # Cleanup
+ # In an ideal world we would use delete_on_close=False, however the linters we use do not like that
+ os.unlink(filesToSign.name)
+
+ def signFilesWithCodesign(self, fileNames: List[str], path: Path):
log.info(f"Signing files: {', '.join(fileNames)}")
workingDirectory = path