diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 8444e30baa030..da114ac091eda 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -119,6 +119,9 @@ jobs: AC_APIKEY_ISSUER_ID: ${{ secrets.AC_APIKEY_ISSUER_ID }} AC_APIKEY_ID: ${{ secrets.AC_APIKEY_ID }} AC_APIKEY_FILE: /tmp/apple_apikey.p8 + CODER_SIGN_WINDOWS: "0" + AUTHENTICODE_CERTIFICATE_FILE: /tmp/windows_cert.pkcs12 + AUTHENTICODE_CERTIFICATE_PASSWORD_FILE: /tmp/windows_cert_password.txt - name: Delete Apple Developer certificate and API key run: rm -f /tmp/{apple_cert.p12,apple_cert_password.txt,apple_apikey.p8} diff --git a/.gitignore b/.gitignore index 25c5e1c798913..9bb066d5f53a6 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,8 @@ site/out/ *.lock.hcl .terraform/ +**/*.syso + .vscode/*.log .vscode/launch.json **/*.swp diff --git a/cmd/coder/coder.exe.ico b/cmd/coder/coder.exe.ico new file mode 100644 index 0000000000000..37cbd495d195f Binary files /dev/null and b/cmd/coder/coder.exe.ico differ diff --git a/cmd/coder/coder.exe.manifest b/cmd/coder/coder.exe.manifest new file mode 100644 index 0000000000000..be7ebfd788e22 --- /dev/null +++ b/cmd/coder/coder.exe.manifest @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/cmd/coder/versioninfo.json b/cmd/coder/versioninfo.json new file mode 100644 index 0000000000000..3da420c00dfb9 --- /dev/null +++ b/cmd/coder/versioninfo.json @@ -0,0 +1,44 @@ +{ + "FixedFileInfo": + { + "FileVersion": { + "Major": 0, + "Minor": 0, + "Patch": 0, + "Build": 0 + }, + "ProductVersion": { + "Major": 0, + "Minor": 0, + "Patch": 0, + "Build": 0 + }, + "FileFlagsMask": "3f", + "FileFlags ": "00", + "FileOS": "040004", + "FileType": "01", + "FileSubType": "00" + }, + "StringFileInfo": + { + "Comments": "https://coder.com", + "CompanyName": "Coder Technologies, Inc", + "FileDescription": "Coder", + "FileVersion": "", + "InternalName": "coder", + "LegalCopyright": "© Coder Technologies, Inc. All rights reserved.", + "LegalTrademarks": "", + "OriginalFilename": "coder.exe", + "PrivateBuild": "", + "ProductName": "Coder®", + "ProductVersion": "", + "SpecialBuild": "" + }, + "VarFileInfo": + { + "Translation": { + "LangID": "0409", + "CharsetID": "04B0" + } + } +} diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 6a1543597d4a2..82fc30fb3c27e 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -62,7 +62,8 @@ Alternatively if you do not want to use nix then you'll need to install the need - on macOS, run `brew install pango` - [`pandoc`]() - on macOS, run `brew install pandocomatic` - +- [`osslsigncode`]() + - on macOS, run `brew install osslsigncode` ### Development workflow diff --git a/dogfood/Dockerfile b/dogfood/Dockerfile index a05a1266ad286..d2318f819ed8a 100644 --- a/dogfood/Dockerfile +++ b/dogfood/Dockerfile @@ -124,6 +124,7 @@ RUN apt-get update --quiet && apt-get install --yes \ openjdk-11-jdk-headless \ openssh-server \ openssl \ + osslsigncode \ pkg-config \ python3 \ python3-pip \ diff --git a/flake.nix b/flake.nix index dfc44b91df36f..d5ab4f1682049 100644 --- a/flake.nix +++ b/flake.nix @@ -32,6 +32,7 @@ nodePackages.typescript nodePackages.typescript-language-server nodejs + osslsigncode openssh openssl postgresql diff --git a/go.mod b/go.mod index f38504b38d9dc..6573a2bbf8adb 100644 --- a/go.mod +++ b/go.mod @@ -302,3 +302,8 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect howett.net/plist v1.0.0 // indirect ) + +require ( + github.com/akavel/rsrc v0.10.2 // indirect + github.com/josephspurrier/goversioninfo v1.4.0 // indirect +) diff --git a/go.sum b/go.sum index 29b60a8021290..43751420da431 100644 --- a/go.sum +++ b/go.sum @@ -170,6 +170,8 @@ github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/akavel/rsrc v0.10.2 h1:Zxm8V5eI1hW4gGaYsJQUhxpjkENuG91ki8B4zCrvEsw= +github.com/akavel/rsrc v0.10.2/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/akutz/memconn v0.1.0 h1:NawI0TORU4hcOMsMr11g7vwlCdkYeLKXBcxWu2W/P8A= github.com/akutz/memconn v0.1.0/go.mod h1:Jo8rI7m0NieZyLI5e2CDlRdRqRRB4S7Xp77ukDjH+Fw= github.com/alecthomas/chroma v0.9.4/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= @@ -1118,6 +1120,8 @@ github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqx github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/josephspurrier/goversioninfo v1.4.0 h1:Puhl12NSHUSALHSuzYwPYQkqa2E1+7SrtAPJorKK0C8= +github.com/josephspurrier/goversioninfo v1.4.0/go.mod h1:JWzv5rKQr+MmW+LvM412ToT/IkYDZjaclF2pKDss8IY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk= github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= diff --git a/scripts/build_go.sh b/scripts/build_go.sh index 3a8649890174f..2d10e8233f2cf 100755 --- a/scripts/build_go.sh +++ b/scripts/build_go.sh @@ -32,10 +32,11 @@ 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}" -args="$(getopt -o "" -l version:,os:,arch:,output:,slim,agpl,sign-darwin -- "$@")" +args="$(getopt -o "" -l version:,os:,arch:,output:,slim,agpl,sign-darwin,sign-windows -- "$@")" eval set -- "$args" while true; do case "$1" in @@ -68,6 +69,10 @@ while true; do sign_darwin=1 shift ;; + --sign-windows) + sign_windows=1 + shift + ;; --) shift break @@ -93,6 +98,20 @@ if [[ "$sign_darwin" == 1 ]]; then requiredenvs AC_CERTIFICATE_FILE AC_CERTIFICATE_PASSWORD_FILE fi +if [[ "$sign_windows" == 1 ]]; then + dependencies osslsigncode + requiredenvs AUTHENTICODE_CERTIFICATE_FILE AUTHENTICODE_CERTIFICATE_PASSWORD_FILE +fi + +if [[ "$os" == "windows" ]]; then + goversioninfo -platform-specific=true \ + -product-version=${version} \ + -icon=cmd/coder/coder.exe.ico \ + -manifest=cmd/coder/coder.exe.manifest \ + cmd/coder/versioninfo.json +fi + + build_args=( -ldflags "-s -w -X 'github.com/coder/coder/buildinfo.tag=$version'" ) @@ -134,4 +153,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..7d83ab009df72 --- /dev/null +++ b/scripts/sign_windows.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +set -x +# This script signs the provided windows binary with a X.509 certificate and +# it's associated private key. +# +# Usage: ./sign_windows.sh path/to/binary +# +# On success, the input file will be signed using the X.509 certificate. +# +# You can check if a binary is signed by running the following command: +# osslsigncode verify path/to/binary +# +# Depends on the osslsigncode utility. Requires the following environment variables +# to be set: +# - $AUTHENTICODE_CERTIFICATE_FILE: The path to the X5.09 certificate file. +# - $AUTHENTICODE_CERTIFICATE_PASSWORD_FILE: The path to the file containing the password +# for the X5.09 certificate. + +set -euo pipefail +# shellcheck source=scripts/lib.sh +source "$(dirname "${BASH_SOURCE[0]}")/lib.sh" + +# Check dependencies +dependencies osslsigncode +requiredenvs AUTHENTICODE_CERTIFICATE_FILE AUTHENTICODE_CERTIFICATE_PASSWORD_FILE + +osslsigncode sign \ + -pkcs12 "$AUTHENTICODE_CERTIFICATE_FILE" \ + -readpass "$AUTHENTICODE_CERTIFICATE_PASSWORD_FILE" \ + -n "Coder" \ + -i "https://coder.com" \ + -t "http://timestamp.sectigo.com" + -in "$@" \ + -out "$@" \ + 1>&2 + +osslsigncodeosslsigncode verify "$@" 1>&2