diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 52f94ec71c..8eef629401 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -64,7 +64,7 @@ jobs: build: needs: [get-go-version, get-product-version] - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 # the GLIBC is too high on 22.04 strategy: matrix: include: @@ -79,20 +79,28 @@ jobs: - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "amd64", component: "cli", pkg_name: "consul-k8s", "bin_name": "consul-k8s.exe" } - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "darwin", goarch: "amd64", component: "cli", pkg_name: "consul-k8s", "bin_name": "consul-k8s" } - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "darwin", goarch: "arm64", component: "cli", pkg_name: "consul-k8s", "bin_name": "consul-k8s" } - # control-plane + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "amd64", component: "cli", pkg_name: "consul-k8s", "bin_name": "consul-k8s", gotags: "fips", env: "CGO_ENABLED=1 GOEXPERIMENT=boringcrypto", fips: ".fips1402" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "arm64", component: "cli", pkg_name: "consul-k8s", "bin_name": "consul-k8s", gotags: "fips", env: "CGO_ENABLED=1 GOEXPERIMENT=boringcrypto CC=aarch64-linux-gnu-gcc", fips: ".fips1402" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "amd64", component: "cli", pkg_name: "consul-k8s", "bin_name": "consul-k8s.exe", gotags: "fips", env: "CGO_ENABLED=1 GOEXPERIMENT=cngcrypto", fips: ".fips1402" } + + # control-plane - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "freebsd", goarch: "386", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "freebsd", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "386", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "arm", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "arm64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } - # solaris is only built for the control plane + # solaris is only built for the control plane - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "solaris", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "386", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane.exe" } - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane.exe" } - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "darwin", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "darwin", goarch: "arm64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } - # consul-cni + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane", gotags: "fips", env: "CGO_ENABLED=1 GOEXPERIMENT=boringcrypto", fips: ".fips1402" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "arm64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane", gotags: "fips", env: "CGO_ENABLED=1 GOEXPERIMENT=boringcrypto CC=aarch64-linux-gnu-gcc", fips: ".fips1402" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane.exe", gotags: "fips", env: "CGO_ENABLED=1 GOEXPERIMENT=cngcrypto", fips: ".fips1402" } + + # consul-cni - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "freebsd", goarch: "386", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni" } - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "freebsd", goarch: "amd64", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni" } - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "386", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni" } @@ -104,10 +112,14 @@ jobs: - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "amd64", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni.exe" } - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "darwin", goarch: "amd64", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni" } - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "darwin", goarch: "arm64", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "amd64", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni", gotags: "fips", env: "CGO_ENABLED=1 GOEXPERIMENT=boringcrypto", fips: ".fips1402" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "arm64", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni", gotags: "fips", env: "CGO_ENABLED=1 GOEXPERIMENT=boringcrypto CC=aarch64-linux-gnu-gcc", fips: ".fips1402" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "amd64", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni.exe", gotags: "fips", env: "CGO_ENABLED=1 GOEXPERIMENT=cngcrypto", fips: ".fips1402" } + fail-fast: true - name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} ${{ matrix.component }} build + name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} ${{ matrix.component }} ${{ matrix.fips }} build steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 @@ -116,6 +128,25 @@ jobs: with: go-version: ${{ matrix.go }} + - name: Replace Go for Windows FIPS with Microsoft Go + if: ${{ matrix.fips == '.fips1402' && matrix.goos == 'windows' }} + run: | + # Uninstall standard Go and use microsoft/go instead + rm -rf /home/runner/actions-runner/_work/_tool/go + curl https://aka.ms/golang/release/latest/go${{ matrix.go }}-1.linux-amd64.tar.gz -Lo go${{ matrix.go }}.linux-amd64.tar.gz + tar -C $HOME -xf go${{ matrix.go }}.linux-amd64.tar.gz + chmod +x $HOME/go/bin + export PATH=$HOME/go/bin:$PATH + if [ $(which go) != "$HOME/go/bin/go" ]; then + echo "Unable to verify microsoft/go toolchain" + exit 1 + fi + + - name: Install cross-compiler for FIPS on arm + if: ${{ matrix.fips == '.fips1402' && matrix.goarch == 'arm64' }} + run: | + sudo apt-get update --allow-releaseinfo-change-suite --allow-releaseinfo-change-version && sudo apt-get install -y gcc-aarch64-linux-gnu + - name: Build env: GOOS: ${{ matrix.goos }} @@ -130,14 +161,14 @@ jobs: export GIT_IMPORT=github.com/hashicorp/consul-k8s/${{ matrix.component }}/version export GOLDFLAGS="-X ${GIT_IMPORT}.GitCommit=${GIT_COMMIT}${GIT_DIRTY} -X ${GIT_IMPORT}.GitDescribe=${{ needs.get-product-version.outputs.product-version }}" - CGO_ENABLED=0 go build -o dist/${{ matrix.bin_name }} -ldflags "${GOLDFLAGS}" . - zip -r -j out/${{ matrix.pkg_name }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip dist/ + ${{ matrix.env }} go build -o dist/${{ matrix.bin_name }} -ldflags "${GOLDFLAGS}" -tags=${{ matrix.gotags }} . + zip -r -j out/${{ matrix.pkg_name }}_${{ needs.get-product-version.outputs.product-version }}${{ matrix.fips }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip dist/ - name: Upload built binaries uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 with: - name: ${{ matrix.pkg_name }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip - path: ${{ matrix.component}}/out/${{ matrix.pkg_name }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip + name: ${{ matrix.pkg_name }}_${{ needs.get-product-version.outputs.product-version }}${{ matrix.fips }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip + path: ${{ matrix.component}}/out/${{ matrix.pkg_name }}_${{ needs.get-product-version.outputs.product-version }}${{ matrix.fips }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip - name: Package rpm and deb files if: ${{ matrix.goos == 'linux' && matrix.component == 'cli' && matrix.goarch == 'amd64'}} @@ -146,7 +177,7 @@ jobs: name: consul-k8s description: "consul-k8s provides a cli interface to first-class integrations between Consul and Kubernetes." arch: ${{ matrix.goarch }} - version: ${{ needs.get-product-version.outputs.product-version }} + version: ${{ needs.get-product-version.outputs.product-version }}${{ matrix.fips }} maintainer: "HashiCorp" homepage: "https://github.com/hashicorp/consul-k8s" license: "MPL-2.0" @@ -171,7 +202,7 @@ jobs: cd /work rpm -ivh out/${{ env.RPM_PACKAGE }} CONSUL_K8S_VERSION="$(consul-k8s version | awk '{print $2}')" - VERSION="v${{ needs.get-product-version.outputs.product-version }}" + VERSION="v${{ needs.get-product-version.outputs.product-version }}${{ matrix.fips }}" if [ "${VERSION}" != "${CONSUL_K8S_VERSION}" ]; then echo "Test FAILED, expected: ${VERSION}, got: ${CONSUL_K8S_VERSION}" exit 1 @@ -196,7 +227,7 @@ jobs: cd /work apt install ./out/${{ env.DEB_PACKAGE }} CONSUL_K8S_VERSION="$(consul-k8s version | awk '{print $2}')" - VERSION="v${{ needs.get-product-version.outputs.product-version }}" + VERSION="v${{ needs.get-product-version.outputs.product-version }}${{ matrix.fips }}" if [ "${VERSION}" != "${CONSUL_K8S_VERSION}" ]; then echo "Test FAILED, expected: ${VERSION}, got: ${CONSUL_K8S_VERSION}" exit 1 @@ -211,24 +242,30 @@ jobs: path: out/${{ env.DEB_PACKAGE }} build-docker: - name: Docker ${{ matrix.arch }} default release build + name: Docker ${{ matrix.goarch }} ${{ matrix.fips }} default release build needs: [get-product-version, build] runs-on: ubuntu-latest strategy: matrix: - arch: ["arm", "arm64", "386", "amd64"] + include: + - { goos: "linux", goarch: "arm" } + - { goos: "linux", goarch: "arm64" } + - { goos: "linux", goarch: "386" } + - { goos: "linux", goarch: "amd64" } + - { goos: "linux", goarch: "amd64", fips: ".fips1402" } + - { goos: "linux", goarch: "arm64", fips: ".fips1402" } env: repo: ${{ github.event.repository.name }} - version: ${{ needs.get-product-version.outputs.product-version }} + version: ${{ needs.get-product-version.outputs.product-version }}${{ matrix.fips }} steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: - name: consul-cni_${{ needs.get-product-version.outputs.product-version }}_linux_${{ matrix.arch }}.zip - path: control-plane/dist/cni/linux/${{ matrix.arch }} + name: consul-cni_${{ needs.get-product-version.outputs.product-version }}${{ matrix.fips }}_${{ matrix.goos}}_${{ matrix.goarch }}.zip + path: control-plane/dist/cni/${{ matrix.goos}}/${{ matrix.goarch }} - name: extract consul-cni zip env: - ZIP_LOCATION: control-plane/dist/cni/linux/${{ matrix.arch }} + ZIP_LOCATION: control-plane/dist/cni/${{ matrix.goos}}/${{ matrix.goarch }} run: | cd "${ZIP_LOCATION}" unzip -j *.zip @@ -244,7 +281,7 @@ jobs: echo "Test PASSED" version: ${{ env.version }} target: release-default - arch: ${{ matrix.arch }} + arch: ${{ matrix.goarch }} pkg_name: consul-k8s-control-plane_${{ env.version }} bin_name: consul-k8s-control-plane workdir: control-plane @@ -255,20 +292,22 @@ jobs: docker.io/hashicorppreview/${{ env.repo }}-control-plane:${{ env.version }}-${{ github.sha }} build-docker-ubi-redhat-registry: - name: Docker ${{ matrix.arch }} UBI build for RedHat Registry + name: Docker ${{ matrix.arch }} ${{ matrix.fips }} UBI build for RedHat Registry needs: [get-product-version, build] runs-on: ubuntu-latest strategy: matrix: - arch: ["amd64"] + include: + - { arch: "amd64" } + - { arch: "amd64", fips: ".fips1402" } env: repo: ${{ github.event.repository.name }} - version: ${{ needs.get-product-version.outputs.product-version }} + version: ${{ needs.get-product-version.outputs.product-version }}${{ matrix.fips }} steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: - name: consul-cni_${{ needs.get-product-version.outputs.product-version }}_linux_${{ matrix.arch }}.zip + name: consul-cni_${{ needs.get-product-version.outputs.product-version }}${{ matrix.fips }}_linux_${{ matrix.arch }}.zip path: control-plane/dist/cni/linux/${{ matrix.arch }} - name: extract consul-cni zip env: @@ -297,20 +336,21 @@ jobs: redhat_tag: quay.io/redhat-isv-containers/611ca2f89a9b407267837100:${{env.version}}-ubi build-docker-ubi-dockerhub: - name: Docker ${{ matrix.arch }} UBI build for DockerHub + name: Docker ${{ matrix.arch }} ${{ matrix.fips }} UBI build for DockerHub needs: [ get-product-version, build ] runs-on: ubuntu-latest strategy: matrix: arch: [ "amd64" ] + fips: [ ".fips1402", "" ] env: repo: ${{ github.event.repository.name }} - version: ${{ needs.get-product-version.outputs.product-version }} + version: ${{ needs.get-product-version.outputs.product-version }}${{ matrix.fips }} steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: - name: consul-cni_${{ needs.get-product-version.outputs.product-version }}_linux_${{ matrix.arch }}.zip + name: consul-cni_${{ needs.get-product-version.outputs.product-version }}${{ matrix.fips }}_linux_${{ matrix.arch }}.zip path: control-plane/dist/cni/linux/${{ matrix.arch }} - name: extract consul-cni zip env: diff --git a/Makefile b/Makefile index 5adfb55657..628b13e2f9 100644 --- a/Makefile +++ b/Makefile @@ -49,6 +49,17 @@ control-plane-dev-docker-multi-arch: check-remote-dev-image-env ## Build consul- --push \ -f $(CURDIR)/control-plane/Dockerfile $(CURDIR)/control-plane +control-plane-fips-dev-docker: ## Build consul-k8s-control-plane FIPS dev Docker image. + @$(SHELL) $(CURDIR)/control-plane/build-support/scripts/build-local.sh -o linux -a $(GOARCH) --fips + @docker build -t '$(DEV_IMAGE)' \ + --target=dev \ + --build-arg 'TARGETARCH=$(GOARCH)' \ + --build-arg 'GIT_COMMIT=$(GIT_COMMIT)' \ + --build-arg 'GIT_DIRTY=$(GIT_DIRTY)' \ + --build-arg 'GIT_DESCRIBE=$(GIT_DESCRIBE)' \ + --push \ + -f $(CURDIR)/control-plane/Dockerfile $(CURDIR)/control-plane + control-plane-test: ## Run go test for the control plane. cd control-plane; go test ./... @@ -98,6 +109,10 @@ cli-dev: @echo "==> Installing consul-k8s CLI tool for ${GOOS}/${GOARCH}" @cd cli; go build -o ./bin/consul-k8s; cp ./bin/consul-k8s ${GOPATH}/bin/ +cli-fips-dev: + @echo "==> Installing consul-k8s CLI tool for ${GOOS}/${GOARCH}" + @cd cli; CGO_ENABLED=1 GOEXPERIMENT=boringcrypto go build -o ./bin/consul-k8s -tags "fips"; cp ./bin/consul-k8s ${GOPATH}/bin/ + cli-lint: ## Run linter in the control-plane directory. cd cli; golangci-lint run -c ../.golangci.yml diff --git a/cli/version/fips_build.go b/cli/version/fips_build.go new file mode 100644 index 0000000000..4d04cc6539 --- /dev/null +++ b/cli/version/fips_build.go @@ -0,0 +1,27 @@ +//go:build fips + +package version + +// This validates during compilation that we are being built with a FIPS enabled go toolchain +import ( + _ "crypto/tls/fipsonly" + "runtime" + "strings" +) + +// IsFIPS returns true if consul-k8s is operating in FIPS-140-2 mode. +func IsFIPS() bool { + return true +} + +func GetFIPSInfo() string { + str := "Enabled" + // Try to get the crypto module name + gover := strings.Split(runtime.Version(), "X:") + if len(gover) >= 2 { + gover_last := gover[len(gover)-1] + // Able to find crypto module name; add that to status string. + str = "FIPS 140-2 Enabled, crypto module " + gover_last + } + return str +} diff --git a/cli/version/non_fips_build.go b/cli/version/non_fips_build.go new file mode 100644 index 0000000000..f72aecae73 --- /dev/null +++ b/cli/version/non_fips_build.go @@ -0,0 +1,12 @@ +//go:build !fips + +package version + +// IsFIPS returns true if consul-k8s is operating in FIPS-140-2 mode. +func IsFIPS() bool { + return false +} + +func GetFIPSInfo() string { + return "" +} diff --git a/cli/version/version.go b/cli/version/version.go index 81433c0a5f..320600c30b 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -39,8 +39,12 @@ func GetHumanVersion() string { release = "dev" } + if IsFIPS() { + version += ".fips1402" + } + if release != "" { - if !strings.HasSuffix(version, "-"+release) { + if !strings.Contains(version, "-"+release) { // if we tagged a prerelease version then the release is in the version already version += fmt.Sprintf("-%s", release) } diff --git a/control-plane/Dockerfile b/control-plane/Dockerfile index de0c1cf1ff..5b3d73e625 100644 --- a/control-plane/Dockerfile +++ b/control-plane/Dockerfile @@ -92,7 +92,11 @@ LABEL name=${BIN_NAME} \ ENV BIN_NAME=${BIN_NAME} ENV VERSION=${PRODUCT_VERSION} -RUN apk add --no-cache ca-certificates libcap openssl su-exec iputils libc6-compat iptables +RUN apk add --no-cache ca-certificates libcap openssl su-exec iputils gcompat libc6-compat libstdc++ iptables + +# for FIPS CGO glibc compatibility in alpine +# see https://github.com/golang/go/issues/59305 +RUN ln -s /lib/libc.so.6 /usr/lib/libresolv.so.2 # TARGETOS and TARGETARCH are set automatically when --platform is provided. ARG TARGETOS diff --git a/control-plane/build-support/functions/20-build.sh b/control-plane/build-support/functions/20-build.sh index a4f36ee3e4..e9540956c9 100644 --- a/control-plane/build-support/functions/20-build.sh +++ b/control-plane/build-support/functions/20-build.sh @@ -180,7 +180,7 @@ function build_consul_local { # * - error # # Note: - # The GOLDFLAGS and GOTAGS environment variables will be used if set + # The GOLDFLAGS, GOEXPERIMENT, and GOTAGS environment variables will be used if set # If the CONSUL_DEV environment var is truthy only the local platform/architecture is built. # If the XC_OS or the XC_ARCH environment vars are present then only those platforms/architectures # will be built. Otherwise all supported platform/architectures are built @@ -188,6 +188,14 @@ function build_consul_local { # build with go install. # The GOXPARALLEL environment variable is used if set + if [ $GOTAGS == "fips" ]; then + CGO_ENABLED=1 + else + CGO_ENABLED=0 + fi + + echo "GOEXPERIMENT: $GOEXPERIMENT, GOTAGS: $GOTAGS CGO_ENABLED: $CGO_ENABLED" >> ~/debug.txt + if ! test -d "$1" then err "ERROR: '$1' is not a directory. build_consul must be called with the path to the top level source as the first argument'" @@ -242,7 +250,7 @@ function build_consul_local { then status "Using gox for concurrent compilation" - CGO_ENABLED=0 gox \ + CGO_ENABLED=${CGO_ENABLED} GOEXPERIMENT=${GOEXPERIMENT} gox \ -os="${build_os}" \ -arch="${build_arch}" \ -ldflags="${GOLDFLAGS}" \ @@ -290,7 +298,7 @@ function build_consul_local { else OS_BIN_EXTENSION="" fi - CGO_ENABLED=0 GOOS=${os} GOARCH=${arch} go build -ldflags "${GOLDFLAGS}" -tags "${GOTAGS}" -o "${outdir}/${bin_name}" + CGO_ENABLED=${CGO_ENABLED} GOEXPERIMENT=${GOEXPERIMENT} GOOS=${os} GOARCH=${arch} go build -ldflags "${GOLDFLAGS}" -tags "${GOTAGS}" -o "${outdir}/${bin_name}" if test $? -ne 0 then err "ERROR: Failed to build Consul for ${osarch}" diff --git a/control-plane/build-support/scripts/build-local.sh b/control-plane/build-support/scripts/build-local.sh index 453310b0b7..7325e025b7 100755 --- a/control-plane/build-support/scripts/build-local.sh +++ b/control-plane/build-support/scripts/build-local.sh @@ -35,6 +35,8 @@ Options: -a | --arch ARCH Space separated string of architectures to build. + --fips FIPS Whether to use FIPS cryptography. + -h | --help Print this help text. EOF } @@ -94,6 +96,11 @@ function main { build_arch="$2" shift 2 ;; + --fips ) + GOTAGS="fips" + GOEXPERIMENT="boringcrypto" + shift 1 + ;; * ) err_usage "ERROR: Unknown argument: '$1'" return 1 diff --git a/control-plane/subcommand/connect-init/command.go b/control-plane/subcommand/connect-init/command.go index 72090d299b..4f83ea98f1 100644 --- a/control-plane/subcommand/connect-init/command.go +++ b/control-plane/subcommand/connect-init/command.go @@ -17,17 +17,19 @@ import ( "time" "github.com/cenkalti/backoff" - "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" - "github.com/hashicorp/consul-k8s/control-plane/consul" - "github.com/hashicorp/consul-k8s/control-plane/namespaces" - "github.com/hashicorp/consul-k8s/control-plane/subcommand/common" - "github.com/hashicorp/consul-k8s/control-plane/subcommand/flags" "github.com/hashicorp/consul-server-connection-manager/discovery" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/sdk/iptables" "github.com/hashicorp/go-hclog" "github.com/mitchellh/cli" "github.com/mitchellh/mapstructure" + + "github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants" + "github.com/hashicorp/consul-k8s/control-plane/consul" + "github.com/hashicorp/consul-k8s/control-plane/namespaces" + "github.com/hashicorp/consul-k8s/control-plane/subcommand/common" + "github.com/hashicorp/consul-k8s/control-plane/subcommand/flags" + "github.com/hashicorp/consul-k8s/control-plane/version" ) const ( @@ -161,6 +163,17 @@ func (c *Command) Run(args []string) int { c.logger.Error("Unable to get client connection", "error", err) return 1 } + if version.IsFIPS() { + // make sure we are also using FIPS Consul + var versionInfo map[string]interface{} + _, err := consulClient.Raw().Query("/v1/agent/version", versionInfo, nil) + if err != nil { + c.logger.Warn("This is a FIPS build of consul-k8s, which should be used with FIPS Consul. Unable to verify FIPS Consul while setting up Consul API client.") + } + if val, ok := versionInfo["FIPS"]; !ok || val == "" { + c.logger.Warn("This is a FIPS build of consul-k8s, which should be used with FIPS Consul. A non-FIPS version of Consul was detected.") + } + } proxyService := &api.AgentService{} if c.flagGatewayKind != "" { err = backoff.Retry(c.getGatewayRegistration(consulClient), backoff.WithMaxRetries(backoff.NewConstantBackOff(1*time.Second), c.serviceRegistrationPollingAttempts)) diff --git a/control-plane/version/fips_build.go b/control-plane/version/fips_build.go new file mode 100644 index 0000000000..4d04cc6539 --- /dev/null +++ b/control-plane/version/fips_build.go @@ -0,0 +1,27 @@ +//go:build fips + +package version + +// This validates during compilation that we are being built with a FIPS enabled go toolchain +import ( + _ "crypto/tls/fipsonly" + "runtime" + "strings" +) + +// IsFIPS returns true if consul-k8s is operating in FIPS-140-2 mode. +func IsFIPS() bool { + return true +} + +func GetFIPSInfo() string { + str := "Enabled" + // Try to get the crypto module name + gover := strings.Split(runtime.Version(), "X:") + if len(gover) >= 2 { + gover_last := gover[len(gover)-1] + // Able to find crypto module name; add that to status string. + str = "FIPS 140-2 Enabled, crypto module " + gover_last + } + return str +} diff --git a/control-plane/version/non_fips_build.go b/control-plane/version/non_fips_build.go new file mode 100644 index 0000000000..f72aecae73 --- /dev/null +++ b/control-plane/version/non_fips_build.go @@ -0,0 +1,12 @@ +//go:build !fips + +package version + +// IsFIPS returns true if consul-k8s is operating in FIPS-140-2 mode. +func IsFIPS() bool { + return false +} + +func GetFIPSInfo() string { + return "" +} diff --git a/control-plane/version/version.go b/control-plane/version/version.go index 81433c0a5f..320600c30b 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -39,8 +39,12 @@ func GetHumanVersion() string { release = "dev" } + if IsFIPS() { + version += ".fips1402" + } + if release != "" { - if !strings.HasSuffix(version, "-"+release) { + if !strings.Contains(version, "-"+release) { // if we tagged a prerelease version then the release is in the version already version += fmt.Sprintf("-%s", release) }