Skip to content

Commit 3e13a43

Browse files
XuanYang-cnclaude
authored andcommitted
enhance: enable OpenSSL FIPS mode for Milvus (milvus-io#48331)
Layer 2 (OpenSSL FIPS) changes: - Add programmatic FIPS activation via OSSL_LIB_CTX_load_config in boring_enabled.go (gated by //go:build boringcrypto) - Add openssl-fips.cnf with fips + default providers and default_properties = fips=yes - Use absolute .include path for fipsmodule.cnf — OpenSSL resolves relative .include from the process working directory, not the config file's directory, causing silent FIPS provider load failure - Add RAND_bytes probe after config load to verify the FIPS provider is truly functional (EVP_default_properties_is_fips_enabled only checks the property string, not whether the provider loaded) - Dockerfiles: add openssl fipsinstall + OPENSSL_MODULES env var - Log OpenSSL FIPS status from C++ via EVP_default_properties_is_fips_enabled Layer 1 (Go BoringCrypto) changes: - Add GOEXPERIMENT=boringcrypto build flag (conditional on MILVUS_FIPS_ENABLED=ON) - Add boringEnabled() build-tagged functions for startup logging s2n-tls upgrade: - Override s2n 1.4.1 (from aws-c-io) to 1.6.0 in conanfile.py. s2n 1.4.1 only detects FIPS via the legacy OPENSSL_FIPS define (not set by OpenSSL 3.x). s2n 1.6.0 adds EVP_default_properties_is_fips_enabled() detection so s2n enters FIPS mode and uses RAND_bytes() through the FIPS provider. See also: milvus-io#48202, milvus-io#48301 Signed-off-by: yangxuan <xuan.yang@zilliz.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: heihutu <heihutu@gmail.com>
1 parent 0e54478 commit 3e13a43

15 files changed

Lines changed: 140 additions & 2 deletions

File tree

Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ use_opendal = OFF
5757
ifdef USE_OPENDAL
5858
use_opendal = ${USE_OPENDAL}
5959
endif
60+
61+
# FIPS: default OFF. Set MILVUS_FIPS_ENABLED=ON to enable BoringCrypto.
62+
GOEXPERIMENT_FLAG :=
63+
ifeq ($(MILVUS_FIPS_ENABLED),ON)
64+
GOEXPERIMENT_FLAG := GOEXPERIMENT=boringcrypto
65+
endif
6066
# golangci-lint
6167
GOLANGCI_LINT_VERSION := 1.64.7
6268
GOLANGCI_LINT_OUTPUT := $(shell $(INSTALL_PATH)/golangci-lint --version 2>/dev/null)
@@ -106,7 +112,7 @@ build-go:
106112
@echo "Building Milvus ..."
107113
@source $(PWD)/scripts/setenv.sh && \
108114
mkdir -p $(INSTALL_PATH) && go env -w CGO_ENABLED="1" && \
109-
CGO_LDFLAGS="$${CGO_LDFLAGS} $(CGO_LDFLAGS)" CGO_CFLAGS="$${CGO_CFLAGS} $(CGO_CFLAGS)" GO111MODULE=on $(GO) build -pgo=$(PGO_PATH)/default.pgo -ldflags="-r $${RPATH} -X '$(OBJPREFIX).BuildTags=$(BUILD_TAGS)' -X '$(OBJPREFIX).BuildTime=$(BUILD_TIME)' -X '$(OBJPREFIX).GitCommit=$(GIT_COMMIT)' -X '$(OBJPREFIX).GoVersion=$(GO_VERSION)' -X '$(OBJPREFIX).MilvusVersion=$(MILVUS_VERSION)'" \
115+
$(GOEXPERIMENT_FLAG) CGO_LDFLAGS="$${CGO_LDFLAGS} $(CGO_LDFLAGS)" CGO_CFLAGS="$${CGO_CFLAGS} $(CGO_CFLAGS)" GO111MODULE=on $(GO) build -pgo=$(PGO_PATH)/default.pgo -ldflags="-r $${RPATH} -X '$(OBJPREFIX).BuildTags=$(BUILD_TAGS)' -X '$(OBJPREFIX).BuildTime=$(BUILD_TIME)' -X '$(OBJPREFIX).GitCommit=$(GIT_COMMIT)' -X '$(OBJPREFIX).GoVersion=$(GO_VERSION)' -X '$(OBJPREFIX).MilvusVersion=$(MILVUS_VERSION)'" \
110116
-tags $(MILVUS_GO_BUILD_TAGS) -o $(INSTALL_PATH)/milvus $(PWD)/cmd/main.go 1>/dev/null
111117

112118
milvus-gpu: build-cpp-gpu print-gpu-build-info

build/docker/milvus/amazonlinux2023/Dockerfile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,15 @@ COPY --chown=root:root --chmod=774 ./configs/ /milvus/configs/
2828

2929
COPY --chown=root:root --chmod=774 ./lib/ /milvus/lib/
3030

31-
3231
ENV PATH=/milvus/bin:$PATH
3332
ENV LD_LIBRARY_PATH=/milvus/lib:$LD_LIBRARY_PATH:/usr/lib
3433
ENV LD_PRELOAD=${MILVUS_ASAN_LIB}:/milvus/lib/libjemalloc.so
3534
ENV MALLOC_CONF=background_thread:true
35+
ENV OPENSSL_MODULES=/milvus/lib/ossl-modules
36+
37+
# Generate fipsmodule.cnf for FIPS module integrity self-test.
38+
# FIPS activation is handled programmatically at startup — no OPENSSL_CONF needed.
39+
RUN openssl fipsinstall -out /milvus/configs/ssl/fipsmodule.cnf -module /milvus/lib/ossl-modules/fips.so
3640

3741
# Change user to milvus
3842
# protobuf 5.x RepeatedField adds container annotations that trigger ASAN

build/docker/milvus/gpu/ubuntu22.04/Dockerfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ ENV PATH=/milvus/bin:$PATH
2727
ENV LD_LIBRARY_PATH=/milvus/lib:$LD_LIBRARY_PATH:/usr/lib
2828
ENV LD_PRELOAD=/milvus/lib/libjemalloc.so
2929
ENV MALLOC_CONF=background_thread:true
30+
ENV OPENSSL_MODULES=/milvus/lib/ossl-modules
31+
32+
# Generate fipsmodule.cnf for FIPS module integrity self-test.
33+
# FIPS activation is handled programmatically at startup — no OPENSSL_CONF needed.
34+
RUN openssl fipsinstall -out /milvus/configs/ssl/fipsmodule.cnf -module /milvus/lib/ossl-modules/fips.so
3035

3136
# Change user to milvus
3237
RUN groupadd -r milvus && useradd -r -g milvus milvus && \

build/docker/milvus/rockylinux9/Dockerfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ ENV PATH=/milvus/bin:$PATH
3636
ENV LD_LIBRARY_PATH=/milvus/lib:$LD_LIBRARY_PATH:/usr/lib
3737
ENV LD_PRELOAD=${MILVUS_ASAN_LIB}:/milvus/lib/libjemalloc.so
3838
ENV MALLOC_CONF=background_thread:true
39+
ENV OPENSSL_MODULES=/milvus/lib/ossl-modules
40+
41+
# Generate fipsmodule.cnf for FIPS module integrity self-test.
42+
# FIPS activation is handled programmatically at startup — no OPENSSL_CONF needed.
43+
RUN openssl fipsinstall -out /milvus/configs/ssl/fipsmodule.cnf -module /milvus/lib/ossl-modules/fips.so
3944

4045
# Change user to milvus
4146
# protobuf 5.x RepeatedField adds container annotations that trigger ASAN

build/docker/milvus/ubuntu22.04/Dockerfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ ENV PATH=/milvus/bin:$PATH
4141
ENV LD_LIBRARY_PATH=/milvus/lib:$LD_LIBRARY_PATH:/usr/lib
4242
ENV LD_PRELOAD=${MILVUS_ASAN_LIB}:/milvus/lib/libjemalloc.so
4343
ENV MALLOC_CONF=background_thread:true
44+
ENV OPENSSL_MODULES=/milvus/lib/ossl-modules
45+
46+
# Generate fipsmodule.cnf for FIPS module integrity self-test.
47+
# FIPS activation is handled programmatically at startup — no OPENSSL_CONF needed.
48+
RUN openssl fipsinstall -out /milvus/configs/ssl/fipsmodule.cnf -module /milvus/lib/ossl-modules/fips.so
4449

4550
# Change user to milvus
4651
# protobuf 5.x RepeatedField adds container annotations that trigger ASAN

cmd/milvus/boring_disabled.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//go:build !boringcrypto
2+
3+
package milvus
4+
5+
func boringEnabled() bool {
6+
return false
7+
}
8+
9+
func maybeEnableOpenSSLFIPS() {}

cmd/milvus/boring_enabled.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//go:build boringcrypto
2+
3+
package milvus
4+
5+
/*
6+
#include <openssl/conf.h>
7+
#include <openssl/evp.h>
8+
#include <openssl/provider.h>
9+
#include <openssl/rand.h>
10+
11+
static int enableOpenSSLFIPS() {
12+
unsigned char buf[1];
13+
14+
if (!OSSL_LIB_CTX_load_config(NULL, "/milvus/configs/ssl/openssl-fips.cnf")) {
15+
return -1; // config load failed
16+
}
17+
if (!EVP_default_properties_is_fips_enabled(NULL)) {
18+
return 0; // config loaded but fips=yes not set
19+
}
20+
// EVP_default_properties_is_fips_enabled only checks the property string,
21+
// not whether the FIPS provider is actually loaded. Verify by checking
22+
// that RAND_bytes works (requires a working FIPS DRBG).
23+
if (RAND_bytes(buf, 1) != 1) {
24+
return -2; // FIPS property set but provider not functional
25+
}
26+
return 1; // FIPS truly enabled and functional
27+
}
28+
*/
29+
import "C"
30+
31+
import (
32+
"crypto/boring"
33+
"log"
34+
"sync"
35+
)
36+
37+
func boringEnabled() bool {
38+
return boring.Enabled()
39+
}
40+
41+
var fipsOnce sync.Once
42+
43+
func maybeEnableOpenSSLFIPS() {
44+
fipsOnce.Do(func() {
45+
rc := C.enableOpenSSLFIPS()
46+
switch rc {
47+
case 1:
48+
log.Println("OpenSSL FIPS mode enabled")
49+
case 0:
50+
log.Println("WARNING: OpenSSL FIPS config loaded but fips=yes not set in default properties")
51+
case -2:
52+
log.Println("FATAL: OpenSSL FIPS property set but FIPS provider not functional (check OPENSSL_MODULES env var and .include path in openssl-fips.cnf)")
53+
default:
54+
log.Println("Failed to load OpenSSL FIPS config")
55+
}
56+
})
57+
}

cmd/milvus/run.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ func (c *run) execute(args []string, flags *flag.FlagSet) {
3737
runtimeDir := createRuntimeDir(serverType)
3838
filename := getPidFileName(serverType, roles.Alias)
3939

40+
maybeEnableOpenSSLFIPS()
4041
c.printBanner(flags.Output())
4142
c.injectVariablesToEnv()
4243
c.printHardwareInfo(flags.Output())
@@ -60,6 +61,7 @@ func (c *run) printBanner(w io.Writer) {
6061
fmt.Fprintln(w, "Built: "+BuildTime)
6162
fmt.Fprintln(w, "GitCommit: "+GitCommit)
6263
fmt.Fprintln(w, "GoVersion: "+GoVersion)
64+
fmt.Fprintf(w, "Milvus FIPS in Go: BoringCrypto %v\n", boringEnabled())
6365
fmt.Fprintln(w)
6466
metrics.BuildInfo.WithLabelValues(getEffectiveVersion(), BuildTime, GitCommit).Set(1)
6567
}

configs/ssl/openssl-fips.cnf

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
config_diagnostics = 1
2+
openssl_conf = openssl_init
3+
4+
.include /milvus/configs/ssl/fipsmodule.cnf
5+
6+
[openssl_init]
7+
providers = provider_sect
8+
alg_section = algorithm_sect
9+
10+
[provider_sect]
11+
fips = fips_sect
12+
default = default_sect
13+
14+
[fips_sect]
15+
activate = 1
16+
17+
[default_sect]
18+
activate = 1
19+
20+
[algorithm_sect]
21+
default_properties = fips=yes

internal/core/conanfile.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ def requirements(self):
111111
if self.settings.os != "Macos":
112112
self.requires("libunwind/1.8.1#97965ef7da98cf1662e14219b14134f7")
113113
self.requires("aws-sdk-cpp/1.11.692@milvus/dev#1e17deac19383217d291a01c23147b33")
114+
# Override s2n 1.4.1 (from aws-c-io) to 1.6.0 for OpenSSL 3.x FIPS detection
115+
if self.settings.os in ["Linux", "FreeBSD"]:
116+
self.requires("s2n/1.6.0")
114117

115118
def imports(self):
116119
self.copy("*.dylib", "../lib", "lib")

0 commit comments

Comments
 (0)