Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 140 additions & 1 deletion .github/workflows/_release-rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,82 @@ on:
required: false
type: string
default: ""
# --- Code signing (opt-in; default off → no change for existing callers) ---
enable_signing:
description: "Enable OS code signing of built binaries"
required: false
type: boolean
default: false
notarize_macos:
description: "Submit macOS binaries for Apple notarization"
required: false
type: boolean
default: true
# NOTE: the CODESIGN_*/PGP_SIGN_* config values are declared under `secrets:`
# below (not here). Callers in public repos store them as secrets, and the
# `secrets` context cannot be referenced from a reusable-workflow `with:` —
# so they must be passed through the `secrets:` block.
jsign_sha256:
description: "Pinned sha256 of the jsign jar"
required: false
type: string
default: ""
rcodesign_sha256:
description: "Pinned sha256 of the rcodesign tarball"
required: false
type: string
default: ""
secrets:
app_id:
description: "GitHub App ID"
required: false
app_pem:
description: "GitHub App PEM"
required: false
# Code-signing secrets. NOTE: no Apple secrets — macOS creds live in GCP
# Secret Manager (fetched via the CODESIGN_* identity).
pgp_cert_base64:
description: "Base64 OpenPGP public cert (Linux)"
required: false
pgp_signer_token:
description: "Token (GitHub App or PAT) with read on private kunobi-ninja/kunobi-pgp-kms"
required: false
windows_cert_chain:
description: "PKCS7 EV certificate chain (Windows Authenticode)"
required: false
# CODESIGN_*/PGP_SIGN_* config — passed as secrets (callers in public repos
# keep these out of Variables; secrets can't ride in a reusable-workflow `with:`).
codesign_wif_provider:
description: "WIF provider for code signing (Windows Authenticode + Apple Secret Manager)"
required: false
codesign_gcp_project:
description: "GCP project for code signing + Apple Secret Manager"
required: false
codesign_service_account:
description: "Service account to impersonate; empty = direct WIF"
required: false
codesign_kms_keyring:
description: "Authenticode KMS keyring"
required: false
codesign_kms_key_alias:
description: "Authenticode KMS key alias"
required: false
pgp_sign_wif_provider:
description: "WIF provider for OpenPGP KMS (Linux)"
required: false
pgp_sign_gcp_project_id:
description: "GCP project for OpenPGP KMS"
required: false
pgp_sign_service_account:
description: "Service account for OpenPGP KMS"
required: false
pgp_sign_kms_key_version:
description: "OpenPGP KMS key version path"
required: false

permissions:
contents: write
id-token: write

jobs:
# --- Job 1: Compute build matrix from target list ---
Expand Down Expand Up @@ -316,6 +382,56 @@ jobs:
strip "$BIN"
fi

# --- Code signing: all platforms sign the BINARY before packaging.
# macOS/Windows embed the signature in the binary; Linux produces a
# detached .asc that gets bundled into the archive next to the binary. ---
- name: Sign macOS binary
if: inputs.enable_signing && contains(matrix.target, 'apple-darwin')
uses: zondax/actions/sign-macos-binary@v1
with:
binary-path: target/${{ matrix.target }}/release/${{ inputs.binary_name }}
workload-identity-provider: ${{ secrets.codesign_wif_provider }}
gcp-project: ${{ secrets.codesign_gcp_project }}
service-account: ${{ secrets.codesign_service_account }}
notarize: ${{ inputs.notarize_macos }}
rcodesign-sha256: ${{ inputs.rcodesign_sha256 }}

- name: Authenticate with GCP (Authenticode)
id: auth-codesign
if: inputs.enable_signing && contains(matrix.target, 'windows')
uses: zondax/actions/gcp-wif-auth@v1
with:
workload_identity_provider: ${{ secrets.codesign_wif_provider }}
project_id: ${{ secrets.codesign_gcp_project }}
service_account: ${{ secrets.codesign_service_account }}
token_format: access_token
create_credentials_file: 'false'
setup_gcloud: 'false'
verify_authentication: 'false'

- name: Sign Windows binary
if: inputs.enable_signing && contains(matrix.target, 'windows')
uses: zondax/actions/sign-windows-binary@v1
with:
binary-path: target/${{ matrix.target }}/release/${{ inputs.binary_name }}.exe
gcp-access-token: ${{ steps.auth-codesign.outputs.access_token }}
kms-keyring: ${{ secrets.codesign_kms_keyring }}
kms-key-alias: ${{ secrets.codesign_kms_key_alias }}
cert-chain: ${{ secrets.windows_cert_chain }}
jsign-sha256: ${{ inputs.jsign_sha256 }}

- name: Sign Linux binary
if: inputs.enable_signing && contains(matrix.target, 'linux')
uses: zondax/actions/sign-linux-binary@v1
with:
target-path: target/${{ matrix.target }}/release/${{ inputs.binary_name }}
workload-identity-provider: ${{ secrets.pgp_sign_wif_provider }}
gcp-project-id: ${{ secrets.pgp_sign_gcp_project_id }}
service-account: ${{ secrets.pgp_sign_service_account }}
signer-token: ${{ secrets.pgp_signer_token }}
kms-key: ${{ secrets.pgp_sign_kms_key_version }}
cert-base64: ${{ secrets.pgp_cert_base64 }}

- name: Package
env:
TARGET: ${{ matrix.target }}
Expand All @@ -335,9 +451,31 @@ jobs:
(cd "target/$TARGET/release" && zip "$OLDPWD/$ARCHIVE" "${BINARY_NAME}${BINARY_EXT}")
fi
else
tar czf "$ARCHIVE" -C "target/$TARGET/release" "${BINARY_NAME}${BINARY_EXT}"
# Bundle the detached .asc (Linux binary signing) into the tarball
# next to the binary, so the signature travels with what it signs.
ASC="${BINARY_NAME}${BINARY_EXT}.asc"
if [ -f "target/$TARGET/release/$ASC" ]; then
tar czf "$ARCHIVE" -C "target/$TARGET/release" "${BINARY_NAME}${BINARY_EXT}" "$ASC"
else
tar czf "$ARCHIVE" -C "target/$TARGET/release" "${BINARY_NAME}${BINARY_EXT}"
fi
fi

# Linux ALSO signs the packaged archive (detached .asc, top-level release
# asset) — in addition to the binary's .asc bundled inside it. Two PGP sigs:
# one over the ELF (inside the tarball), one over the .tar.gz (download).
- name: Sign Linux archive
if: inputs.enable_signing && contains(matrix.target, 'linux')
uses: zondax/actions/sign-linux-binary@v1
with:
target-path: ${{ inputs.binary_name }}-${{ matrix.target }}.${{ matrix.archive_ext }}
workload-identity-provider: ${{ secrets.pgp_sign_wif_provider }}
gcp-project-id: ${{ secrets.pgp_sign_gcp_project_id }}
service-account: ${{ secrets.pgp_sign_service_account }}
signer-token: ${{ secrets.pgp_signer_token }}
kms-key: ${{ secrets.pgp_sign_kms_key_version }}
cert-base64: ${{ secrets.pgp_cert_base64 }}

- name: Checksum
env:
TARGET: ${{ matrix.target }}
Expand All @@ -364,6 +502,7 @@ jobs:
path: |
${{ inputs.binary_name }}-${{ matrix.target }}.${{ matrix.archive_ext }}
${{ inputs.binary_name }}-${{ matrix.target }}.${{ matrix.archive_ext }}.sha256
${{ inputs.binary_name }}-${{ matrix.target }}.${{ matrix.archive_ext }}.asc

# --- Job 3: Create/upload GitHub Release ---
release:
Expand Down