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 asDockerfile.build.ubi), appendingGOFIPS140=${GO_FIPS140_MODULE_VERSION}to$GOROOT/go.env. Since every Go component build doesCOPY --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_TAG→GO_FIPS140_MODULE_VERSION: "v1.0.0"(single-variable bump tov1.26.0when its validation completes).build-scripts/build.sh: dropEXTRA_EXPERIMENT_FLAGS="boringcrypto"injection and theGO_VERSION=${GO_FIPS_VERSION}override (one Go version everywhere).build-scripts/container_versions.sh: module version participates inget_go_version()hash so a module-only bump rebuilds all dependents.gitlab-pages/Dockerfile.build.ubi: remove the (only)GOEXPERIMENTpass-through.gitlab-base/scripts/entrypoint.sh: keeps exportingGOLANG_FIPS=1(read only by legacy golang-fips binaries; inert for the native module — preserves rollback) and deliberately sets nofips140GODEBUG: native binaries are alreadyfips140=onvia the bakedGOFIPS140default, anyGODEBUG=fips140=*value is fatal at init to golang-fips binaries, andfips140=onlyis documented by Go as a testing mode not for production (crashes by design, e.g.crypto/md5in S3 ETag paths).onlyescalation 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-goFIPS image: assertions pass; probe binary recordsbuild GOFIPS140=v1.0.0-c2097c7c(the exact snapshot named in cert #5247). - Green
fips_pipeline(manual job inpreparestage) - Spot-check FIPS images:
go version -mshowsGOFIPS140=v1.0.0-…;go tool nm | grep -ci goboringcrypto→ 0 -
rpm-verify-fipscomponent jobs stay green
Related issues
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)
Related to #2361