From 649bef0a70973c57585409823c4ff221646a49cf Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 21 Feb 2025 07:46:06 +0100 Subject: [PATCH] Fix docker image build for FIPS variants (#4472) (#4505) Fix multiple -tags= flags occurances. Correct the resulting docker image that's created when FIPS is used. Add fips e2e test that verifies a binary. (cherry picked from commit c83472bc44cabca4d5e1eada938cd7b801bcdb4d) Co-authored-by: Michel Laterman <82832767+michel-laterman@users.noreply.github.com> --- .buildkite/pipeline.yml | 17 +++++ .github/workflows/golangci-lint.yml | 6 +- .golangci.yml | 11 ++- Dockerfile.fips | 10 +-- Makefile | 73 +++++++++++++++---- dev-tools/e2e/Dockerfile | 6 +- dev-tools/e2e/build.sh | 9 +++ testing/e2e/agent_container_test.go | 2 +- testing/e2e/agent_install_test.go | 2 +- testing/e2e/fips_test.go | 89 +++++++++++++++++++++++ testing/e2e/stand_alone_api_test.go | 2 +- testing/e2e/stand_alone_container_test.go | 5 +- testing/e2e/stand_alone_test.go | 2 +- testing/e2e/statusProxy.go | 2 - 14 files changed, 196 insertions(+), 40 deletions(-) create mode 100644 testing/e2e/fips_test.go diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 3ff711bd6..175340c08 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -127,6 +127,23 @@ steps: branches: "main" debug: true + - label: "FIPS E2E Test" + key: "fips-e2e-test" + env: + FIPS: true + command: ".buildkite/scripts/e2e_test.sh" + agents: + provider: "gcp" + artifact_paths: + - build/*.xml + - build/e2e-coverage.out + plugins: + - test-collector#v1.10.2: + files: "build/test-*.xml" + format: "junit" + branches: "main" + debug: true + - label: ":junit: Junit annotate" plugins: - junit-annotate#v2.4.1: diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 69ca82e0e..e7eeeff12 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -10,6 +10,7 @@ permissions: contents: read # Optional: allow read access to pull request. Use with `only-new-issues` option. pull-requests: read + checks: write jobs: golangci: strategy: @@ -38,7 +39,7 @@ jobs: uses: golangci/golangci-lint-action@v2 with: # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version - version: v1.61.0 + version: v1.64.5 # Give the job more time to execute. # Regarding `--whole-files`, the linter is supposed to support linting of changed a patch only but, @@ -49,8 +50,5 @@ jobs: # into fixing all linting issues in the whole file instead. args: --timeout=30m --whole-files - # Optional: if set to true then the action will use pre-installed Go. - skip-go-installation: true - # Optional: show only new issues if it's a pull request. The default value is `false`. only-new-issues: true diff --git a/.golangci.yml b/.golangci.yml index 23711053e..b1dfcf363 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -2,7 +2,8 @@ run: # timeout for analysis, e.g. 30s, 5m, default is 1m timeout: 1m - build-tags: integration + build-tags: + - integration go: "1.23.6" issues: @@ -52,7 +53,6 @@ linters: - asciicheck # simple linter to check that your code does not contain non-ASCII identifiers - bodyclose # checks whether HTTP response body is closed successfully - durationcheck # check for two durations multiplied together - - exportloopref # checks for pointers to enclosing loop variables - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports - gosec # inspects source code for security problems - importas # enforces consistent import aliases @@ -64,7 +64,8 @@ linters: - asasalint - bidichk - gocheckcompilerdirectives - - tenv + - copyloopvar + - usetesting # all available settings of specific linters @@ -97,7 +98,7 @@ linters-settings: forbid: - fmt.Print.* # too much log noise # Exclude godoc examples from forbidigo checks. Default is true. - exclude_godoc_examples: true + exclude-godoc-examples: true gomoddirectives: # Allow local `replace` directives. Default is false. @@ -119,8 +120,6 @@ linters-settings: nolintlint: # Enable to ensure that nolint directives are all used. Default is true. allow-unused: false - # Disable to ensure that nolint directives don't have a leading space. Default is true. - allow-leading-space: true # Exclude following linters from requiring an explanation. Default is []. allow-no-explanation: [] # Enable to require an explanation of nonzero length after each nolint directive. Default is false. diff --git a/Dockerfile.fips b/Dockerfile.fips index be39e9d4e..fdaa7de4a 100644 --- a/Dockerfile.fips +++ b/Dockerfile.fips @@ -27,19 +27,19 @@ ARG TARGETPLATFORM RUN FIPS=true CGO_ENABLED=1 GCFLAGS="${GCFLAGS}" LDFLAGS="${LDFLAGS}" DEV="${DEV}" make release-${TARGETPLATFORM} -FROM docker.elastic.co/wolfi/glibc-openssl-fips:latest +FROM docker.elastic.co/wolfi/chainguard-base-fips:latest ARG VERSION ARG TARGETOS ARG TARGETARCH -RUN groupadd --gid 1000 fleet-server && \ - useradd -M --uid 1000 --gid 1000 fleet-server +RUN addgroup --gid 1000 fleet-server && \ + adduser -H -D -u 1000 -G fleet-server fleet-server USER fleet-server COPY --chown=fleet-server:fleet-server --chmod=644 fleet-server.yml /etc/fleet-server.yml -COPY --chown=fleet-server:fleet-server --chmod=755 --from=builder /usr/src/fleet-server/build/binaries/fleet-server-${VERSION}-${TARGETOS:-linux}-*/fleet-server /usr/bin/fleet-server +COPY --chown=fleet-server:fleet-server --chmod=555 --from=builder /go/src/github.com/elastic/fleet-server/build/binaries/fleet-server-${VERSION}-${TARGETOS:-linux}-*-fips/fleet-server /usr/bin/fleet-server ENV GOFIPS=1 -CMD /usr/bin/fleet-server -c /etc/fleet-server.yml +CMD [ "/usr/bin/fleet-server", "-c", "/etc/fleet-server.yml" ] diff --git a/Makefile b/Makefile index 388a7fac6..99b72029e 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,11 @@ +# Makefile for fleet-server +# Many of the targets can change behaviour based on the following flags: +# - SNAPSHOT - true/false (default false); Make a SNAPSHOT build; fleet-server will allow agents on the next minor version to connect +# - DEV - true/false (default false); Make a dev build, compiler inlining and optimizations are disabled and the symbols table is kept +# - FIPS - true/false (default false); Make a FIPS build. +# +# Additionally the PLATFORMS env var can be used to deterimine outputs for specific targets, such as release. + SHELL=/usr/bin/env bash GO_VERSION=$(shell cat '.go-version') DEFAULT_VERSION=$(shell awk '/const DefaultVersion/{print $$NF}' version/version.go | tr -d '"') @@ -11,6 +19,7 @@ BUILDMODE_darwin_amd64=-buildmode=pie BUILDMODE_darwin_arm64=-buildmode=pie CROSSBUILD_SUFFIX=main-debian11 +STANDALONE_DOCKERFILE=Dockerfile BUILDER_IMAGE=fleet-server-builder:${GO_VERSION} #Benchmark related targets @@ -32,14 +41,29 @@ ifdef VERSION_QUALIFIER DEFAULT_VERSION:=${DEFAULT_VERSION}-${VERSION_QUALIFIER} endif +# gobuildtags is an intermediate variable that is used to properly assemble GOBUILDTAGS, a comma seperated list of tags to use with go build +gobuildtags= ifeq ($(SNAPSHOT),true) VERSION=${DEFAULT_VERSION}-SNAPSHOT +gobuildtags=snapshot else VERSION=${DEFAULT_VERSION} endif DOCKER_PLATFORMS ?= linux/amd64 linux/arm64 +# defing the docker image tag used for stand-alone fleet-server images +# only want to define the tag if none is specified, this allows an invocation like +# FIPS=true make test-e2e +# to use a tag like X.Y.Z-fips and not X.Y.Z-fips-fips as the test-e2e target calls into make +ifndef DOCKER_IMAGE_TAG DOCKER_IMAGE_TAG?=${VERSION} +ifeq "${DEV}" "true" +DOCKER_IMAGE_TAG:=${DOCKER_IMAGE_TAG}-dev +endif +ifeq "${FIPS}" "true" +DOCKER_IMAGE_TAG:=${DOCKER_IMAGE_TAG}-fips +endif +endif DOCKER_IMAGE?=docker.elastic.co/fleet-server/fleet-server PLATFORM_TARGETS=$(addprefix release-, $(PLATFORMS)) @@ -64,11 +88,24 @@ OS_NAME:=$(shell uname -s) # Set FIPS=true to force FIPS compliance when building FIPS?= +# NOTE: We are assuming that the only GOEXPIREMENT flag will be associated with FIPS +GOFIPSEXPERIMENT?= +FIPSSUFFIX= ifeq "${FIPS}" "true" BUILDER_IMAGE=fleet-server-fips-builder:${GO_VERSION} +STANDALONE_DOCKERFILE=Dockerfile.fips PLATFORMS = linux/amd64 linux/arm64 +gobuildtags += requirefips +GOFIPSEXPERIMENT=GOEXPERIMENT=systemcrypto +FIPSSUFFIX=-fips endif +# Assemble GOBUILDTAGS with some Makefile trickery as we need to avoid sending multiple -tags flags +# the character of a comma needs a variable so it can be used as a value in a subst call +comma=, +# transform the space-seperated values in gobuildtags to a comma seperated string +GOBUILDTAGS=$(subst $() $(),$(comma),$(gobuildtags)) + .EXPORT_ALL_VARIABLES: FIPS=${FIPS} @@ -100,7 +137,7 @@ list-platforms: ## - Show the possible PLATFORMS .PHONY: local local: ## - Build local binary for local environment (bin/fleet-server) @printf "${CMD_COLOR_ON} Build binaries using local go installation\n${CMD_COLOR_OFF}" - $(if $(FIPS),GOEXPERIMENT=systemcrypto) go build $(if $(SNAPSHOT),-tags="snapshot",) $(if $(FIPS),-tags="requirefips",) -gcflags="${GCFLAGS}" -ldflags="${LDFLAGS}" -o ./bin/fleet-server . + ${GOFIPSEXPERIMENT} go build -tags=${GOBUILDTAGS} -gcflags="${GCFLAGS}" -ldflags="${LDFLAGS}" -o ./bin/fleet-server . @printf "${CMD_COLOR_ON} Binaries in ./bin/\n${CMD_COLOR_OFF}" .PHONY: $(COVER_TARGETS) @@ -110,7 +147,7 @@ $(COVER_TARGETS): cover-%: ## - Build a binary with the -cover flag for integrat $(eval $@_GO_ARCH := $(lastword $(subst /, ,$(lastword $(subst cover-, ,$@))))) $(eval $@_ARCH := $(TARGET_ARCH_$($@_GO_ARCH))) $(eval $@_BUILDMODE:= $(BUILDMODE_$($@_OS)_$($@_GO_ARCH))) - GOOS=$($@_OS) GOARCH=$($@_GO_ARCH) $(if $(FIPS),GOEXPERIMENT=systemcrypto) go build $(if $(SNAPSHOT),-tags="snapshot",) $(if $(FIPS),-tags="requirefips",) -cover -coverpkg=./... -gcflags="${GCFLAGS}" -ldflags="${LDFLAGS}" $($@_BUILDMODE) -o build/cover/fleet-server-$(VERSION)-$($@_OS)-$($@_ARCH)/fleet-server$(if $(filter windows,$($@_OS)),.exe,) . + GOOS=$($@_OS) GOARCH=$($@_GO_ARCH) ${GOFIPSEXPERIMENT} go build -tags=${GOBUILDTAGS} -cover -coverpkg=./... -gcflags="${GCFLAGS}" -ldflags="${LDFLAGS}" $($@_BUILDMODE) -o build/cover/fleet-server-$(VERSION)-$($@_OS)-$($@_ARCH)$(FIPSSUFFIX)/fleet-server$(if $(filter windows,$($@_OS)),.exe,) . .PHONY: clean clean: ## - Clean up build artifacts @@ -146,7 +183,7 @@ check-headers: ## - Check copyright headers .PHONY: check-go check-go: ## - Run golangci-lint - @curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/d58dbde584c801091e74a00940e11ff18c6c68bd/install.sh | sh -s v1.61.0 + @curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/d58dbde584c801091e74a00940e11ff18c6c68bd/install.sh | sh -s v1.64.5 @./bin/golangci-lint run -v .PHONY: notice @@ -185,11 +222,11 @@ test-release: ## - Check that all release binaries are created .PHONY: test-unit test-unit: prepare-test-context ## - Run unit tests only - set -o pipefail; go test ${GO_TEST_FLAG} $(if $(FIPS),-tags="requirefips",) -v -race -coverprofile=build/coverage-${OS_NAME}.out ./... | tee build/test-unit-${OS_NAME}.out + set -o pipefail; go test ${GO_TEST_FLAG} -tags=$(GOBUILDTAGS) -v -race -coverprofile=build/coverage-${OS_NAME}.out ./... | tee build/test-unit-${OS_NAME}.out .PHONY: benchmark benchmark: prepare-test-context install-benchstat ## - Run benchmark tests only - set -o pipefail; go test -bench=$(BENCHMARK_FILTER) $(if $(FIPS),-tags="requirefips",) -run=$(BENCHMARK_FILTER) $(BENCHMARK_ARGS) $(BENCHMARK_PACKAGE) | tee "build/$(BENCH_BASE)" + set -o pipefail; go test -bench=$(BENCHMARK_FILTER) -tags=$(GOBUILDTAGS) -run=$(BENCHMARK_FILTER) $(BENCHMARK_ARGS) $(BENCHMARK_PACKAGE) | tee "build/$(BENCH_BASE)" .PHONY: install-benchstat install-benchstat: ## - Install the benchstat package @@ -225,7 +262,7 @@ $(PLATFORM_TARGETS): release-%: $(eval $@_GO_ARCH := $(lastword $(subst /, ,$(lastword $(subst release-, ,$@))))) $(eval $@_ARCH := $(TARGET_ARCH_$($@_GO_ARCH))) $(eval $@_BUILDMODE:= $(BUILDMODE_$($@_OS)_$($@_GO_ARCH))) - GOOS=$($@_OS) GOARCH=$($@_GO_ARCH) $(if $(FIPS),GOEXPERIMENT=systemcrypto) go build $(if $(SNAPSHOT),-tags="snapshot",) $(if $(FIPS),-tags="requirefips",) -gcflags="${GCFLAGS}" -ldflags="${LDFLAGS}" $($@_BUILDMODE) -o build/binaries/fleet-server-$(VERSION)-$($@_OS)-$($@_ARCH)$(if $(FIPS),-fips,)/fleet-server . + GOOS=$($@_OS) GOARCH=$($@_GO_ARCH) ${GOFIPSEXPERIMENT} go build -tags=${GOBUILDTAGS} -gcflags="${GCFLAGS}" -ldflags="${LDFLAGS}" $($@_BUILDMODE) -o build/binaries/fleet-server-$(VERSION)-$($@_OS)-$($@_ARCH)$(FIPSSUFFIX)/fleet-server . @$(MAKE) OS=$($@_OS) ARCH=$($@_ARCH) package-target .PHONY: build-docker @@ -237,7 +274,8 @@ build-docker: --build-arg=DEV="$(DEV)" \ --build-arg=SNAPSHOT="$(SNAPSHOT)" \ --build-arg=VERSION="$(VERSION)" \ - -t $(DOCKER_IMAGE):$(DOCKER_IMAGE_TAG)$(if $(DEV),-dev,) . + -f $(STANDALONE_DOCKERFILE) \ + -t $(DOCKER_IMAGE):$(DOCKER_IMAGE_TAG) . .PHONY: build-and-push-docker build-and-push-docker: @@ -250,12 +288,12 @@ build-and-push-docker: --build-arg=DEV="$(DEV)" \ --build-arg=SNAPSHOT="$(SNAPSHOT)" \ --build-arg=VERSION="$(VERSION)" \ - -t $(DOCKER_IMAGE):$(DOCKER_IMAGE_TAG)$(if $(DEV),-dev,) . + -t $(DOCKER_IMAGE):$(DOCKER_IMAGE_TAG) . .PHONY: release-docker release-docker: docker push \ - $(DOCKER_IMAGE):$(DOCKER_IMAGE_TAG)$(if $(DEV),-dev,) + $(DOCKER_IMAGE):$(DOCKER_IMAGE_TAG) .PHONY: package-target package-target: build/distributions @@ -268,8 +306,8 @@ else ifeq ($(OS)-$(ARCH),darwin-arm64) @tar -C build/binaries -zcf build/distributions/fleet-server-$(VERSION)-$(OS)-aarch64.tar.gz fleet-server-$(VERSION)-$(OS)-aarch64 @cd build/distributions && sha512sum fleet-server-$(VERSION)-$(OS)-aarch64.tar.gz > fleet-server-$(VERSION)-$(OS)-aarch64.tar.gz.sha512 else - @tar -C build/binaries -zcf build/distributions/fleet-server-$(VERSION)-$(OS)-$(ARCH)$(if $(FIPS),-fips,).tar.gz fleet-server-$(VERSION)-$(OS)-$(ARCH)$(if $(FIPS),-fips,) - @cd build/distributions && sha512sum fleet-server-$(VERSION)-$(OS)-$(ARCH)$(if $(FIPS),-fips,).tar.gz > fleet-server-$(VERSION)-$(OS)-$(ARCH)$(if $(FIPS),-fips,).tar.gz.sha512 + @tar -C build/binaries -zcf build/distributions/fleet-server-$(VERSION)-$(OS)-$(ARCH)$(FIPSSUFFIX).tar.gz fleet-server-$(VERSION)-$(OS)-$(ARCH)$(FIPSSUFFIX) + @cd build/distributions && sha512sum fleet-server-$(VERSION)-$(OS)-$(ARCH)$(FIPSSUFFIX).tar.gz > fleet-server-$(VERSION)-$(OS)-$(ARCH)$(FIPSSUFFIX).tar.gz.sha512 endif build-releaser: ## - Build a Docker image to run make package including all build tools @@ -290,8 +328,13 @@ docker-release: build-releaser ## - Builds a release for all platforms in a dock .PHONY: docker-cover-e2e-binaries docker-cover-e2e-binaries: build-releaser +ifeq "${FIPS}" "true" + ## non-linux is currently unsupported for FIPS + docker run --rm -u $(shell id -u):$(shell id -g) --volume $(PWD):/go/src/github.com/elastic/fleet-server -e SNAPSHOT=true -e DEV=$(DEV) -e FIPS=$(FIPS) $(BUILDER_IMAGE) cover-linux/$(shell go env GOARCH) +else ## Build for local architecture and for linux/$ARCH for docker images. - docker run --rm -u $(shell id -u):$(shell id -g) --volume $(PWD):/go/src/github.com/elastic/fleet-server -e SNAPSHOT=true $(if $(FIPS),-e FIPS=true) $(BUILDER_IMAGE) cover-linux/$(shell go env GOARCH) cover-$(shell go env GOOS)/$(shell go env GOARCH) + docker run --rm -u $(shell id -u):$(shell id -g) --volume $(PWD):/go/src/github.com/elastic/fleet-server -e SNAPSHOT=true -e DEV=$(DEV) -e FIPS=$(FIPS) $(BUILDER_IMAGE) cover-linux/$(shell go env GOARCH) cover-$(shell go env GOOS)/$(shell go env GOARCH) +endif .PHONY: release release: $(PLATFORM_TARGETS) ## - Builds a release. Specify exact platform with PLATFORMS env. @@ -370,7 +413,7 @@ test-int-set: ## - Run integration tests without setup .PHONY: build-e2e-agent-image build-e2e-agent-image: docker-cover-e2e-binaries ## - Build a custom elastic-agent image with fleet-server binaries with coverage enabled injected @printf "${CMD_COLOR_ON} Creating test e2e agent image\n${CMD_COLOR_OFF}" - FLEET_VERSION=${DEFAULT_VERSION}-SNAPSHOT ./dev-tools/e2e/build.sh # force fleet version to be equal to VERSION-SNAPSHOT + FIPS=${FIPS} FLEET_VERSION=${DEFAULT_VERSION}-SNAPSHOT ./dev-tools/e2e/build.sh # force fleet version to be equal to VERSION-SNAPSHOT .PHONY: e2e-certs e2e-certs: ## - Use openssl to create a CA, encrypted private key, and signed fleet-server cert testing purposes @@ -404,9 +447,9 @@ test-e2e-set: ## - Run the blackbox end to end tests without setup. ELASTICSEARCH_SERVICE_TOKEN=$(shell ./dev-tools/integration/get-elasticsearch-servicetoken.sh ${ELASTICSEARCH_USERNAME}:${ELASTICSEARCH_PASSWORD}@${TEST_ELASTICSEARCH_HOSTS} "fleet-server") \ ELASTICSEARCH_HOSTS=${TEST_ELASTICSEARCH_HOSTS} ELASTICSEARCH_USERNAME=${ELASTICSEARCH_USERNAME} ELASTICSEARCH_PASSWORD=${ELASTICSEARCH_PASSWORD} \ AGENT_E2E_IMAGE=$(shell cat "build/e2e-image") \ - STANDALONE_E2E_IMAGE=$(DOCKER_IMAGE):$(DOCKER_IMAGE_TAG)$(if $(DEV),-dev,) \ + STANDALONE_E2E_IMAGE=$(DOCKER_IMAGE):$(DOCKER_IMAGE_TAG) \ CGO_ENABLED=1 \ - go test -v -timeout 30m -tags=e2e -count=1 -race -p 1 ./... + go test -v -timeout 30m -tags=e2e,$(GOBUILDTAGS) -count=1 -race -p 1 ./... ################################################## # Cloud testing targets diff --git a/dev-tools/e2e/Dockerfile b/dev-tools/e2e/Dockerfile index e92156b43..0b7436dda 100644 --- a/dev-tools/e2e/Dockerfile +++ b/dev-tools/e2e/Dockerfile @@ -2,14 +2,16 @@ ARG ELASTIC_AGENT_IMAGE # e.g. docker.elastic.co/cloud-release/elastic-agent-clo FROM --platform=linux/amd64 ${ELASTIC_AGENT_IMAGE} as elastic_agent_amd64 ARG STACK_VERSION # e.g. 8.5.0-SNAPSHOT +ARG FLEET_SUFFIX # e.g. -linux-x86_64 ARG VCS_REF_SHORT # e.g. abc123 -ONBUILD COPY --chmod=0755 --chown=elastic-agent cover/fleet-server-${STACK_VERSION}-linux-x86_64/fleet-server \ +ONBUILD COPY --chmod=0755 --chown=elastic-agent cover/fleet-server-${STACK_VERSION}${FLEET_SUFFIX}/fleet-server \ ./data/elastic-agent-${VCS_REF_SHORT}/components/fleet-server FROM --platform=linux/arm64 ${ELASTIC_AGENT_IMAGE} as elastic_agent_arm64 ARG STACK_VERSION # e.g. 8.5.0-SNAPSHOT +ARG FLEET_SUFFIX # e.g. -linux-x86_64 ARG VCS_REF_SHORT # e.g. abc123 -ONBUILD COPY --chmod=0755 --chown=elastic-agent cover/fleet-server-${STACK_VERSION}-linux-arm64/fleet-server \ +ONBUILD COPY --chmod=0755 --chown=elastic-agent cover/fleet-server-${STACK_VERSION}${FLEET_SUFFIX}/fleet-server \ ./data/elastic-agent-${VCS_REF_SHORT}/components/fleet-server FROM elastic_agent_${TARGETARCH} diff --git a/dev-tools/e2e/build.sh b/dev-tools/e2e/build.sh index 1642e24ad..64d6babb7 100755 --- a/dev-tools/e2e/build.sh +++ b/dev-tools/e2e/build.sh @@ -24,10 +24,19 @@ VCS_REF=$(docker inspect -f '{{index .Config.Labels "org.label-schema.vcs-ref"}} CUSTOM_IMAGE_TAG=${STACK_VERSION}-e2e-${COMMIT}-$(date +%s) +FLEET_SUFFIX="-linux-x86_64" +if [[ "$GOARCH" == "arm64" ]]; then + FLEET_SUFFIX="-linux-arm64" +fi +if [[ "$FIPS" == "true" ]]; then + FLEET_SUFFIX="${FLEET_SUFFIX}-fips" +fi + docker build \ -f $REPO_ROOT/dev-tools/e2e/Dockerfile \ --build-arg ELASTIC_AGENT_IMAGE=$BASE_IMAGE \ --build-arg STACK_VERSION=${FLEET_VERSION} \ + --build-arg FLEET_SUFFIX=${FLEET_SUFFIX} \ --build-arg VCS_REF_SHORT=${VCS_REF:0:6} \ --platform linux/$GOARCH \ -t ${CI_ELASTIC_AGENT_DOCKER_IMAGE}:${CUSTOM_IMAGE_TAG} \ diff --git a/testing/e2e/agent_container_test.go b/testing/e2e/agent_container_test.go index 4a1952295..724b4709f 100644 --- a/testing/e2e/agent_container_test.go +++ b/testing/e2e/agent_container_test.go @@ -2,7 +2,7 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -//go:build e2e +//go:build e2e && !requirefips package e2e diff --git a/testing/e2e/agent_install_test.go b/testing/e2e/agent_install_test.go index 44ac9684c..fd5e4a5c1 100644 --- a/testing/e2e/agent_install_test.go +++ b/testing/e2e/agent_install_test.go @@ -2,7 +2,7 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -//go:build e2e +//go:build e2e && !requirefips package e2e diff --git a/testing/e2e/fips_test.go b/testing/e2e/fips_test.go new file mode 100644 index 000000000..993fe7f59 --- /dev/null +++ b/testing/e2e/fips_test.go @@ -0,0 +1,89 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +//go:build e2e && requirefips + +package e2e + +import ( + "context" + "debug/buildinfo" + "fmt" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/elastic/fleet-server/testing/e2e/scaffold" + "github.com/elastic/fleet-server/v7/version" +) + +type FIPSStandAlone struct { + scaffold.Scaffold + + binaryPath string +} + +func TestFIPSStandAlone(t *testing.T) { + suite.Run(t, new(FIPSStandAlone)) +} + +func (suite *FIPSStandAlone) SetupSuite() { + arch := runtime.GOARCH + if arch == "amd64" { + arch = "x86_64" + } + // NOTE the path checked is hardcoded to linux as we currently only support linux for FIPS builds + path, err := filepath.Abs(filepath.Join("..", "..", "build", "cover", fmt.Sprintf("fleet-server-%s-SNAPSHOT-linux-%s-fips", version.DefaultVersion, arch), binaryName)) + suite.Require().NoError(err) + suite.binaryPath = path + _, err = os.Stat(suite.binaryPath) + suite.Require().NoError(err) + + suite.Setup() // base setup +} + +// TestVerifyArtifact verifies the artifact has FIPS indicators. +func (suite *FIPSStandAlone) TestVerifyArtifact() { + info, err := buildinfo.ReadFile(suite.binaryPath) + suite.Require().NoError(err) + + checkLinks := false + foundTags := false + foundExperiment := false + for _, setting := range info.Settings { + switch setting.Key { + case "-tags": + foundTags = true + suite.Require().Contains(setting.Value, "requirefips") + continue + case "GOEXPERIMENT": + foundExperiment = true + suite.Require().Contains(setting.Value, "systemcrypto") + continue + case "-ldflags": + if !strings.Contains(setting.Value, "-s") { + checkLinks = true + continue + } + } + } + + suite.Require().True(foundTags, "Did not find -tags within binary description") + suite.Require().True(foundExperiment, "Did not find GOEXPERIMENT within binary description") + + if checkLinks { + suite.T().Log("checking artifact symbols") + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + cmd := exec.CommandContext(ctx, "go", "tool", "nm", suite.binaryPath) // TODO replace ctx with suite.T().Context() once we upgrade to go 1.24 + output, err := cmd.CombinedOutput() + suite.Require().NoError(err) + suite.Require().Contains(string(output), "OpenSSL_version", "Unable to find OpenSSL symbol links within binary") + } +} diff --git a/testing/e2e/stand_alone_api_test.go b/testing/e2e/stand_alone_api_test.go index 322d4d8ff..06567814c 100644 --- a/testing/e2e/stand_alone_api_test.go +++ b/testing/e2e/stand_alone_api_test.go @@ -2,7 +2,7 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -//go:build e2e +//go:build e2e && !requirefips package e2e diff --git a/testing/e2e/stand_alone_container_test.go b/testing/e2e/stand_alone_container_test.go index 43a79dc80..196c3b544 100644 --- a/testing/e2e/stand_alone_container_test.go +++ b/testing/e2e/stand_alone_container_test.go @@ -2,7 +2,7 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -//go:build e2e +//go:build e2e && !requirefips package e2e @@ -19,9 +19,10 @@ import ( toxiproxy "github.com/Shopify/toxiproxy/client" "github.com/docker/docker/api/types/container" - "github.com/elastic/elastic-agent-client/v7/pkg/client" "github.com/stretchr/testify/suite" "github.com/testcontainers/testcontainers-go" + + "github.com/elastic/elastic-agent-client/v7/pkg/client" ) type StandAloneContainerSuite struct { diff --git a/testing/e2e/stand_alone_test.go b/testing/e2e/stand_alone_test.go index 2b471b64d..40999d228 100644 --- a/testing/e2e/stand_alone_test.go +++ b/testing/e2e/stand_alone_test.go @@ -2,7 +2,7 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -//go:build e2e +//go:build e2e && !requirefips package e2e diff --git a/testing/e2e/statusProxy.go b/testing/e2e/statusProxy.go index e348fc1e5..2ab942415 100644 --- a/testing/e2e/statusProxy.go +++ b/testing/e2e/statusProxy.go @@ -2,8 +2,6 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -//go:build e2e - package e2e import (