Skip to content

Latest commit

 

History

History
328 lines (237 loc) · 11.3 KB

File metadata and controls

328 lines (237 loc) · 11.3 KB

Release Workflow

The release.yaml workflow handles the complete release process for connector repositories, including building, signing, attestation, and publishing.

Overview

Release Workflow

When a tag is pushed to a connector repository, the shared release workflow:

  1. Builds binaries for macOS and Linux (with Apple codesigning)
  2. Builds Windows zip and MSI installer (with WiX Toolset)
  3. Builds multi-arch Docker images
  4. Signs all artifacts with Sigstore (keyless)
  5. Generates SLSA provenance attestations
  6. Publishes to S3 and ECR Public
  7. Records the release in the connector registry API

Jobs

validate-inputs

Validates workflow inputs before proceeding:

  • Ensures tag is valid semver starting with 'v' (e.g., v1.2.3)
  • Ensures dockerfile_template is only used when lambda: false
  • Ensures docker_extra_files is only used when dockerfile_template is set
  • Ensures msi_wxs_path has no path traversal (.. or absolute paths)
  • Ensures GORELEASER_PRO_KEY is provided when msi: true

determine-workflows-ref

Resolves the exact SHA of the shared workflow being used. This pinned reference is embedded in all provenance attestations, ensuring verifiability.

goreleaser-binaries (macOS)

Builds and signs binary archives for macOS and Linux:

  • Cross-compiles for darwin/linux (amd64/arm64)
  • Apple codesigning via gon (macOS only)
  • Generates SBOMs using Syft
  • Creates SLSA v1 provenance attestations
  • Signs SBOMs as attestation bundles
  • Uploads all artifacts to S3

Outputs: *.zip (macOS), *.tar.gz (Linux), *.provenance.sigstore.json, *.sbom.sigstore.json

goreleaser-windows (Windows)

Builds Windows zip and MSI installer:

  • Native Windows build on Windows runner (not cross-compiled)
  • Produces both .zip archive 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
  • Generates SBOMs and SLSA v1 provenance attestations
  • Uploads all artifacts to S3

Outputs: *.zip, *.msi, *.provenance.sigstore.json, *.sbom.sigstore.json

Custom WXS: For connectors requiring custom MSI behavior (Windows Service, registry keys, etc.), provide a custom WXS template via msi_wxs_path. If not provided, uses the default CLI installer template.

goreleaser-docker (Linux)

Builds and publishes container images:

  • Multi-arch Docker images (amd64/arm64)
  • Pushes to ECR Public (for Lambda deployment)
  • Attaches provenance attestations to images (OCI referrers)

Outputs: ECR Public images with attached attestations

publish-release-manifest

Finalizes distributable release artifacts:

  • Creates unified checksums file (all platforms)
  • Merges binary, Windows, and image manifests
  • Signs manifest.json and checksums with Sigstore
  • Uploads manifest and checksums to S3
  • Exposes the final manifest to the registry API recording job

record-registry-api

Records release metadata in the connector registry API:

  • Reuses the exact manifest uploaded to S3
  • Includes documentation and changelog data when present
  • Includes config_schema.json and baton_capabilities.json when present
  • Sends release timestamp, commit SHA, and workflow run metadata

verify-release

Post-release validation (non-blocking):

  • Validates all artifacts are accessible
  • Verifies all attestations with cosign
  • Triggers Datadog notification on failure

Security Properties

Keyless Signing

All signatures use Sigstore's keyless signing:

  • No long-lived keys to manage or rotate
  • Identity based on GitHub Actions OIDC token
  • Signatures recorded in Rekor transparency log

Provenance Attestations

Every artifact includes SLSA v1 provenance that links it to:

  • Source repository and commit
  • Workflow that built it (pinned SHA)
  • Build environment (runner OS, architecture)
  • Build timestamp

SBOM Attestations

Software Bill of Materials (SPDX format) for each binary:

  • Generated by Syft during build
  • Signed as in-toto attestation
  • Links SBOM to the specific artifact

Windows MSI Installers

MSI installers are built using WiX Toolset with GoReleaser Pro:

  • UpgradeCode: Deterministic UUID v5 generated from repository name, ensuring consistent upgrade behavior across versions
  • Default template: Installs to C:\Program Files\ConductorOne\<connector> and adds to PATH
  • Custom templates: Connectors can provide custom WXS via msi_wxs_path input for Windows Service, registry keys, etc.

The MSI uses a WiX-compatible version format (x.x.x.0) since WiX doesn't support semver prerelease suffixes.

Both Windows zip and MSI have:

  • Cosign signatures (.sig, .cert)
  • SLSA provenance attestations
  • SBOM attestations

Note: Windows code signing via Azure Trusted Signing is planned for Stage 2.

Verification

Anyone can verify artifacts using cosign:

# Verify binary provenance
cosign verify-blob-attestation \
  --bundle artifact.provenance.sigstore.json \
  --type https://slsa.dev/provenance/v1 \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --certificate-identity-regexp 'https://github.com/ConductorOne/github-workflows/.github/workflows/release.yaml@.*' \
  artifact.zip

# Verify image provenance
cosign verify-attestation \
  --type https://slsa.dev/provenance/v1 \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --certificate-identity-regexp 'https://github.com/ConductorOne/github-workflows/.github/workflows/release.yaml@.*' \
  public.ecr.aws/conductorone/baton-foo@sha256:abc123

Certificate Identity

All attestations are signed with a certificate containing:

  • Issuer: https://token.actions.githubusercontent.com
  • Identity: https://github.com/ConductorOne/github-workflows/.github/workflows/release.yaml@<ref>

Verification requires matching both issuer and identity pattern.

Directory Structure

$GITHUB_WORKSPACE/
├── _caller/              # Connector repo checkout
│   └── dist/             # GoReleaser output, attestation bundles
└── _workflows/           # github-workflows repo checkout
    ├── _generated/       # Generated configs (goreleaser, gon, predicate)
    ├── _output/          # Final manifest and signatures
    ├── templates/        # Source templates
    └── cmd/              # Go commands

S3 File Structure

releases/{org}/{repo}/{tag}/
├── manifest.json
├── manifest.json.sig
├── manifest.json.cert
├── baton-foo_1.0.0_checksums.txt
├── baton-foo_1.0.0_checksums.txt.sig
├── baton-foo_1.0.0_checksums.txt.cert
├── baton-foo-v1.0.0-darwin-arm64.zip
├── baton-foo-v1.0.0-darwin-arm64.zip.sig
├── baton-foo-v1.0.0-darwin-arm64.zip.cert
├── baton-foo-v1.0.0-darwin-arm64.zip.provenance.sigstore.json
├── baton-foo-v1.0.0-darwin-arm64.zip.sbom.sigstore.json
├── baton-foo-v1.0.0-linux-amd64.tar.gz
├── baton-foo-v1.0.0-linux-amd64.tar.gz.sig
├── baton-foo-v1.0.0-linux-amd64.tar.gz.cert
├── baton-foo-v1.0.0-linux-amd64.tar.gz.provenance.sigstore.json
├── baton-foo-v1.0.0-linux-amd64.tar.gz.sbom.sigstore.json
├── baton-foo-v1.0.0-windows-amd64.zip
├── baton-foo-v1.0.0-windows-amd64.zip.sig
├── baton-foo-v1.0.0-windows-amd64.zip.cert
├── baton-foo-v1.0.0-windows-amd64.zip.provenance.sigstore.json
├── baton-foo-v1.0.0-windows-amd64.zip.sbom.sigstore.json
├── baton-foo_v1.0.0_windows_amd64.msi
├── baton-foo_v1.0.0_windows_amd64.msi.sig
├── baton-foo_v1.0.0_windows_amd64.msi.cert
├── baton-foo_v1.0.0_windows_amd64.msi.provenance.sigstore.json
├── baton-foo_v1.0.0_windows_amd64.msi.sbom.sigstore.json
└── ...

Testing Changes

Test Repositories

Use test connectors for validation:

  • ConductorOne/baton-runner - Custom WXS template testing (via msi_wxs_path at ci/app.wxs)
  • ConductorOne/baton-github-test - Default WXS template testing

Testing Process

  1. Make workflow changes on a branch
  2. Point test repo at your branch:
    uses: ConductorOne/github-workflows/.github/workflows/release.yaml@your-branch
  3. Create a test release on test connector repo via UI
  4. Wait for workflow to complete
  5. Validate outputs:
    ./scripts/validate-release-artifacts.sh ConductorOne/baton-github-test v0.1.xxx

Validation Script

The scripts/validate-release-artifacts.sh script validates:

  • Manifest structure and version match
  • All binary assets are downloadable
  • Provenance and SBOM attestations exist and verify
  • ECR Public image attestations (if present)
  • Manifest signature (if present)
./scripts/validate-release-artifacts.sh ORG/REPO VERSION

Exit codes: 0 = all passed, 1 = failures

Manual Verification

# Download and verify binary provenance
curl -LO "https://dist.conductorone.com/releases/ConductorOne/baton-github-test/v0.1.102/baton-github-test-v0.1.102-darwin-arm64.zip"
curl -LO "https://dist.conductorone.com/releases/ConductorOne/baton-github-test/v0.1.102/baton-github-test-v0.1.102-darwin-arm64.zip.provenance.sigstore.json"

cosign verify-blob-attestation \
  --bundle baton-github-test-v0.1.102-darwin-arm64.zip.provenance.sigstore.json \
  --type https://slsa.dev/provenance/v1 \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --certificate-identity-regexp 'https://github.com/ConductorOne/github-workflows/.github/workflows/release.yaml@.*' \
  baton-github-test-v0.1.102-darwin-arm64.zip

MSI Installation Testing

Test the MSI installer on an actual Windows machine:

  1. Download MSI from S3:

    curl -LO "https://dist.conductorone.com/releases/ConductorOne/baton-runner/vX.Y.Z/baton-runner_vX.Y.Z_windows_amd64.msi"
  2. Install and verify:

    • Double-click MSI or run msiexec /i baton-runner_vX.Y.Z_windows_amd64.msi
    • Check installation path: C:\Program Files\ConductorOne\baton-runner\
    • Verify PATH includes installation directory
    • Run baton-runner --help from new terminal
  3. Test upgrade scenario:

    • Install older version first
    • Install newer version over it
    • Verify clean upgrade (no duplicate entries, old version removed)
  4. Test uninstall:

    • Uninstall via Settings > Apps or msiexec /x
    • Verify files removed from Program Files
    • Verify PATH entry removed
  5. Verify UpgradeCode consistency:

    • UpgradeCode is deterministic UUID v5 from repository name
    • Must be identical across all versions for upgrades to work

Common Issues

  • Cosign version: Ensure using latest cosign (cosign version)
  • MSI UpgradeCode: If upgrades don't work, verify UpgradeCode is consistent across versions

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

Other Potential Improvements

  • Support for Windows ARM64 builds
  • Windows Service installer templates (for connectors that run as services)