Skip to content

Commit 66adc79

Browse files
[8.x](backport #4581) Add go1.24 GODEBUG=fips140=only test (#4612)
* Add go1.24 GODEBUG=fips140=only test (#4581) Add a new target that uses GODEBUG=fips140=only to run unit tests. This target should use the FIPS=true flag in order to pass -tags=requirefips. (cherry picked from commit 8e304bd) * Split 8.x TLS min version tests for FIPS * Fix ES Output TLS tests --------- Co-authored-by: Michel Laterman <82832767+michel-laterman@users.noreply.github.com> Co-authored-by: michel-laterman <michel.laterman@elastic.co>
1 parent b8e77f7 commit 66adc79

9 files changed

+350
-106
lines changed

.buildkite/pipeline.yml

+11
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,17 @@ steps:
8787
- build/*.xml
8888
- build/coverage*.out
8989

90+
- label: ":smartbear-testexecute: Run FIPS unit tests"
91+
key: unit-test-fips
92+
command: ".buildkite/scripts/unit_test.sh"
93+
env:
94+
FIPS: "true"
95+
agents:
96+
provider: "gcp"
97+
artifact_paths:
98+
- build/*.xml
99+
- build/coverage*.out
100+
90101
- label: ":smartbear-testexecute: Run unit tests: MacOS 13"
91102
key: unit-test-macos-13
92103
command: ".buildkite/scripts/unit_test.sh"

.buildkite/scripts/unit_test.sh

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,8 @@ add_bin_path
99
with_go
1010

1111
echo "Starting the unit tests..."
12-
make test-unit junit-report
12+
if [[ ${FIPS:-} == "true" ]]; then
13+
make test-unit-fips junit-report
14+
else
15+
make test-unit junit-report
16+
fi

Makefile

+8-1
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,16 @@ test: prepare-test-context ## - Run all tests
221221
test-release: ## - Check that all release binaries are created
222222
./.buildkite/scripts/test-release.sh $(DEFAULT_VERSION)
223223

224+
# If FIPS=true unit tests need microsoft/go + OpenSSL with FIPS
224225
.PHONY: test-unit
225226
test-unit: prepare-test-context ## - Run unit tests only
226-
set -o pipefail; go test ${GO_TEST_FLAG} -tags=$(GOBUILDTAGS) -v -race -coverprofile=build/coverage-${OS_NAME}.out ./... | tee build/test-unit-${OS_NAME}.out
227+
set -o pipefail; ${GOFIPSEXPERIMENT} go test ${GO_TEST_FLAG} -tags=$(GOBUILDTAGS) -v -race -coverprofile=build/coverage-${OS_NAME}.out ./... | tee build/test-unit-${OS_NAME}.out
228+
229+
# FIPS unit tests are meant to use go v1.24 to check FIPS compliance.
230+
# This check is very strict, and should be thought of as a static-code analysis tool.
231+
.PHONY: test-unit-fips
232+
test-unit-fips: prepare-test-context ## - Run unit tests with go 1.24's fips140=only for testing
233+
set -o pipefail; GOFIPS140=latest GODEBUG=fips140=only go test ${GO_TEST_FLAG} -tags=$(GOBUILDTAGS) -v -race -coverprofile=build/coverage-${OS_NAME}.out ./... | tee build/test-unit-fips-${OS_NAME}.out
227234

228235
.PHONY: benchmark
229236
benchmark: prepare-test-context install-benchstat ## - Run benchmark tests only
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
// or more contributor license agreements. Licensed under the Elastic License;
3+
// you may not use this file except in compliance with the Elastic License.
4+
5+
//go:build !integration && requirefips
6+
7+
package config
8+
9+
import (
10+
"crypto/tls"
11+
"path/filepath"
12+
"testing"
13+
14+
"github.com/stretchr/testify/assert"
15+
"github.com/stretchr/testify/require"
16+
17+
"github.com/elastic/elastic-agent-libs/transport/tlscommon"
18+
)
19+
20+
func TestTLSDefaults(t *testing.T) {
21+
c, err := LoadFile(filepath.Join("testdata", "tls.yml"))
22+
require.NoError(t, err)
23+
require.NotNil(t, c.Output.Elasticsearch.TLS)
24+
25+
common, err := tlscommon.LoadTLSConfig(c.Output.Elasticsearch.TLS)
26+
require.NoError(t, err)
27+
cfg := common.ToConfig()
28+
assert.Equal(t, uint16(tls.VersionTLS12), cfg.MinVersion)
29+
assert.Equal(t, uint16(tls.VersionTLS13), cfg.MaxVersion)
30+
}
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
// or more contributor license agreements. Licensed under the Elastic License;
3+
// you may not use this file except in compliance with the Elastic License.
4+
5+
//go:build !integration && !requirefips
6+
7+
package config
8+
9+
import (
10+
"crypto/tls"
11+
"path/filepath"
12+
"testing"
13+
14+
"github.com/stretchr/testify/assert"
15+
"github.com/stretchr/testify/require"
16+
17+
"github.com/elastic/elastic-agent-libs/transport/tlscommon"
18+
)
19+
20+
func TestTLSDefaults(t *testing.T) {
21+
c, err := LoadFile(filepath.Join("testdata", "tls.yml"))
22+
require.NoError(t, err)
23+
require.NotNil(t, c.Output.Elasticsearch.TLS)
24+
25+
common, err := tlscommon.LoadTLSConfig(c.Output.Elasticsearch.TLS)
26+
require.NoError(t, err)
27+
cfg := common.ToConfig()
28+
assert.Equal(t, uint16(tls.VersionTLS11), cfg.MinVersion)
29+
assert.Equal(t, uint16(tls.VersionTLS13), cfg.MaxVersion)
30+
}
31+
32+
func TestTLS10(t *testing.T) {
33+
c, err := LoadFile(filepath.Join("testdata", "tls10.yml"))
34+
require.NoError(t, err)
35+
require.NotNil(t, c.Output.Elasticsearch.TLS)
36+
37+
common, err := tlscommon.LoadTLSConfig(c.Output.Elasticsearch.TLS)
38+
require.NoError(t, err)
39+
cfg := common.ToConfig()
40+
assert.Equal(t, uint16(tls.VersionTLS10), cfg.MinVersion)
41+
assert.Equal(t, uint16(tls.VersionTLS10), cfg.MaxVersion)
42+
}

internal/pkg/config/config_test.go

-26
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,11 @@
77
package config
88

99
import (
10-
"crypto/tls"
1110
"path/filepath"
1211
"sync/atomic"
1312
"testing"
1413
"time"
1514

16-
"github.com/elastic/elastic-agent-libs/transport/tlscommon"
1715
testlog "github.com/elastic/fleet-server/v7/internal/pkg/testing/log"
1816

1917
"github.com/gofrs/uuid"
@@ -630,27 +628,3 @@ func TestDeprecationWarnings(t *testing.T) {
630628
require.NoError(t, err)
631629
assert.Equal(t, uint64(3), logCount.Load(), "Expected 3 log messages")
632630
}
633-
634-
func TestTLSDefaults(t *testing.T) {
635-
c, err := LoadFile(filepath.Join("testdata", "tls.yml"))
636-
require.NoError(t, err)
637-
require.NotNil(t, c.Output.Elasticsearch.TLS)
638-
639-
common, err := tlscommon.LoadTLSConfig(c.Output.Elasticsearch.TLS)
640-
require.NoError(t, err)
641-
cfg := common.ToConfig()
642-
assert.Equal(t, uint16(tls.VersionTLS11), cfg.MinVersion)
643-
assert.Equal(t, uint16(tls.VersionTLS13), cfg.MaxVersion)
644-
}
645-
646-
func TestTLS10(t *testing.T) {
647-
c, err := LoadFile(filepath.Join("testdata", "tls10.yml"))
648-
require.NoError(t, err)
649-
require.NotNil(t, c.Output.Elasticsearch.TLS)
650-
651-
common, err := tlscommon.LoadTLSConfig(c.Output.Elasticsearch.TLS)
652-
require.NoError(t, err)
653-
cfg := common.ToConfig()
654-
assert.Equal(t, uint16(tls.VersionTLS10), cfg.MinVersion)
655-
assert.Equal(t, uint16(tls.VersionTLS10), cfg.MaxVersion)
656-
}
+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
// or more contributor license agreements. Licensed under the Elastic License;
3+
// you may not use this file except in compliance with the Elastic License.
4+
5+
//go:build !integration && requirefips
6+
7+
package config
8+
9+
import (
10+
"crypto/tls"
11+
"net/http"
12+
"testing"
13+
"time"
14+
15+
"github.com/google/go-cmp/cmp"
16+
"github.com/google/go-cmp/cmp/cmpopts"
17+
"github.com/stretchr/testify/assert"
18+
"github.com/stretchr/testify/require"
19+
20+
"github.com/elastic/elastic-agent-libs/transport/tlscommon"
21+
testlog "github.com/elastic/fleet-server/v7/internal/pkg/testing/log"
22+
"github.com/elastic/go-elasticsearch/v8"
23+
)
24+
25+
func TestToESConfigTLS(t *testing.T) {
26+
testcases := map[string]struct {
27+
cfg Elasticsearch
28+
result elasticsearch.Config
29+
}{
30+
"https": {
31+
cfg: Elasticsearch{
32+
Protocol: "https",
33+
Hosts: []string{"localhost:9200", "other-host:9200"},
34+
ServiceToken: "test-token",
35+
Headers: map[string]string{
36+
"X-Custom-Header": "Header-Value",
37+
},
38+
MaxRetries: 6,
39+
MaxConnPerHost: 256,
40+
Timeout: 120 * time.Second,
41+
TLS: &tlscommon.Config{
42+
VerificationMode: tlscommon.VerifyNone,
43+
},
44+
},
45+
result: elasticsearch.Config{
46+
Addresses: []string{"https://localhost:9200", "https://other-host:9200"},
47+
ServiceToken: "test-token",
48+
Header: http.Header{"X-Custom-Header": {"Header-Value"}},
49+
MaxRetries: 6,
50+
Transport: &http.Transport{
51+
TLSClientConfig: &tls.Config{
52+
InsecureSkipVerify: true, //nolint:gosec // test case
53+
MinVersion: tls.VersionTLS12,
54+
MaxVersion: tls.VersionTLS13,
55+
Certificates: []tls.Certificate{},
56+
CurvePreferences: []tls.CurveID{},
57+
},
58+
TLSHandshakeTimeout: 10 * time.Second,
59+
MaxIdleConns: 100,
60+
MaxIdleConnsPerHost: 32,
61+
MaxConnsPerHost: 256,
62+
IdleConnTimeout: 60 * time.Second,
63+
ResponseHeaderTimeout: 120 * time.Second,
64+
ExpectContinueTimeout: 1 * time.Second,
65+
},
66+
},
67+
},
68+
"mixed-https": {
69+
cfg: Elasticsearch{
70+
Protocol: "http",
71+
Hosts: []string{"localhost:9200", "https://other-host:9200"},
72+
ServiceToken: "test-token",
73+
Headers: map[string]string{
74+
"X-Custom-Header": "Header-Value",
75+
},
76+
MaxRetries: 6,
77+
MaxConnPerHost: 256,
78+
Timeout: 120 * time.Second,
79+
TLS: &tlscommon.Config{
80+
VerificationMode: tlscommon.VerifyNone,
81+
},
82+
},
83+
result: elasticsearch.Config{
84+
Addresses: []string{"http://localhost:9200", "https://other-host:9200"},
85+
ServiceToken: "test-token",
86+
Header: http.Header{"X-Custom-Header": {"Header-Value"}},
87+
MaxRetries: 6,
88+
Transport: &http.Transport{
89+
TLSClientConfig: &tls.Config{
90+
InsecureSkipVerify: true, //nolint:gosec // test case
91+
MinVersion: tls.VersionTLS12,
92+
MaxVersion: tls.VersionTLS13,
93+
Certificates: []tls.Certificate{},
94+
CurvePreferences: []tls.CurveID{},
95+
},
96+
TLSHandshakeTimeout: 10 * time.Second,
97+
MaxIdleConns: 100,
98+
MaxIdleConnsPerHost: 32,
99+
MaxConnsPerHost: 256,
100+
IdleConnTimeout: 60 * time.Second,
101+
ResponseHeaderTimeout: 120 * time.Second,
102+
ExpectContinueTimeout: 1 * time.Second,
103+
},
104+
},
105+
},
106+
}
107+
108+
copts := cmp.Options{
109+
cmpopts.IgnoreUnexported(http.Transport{}),
110+
cmpopts.IgnoreFields(http.Transport{}, "DialContext"),
111+
cmpopts.IgnoreUnexported(tls.Config{}), //nolint:gosec //test case
112+
}
113+
114+
for name, test := range testcases {
115+
t.Run(name, func(t *testing.T) {
116+
_ = testlog.SetLogger(t)
117+
res, err := test.cfg.ToESConfig(false)
118+
require.NoError(t, err)
119+
120+
// cmp.Diff can't handle function pointers.
121+
res.Transport.(*http.Transport).Proxy = nil
122+
123+
test.result.Header.Set("X-elastic-product-origin", "fleet")
124+
assert.True(t, cmp.Equal(test.result, res, copts...), "mismatch (-want +got)\n%s", cmp.Diff(test.result, res, copts...))
125+
})
126+
}
127+
}

0 commit comments

Comments
 (0)