Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,56 @@ jobs:
exit 1
fi

# Go picks its cryptographic module at build time via GOFIPS140, so the module
# a binary uses is a property of the build and not of the code. The regular
# test job builds without it, which leaves the FIPS module unexercised: FIPS
# mode narrows the cipher suites the TLS client offers, and nothing else here
# would notice if that broke a handshake or a hashing call. Build the CLI with
# the validated module and run the acceptance suite against it.
#
# Linux only: the module is platform-independent, so a second OS would spend
# the wall-clock time to re-test the same crypto.
test-fips:
needs:
- cleanups
- testmask

if: ${{ contains(fromJSON(needs.testmask.outputs.targets), 'test') }}
name: "task test (linux, fips)"
runs-on:
group: databricks-protected-runner-group-large
labels: linux-ubuntu-latest-large

defaults:
run:
shell: bash

permissions:
id-token: write
contents: read

steps:
- name: Checkout repository and submodules
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Setup build environment
uses: ./.github/actions/setup-build-environment
with:
cache-key: test-fips

- name: Run tests
env:
# Pinned to a frozen module version that has completed CMVP validation.
# "latest" also enables FIPS mode, but tracks the in-tree source and so
# moves with every Go release, leaving no fixed artifact to cite.
GOFIPS140: v1.0.0
ENVFILTER: DATABRICKS_BUNDLE_ENGINE=direct
run: go tool -modfile=tools/task/go.mod task test

- name: Summarize failed tests
if: ${{ failure() }}
run: uv run tools/summarize_failed_tests.py test-output.json | tee -a "$GITHUB_STEP_SUMMARY"

test-exp-aitools:
needs:
- cleanups
Expand Down
53 changes: 53 additions & 0 deletions acceptance/fips_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package acceptance_test

import (
"os"
"os/exec"
"runtime"
"testing"

"github.com/stretchr/testify/require"
)

// approvedFIPSModule is the frozen Go Cryptographic Module version that has
// completed CMVP validation. GOFIPS140=latest also enables FIPS mode, but tracks
// the in-tree source and moves with every Go release, so it leaves no fixed
// artifact to cite; only a frozen version is accepted here.
const approvedFIPSModule = "v1.0.0"

// TestCLIBuiltWithFIPSModule asserts that the binary the acceptance suite just
// exercised really was built against the validated module.
//
// Without this, the FIPS CI job would still pass if GOFIPS140 silently stopped
// reaching the compiler -- the suite would run happily against an ordinary
// build and report that FIPS "works". The setting is only observable in the
// binary's own build info, so read it back from there.
//
// Skipped unless GOFIPS140 is set, so the default build is unaffected.
func TestCLIBuiltWithFIPSModule(t *testing.T) {
if os.Getenv("GOFIPS140") == "" {
t.Skip("not a FIPS build")
}

cwd, err := os.Getwd()
require.NoError(t, err)

execPath := BuildCLI(t, getBuildDir(t, cwd, runtime.GOOS, runtime.GOARCH), "", runtime.GOOS, runtime.GOARCH)

out, err := exec.Command("go", "version", "-m", execPath).Output()
require.NoError(t, err)
buildInfo := string(out)

// The stamped value carries a hash suffix (v1.0.0-<hash>) that moves with the
// toolchain, so match the version prefix rather than the whole string.
require.Contains(t, buildInfo, "GOFIPS140="+approvedFIPSModule,
"binary was not built against the approved FIPS module")

// GOFIPS140 links the module and defaults FIPS mode on. Both matter: a binary
// that links the module but leaves the mode off behaves like a plain build.
require.Contains(t, buildInfo, "DefaultGODEBUG=fips140=on",
"FIPS module is linked but FIPS mode is not enabled by default")

require.NotContains(t, buildInfo, "GOFIPS140=latest",
"binary was built with an unvalidated module version")
}
Loading