Use Go's native FIPS 140-3 module for FIPS builds

What does this MR do?

Replaces the golang-fips toolchain (OpenSSL via CGO, activated through the repurposed GOEXPERIMENT=boringcrypto) with upstream Go's native Go Cryptographic Module, selected via GOFIPS140.

Module v1.0.0 — shipped in lib/fips140/ of the Go distribution (including go1.26.4) — holds full CMVP certification (#5247) as of 2026-04-27, satisfying FedRAMP. Upstream golang-fips intends to sunset its OpenSSL patches now that this certification exists.

Changes

  • gitlab-go/Dockerfile.build.fips: rewritten to use the official GPG-verified binary distribution (same flow as Dockerfile.build.ubi), appending GOFIPS140=${GO_FIPS140_MODULE_VERSION} to $GOROOT/go.env. Since every Go component build does COPY --from=build_gitlab-go /assets /, the module selection is inherited everywhere with zero per-component configuration — including components that pass no FIPS knobs today (container-registry, elasticsearch-indexer). Build-time assertions fail loudly if the module snapshot is missing, not the default, or not recorded in built binaries.
  • ci_files/variables.yml: GO_FIPS_VERSION/GO_FIPS_TAGGO_FIPS140_MODULE_VERSION: "v1.0.0" (single-variable bump to v1.26.0 when its validation completes).
  • build-scripts/build.sh: drop EXTRA_EXPERIMENT_FLAGS="boringcrypto" injection and the GO_VERSION=${GO_FIPS_VERSION} override (one Go version everywhere).
  • build-scripts/container_versions.sh: module version participates in get_go_version() hash so a module-only bump rebuilds all dependents.
  • gitlab-pages/Dockerfile.build.ubi: remove the (only) GOEXPERIMENT pass-through.
  • gitlab-base/scripts/entrypoint.sh: keeps exporting GOLANG_FIPS=1 (read only by legacy golang-fips binaries; inert for the native module — preserves rollback) and deliberately sets no fips140 GODEBUG: native binaries are already fips140=on via the baked GOFIPS140 default, any GODEBUG=fips140=* value is fatal at init to golang-fips binaries, and fips140=only is documented by Go as a testing mode not for production (crashes by design, e.g. crypto/md5 in S3 ETag paths). only escalation is deferred to a QA-backed follow-up. OpenSSL/GnuTLS/gcrypt enforcement is untouched (non-Go binaries still need it).

Note: cmd/go refuses GOFIPS140 combined with GOEXPERIMENT=boringcrypto, so any upstream component Makefile still setting boringcrypto under FIPS_MODE=1 will fail its build visibly in this pipeline — that is the audit mechanism for the coordination tail.

Verification

  • Local build of the new gitlab-go FIPS image: assertions pass; probe binary records build GOFIPS140=v1.0.0-c2097c7c (the exact snapshot named in cert #5247).
  • Green fips_pipeline (manual job in prepare stage)
  • Spot-check FIPS images: go version -m shows GOFIPS140=v1.0.0-…; go tool nm | grep -ci goboringcrypto → 0
  • rpm-verify-fips component jobs stay green

Relates to gitlab-org/distribution/team-tasks#1706

Checklist

See Definition of done.

Required

  • Merge Request Title, and Description are up to date, accurate, and descriptive
  • MR targeting the appropriate branch
  • MR has a green pipeline on GitLab.com
  • When ready for review, MR is labeled "~workflow::ready for review" per the Distribution MR workflow

Expected (please provide an explanation if not completing)

  • Test plan indicating conditions for success has been posted and passes
  • Documentation created/updated
  • Integration tests added to GitLab QA
  • The impact any change in container size has should be evaluated (gitlab-go FIPS asset image shrinks: no compiler toolchain, no golang-fips source tree)
  • New dependencies are managed with GitLab forked renovatebot (GO_FIPS_VERSION/GO_FIPS_TAG renovate rules need retiring — coordination item)

🤖 Generated with Claude Code

Related to #2361

Edited by Jason Plum

Merge request reports

Loading
Loading