Code Signing – Windows-Binaries signieren
Die code-signing-Komponente signiert Windows-Binaries (EXE, DLL, MSI) über den Azure Trusted Signing Service direkt in der GitLab CI/CD Pipeline. Sie nutzt Microsofts SignTool aus dem Windows SDK zusammen mit der Azure Code Signing Dlib.
Funktionsweise
- SignTool wird aus dem Windows 10 SDK lokalisiert
- Die Azure Code Signing Dlib wird per NuGet heruntergeladen
- Eine
metadata.jsonwird aus den CI/CD-Variablen generiert - Alle Dateien im
input_path, die denfile_patternsentsprechen, werden signiert (SHA256 + RFC 3161 Timestamp) - Die Signaturen werden automatisch verifiziert
- Optional werden die signierten Dateien in ein separates
output_pathkopiert
Voraussetzungen
Windows Runner
Der Runner muss folgende Software installiert haben:
- Windows 10 SDK (Version 10.0.22621+) mit
signtool.exe - nuget.exe im PATH oder im Projekt-Root
Standard-Runner: build-windows-10-64
Azure CI/CD-Variablen
Folgende Variablen müssen in der Pipeline verfügbar sein:
| Variable | Beschreibung |
|---|---|
AZURE_TENANT_ID | Azure AD Tenant ID |
AZURE_CLIENT_ID | Azure Service Principal Client ID |
AZURE_CLIENT_SECRET | Azure Service Principal Client Secret |
SIGNING_ENDPOINT | Azure Trusted Signing Endpoint URL |
SIGNING_ACCOUNT_NAME | Code Signing Account Name |
Empfehlung: Vault Secrets verwenden
Diese Variablen sollten vorzugsweise über die Vault Secrets-Komponente aus Vault geladen werden. Das ist sicherer als manuell gepflegte CI/CD-Variablen, da Secrets zentral verwaltet und automatisch rotiert werden können. Siehe Kombination mit Vault Secrets weiter unten.
Alternativ können die Variablen auf Projekt- oder Gruppenebene unter Settings → CI/CD → Variables gesetzt werden – dabei AZURE_CLIENT_SECRET als Protected und Masked konfigurieren.
Einrichtung
Einfaches Beispiel
stages:
- build
- sign
include:
- component: git.styrion.net/iteas/gitlab-components/code-signing@main
inputs:
input_path: "MyApp/bin/Release"
build:
stage: build
tags:
- build-windows-10-64
script:
- dotnet build -c Release
artifacts:
paths:
- MyApp/bin/Release/Der code-signing-Job wird automatisch in der sign-Stage erstellt und signiert alle .exe, .dll und .msi Dateien im angegebenen Verzeichnis.
Eigenes Zertifikatsprofil
include:
- component: git.styrion.net/iteas/gitlab-components/code-signing@main
inputs:
input_path: "MyApp/bin/Release"
cert_profile_name: "MyCompany-Production-Signing"Separates Ausgabeverzeichnis
include:
- component: git.styrion.net/iteas/gitlab-components/code-signing@main
inputs:
input_path: "build/unsigned"
output_path: "build/signed"Die signierten Dateien werden nach build/signed kopiert, die Originale in build/unsigned bleiben unverändert.
Konfigurationsoptionen
| Input | Beschreibung | Pflicht | Standard |
|---|---|---|---|
job_name | Name des generierten CI-Jobs (erlaubt mehrfache Einbindung) | Nein | code-signing |
input_path | Verzeichnis mit den unsignierten Dateien | Ja | - |
output_path | Verzeichnis für signierte Artifacts (Standard: gleich wie input_path) | Nein | (leer) |
file_patterns | Kommaseparierte Dateimuster zum Signieren | Nein | *.exe, *.dll, *.msi |
stage | Pipeline-Stage für den Signing-Job | Nein | sign |
cert_profile_name | Azure Trusted Signing Zertifikatsprofil-Name | Nein | ITeas-Test-Signing |
runner_tag | GitLab Runner Tag für den Windows-Build-Runner | Nein | build-windows-10-64 |
Technische Details
| Eigenschaft | Wert |
|---|---|
| Runner | build-windows-10-64 (konfigurierbar) |
| Plattform | Windows (PowerShell) |
| Signatur-Algorithmus | SHA256 |
| Timestamp-Server | http://timestamp.acs.microsoft.com (RFC 3161) |
| Artifact-Ablauf | 1 Stunde |
Pipeline-Regeln
Die Komponente läuft auf:
- Branch-Pipelines (außer wenn ein Merge Request offen ist)
- Tag-Pipelines
- Merge-Request-Pipelines (die auf den Default-Branch zielen)
Erweiterte Konfiguration
Mehrfaches Signieren in einer Pipeline
Über den job_name-Parameter kann die Komponente mehrfach eingebunden werden – z.B. um zuerst Binaries zu signieren, dann einen Installer zu bauen und diesen ebenfalls zu signieren:
stages:
- build
- sign
- installer
- sign-installer
include:
# Schritt 1: Binaries signieren
- component: git.styrion.net/iteas/gitlab-components/code-signing@main
inputs:
job_name: "sign-binaries"
input_path: "MyApp/bin/Release"
file_patterns: "*.exe, *.dll"
stage: sign
# Schritt 2: Installer signieren
- component: git.styrion.net/iteas/gitlab-components/code-signing@main
inputs:
job_name: "sign-installer"
input_path: "installer/output"
file_patterns: "*.msi"
stage: sign-installer
build:
stage: build
tags:
- build-windows-10-64
script:
- dotnet build -c Release
artifacts:
paths:
- MyApp/bin/Release/
build-installer:
stage: installer
tags:
- build-windows-10-64
needs:
- job: sign-binaries
artifacts: true
script:
- # Installer aus signierten Binaries bauen
artifacts:
paths:
- installer/output/Nur bestimmte Dateitypen signieren
include:
- component: git.styrion.net/iteas/gitlab-components/code-signing@main
inputs:
input_path: "build/output"
file_patterns: "*.exe" # Nur EXE-DateienKombination mit Vault Secrets
Die Azure-Credentials können statt als CI/CD-Variablen auch über die Vault Secrets-Komponente geladen werden:
stages:
- build
- sign
include:
- component: git.styrion.net/iteas/gitlab-components/vault-secrets@main
inputs:
secrets: |
AZURE_TENANT_ID=secret/gitlab/azure/signing@tenant_id
AZURE_CLIENT_ID=secret/gitlab/azure/signing@client_id
AZURE_CLIENT_SECRET=secret/gitlab/azure/signing@client_secret
SIGNING_ENDPOINT=secret/gitlab/azure/signing@endpoint
SIGNING_ACCOUNT_NAME=secret/gitlab/azure/signing@account_name
- component: git.styrion.net/iteas/gitlab-components/code-signing@main
inputs:
input_path: "build/output"
cert_profile_name: "Production-Signing"Fehlerbehebung
signtool.exe not found
Windows 10 SDK (Version 10.0.22621 oder neuer) muss auf dem Runner installiert sein. Die Komponente sucht automatisch unter C:\Program Files (x86)\Windows Kits\10\bin\.
nuget.exe not found
NuGet CLI muss auf dem Runner verfügbar sein – entweder im PATH, im Projekt-Root oder als Teil einer Visual Studio Installation.
Azure credentials not configured
Die Variablen AZURE_TENANT_ID, AZURE_CLIENT_ID und AZURE_CLIENT_SECRET müssen als CI/CD-Variablen oder über Vault Secrets gesetzt sein.
Signatur-Verifikation schlägt fehl
Bei Test-Zertifikaten (ITeas-Test-Signing) ist es normal, dass die Verifikation eine Warnung ausgibt, da die Root-CA nicht im Trusted Store ist. Die Signatur selbst ist dennoch gültig. Für Produktions-Zertifikate sollte die Verifikation erfolgreich sein.
