diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 26493d144b9fe..faa6593452e25 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -128,6 +128,13 @@ jobs: - name: Setup Node uses: ./.github/actions/setup-node + # Necessary for signing Windows binaries. + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: "zulu" + java-version: "11.0" + - name: Install nsis and zstd run: sudo apt-get install -y nsis zstd @@ -161,10 +168,32 @@ jobs: AC_CERTIFICATE_PASSWORD: ${{ secrets.AC_CERTIFICATE_PASSWORD }} AC_APIKEY_P8_BASE64: ${{ secrets.AC_APIKEY_P8_BASE64 }} + - name: Setup Windows EV Signing Certificate + run: | + set -euo pipefail + touch /tmp/ev_cert.pem + chmod 600 /tmp/ev_cert.pem + echo "$EV_SIGNING_CERT" > /tmp/ev_cert.pem + wget https://github.com/ebourg/jsign/releases/download/6.0/jsign-6.0.jar -O /tmp/jsign-6.0.jar + env: + EV_SIGNING_CERT: ${{ secrets.EV_SIGNING_CERT }} + - name: Test migrations from current ref to main run: | make test-migrations + # Setup GCloud for signing Windows binaries. + - name: Authenticate to Google Cloud + id: gcloud_auth + uses: google-github-actions/auth@v2 + with: + workload_identity_provider: ${{ secrets.GCP_CODE_SIGNING_WORKLOAD_ID_PROVIDER }} + service_account: ${{ secrets.GCP_CODE_SIGNING_SERVICE_ACCOUNT }} + token_format: "access_token" + + - name: Setup GCloud SDK + uses: "google-github-actions/setup-gcloud@v2" + - name: Build binaries run: | set -euo pipefail @@ -179,16 +208,26 @@ jobs: build/coder_helm_"$version".tgz \ build/provisioner_helm_"$version".tgz env: + CODER_SIGN_WINDOWS: "1" CODER_SIGN_DARWIN: "1" AC_CERTIFICATE_FILE: /tmp/apple_cert.p12 AC_CERTIFICATE_PASSWORD_FILE: /tmp/apple_cert_password.txt AC_APIKEY_ISSUER_ID: ${{ secrets.AC_APIKEY_ISSUER_ID }} AC_APIKEY_ID: ${{ secrets.AC_APIKEY_ID }} AC_APIKEY_FILE: /tmp/apple_apikey.p8 + EV_KEY: ${{ secrets.EV_KEY }} + EV_KEYSTORE: ${{ secrets.EV_KEYSTORE }} + EV_TSA_URL: ${{ secrets.EV_TSA_URL }} + EV_CERTIFICATE_PATH: /tmp/ev_cert.pem + GCLOUD_ACCESS_TOKEN: ${{ steps.gcloud_auth.outputs.access_token }} + JSIGN_PATH: /tmp/jsign-6.0.jar - name: Delete Apple Developer certificate and API key run: rm -f /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8} + - name: Delete Windows EV Signing Cert + run: rm /tmp/ev_cert.pem + - name: Determine base image tag id: image-base-tag run: | diff --git a/scripts/build_go.sh b/scripts/build_go.sh index b8be1cb8cd4a6..bfecb6763ac7b 100755 --- a/scripts/build_go.sh +++ b/scripts/build_go.sh @@ -35,6 +35,7 @@ os="${GOOS:-linux}" arch="${GOARCH:-amd64}" slim="${CODER_SLIM_BUILD:-0}" sign_darwin="${CODER_SIGN_DARWIN:-0}" +sign_windows="${CODER_SIGN_WINDOWS:-0}" output_path="" agpl="${CODER_BUILD_AGPL:-0}" boringcrypto=${CODER_BUILD_BORINGCRYPTO:-0} @@ -106,6 +107,11 @@ if [[ "$sign_darwin" == 1 ]]; then requiredenvs AC_CERTIFICATE_FILE AC_CERTIFICATE_PASSWORD_FILE fi +if [[ "$sign_windows" == 1 ]]; then + dependencies java + requiredenvs JSIGN_PATH EV_KEYSTORE EV_KEY EV_CERTIFICATE_PATH EV_TSA_URL GCLOUD_ACCESS_TOKEN +fi + ldflags=( -X "'github.com/coder/coder/v2/buildinfo.tag=$version'" ) @@ -176,4 +182,8 @@ if [[ "$sign_darwin" == 1 ]] && [[ "$os" == "darwin" ]]; then execrelative ./sign_darwin.sh "$output_path" 1>&2 fi +if [[ "$sign_windows" == 1 ]] && [[ "$os" == "windows" ]]; then + execrelative ./sign_windows.sh "$output_path" 1>&2 +fi + echo "$output_path" diff --git a/scripts/sign_windows.sh b/scripts/sign_windows.sh new file mode 100755 index 0000000000000..f67ecfdd0b2b6 --- /dev/null +++ b/scripts/sign_windows.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +# This script signs the provided windows binary with an Extended Validation +# code signing certificate. +# +# Usage: ./sign_windows.sh path/to/binary +# +# On success, the input file will be signed using the EV cert. +# +# Depends on the jsign utility (and thus Java). Requires the following environment variables +# to be set: +# - $JSIGN_PATH: The path to the jsign jar. +# - $EV_KEYSTORE: The name of the keyring containing the private key +# - $EV_KEY: The name of the key. +# - $EV_CERTIFICATE_PATH: The path to the certificate. +# - $EV_TSA_URL: The url of the timestamp server to use. + +set -euo pipefail +# shellcheck source=scripts/lib.sh +source "$(dirname "${BASH_SOURCE[0]}")/lib.sh" + +# Check dependencies +dependencies java +requiredenvs JSIGN_PATH EV_KEYSTORE EV_KEY EV_CERTIFICATE_PATH EV_TSA_URL GCLOUD_ACCESS_TOKEN + +java -jar "$JSIGN_PATH" \ + --storetype GOOGLECLOUD \ + --storepass "$GCLOUD_ACCESS_TOKEN" \ + --keystore "$EV_KEYSTORE" \ + --alias "$EV_KEY" \ + --certfile "$EV_CERTIFICATE_PATH" \ + --tsmode RFC3161 \ + --tsaurl "$EV_TSA_URL" \ + "$@" \ + 1>&2