From c47024579fcb91a3997b1932d467f8b740e956b0 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Tue, 5 Sep 2023 11:15:13 +0000 Subject: [PATCH 1/3] feat: add boringcrypto builds for linux Signed-off-by: Spike Curtis --- .github/workflows/release.yaml | 16 ++++++++++++++++ Makefile | 17 +++++++++++++++++ scripts/build_go.sh | 29 +++++++++++++++++++++++++---- 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 514b8dda4f2cc..7c40ae2b4f7ac 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -151,6 +151,22 @@ jobs: AC_APIKEY_ID: ${{ secrets.AC_APIKEY_ID }} AC_APIKEY_FILE: /tmp/apple_apikey.p8 + - name: Check Boring Crypto + run: | + set -euo pipefail + + version="$(./scripts/version.sh)" + go tool nm build/coder_"$version"_linux_amd64 | grep "_Cfunc__goboringcrypto_" &>/dev/null + if [[ "$?" == "1" ]]; then + echo "build/coder_${version}_linux_amd64 is not built with Boring Crypto" + exit 1 + fi + go tool nm build/coder-slim_"$version"_linux_amd64 | grep "_Cfunc__goboringcrypto_" &>/dev/null + if [[ "$?" == "1" ]]; then + echo "build/coder-slim_${version}_linux_amd64 is not built with Boring Crypto" + exit 1 + fi + - 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/Makefile b/Makefile index 65196d0a4bd1d..d0c7337ace0f8 100644 --- a/Makefile +++ b/Makefile @@ -105,6 +105,17 @@ CODER_ARCH_IMAGE_PREREQUISITES := \ build/coder_$(VERSION)_%.tar.gz endif +# used to decide if we can build with boringcrypto +ifeq ($(OS),Windows_NT) + local_os:=Windows + local_arch:="" #ignored, no boringcrypto support for Windows +else + local_os:=$(shell uname -s) + local_arch:=$(shell uname -m) +endif +ifeq ($(local_arch),x86_64) + local_arch:=amd64 +endif clean: rm -rf build site/out @@ -222,6 +233,12 @@ $(CODER_ALL_BINARIES): go.mod go.sum \ build_args+=(--slim) fi + # boringcrypto is only supported on Linux + # boringcrypto uses CGO, which isn't supported when cross compiling architectures + if [[ "$$os" == "linux" ]] && [[ "${local_os}" == "Linux" ]] && [[ "$$arch" == "${local_arch}" ]]; then + build_args+=(--boringcrypto) + fi + ./scripts/build_go.sh "$${build_args[@]}" if [[ "$$mode" == "slim" ]]; then diff --git a/scripts/build_go.sh b/scripts/build_go.sh index df5ea96085242..b8ee7f577cf99 100755 --- a/scripts/build_go.sh +++ b/scripts/build_go.sh @@ -2,7 +2,7 @@ # This script builds a single Go binary of Coder with the given parameters. # -# Usage: ./build_go.sh [--version 1.2.3-devel+abcdef] [--os linux] [--arch amd64] [--output path/to/output] [--slim] [--agpl] +# Usage: ./build_go.sh [--version 1.2.3-devel+abcdef] [--os linux] [--arch amd64] [--output path/to/output] [--slim] [--agpl] [--boringcrypto] # # Defaults to linux:amd64 with slim disabled, but can be controlled with GOOS, # GOARCH and CODER_SLIM_BUILD=1. If no version is specified, defaults to the @@ -22,6 +22,9 @@ # # If the --agpl parameter is specified, builds only the AGPL-licensed code (no # Coder enterprise features). +# +# If the --boringcrypto parameter is specified, builds use boringcrypto instead of +# the standard go crypto libraries. set -euo pipefail # shellcheck source=scripts/lib.sh @@ -34,8 +37,9 @@ slim="${CODER_SLIM_BUILD:-0}" sign_darwin="${CODER_SIGN_DARWIN:-0}" output_path="" agpl="${CODER_BUILD_AGPL:-0}" +boringcrypto=${CODER_BUILD_BORINGCRYPTO:-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,boringcrypto -- "$@")" eval set -- "$args" while true; do case "$1" in @@ -68,6 +72,10 @@ while true; do sign_darwin=1 shift ;; + --boringcrypto) + boringcrypto=1 + shift + ;; --) shift break @@ -94,11 +102,16 @@ if [[ "$sign_darwin" == 1 ]]; then fi ldflags=( - -s -w -X "'github.com/coder/coder/v2/buildinfo.tag=$version'" ) +# For boringcrypto we want to leave the symbols so we can verify it was build correctly for +# FIPS compliance. This adds a few MiB to the binary. +if [[ "$boringcrypto" == 0 ]]; then + ldflags+=(-s) +fi + # We use ts_omit_aws here because on Linux it prevents Tailscale from importing # github.com/aws/aws-sdk-go-v2/aws, which adds 7 MB to the binary. TS_EXTRA_SMALL="ts_omit_aws,ts_omit_bird,ts_omit_tap,ts_omit_kube" @@ -140,7 +153,15 @@ cmd_path="./enterprise/cmd/coder" if [[ "$agpl" == 1 ]]; then cmd_path="./cmd/coder" fi -CGO_ENABLED=0 GOOS="$os" GOARCH="$arch" GOARM="$arm_version" go build \ + +cgo=0 +goexp="" +if [[ "$boringcrypto" == 1 ]]; then + cgo=1 + goexp="boringcrypto" +fi + +GOEXPERIMENT="$goexp" CGO_ENABLED="$cgo" GOOS="$os" GOARCH="$arch" GOARM="$arm_version" go build \ "${build_args[@]}" \ "$cmd_path" 1>&2 From dbb504f36f8f1000e3cf696e6e85ad0b5759013d Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Tue, 5 Sep 2023 12:49:07 +0000 Subject: [PATCH 2/3] strip debug symbols, add BoringCryto to buildinfo Signed-off-by: Spike Curtis --- .github/workflows/release.yaml | 16 ---------------- Makefile | 14 +++----------- buildinfo/boring.go | 7 +++++++ buildinfo/buildinfo.go | 4 ++++ buildinfo/notboring.go | 5 +++++ cli/version.go | 25 +++++++++++++++---------- scripts/build_go.sh | 7 +------ 7 files changed, 35 insertions(+), 43 deletions(-) create mode 100644 buildinfo/boring.go create mode 100644 buildinfo/notboring.go diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 7c40ae2b4f7ac..514b8dda4f2cc 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -151,22 +151,6 @@ jobs: AC_APIKEY_ID: ${{ secrets.AC_APIKEY_ID }} AC_APIKEY_FILE: /tmp/apple_apikey.p8 - - name: Check Boring Crypto - run: | - set -euo pipefail - - version="$(./scripts/version.sh)" - go tool nm build/coder_"$version"_linux_amd64 | grep "_Cfunc__goboringcrypto_" &>/dev/null - if [[ "$?" == "1" ]]; then - echo "build/coder_${version}_linux_amd64 is not built with Boring Crypto" - exit 1 - fi - go tool nm build/coder-slim_"$version"_linux_amd64 | grep "_Cfunc__goboringcrypto_" &>/dev/null - if [[ "$?" == "1" ]]; then - echo "build/coder-slim_${version}_linux_amd64 is not built with Boring Crypto" - exit 1 - fi - - 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/Makefile b/Makefile index d0c7337ace0f8..088acdbefbb8c 100644 --- a/Makefile +++ b/Makefile @@ -106,16 +106,8 @@ CODER_ARCH_IMAGE_PREREQUISITES := \ endif # used to decide if we can build with boringcrypto -ifeq ($(OS),Windows_NT) - local_os:=Windows - local_arch:="" #ignored, no boringcrypto support for Windows -else - local_os:=$(shell uname -s) - local_arch:=$(shell uname -m) -endif -ifeq ($(local_arch),x86_64) - local_arch:=amd64 -endif +local_os:=$(shell go env GOHOSTOS) +local_arch:=$(shell go env GOHOSTARCH) clean: rm -rf build site/out @@ -235,7 +227,7 @@ $(CODER_ALL_BINARIES): go.mod go.sum \ # boringcrypto is only supported on Linux # boringcrypto uses CGO, which isn't supported when cross compiling architectures - if [[ "$$os" == "linux" ]] && [[ "${local_os}" == "Linux" ]] && [[ "$$arch" == "${local_arch}" ]]; then + if [[ "$$os" == "linux" ]] && [[ "${local_os}" == "linux" ]] && [[ "$$arch" == "${local_arch}" ]]; then build_args+=(--boringcrypto) fi diff --git a/buildinfo/boring.go b/buildinfo/boring.go new file mode 100644 index 0000000000000..ec2f0b4e3c286 --- /dev/null +++ b/buildinfo/boring.go @@ -0,0 +1,7 @@ +//go:build boringcrypto + +package buildinfo + +import "crypto/boring" + +var boringcrypto = boring.Enabled() diff --git a/buildinfo/buildinfo.go b/buildinfo/buildinfo.go index bafd3a916bcf2..bf35d4eca5143 100644 --- a/buildinfo/buildinfo.go +++ b/buildinfo/buildinfo.go @@ -87,6 +87,10 @@ func IsAGPL() bool { return strings.Contains(agpl, "t") } +func IsBoringCrypto() bool { + return boringcrypto +} + // ExternalURL returns a URL referencing the current Coder version. // For production builds, this will link directly to a release. // For development builds, this will link to a commit. diff --git a/buildinfo/notboring.go b/buildinfo/notboring.go new file mode 100644 index 0000000000000..70799b2c8d1eb --- /dev/null +++ b/buildinfo/notboring.go @@ -0,0 +1,5 @@ +//go:build !boringcrypto + +package buildinfo + +var boringcrypto = false diff --git a/cli/version.go b/cli/version.go index 84e45fb74fe22..70cac4f78d8e6 100644 --- a/cli/version.go +++ b/cli/version.go @@ -13,11 +13,12 @@ import ( // versionInfo wraps the stuff we get from buildinfo so that it's // easier to emit in different formats. type versionInfo struct { - Version string `json:"version"` - BuildTime time.Time `json:"build_time"` - ExternalURL string `json:"external_url"` - Slim bool `json:"slim"` - AGPL bool `json:"agpl"` + Version string `json:"version"` + BuildTime time.Time `json:"build_time"` + ExternalURL string `json:"external_url"` + Slim bool `json:"slim"` + AGPL bool `json:"agpl"` + BoringCrypto bool `json:"boring_crypto"` } // String() implements Stringer @@ -28,6 +29,9 @@ func (vi versionInfo) String() string { _, _ = str.WriteString("(AGPL) ") } _, _ = str.WriteString(vi.Version) + if vi.BoringCrypto { + _, _ = str.WriteString(" BoringCrypto") + } if !vi.BuildTime.IsZero() { _, _ = str.WriteString(" " + vi.BuildTime.Format(time.UnixDate)) @@ -45,11 +49,12 @@ func (vi versionInfo) String() string { func defaultVersionInfo() *versionInfo { buildTime, _ := buildinfo.Time() return &versionInfo{ - Version: buildinfo.Version(), - BuildTime: buildTime, - ExternalURL: buildinfo.ExternalURL(), - Slim: buildinfo.IsSlim(), - AGPL: buildinfo.IsAGPL(), + Version: buildinfo.Version(), + BuildTime: buildTime, + ExternalURL: buildinfo.ExternalURL(), + Slim: buildinfo.IsSlim(), + AGPL: buildinfo.IsAGPL(), + BoringCrypto: buildinfo.IsBoringCrypto(), } } diff --git a/scripts/build_go.sh b/scripts/build_go.sh index b8ee7f577cf99..bf435477fcb3e 100755 --- a/scripts/build_go.sh +++ b/scripts/build_go.sh @@ -102,16 +102,11 @@ if [[ "$sign_darwin" == 1 ]]; then fi ldflags=( + -s -w -X "'github.com/coder/coder/v2/buildinfo.tag=$version'" ) -# For boringcrypto we want to leave the symbols so we can verify it was build correctly for -# FIPS compliance. This adds a few MiB to the binary. -if [[ "$boringcrypto" == 0 ]]; then - ldflags+=(-s) -fi - # We use ts_omit_aws here because on Linux it prevents Tailscale from importing # github.com/aws/aws-sdk-go-v2/aws, which adds 7 MB to the binary. TS_EXTRA_SMALL="ts_omit_aws,ts_omit_bird,ts_omit_tap,ts_omit_kube" From d79bdc688127d1008720ca80e64c44942f3c91de Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Tue, 5 Sep 2023 13:03:52 +0000 Subject: [PATCH 3/3] Fix TestVersion Signed-off-by: Spike Curtis --- cli/version_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cli/version_test.go b/cli/version_test.go index 20068d29bf124..76c4f4392fbd7 100644 --- a/cli/version_test.go +++ b/cli/version_test.go @@ -34,7 +34,8 @@ Full build of Coder, supports the  server  subcomm "build_time": "0001-01-01T00:00:00Z", "external_url": "https://github.com/coder/coder", "slim": false, - "agpl": false + "agpl": false, + "boring_crypto": false } ` for _, tt := range []struct {