@@ -8,12 +8,15 @@ import (
88 "context"
99 "crypto/tls"
1010 "crypto/x509"
11+ _ "embed"
1112 "fmt"
1213 "net/http"
1314 "net/http/httptest"
1415 "testing"
16+ "time"
1517
1618 "github.com/elastic/elastic-agent-libs/transport/tlscommon"
19+ "github.com/elastic/fleet-server/v7/internal/pkg/build"
1720 "github.com/elastic/fleet-server/v7/internal/pkg/config"
1821 "github.com/elastic/fleet-server/v7/internal/pkg/testing/certs"
1922 "github.com/stretchr/testify/require"
@@ -42,7 +45,7 @@ func TestClientCerts(t *testing.T) {
4245 defer server .Close ()
4346
4447 // client does not use client certs
45- client , err := NewClient (context . Background (), & config.Config {
48+ client , err := NewClient (t . Context (), & config.Config {
4649 Output : config.Output {
4750 Elasticsearch : config.Elasticsearch {
4851 Protocol : "https" ,
@@ -56,7 +59,7 @@ func TestClientCerts(t *testing.T) {
5659 }, false )
5760 require .NoError (t , err )
5861
59- req , err := http .NewRequestWithContext (context . Background (), "GET" , server .URL , nil )
62+ req , err := http .NewRequestWithContext (t . Context (), "GET" , server .URL , nil )
6063 require .NoError (t , err )
6164
6265 resp , err := client .Perform (req )
@@ -87,7 +90,7 @@ func TestClientCerts(t *testing.T) {
8790 cert := certs .GenCert (t , ca )
8891
8992 // client uses valid, matching certs
90- client , err := NewClient (context . Background (), & config.Config {
93+ client , err := NewClient (t . Context (), & config.Config {
9194 Output : config.Output {
9295 Elasticsearch : config.Elasticsearch {
9396 Protocol : "https" ,
@@ -105,7 +108,7 @@ func TestClientCerts(t *testing.T) {
105108 }, false )
106109 require .NoError (t , err )
107110
108- req , err := http .NewRequestWithContext (context . Background (), "GET" , server .URL , nil )
111+ req , err := http .NewRequestWithContext (t . Context (), "GET" , server .URL , nil )
109112 require .NoError (t , err )
110113
111114 resp , err := client .Perform (req )
@@ -137,7 +140,7 @@ func TestClientCerts(t *testing.T) {
137140 cert := certs .GenCert (t , certCA )
138141
139142 // client uses certs that are signed by a different CA
140- client , err := NewClient (context . Background (), & config.Config {
143+ client , err := NewClient (t . Context (), & config.Config {
141144 Output : config.Output {
142145 Elasticsearch : config.Elasticsearch {
143146 Protocol : "https" ,
@@ -155,10 +158,93 @@ func TestClientCerts(t *testing.T) {
155158 }, false )
156159 require .NoError (t , err )
157160
158- req , err := http .NewRequestWithContext (context . Background (), "GET" , server .URL , nil )
161+ req , err := http .NewRequestWithContext (t . Context (), "GET" , server .URL , nil )
159162 require .NoError (t , err )
160163
161164 _ , err = client .Perform (req ) //nolint:bodyclose // no response is expected
162165 require .Error (t , err )
163166 })
164167}
168+
169+ // TestConnectionTLS tries to connect to a test HTTPS server (pretending
170+ // to be an Elasticsearch cluster), that deliberately presents TLS options
171+ // that are not FIPS-compliant.
172+ // - If the test is running with a FIPS-capable build, the client, being FIPS-
173+ // capable, should fail the TLS handshake. Concretely, the conn.Connect() method
174+ // should return an error.
175+ // - If the test is not running with a FIPS-capable build, the client should
176+ // complete the TLS handshake successfully. Concretely, the conn.Connect() method
177+ // should not return an error.
178+ func TestConnectionTLS (t * testing.T ) {
179+ server := startTLSServer (t )
180+ defer server .Close ()
181+
182+ cfg := & config.Config {
183+ Output : config.Output {
184+ Elasticsearch : config.Elasticsearch {
185+ Protocol : "https" ,
186+ Hosts : []string {server .URL },
187+ TLS : & tlscommon.Config {
188+ Enabled : & enabled ,
189+ CAs : []string {string (caCertPEM )},
190+ },
191+ },
192+ },
193+ }
194+
195+ ctx , cancel := context .WithTimeout (t .Context (), 30 * time .Second )
196+ defer cancel ()
197+
198+ client , err := NewClient (ctx , cfg , false )
199+ require .NoError (t , err )
200+
201+ _ , err = FetchESVersion (ctx , client )
202+
203+ if build .FIPSDistribution {
204+ require .ErrorContains (t , err , "tls: internal error" )
205+ } else {
206+ require .NoError (t , err )
207+ }
208+ }
209+
210+ //go:embed testdata/ca.crt
211+ var caCertPEM []byte
212+
213+ //go:embed testdata/fips_invalid.key
214+ var serverKeyPEM []byte // RSA key with length = 1024 bits
215+
216+ //go:embed testdata/fips_invalid.crt
217+ var serverCertPEM []byte
218+
219+ //go:embed testdata/es_ping_response.json
220+ var esPingResponse []byte
221+
222+ func startTLSServer (t * testing.T ) * httptest.Server {
223+ // Configure server and start it
224+ caCertPool := x509 .NewCertPool ()
225+ caCertPool .AppendCertsFromPEM (caCertPEM )
226+
227+ // Create HTTPS server
228+ server := httptest .NewUnstartedServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
229+ w .Header ().Set ("X-Elastic-Product" , "Elasticsearch" )
230+ w .Header ().Set ("Content-Type" , "application/json" )
231+ w .WriteHeader (http .StatusOK )
232+ _ , err := w .Write (esPingResponse )
233+ require .NoError (t , err )
234+ }))
235+
236+ serverCert , err := tls .X509KeyPair (serverCertPEM , serverKeyPEM )
237+ require .NoError (t , err )
238+
239+ server .TLS = & tls.Config {
240+ MinVersion : tls .VersionTLS12 ,
241+ RootCAs : caCertPool ,
242+ Certificates : []tls.Certificate {serverCert },
243+ ClientCAs : caCertPool ,
244+ ClientAuth : tls .NoClientCert ,
245+ }
246+
247+ server .StartTLS ()
248+
249+ return server
250+ }
0 commit comments