From 9e03c7557f0e32ed377724af66ed73878d57370c Mon Sep 17 00:00:00 2001 From: jeffreyc-splunk Date: Wed, 26 Jun 2024 18:33:03 -0400 Subject: [PATCH] fips: otelcol binaries for linux and windows --- .github/workflows/otelcol-fips.yml | 81 +++++++++++++++++++++++ .gitlab-ci.yml | 39 ++++++++++- CHANGELOG.md | 8 +++ Makefile | 30 ++++++++- cmd/otelcol/fips/build/Dockerfile.linux | 39 +++++++++++ cmd/otelcol/fips/build/Dockerfile.windows | 35 ++++++++++ cmd/otelcol/main_fipsonly.go | 20 ++++++ 7 files changed, 250 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/otelcol-fips.yml create mode 100644 cmd/otelcol/fips/build/Dockerfile.linux create mode 100644 cmd/otelcol/fips/build/Dockerfile.windows create mode 100644 cmd/otelcol/main_fipsonly.go diff --git a/.github/workflows/otelcol-fips.yml b/.github/workflows/otelcol-fips.yml new file mode 100644 index 0000000000..c1d6097b8d --- /dev/null +++ b/.github/workflows/otelcol-fips.yml @@ -0,0 +1,81 @@ +name: "otelcol-fips" + +on: + push: + branches: + - main + pull_request: + paths: + - '.github/workflows/otelcol-fips.yml' + - 'cmd/otelcol/**' + - 'internal/**' + - 'pkg/**' + - 'tests/**' + - 'Makefile' + - 'Makefile.Common' + - 'go.mod' + - 'go.sum' + - '!**.md' + - '!internal/buildscripts/**' + +concurrency: + group: otelcol-fips-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + GO_VERSION: "1.22.7" + +jobs: + otelcol-fips: + runs-on: ${{ fromJSON('["ubuntu-20.04", "otel-arm64"]')[matrix.GOARCH == 'arm64'] }} + strategy: + matrix: + include: + - GOOS: linux + GOARCH: amd64 + - GOOS: linux + GOARCH: arm64 + - GOOS: windows + GOARCH: amd64 + fail-fast: false + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + cache-dependency-path: '**/go.sum' + - run: make otelcol-fips + env: + GOOS: ${{ matrix.GOOS }} + GOARCH: ${{ matrix.GOARCH }} + - uses: actions/upload-artifact@v4 + with: + name: otelcol-fips-${{ matrix.GOOS }}-${{ matrix.GOARCH }} + path: ./bin/* + + win-binary-test: + runs-on: windows-2022 + needs: [ otelcol-fips ] + strategy: + matrix: + FIPSMODE: [ "1", "0" ] + fail-fast: false + steps: + - uses: actions/download-artifact@v4 + with: + name: otelcol-fips-windows-amd64 + path: ./bin + - run: Set-ItemProperty -Path HKLM:\System\CurrentControlSet\Control\Lsa\FipsAlgorithmPolicy -Name Enabled -Value ${{ matrix.FIPSMODE }} + - run: ./bin/otelcol-fips_windows_amd64.exe --version + id: run-otelcol + continue-on-error: true + - run: echo "FIPS enabled, started successfully" + if: matrix.FIPSMODE == '1' && steps.run-otelcol.outcome == 'success' + - run: throw "FIPS enabled, should not have failed" + if: matrix.FIPSMODE == '1' && steps.run-otelcol.outcome == 'failure' + - run: echo "FIPS disabled, failed successfully" + if: matrix.FIPSMODE == '0' && steps.run-otelcol.outcome == 'failure' + - run: throw "FIPS disabled, should have failed" + if: matrix.FIPSMODE == '0' && steps.run-otelcol.outcome == 'success' diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7cb43d53cd..cb81c6cc46 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -311,6 +311,40 @@ compile: - bin/otelcol_* - bin/migratecheckpoint_* +otelcol-fips: + image: '${DOCKER_CICD_REPO}/ci-container/golang-1.22:3.4.0' + extends: + - .trigger-filter + stage: build + needs: [] + parallel: + matrix: + - GOOS: linux + GOARCH: amd64 + TAG: main + - GOOS: linux + GOARCH: arm64 + TAG: arm + - GOOS: windows + GOARCH: amd64 + TAG: main + tags: + - $TAG + id_tokens: # http://go/gitlab-17 + CI_JOB_JWT: + aud: $CICD_VAULT_ADDR + script: + - *docker-reader-role + - | + if [[ -n "${CI_COMMIT_TAG:-}" ]]; then + make otelcol-fips VERSION=${CI_COMMIT_TAG} DOCKER_REPO=${DOCKER_HUB_REPO} + else + make otelcol-fips DOCKER_REPO=${DOCKER_HUB_REPO} + fi + artifacts: + paths: + - bin/otelcol-fips_* + libsplunk: extends: .trigger-filter stage: build @@ -437,9 +471,10 @@ sign-exe: retry: 2 needs: - compile + - otelcol-fips parallel: matrix: - - TARGET: [otelcol] + - TARGET: [otelcol, otelcol-fips] variables: ARTIFACT: bin/${TARGET}_windows_amd64.exe SIGN_TYPE: WIN @@ -1299,6 +1334,7 @@ github-release: stage: github-release dependencies: - compile + - otelcol-fips - libsplunk - sign-exe - sign-osx @@ -1312,6 +1348,7 @@ github-release: script: - mkdir -p dist/assets - cp bin/otelcol_linux_* dist/assets/ + - cp bin/otelcol-fips_linux_* dist/assets/ - cp instrumentation/dist/libsplunk_*.so dist/assets/ - cp dist/signed/* dist/assets/ - | diff --git a/CHANGELOG.md b/CHANGELOG.md index 48481e46ae..ce3c322483 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ - (Splunk) Deprecate the jaegergrpc monitor ([#5428](https://github.com/signalfx/splunk-otel-collector/pull/5428)) +### 💡 Enhancements 💡 + +- (Splunk) Initial release of standalone collector binaries for Linux (amd64/arm64) and Windows (amd64) with FIPS 140-2 support. These are experimental (alpha) binaries, and it is not suitable to use them in production environments. ([#5378](https://github.com/signalfx/splunk-otel-collector/pull/5378)): + - `otelcol-fips_linux_`: Built with [`GOEXPERIMENT=boringcrypto`](https://go.dev/src/crypto/internal/boring/README) and [`crypto/tls/fipsonly`](https://go.dev/src/crypto/tls/fipsonly/fipsonly.go). + - `otelcol-fips_windows_amd64.exe`: Built with [`GOEXPERIMENT=cngcrypto`](https://github.com/microsoft/go/blob/microsoft/main/eng/doc/fips/README.md) and [`requirefips`](https://github.com/microsoft/go/blob/microsoft/main/eng/doc/fips/README.md#build-option-to-require-fips-mode) (the collector will panic if FIPS is not enabled on the Windows host). + - Smart Agent components are not currently supported. + - Download the binaries from the list of assets below. + ## v0.110.0 This Splunk OpenTelemetry Collector release includes changes from the [opentelemetry-collector v0.110.0](https://github.com/open-telemetry/opentelemetry-collector/releases/tag/v0.110.0) and the [opentelemetry-collector-contrib v0.110.0](https://github.com/open-telemetry/opentelemetry-collector-contrib/releases/tag/v0.110.0) releases where appropriate. diff --git a/Makefile b/Makefile index cb361c1a6c..24efeb957b 100644 --- a/Makefile +++ b/Makefile @@ -30,6 +30,7 @@ BUILD_X1=-X $(BUILD_INFO_IMPORT_PATH).Version=$(VERSION) BUILD_X2=-X $(BUILD_INFO_IMPORT_PATH_CORE).Version=$(VERSION) BUILD_INFO=-ldflags "${BUILD_X1} ${BUILD_X2}" BUILD_INFO_TESTS=-ldflags "-X $(BUILD_INFO_IMPORT_PATH_TESTS).Version=$(VERSION)" +CGO_ENABLED?=0 JMX_METRIC_GATHERER_RELEASE=$(shell cat internal/buildscripts/packaging/jmx-metric-gatherer-release.txt) SKIP_COMPILE=false @@ -135,13 +136,14 @@ generate-metrics: .PHONY: otelcol otelcol: go generate ./... - GO111MODULE=on CGO_ENABLED=0 go build -trimpath -o ./bin/otelcol_$(GOOS)_$(GOARCH)$(EXTENSION) $(BUILD_INFO) ./cmd/otelcol + GO111MODULE=on CGO_ENABLED=$(CGO_ENABLED) go build -trimpath -o ./bin/otelcol_$(GOOS)_$(GOARCH)$(EXTENSION) $(BUILD_INFO) ./cmd/otelcol ifeq ($(OS), Windows_NT) $(LINK_CMD) .\bin\otelcol$(EXTENSION) .\bin\otelcol_$(GOOS)_$(GOARCH)$(EXTENSION) else $(LINK_CMD) otelcol_$(GOOS)_$(GOARCH)$(EXTENSION) ./bin/otelcol$(EXTENSION) endif + .PHONY: migratecheckpoint migratecheckpoint: go generate ./... @@ -241,3 +243,29 @@ install-test-tools: integration-test-split: install-test-tools @set -e; cd tests && gotesplit --total=$(GOTESPLIT_TOTAL) --index=$(GOTESPLIT_INDEX) ./... -- -p 1 $(BUILD_INFO_TESTS) --tags=integration -v -timeout 5m -count 1 +.PHONY: otelcol-fips +otelcol-fips: +ifeq ($(GOOS), linux) + ifeq ($(filter $(GOARCH), amd64 arm64),) + $(error GOOS=$(GOOS) GOARCH=$(GOARCH) not supported) + endif + $(eval BUILD_INFO = -ldflags "${BUILD_X1} ${BUILD_X2} -linkmode=external -extldflags=-static") +else ifeq ($(GOOS), windows) + ifeq ($(filter $(GOARCH), amd64),) + $(error GOOS=$(GOOS) GOARCH=$(GOARCH) not supported) + endif + $(eval EXTENSION = .exe) +else + $(error GOOS=$(GOOS) GOARCH=$(GOARCH) not supported) +endif + docker buildx build --pull \ + --tag otelcol-fips-builder-$(GOOS)-$(GOARCH) \ + --platform linux/$(GOARCH) \ + --build-arg DOCKER_REPO=$(DOCKER_REPO) \ + --build-arg BUILD_INFO='$(BUILD_INFO)' \ + --file cmd/otelcol/fips/build/Dockerfile.$(GOOS) ./ + @docker rm -f otelcol-fips-builder-$(GOOS)-$(GOARCH) >/dev/null 2>&1 || true + @mkdir -p ./bin + docker create --platform linux/$(GOARCH) --name otelcol-fips-builder-$(GOOS)-$(GOARCH) otelcol-fips-builder-$(GOOS)-$(GOARCH) true >/dev/null + docker cp otelcol-fips-builder-$(GOOS)-$(GOARCH):/src/bin/otelcol_$(GOOS)_$(GOARCH)$(EXTENSION) ./bin/otelcol-fips_$(GOOS)_$(GOARCH)$(EXTENSION) + @docker rm -f otelcol-fips-builder-$(GOOS)-$(GOARCH) >/dev/null diff --git a/cmd/otelcol/fips/build/Dockerfile.linux b/cmd/otelcol/fips/build/Dockerfile.linux new file mode 100644 index 0000000000..51862af477 --- /dev/null +++ b/cmd/otelcol/fips/build/Dockerfile.linux @@ -0,0 +1,39 @@ +ARG DOCKER_REPO=docker.io +ARG GO_VERSION=1.22.7 +FROM ${DOCKER_REPO}/golang:${GO_VERSION} + +# https://splunk.atlassian.net/wiki/x/qYqRDfs +ENV BORING_SHA="c1dd71f0ea77e385796db11102c461896ee0824825c773979751983e2bf49912" +ENV BORING_PATH="src/crypto/internal/boring/syso/goboringcrypto_linux_amd64.syso" +RUN echo "$BORING_SHA" "$( go env GOROOT )/${BORING_PATH}" | sha256sum --check || ( echo "$BORING_PATH SHA256 doesn't match $BORING_SHA" && exit 1 ) + +# install toolchain to build a statically linked binary with cgo enabled +RUN apt-get update && \ + apt-get install -y --no-install-recommends file musl-dev musl-tools + +COPY cmd /src/cmd +COPY internal /src/internal +COPY pkg /src/pkg +COPY Makefile /src/ +COPY Makefile.Common /src/ +COPY go.mod /src/ +COPY go.sum /src/ + +ARG TARGETARCH +ARG BUILD_INFO +ENV GOOS=linux +ENV GOARCH=${TARGETARCH} +ENV GOEXPERIMENT=boringcrypto +ENV GOMODCACHE=/go/pkg/mod +ENV CGO_ENABLED=1 +ENV CC=musl-gcc + +WORKDIR /src +RUN --mount=type=cache,target=${GOMODCACHE} make otelcol BUILD_INFO="${BUILD_INFO}" + +# check the binary +RUN file ./bin/otelcol_${GOOS}_${GOARCH} | grep -i "statically linked" || ( echo "the binary is not statically linked" && exit 1 ) +RUN go version ./bin/otelcol_${GOOS}_${GOARCH} | grep "X:${GOEXPERIMENT}" +RUN go tool nm ./bin/otelcol_${GOOS}_${GOARCH} > symbols +RUN grep -i "fipsonly" symbols +RUN grep -m5 "_Cfunc__goboringcrypto" symbols diff --git a/cmd/otelcol/fips/build/Dockerfile.windows b/cmd/otelcol/fips/build/Dockerfile.windows new file mode 100644 index 0000000000..1bda629500 --- /dev/null +++ b/cmd/otelcol/fips/build/Dockerfile.windows @@ -0,0 +1,35 @@ +ARG GO_VERSION=1.22.7 +FROM mcr.microsoft.com/oss/go/microsoft/golang:${GO_VERSION} + +ARG TARGETARCH + +# install toolchain for cgo +RUN apt-get update && \ + apt-get install -y --no-install-recommends gcc-mingw-w64 + +COPY cmd /src/cmd +COPY internal /src/internal +COPY pkg /src/pkg +COPY Makefile /src/ +COPY Makefile.Common /src/ +COPY go.mod /src/ +COPY go.sum /src/ + +ARG BUILD_INFO +ENV GOOS=windows +ENV GOARCH=${TARGETARCH} +ENV GOEXPERIMENT=cngcrypto +ENV GOMODCACHE=/go/pkg/mod +ENV CGO_ENABLED=1 +ENV CC=x86_64-w64-mingw32-gcc +ENV CXX=x86_64-w64-mingw32-g++ +ENV GOFLAGS="-tags=requirefips" +ENV EXTENSION=.exe + +WORKDIR /src +RUN --mount=type=cache,target=${GOMODCACHE} make otelcol BUILD_INFO="${BUILD_INFO}" + +# check the binary +RUN go version ./bin/otelcol_${GOOS}_${GOARCH}${EXTENSION} | grep "X:${GOEXPERIMENT}" +RUN go tool nm ./bin/otelcol_${GOOS}_${GOARCH}${EXTENSION} > symbols +RUN grep -m5 "github.com/microsoft/go-crypto-winnative" symbols diff --git a/cmd/otelcol/main_fipsonly.go b/cmd/otelcol/main_fipsonly.go new file mode 100644 index 0000000000..ec447b0106 --- /dev/null +++ b/cmd/otelcol/main_fipsonly.go @@ -0,0 +1,20 @@ +// Copyright Splunk, Inc. +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build linux && boringcrypto && cgo && (amd64 || arm64) + +package main + +import _ "crypto/tls/fipsonly"