From da4a4bbe6dcd54543c534ba10897e86e166aef09 Mon Sep 17 00:00:00 2001 From: John Allers Date: Tue, 23 Jun 2026 15:45:04 +0000 Subject: [PATCH] Add opt-in Windows Authenticode signing via Azure Trusted Signing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Windows .exe and .msi artifacts are currently only Sigstore-signed, which does not satisfy Windows SmartScreen — so downloaded connector executables (e.g. baton-active-directory) trigger SmartScreen warnings (CE-424). Add Authenticode signing to the goreleaser-windows job using Azure Trusted Signing (CE-178), gated behind a new windows_authenticode_signing input (default false) so existing releases are unaffected until the Azure account is provisioned. When enabled, the job: - logs in to Azure via GitHub Actions OIDC (no certificate material in secrets) - installs the Microsoft `sign` CLI - signs the raw .exe in a GoReleaser build post-hook, before it is packaged, so the binary in both the .zip and the .msi is signed - signs the .msi in place via a GoReleaser signs entry ordered ahead of the cosign signature, so the Sigstore bundle and all downstream hashes cover the Authenticode-signed bytes Signing logic lives in scripts/sign-windows-authenticode.ps1, which calls `sign code trusted-signing` and verifies the result. New optional inputs (trusted_signing_*) and secrets (AZURE_CLIENT_ID/TENANT_ID/SUBSCRIPTION_ID) are validated up front. README and release-workflow docs updated. Co-authored-by: c1-squire-dev[bot] --- .github/workflows/release.yaml | 120 ++++++++++++++++++ README.md | 36 ++++++ cmd/generate-windows-manifest/main.go | 5 +- docs/release-workflow.md | 82 ++++++++++-- scripts/sign-windows-authenticode.ps1 | 117 +++++++++++++++++ .../.goreleaser-windows-template.yaml.tmpl | 4 +- 6 files changed, 347 insertions(+), 17 deletions(-) create mode 100644 scripts/sign-windows-authenticode.ps1 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 074e268..91326d4 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -52,6 +52,26 @@ on: type: string default: "" description: "Path to a custom WXS file in the caller repo for MSI generation (relative to repo root). If not provided, uses default template." + windows_authenticode_signing: + required: false + type: boolean + default: false + description: "Whether to Authenticode-sign Windows .exe and .msi artifacts with Azure Trusted Signing. When true, the AZURE_CLIENT_ID/AZURE_TENANT_ID/AZURE_SUBSCRIPTION_ID secrets and the trusted_signing_* inputs are required." + trusted_signing_endpoint: + required: false + type: string + default: "" + description: "Azure Trusted Signing region endpoint (e.g. https://wus2.codesigning.azure.net/). Required when windows_authenticode_signing is true." + trusted_signing_account_name: + required: false + type: string + default: "" + description: "Azure Trusted Signing account name. Required when windows_authenticode_signing is true." + trusted_signing_certificate_profile: + required: false + type: string + default: "" + description: "Azure Trusted Signing certificate profile name. Required when windows_authenticode_signing is true." secrets: RELENG_GITHUB_TOKEN: required: true @@ -68,6 +88,15 @@ on: GORELEASER_PRO_KEY: required: false description: "GoReleaser Pro license key for MSI builds. Required when msi is true." + AZURE_CLIENT_ID: + required: false + description: "Client ID of the Azure AD app used for Trusted Signing OIDC login. Required when windows_authenticode_signing is true." + AZURE_TENANT_ID: + required: false + description: "Azure AD tenant ID for Trusted Signing OIDC login. Required when windows_authenticode_signing is true." + AZURE_SUBSCRIPTION_ID: + required: false + description: "Azure subscription ID hosting the Trusted Signing account. Required when windows_authenticode_signing is true." env: CDN_BASE_URL: "https://dist.conductorone.com" @@ -164,6 +193,53 @@ jobs: exit 1 fi + - name: Validate Authenticode signing configuration + if: inputs.windows_authenticode_signing == true + env: + HAS_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID != '' }} + HAS_TENANT_ID: ${{ secrets.AZURE_TENANT_ID != '' }} + HAS_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID != '' }} + TS_ENDPOINT: ${{ inputs.trusted_signing_endpoint }} + TS_ACCOUNT: ${{ inputs.trusted_signing_account_name }} + TS_PROFILE: ${{ inputs.trusted_signing_certificate_profile }} + MSI_ENABLED: ${{ inputs.msi }} + run: | + if [ "$MSI_ENABLED" != "true" ]; then + echo "::error::windows_authenticode_signing requires msi to be true (the Windows build job is gated on msi)" + exit 1 + fi + + missing=0 + require_secret() { + if [ "$2" != "true" ]; then + echo "::error::$1 secret is required when windows_authenticode_signing is true" + missing=1 + fi + } + require_input() { + if [ -z "$2" ]; then + echo "::error::$1 input is required when windows_authenticode_signing is true" + missing=1 + fi + } + + require_secret "AZURE_CLIENT_ID" "$HAS_CLIENT_ID" + require_secret "AZURE_TENANT_ID" "$HAS_TENANT_ID" + require_secret "AZURE_SUBSCRIPTION_ID" "$HAS_SUBSCRIPTION_ID" + require_input "trusted_signing_endpoint" "$TS_ENDPOINT" + require_input "trusted_signing_account_name" "$TS_ACCOUNT" + require_input "trusted_signing_certificate_profile" "$TS_PROFILE" + + if [ -n "$TS_ENDPOINT" ] && [[ ! "$TS_ENDPOINT" =~ ^https://[A-Za-z0-9.-]+/?$ ]]; then + echo "::error::trusted_signing_endpoint must be an https URL (e.g. https://wus2.codesigning.azure.net/). Got: $TS_ENDPOINT" + missing=1 + fi + + if [ "$missing" -ne 0 ]; then + exit 1 + fi + echo "✅ Authenticode signing configuration valid" + determine-workflows-ref: needs: validate-inputs runs-on: ubuntu-latest @@ -589,15 +665,54 @@ jobs: WXS_PATH: ${{ steps.wxs.outputs.wxs_path }} WORKFLOWS_REF: ${{ needs.determine-workflows-ref.outputs.ref }} RELEASE_TAG: ${{ inputs.tag }} + AUTHENTICODE: ${{ inputs.windows_authenticode_signing }} run: | export BUILD_STARTED_ON=$(date -u +"%Y-%m-%dT%H:%M:%SZ") + # Authenticode signing is opt-in. When enabled, inject two blocks into + # the GoReleaser config (same envsubst block pattern used for Docker + # extra_files), so the template stays valid YAML when signing is off: + # - WINDOWS_BUILD_SIGN_HOOK: a build post-hook that signs the raw + # .exe BEFORE it is packaged into the zip and the MSI. + # - WINDOWS_AUTHENTICODE_MSI_SIGN: a `signs` entry that signs the + # .msi in place, ordered ahead of the cosign signature so the + # Sigstore bundle covers the Authenticode-signed bytes. + export WINDOWS_BUILD_SIGN_HOOK="" + export WINDOWS_AUTHENTICODE_MSI_SIGN="" + if [ "${AUTHENTICODE}" = "true" ]; then + echo "Authenticode signing enabled: injecting signing config" + SIGN_SCRIPT="../_workflows/scripts/sign-windows-authenticode.ps1" + + WINDOWS_BUILD_SIGN_HOOK=$(printf '\n hooks:\n post:\n - cmd: pwsh -NoProfile -File %s -Path "{{ .Path }}"\n output: true' "$SIGN_SCRIPT") + + WINDOWS_AUTHENTICODE_MSI_SIGN=$(printf '\n - id: authenticode-msi\n cmd: pwsh\n artifacts: installer\n ids:\n - windows-msi\n signature: "{{ .Env.artifact }}.authenticode.json"\n output: true\n args:\n - "-NoProfile"\n - "-File"\n - "%s"\n - "-Path"\n - "{{ .Env.artifact }}"\n - "-EmitMarker"' "$SIGN_SCRIPT") + fi + # Generate GoReleaser config envsubst < templates/.goreleaser-windows-template.yaml.tmpl | tee "_generated/.goreleaser.windows.yaml" # Generate provenance predicate envsubst < templates/.slsa-provenance-predicate-template.json.tmpl | tee "_generated/predicate.json" + - name: Azure login for Trusted Signing (OIDC) + if: inputs.windows_authenticode_signing == true + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Install Microsoft sign tool + if: inputs.windows_authenticode_signing == true + shell: pwsh + run: | + # The `sign` tool currently ships pre-release only. Pin a specific + # version here once validated against the provisioned Trusted Signing + # account for reproducible, supply-chain-stable signing. + dotnet tool install --global sign --prerelease + # Surface the global tools directory for subsequent steps / hooks. + "$env:USERPROFILE\.dotnet\tools" | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8 + - name: Run GoReleaser for Windows uses: goreleaser/goreleaser-action@v6 with: @@ -608,6 +723,11 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.RELENG_GITHUB_TOKEN }} GORELEASER_KEY: ${{ secrets.GORELEASER_PRO_KEY }} + # Consumed by scripts/sign-windows-authenticode.ps1 (invoked from the + # build post-hook and the MSI signs entry). Empty when signing is off. + TRUSTED_SIGNING_ENDPOINT: ${{ inputs.trusted_signing_endpoint }} + TRUSTED_SIGNING_ACCOUNT_NAME: ${{ inputs.trusted_signing_account_name }} + TRUSTED_SIGNING_CERTIFICATE_PROFILE: ${{ inputs.trusted_signing_certificate_profile }} - name: Flatten MSI directory structure shell: pwsh diff --git a/README.md b/README.md index 34d831d..2cb5d78 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,10 @@ The release workflow accepts the following input parameters: | `docker_extra_files` | No | `""` | Comma-separated list of extra files/dirs to include in Docker build context | | `msi` | No | `true` | Whether to build MSI Windows installers | | `msi_wxs_path` | No | `""` | Path to custom WXS template for MSI installer (uses default if not set) | +| `windows_authenticode_signing` | No | `false` | Authenticode-sign Windows `.exe` and `.msi` via Azure Trusted Signing (requires the `trusted_signing_*` inputs and `AZURE_*` secrets) | +| `trusted_signing_endpoint` | No | `""` | Azure Trusted Signing region endpoint (e.g. `https://wus2.codesigning.azure.net/`); required when `windows_authenticode_signing: true` | +| `trusted_signing_account_name` | No | `""` | Azure Trusted Signing account name; required when `windows_authenticode_signing: true` | +| `trusted_signing_certificate_profile` | No | `""` | Azure Trusted Signing certificate profile name; required when `windows_authenticode_signing: true` | 2. Ensure your repository has the following secrets configured: @@ -92,6 +96,7 @@ The release workflow accepts the following input parameters: - `AC_PROVIDER`: Apple Connect provider - `DATADOG_API_KEY`: Datadog API key for monitoring releases - `GORELEASER_PRO_KEY`: GoReleaser Pro license key (required when `msi: true`, the default) + - `AZURE_CLIENT_ID` / `AZURE_TENANT_ID` / `AZURE_SUBSCRIPTION_ID`: Azure OIDC identity for Trusted Signing (required only when `windows_authenticode_signing: true`) 3. Remove all GoReleaser, gon files, Dockerfile, and Dockerfile.lambda files from your connector repository, if they were previously created there. @@ -175,6 +180,37 @@ To disable MSI builds entirely (e.g., for connectors that don't need Windows ins When `msi: false`, the `GORELEASER_PRO_KEY` secret is not required. +### Windows Authenticode Signing + +Sigstore (cosign) signatures prove provenance but do not satisfy Windows +SmartScreen. To eliminate SmartScreen warnings on the `.exe` and `.msi`, enable +Authenticode signing via [Azure Trusted Signing](https://learn.microsoft.com/azure/trusted-signing/): + +```yaml +jobs: + release: + uses: ConductorOne/github-workflows/.github/workflows/release.yaml@v4 + with: + tag: ${{ github.ref_name }} + windows_authenticode_signing: true + trusted_signing_endpoint: https://wus2.codesigning.azure.net/ + trusted_signing_account_name: conductorone-signing + trusted_signing_certificate_profile: conductorone + secrets: + # ... existing secrets ... + AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} + AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} + AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} +``` + +This is **opt-in** (default `false`) so connectors keep releasing unchanged +until the Azure Trusted Signing account is provisioned. Authentication uses +GitHub Actions OIDC — no signing certificate is stored in repository secrets. +The `.exe` is signed before it is packaged, so both the standalone binary (in +the `.zip`) and the copy inside the `.msi` carry the signature. See the +[release workflow docs](docs/release-workflow.md#windows-authenticode-signing-azure-trusted-signing) +for Azure setup and verification details. + ## Verify Workflow Runs linting, tests, and optional regression verification. See [detailed documentation](docs/verify-workflow.md) for jobs, regression testing, and all options. diff --git a/cmd/generate-windows-manifest/main.go b/cmd/generate-windows-manifest/main.go index d17457c..6bdcdbd 100644 --- a/cmd/generate-windows-manifest/main.go +++ b/cmd/generate-windows-manifest/main.go @@ -93,7 +93,10 @@ func main() { } // MSI uses key "windows-amd64-msi" - // MSI has cosign signatures and attestations; Azure Trusted Signing (Windows code signing) planned for Stage 2 + // MSI always has cosign signatures and attestations; Windows Authenticode + // signing (Azure Trusted Signing) is applied in-place earlier in the + // pipeline when windows_authenticode_signing is enabled, so the hash here + // covers the Authenticode-signed bytes. assets["windows-amd64-msi"] = asset fmt.Fprintf(os.Stderr, "✅ Added MSI asset: windows-amd64-msi -> %s\n", filename) } diff --git a/docs/release-workflow.md b/docs/release-workflow.md index 52685fe..24c93ac 100644 --- a/docs/release-workflow.md +++ b/docs/release-workflow.md @@ -56,6 +56,8 @@ Builds Windows zip and MSI installer: - MSI built using WiX Toolset with GoReleaser Pro - Deterministic UpgradeCode via UUID v5 from repository name - Supports custom WXS templates via `msi_wxs_path` input +- Optionally Authenticode-signs the `.exe` and `.msi` with Azure Trusted Signing + (opt-in via `windows_authenticode_signing`; see Security Properties) - Generates SBOMs and SLSA v1 provenance attestations - Uploads all artifacts to S3 with no-overwrite writes @@ -167,7 +169,55 @@ Both Windows zip and MSI have: - SLSA provenance attestations - SBOM attestations -**Note:** Windows code signing via Azure Trusted Signing is planned for Stage 2. +### Windows Authenticode Signing (Azure Trusted Signing) + +Sigstore signatures prove supply-chain provenance but are not recognized by +Windows SmartScreen. To remove SmartScreen warnings, the workflow can also +Authenticode-sign Windows artifacts with **Azure Trusted Signing**. This is +**opt-in** via the `windows_authenticode_signing` input (default `false`), so +releases continue to work unchanged until the Azure account is provisioned. + +When enabled, the `goreleaser-windows` job: + +1. Logs in to Azure via GitHub Actions OIDC (`azure/login`) — no long-lived + certificate material is stored in secrets. +2. Installs the Microsoft [`sign`](https://github.com/dotnet/sign) CLI. +3. Signs the raw `.exe` in a GoReleaser **build post-hook**, before it is + packaged — so the binary inside both the `.zip` and the `.msi` is signed. +4. Signs the `.msi` in place via a GoReleaser `signs` entry that is ordered + **ahead of** the cosign signature, so the Sigstore `.sig`/`.cert` and all + downstream hashes/attestations cover the Authenticode-signed bytes. + +All signing is delegated to `scripts/sign-windows-authenticode.ps1`, which calls +`sign code trusted-signing` and then verifies the result with +`Get-AuthenticodeSignature`. + +Because Azure Trusted Signing issues short-lived certificates chained to a +Microsoft-managed root, SmartScreen reputation is immediate — unlike standard OV +certificates, which must accrue reputation through download volume. + +**Required configuration when `windows_authenticode_signing: true`:** + +| Kind | Name | Description | +|-|-|-| +| input | `trusted_signing_endpoint` | Region endpoint, e.g. `https://wus2.codesigning.azure.net/` | +| input | `trusted_signing_account_name` | Trusted Signing account name | +| input | `trusted_signing_certificate_profile` | Certificate profile name | +| secret | `AZURE_CLIENT_ID` | App registration (federated credential) client ID | +| secret | `AZURE_TENANT_ID` | Azure AD tenant ID | +| secret | `AZURE_SUBSCRIPTION_ID` | Subscription hosting the Trusted Signing account | + +The federated credential on the Azure AD app must trust the connector +repository's GitHub OIDC subject, and the identity must hold the **Trusted +Signing Certificate Profile Signer** role on the account. + +**Verification** (on a Windows machine): + +```powershell +Get-AuthenticodeSignature .\baton-foo_v1.0.0_windows_amd64.msi | Format-List +# Status should be 'Valid'; SignerCertificate should chain to the Microsoft root. +signtool verify /pa /v .\baton-foo_v1.0.0_windows_amd64.msi +``` ### Verification @@ -335,19 +385,23 @@ Test the MSI installer on an actual Windows machine: ## Future Work -### Stage 2: Windows Code Signing - -Currently MSI installers have Sigstore signatures (cosign) but not Windows Authenticode signatures. Stage 2 will add: - -- **Azure Trusted Signing** integration for Authenticode signatures -- MSI files will be signed with Microsoft-trusted certificate -- Windows SmartScreen warnings will be eliminated -- Users can verify publisher identity in Windows UAC prompts - -This requires: -- Azure Trusted Signing account setup -- GitHub Actions OIDC integration with Azure -- Workflow updates to sign MSI after build +### Windows Code Signing (implemented, opt-in) + +Windows Authenticode signing via **Azure Trusted Signing** is implemented and +gated behind the `windows_authenticode_signing` input (see +[Windows Authenticode Signing](#windows-authenticode-signing-azure-trusted-signing)). +It remains off by default pending Azure Trusted Signing account provisioning +(tracked in CE-178). To roll it out: + +1. Provision an Azure Trusted Signing account and certificate profile. +2. Create an Azure AD app with a federated credential trusting the connector + repos' GitHub OIDC subjects, and grant it the **Trusted Signing Certificate + Profile Signer** role. +3. Add the `AZURE_CLIENT_ID` / `AZURE_TENANT_ID` / `AZURE_SUBSCRIPTION_ID` + secrets and set `windows_authenticode_signing: true` plus the + `trusted_signing_*` inputs in each connector's release workflow. +4. Validate on a test connector per [Testing Changes](#testing-changes) and + confirm `Get-AuthenticodeSignature` reports `Valid`. ### Other Potential Improvements diff --git a/scripts/sign-windows-authenticode.ps1 b/scripts/sign-windows-authenticode.ps1 new file mode 100644 index 0000000..25e6558 --- /dev/null +++ b/scripts/sign-windows-authenticode.ps1 @@ -0,0 +1,117 @@ +<# +.SYNOPSIS + Authenticode-sign a Windows artifact (.exe or .msi) with Azure Trusted Signing. + +.DESCRIPTION + Thin, idempotent wrapper around the Microsoft `sign` dotnet CLI tool + (https://github.com/dotnet/sign) configured for Azure Trusted Signing. + + Authentication is handled by Azure.Identity's credential chain, which the + preceding `azure/login` step populates via GitHub Actions OIDC (no long-lived + certificate material is stored anywhere in this repo or its secrets). + + This script is invoked from the GoReleaser Windows pipeline in two places: + 1. As a build post-hook, to sign the raw `.exe` BEFORE it is packaged into + the zip archive and the MSI installer (so every distributed copy of the + binary carries the signature). + 2. As a GoReleaser `signs` entry, to sign the `.msi` installer in place, + ordered BEFORE the cosign signature so the Sigstore bundle covers the + final, Authenticode-signed bytes. + +.PARAMETER Path + Path to the artifact to sign. Signing is performed in place. + +.PARAMETER EmitMarker + When set, writes a sidecar `.authenticode.json` describing the applied + signature. GoReleaser's `signs` stage expects each signer to produce a + distinct signature output file; the MSI signer points its `signature` at this + marker so GoReleaser does not collide the signature path with the in-place + signed installer. The marker is informational and is not uploaded to S3 + (the release uploader ignores unknown extensions). + +.NOTES + Required environment variables (set by the release workflow when + windows_authenticode_signing is enabled): + TRUSTED_SIGNING_ENDPOINT - e.g. https://wus2.codesigning.azure.net/ + TRUSTED_SIGNING_ACCOUNT_NAME - Trusted Signing account name + TRUSTED_SIGNING_CERTIFICATE_PROFILE - certificate profile name + + Optional: + TRUSTED_SIGNING_TIMESTAMP_URL - RFC 3161 timestamp authority + (default: http://timestamp.acs.microsoft.com) +#> +param( + [Parameter(Mandatory = $true)] + [string]$Path, + + [switch]$EmitMarker +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) { + throw "Artifact to sign not found: $Path" +} + +$Endpoint = $env:TRUSTED_SIGNING_ENDPOINT +$Account = $env:TRUSTED_SIGNING_ACCOUNT_NAME +# Note: avoid the name $Profile, which is a PowerShell automatic variable. +$CertProfile = $env:TRUSTED_SIGNING_CERTIFICATE_PROFILE +$TimestampUrl = if ($env:TRUSTED_SIGNING_TIMESTAMP_URL) { + $env:TRUSTED_SIGNING_TIMESTAMP_URL +} else { + "http://timestamp.acs.microsoft.com" +} + +foreach ($pair in @( + @{ Name = "TRUSTED_SIGNING_ENDPOINT"; Value = $Endpoint }, + @{ Name = "TRUSTED_SIGNING_ACCOUNT_NAME"; Value = $Account }, + @{ Name = "TRUSTED_SIGNING_CERTIFICATE_PROFILE"; Value = $CertProfile } + )) { + if ([string]::IsNullOrWhiteSpace($pair.Value)) { + throw "Required environment variable $($pair.Name) is not set" + } +} + +$FullPath = (Resolve-Path -LiteralPath $Path).Path +Write-Host "Authenticode-signing via Azure Trusted Signing: $FullPath" + +# `sign code trusted-signing` signs the file in place. The Azure Trusted Signing +# service applies the timestamp, so SmartScreen reputation is tied to the +# Microsoft-trusted certificate rather than to download volume. +& sign code trusted-signing ` + --trusted-signing-endpoint $Endpoint ` + --trusted-signing-account $Account ` + --trusted-signing-certificate-profile $CertProfile ` + --timestamp-url $TimestampUrl ` + --file-digest SHA256 ` + --timestamp-digest SHA256 ` + --verbosity information ` + $FullPath + +if ($LASTEXITCODE -ne 0) { + throw "sign code trusted-signing failed for ${FullPath} with exit code ${LASTEXITCODE}" +} + +# Fail loudly if the file did not end up validly signed. +$sig = Get-AuthenticodeSignature -LiteralPath $FullPath +if ($sig.Status -ne "Valid") { + throw "Authenticode signature is not valid for ${FullPath}: status=$($sig.Status) message=$($sig.StatusMessage)" +} + +Write-Host "Signed and verified: $FullPath (signer: $($sig.SignerCertificate.Subject))" + +if ($EmitMarker) { + $markerPath = "$FullPath.authenticode.json" + $marker = [ordered]@{ + artifact = (Split-Path -Leaf $FullPath) + status = [string]$sig.Status + signer = [string]$sig.SignerCertificate.Subject + thumbprint = [string]$sig.SignerCertificate.Thumbprint + timestamp = [string]$sig.TimeStamperCertificate.Subject + signedAtUtc = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") + } + $marker | ConvertTo-Json -Depth 4 | Out-File -LiteralPath $markerPath -Encoding utf8 + Write-Host "Wrote signature marker: $markerPath" +} diff --git a/templates/.goreleaser-windows-template.yaml.tmpl b/templates/.goreleaser-windows-template.yaml.tmpl index 5f3aad8..0c440c4 100644 --- a/templates/.goreleaser-windows-template.yaml.tmpl +++ b/templates/.goreleaser-windows-template.yaml.tmpl @@ -11,7 +11,7 @@ builds: goos: - windows goarch: - - amd64 + - amd64${WINDOWS_BUILD_SIGN_HOOK} archives: - id: windows-archive builds: @@ -40,7 +40,7 @@ sboms: artifacts: installer ids: - windows-msi -signs: +signs:${WINDOWS_AUTHENTICODE_MSI_SIGN} - id: cosign-archives output: true cmd: cosign