Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FIPS builds #2165

Merged
merged 9 commits into from
Jun 8, 2023
Merged
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
92 changes: 66 additions & 26 deletions .github/workflows/build.yml

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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.
curtbushko marked this conversation as resolved.
Show resolved Hide resolved
@$(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 ./...

Expand Down Expand Up @@ -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:
curtbushko marked this conversation as resolved.
Show resolved Hide resolved
@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
Expand Down
27 changes: 27 additions & 0 deletions cli/version/fips_build.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//go:build fips
curtbushko marked this conversation as resolved.
Show resolved Hide resolved

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
}
12 changes: 12 additions & 0 deletions cli/version/non_fips_build.go
Original file line number Diff line number Diff line change
@@ -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 ""
}
6 changes: 5 additions & 1 deletion cli/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
6 changes: 5 additions & 1 deletion control-plane/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
curtbushko marked this conversation as resolved.
Show resolved Hide resolved

# TARGETOS and TARGETARCH are set automatically when --platform is provided.
ARG TARGETOS
Expand Down
14 changes: 11 additions & 3 deletions control-plane/build-support/functions/20-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,22 @@ 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
# The NOGOX environment variable will be used if present. This will prevent using gox and instead
# 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'"
Expand Down Expand Up @@ -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}" \
Expand Down Expand Up @@ -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}"
Expand Down
7 changes: 7 additions & 0 deletions control-plane/build-support/scripts/build-local.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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
Expand Down
23 changes: 18 additions & 5 deletions control-plane/subcommand/connect-init/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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))
Expand Down
27 changes: 27 additions & 0 deletions control-plane/version/fips_build.go
Original file line number Diff line number Diff line change
@@ -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
}
12 changes: 12 additions & 0 deletions control-plane/version/non_fips_build.go
Original file line number Diff line number Diff line change
@@ -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 ""
}
6 changes: 5 additions & 1 deletion control-plane/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down