Skip to content

continuous-delphi/delphi-codesign-azure

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

delphi-codesign-azure

delphi-codesign-azure logo

Delphi CI GitHub Release License: MIT Ask DeepWiki Continuous Delphi

A PowerShell utility for Authenticode code signing and verification using Azure Artifact Signing and signtool.exe.


Quick Start

# Sign an executable
pwsh -File source/delphi-codesign-azure.ps1 -Sign -Files app.exe -EnvFile .env -Format text

# Sign multiple files
pwsh -File source/delphi-codesign-azure.ps1 -Sign -Files app.exe,lib.bpl -EnvFile .env -Format text

# Verify a signed executable
pwsh -File source/delphi-codesign-azure.ps1 -Verify -FilePath app.exe -Format text

# Version info
pwsh -File source/delphi-codesign-azure.ps1 -Version -Format text

Commands

-Sign

Signs one or more files using Azure Trusted Signing via signtool.exe sign with SHA256 digest and RFC 3161 timestamping.

Parameter Type Required Description
-Sign switch yes Select the sign command
-Files string[] yes One or more file paths to sign
-SignToolPath string no Explicit path to signtool.exe. Auto-discovered from the Windows SDK if omitted
-DlibPath string no Path to Azure.CodeSigning.Dlib.dll. Defaults to %LOCALAPPDATA%\Microsoft\MicrosoftTrustedSigningClientTools\
-MetadataPath string no Path to metadata.json. Defaults to the source/ directory
-EnvFile string no .env file with Azure credentials (see Prerequisites)
-Format string no Output format: object (default), text, json

Prerequisites:

  • signtool.exe from the Windows SDK
  • Azure.CodeSigning.Dlib.dll -- install via winget install -e --id Microsoft.Azure.TrustedSigningClientTools
  • metadata.json with Azure Trusted Signing endpoint, account name, and certificate profile
  • Azure credentials: AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET (via environment or - EnvFile)

See docs/machine_setup.md for first-time setup instructions.

Exit codes:

Code Meaning
0 All files signed successfully
2 Partial failure (some files failed)
3 Fatal error (prerequisites missing, no files signed)

Examples:

# Sign a single file
pwsh -File source/delphi-codesign-azure.ps1 -Sign -Files app.exe -EnvFile .env -Format text

# Sign multiple files
pwsh -File source/delphi-codesign-azure.ps1 -Sign -Files app.exe,lib.bpl -EnvFile .env -Format text

# JSON output for CI
pwsh -File source/delphi-codesign-azure.ps1 -Sign -Files app.exe -EnvFile .env -Format json

# Pipeline use
$result = & source/delphi-codesign-azure.ps1 -Sign -Files app.exe -EnvFile .env
$result.ok              # $true if all signed
$result.result.signed   # count of signed files
$result.result.failed   # count of failed files

-Verify

Verifies the Authenticode signature on a file using signtool.exe verify /pa /v.

Parameter Type Required Description
-Verify switch yes Select the verify command
-FilePath string yes Path to the file to verify
-SignToolPath string no Explicit path to signtool.exe. Auto-discovered from the Windows SDK if omitted
-Format string no Output format: object (default), text, json

Exit codes:

Code Meaning
0 Signature is valid
1 Signature is invalid or file is not signed
3 Fatal error (file not found, signtool not found)

Examples:

# Verify a signed executable (text output)
pwsh -File source/delphi-codesign-azure.ps1 -Verify -FilePath app.exe -Format text

# JSON output for CI consumption
pwsh -File source/delphi-codesign-azure.ps1 -Verify -FilePath app.exe -Format json

# Pipeline use (object output, default)
$result = & source/delphi-codesign-azure.ps1 -Verify -FilePath app.exe
$result.ok            # $true if signed
$result.result.signed # $true if signed

# Explicit signtool path
pwsh -File source/delphi-codesign-azure.ps1 -Verify -FilePath app.exe -SignToolPath "C:\path\to\signtool.exe"

signtool.exe discovery:

When -SignToolPath is not specified, the tool searches C:\Program Files (x86)\Windows Kits\10\bin for the latest x64 version of signtool.exe. Install the Windows SDK if it is not found: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/

-Version

Displays tool name and version.

Parameter Type Required Description
-Version switch yes Select the version command
-Format string no Output format: object (default), text, json

Examples:

# Text format
pwsh -File source/delphi-codesign-azure.ps1 -Version -Format text
# => delphi-codesign-azure 0.1.0

# JSON format
pwsh -File source/delphi-codesign-azure.ps1 -Version -Format json
# => {"ok":true,"command":"version","tool":{"name":"delphi-codesign-azure","version":"0.1.0"}}

metadata.json

The -Sign command requires a metadata.json file that tells Azure Trusted Signing which endpoint, account, and certificate profile to use.

{
  "Endpoint": "https://eus.codesigning.azure.net/",
  "CodeSigningAccountName": "yourAccountName",
  "CertificateProfileName": "yourCertificateProfileName"
}

See docs/metadata.json for an example.

Fields

Field Description
Endpoint Azure Trusted Signing regional endpoint URL. Use eus (East US), wus (West US), neu (North Europe), or weu (West Europe)
CodeSigningAccountName Name of the Trusted Signing account in the Azure portal
CertificateProfileName Name of the certificate profile under the signing account

Location

By default the tool looks for metadata.json in the same directory as the script (source/). Override with -MetadataPath:

pwsh -File source/delphi-codesign-azure.ps1 -Sign -Files app.exe -MetadataPath path/to/metadata.json

Obtaining the values

  1. Endpoint: Azure portal > Trusted Signing account > Overview > Account URI
  2. CodeSigningAccountName: Azure portal > Trusted Signing account > Overview > Name
  3. CertificateProfileName: Azure portal > Trusted Signing account > Certificate profiles > Profile name

Azure Credentials

The -Sign command requires three Azure environment variables for authentication with Azure Trusted Signing:

Variable Description
AZURE_TENANT_ID Entra ID tenant ID
AZURE_CLIENT_ID Application (client) ID of the app registration
AZURE_CLIENT_SECRET Client secret value (not the secret ID)

Setting credentials in the shell

PowerShell:

$env:AZURE_TENANT_ID = 'your-tenant-id'
$env:AZURE_CLIENT_ID = 'your-client-id'
$env:AZURE_CLIENT_SECRET = 'your-client-secret'

Batch:

set AZURE_TENANT_ID=your-tenant-id
set AZURE_CLIENT_ID=your-client-id
set AZURE_CLIENT_SECRET=your-client-secret

Using a .env file

For local development, credentials can be stored in a .env file and loaded via the -EnvFile parameter:

pwsh -File source/delphi-codesign-azure.ps1 -Sign -Files app.exe -EnvFile .env -Format text

See docs/.env.example for the file format.

Format rules:

  • One KEY=VALUE pair per line
  • Lines starting with # are comments
  • Blank lines are ignored
  • Existing environment variables are not overwritten -- the .env file only fills in values that are not already set

Security: The .env file contains secrets and should not be committed. Add it to .gitignore.

Obtaining credentials from Azure

  1. AZURE_TENANT_ID: Azure portal > Entra ID > Overview > Tenant ID
  2. AZURE_CLIENT_ID: Azure portal > Entra ID > App registrations > your app > Application (client) ID
  3. AZURE_CLIENT_SECRET: Azure portal > Entra ID > App registrations > your app > Certificates & secrets

New client secret > copy the Value (not the Secret ID)

If the client secret has expired, create a new one in the portal.


Output Formats

The -Format parameter controls output across all commands:

Format Description
object Default. Returns a PSCustomObject for pipeline use
text Human-readable text to the console
json Single-line compressed JSON for CI/scripting

JSON Envelope

Success:

{
  "ok": true,
  "command": "verify",
  "tool": { "name": "delphi-codesign-azure", "version": "0.1.0" },
  "result": {
    "filePath": "C:/path/to/file.exe",
    "signed": true,
    "signtoolExitCode": 0,
    "signtoolOutput": ["..."]
  }
}

Error:

{
  "ok": false,
  "command": "verify",
  "tool": { "name": "delphi-codesign-azure", "version": "0.1.0" },
  "error": { "code": 3, "message": "File not found: missing.exe" }
}

Running Tests

Requires PowerShell 7+, Pester 5.7+, and PSScriptAnalyzer.

./tests/run-tests.ps1

Continuous-Delphi

This tool is part of the Continuous-Delphi ecosystem, focused on strengthening Delphi's continued success.

continuous-delphi logo