Skip to content
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
16 changes: 12 additions & 4 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
env:
DOCKER_COMPOSE_VERSION: "1.25.5"
TERRAFORM_VERSION: "1.6.4"
IMAGE_UBUNTU_X86_64_FIPS: "platform-ingest-fleet-server-ubuntu-2204-fips-1751684469"

# This section is used to define the plugins that will be used in the pipeline.
# See https://buildkite.com/docs/pipelines/integrations/plugins/using#using-yaml-anchors-with-plugins
Expand Down Expand Up @@ -114,24 +115,31 @@ steps:
- build/*.xml
- build/coverage*.out

- label: ":smartbear-testexecute: Run unit tests with requirefips build tag"
- label: ":smartbear-testexecute: Run unit tests with requirefips build tag and FIPS provider"
key: unit-test-fips-tag
command: ".buildkite/scripts/unit_test.sh"
env:
FIPS: "true"
GOEXPERIMENT: "systemcrypto"
GO_DISTRO: "microsoft"
agents:
provider: "gcp"
provider: "aws"
image: "${IMAGE_UBUNTU_X86_64_FIPS}"
instanceType: "m5.xlarge"
artifact_paths:
- build/*.xml
- build/coverage*.out

- label: ":smartbear-testexecute: Run fips140=only unit tests"
- label: ":smartbear-testexecute: Run fips140=only unit tests with FIPS provider"
key: unit-test-fips140-only
command: ".buildkite/scripts/unit_test_fipsonly.sh"
env:
FIPS: "true"
GO_DISTRO: "stdlib"
agents:
provider: "gcp"
provider: "aws"
image: "${IMAGE_UBUNTU_X86_64_FIPS}"
instanceType: "m5.xlarge"
artifact_paths:
- build/*.xml
- build/coverage*.out
Expand Down
7 changes: 5 additions & 2 deletions .buildkite/scripts/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,12 @@ with_msft_go() {
echo "Setting up microsoft/go"
create_workspace
check_platform_architeture

# Use a temporary folder to house the Go SDK downloaded from Microsoft
tempfolder=$(mktemp -d)
MSFT_DOWNLOAD_URL=https://aka.ms/golang/release/latest/go$(cat .go-version).${platform_type}-${arch_type}.tar.gz
retry 5 $(curl -sL -o - $MSFT_DOWNLOAD_URL | tar -xz -f - -C ${WORKSPACE})
export PATH="${PATH}:${WORKSPACE}/go/bin"
retry 5 $(curl -sL -o - $MSFT_DOWNLOAD_URL | tar -xz -f - -C ${tempfolder}/)
export PATH="${PATH}:${tempfolder}/go/bin"
go version
which go
export PATH="${PATH}:$(go env GOPATH)/bin"
Expand Down
6 changes: 5 additions & 1 deletion .buildkite/scripts/unit_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ source .buildkite/scripts/common.sh

add_bin_path

with_go
if [[ ${FIPS:-false} == "true" && ${GO_DISTRO:-stdlib} == "microsoft" ]]; then
with_msft_go
else
with_go
fi

with_mage

Expand Down
6 changes: 5 additions & 1 deletion .buildkite/scripts/unit_test_fipsonly.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ source .buildkite/scripts/common.sh

add_bin_path

with_go
if [[ ${FIPS:-false} == "true" && ${GO_DISTRO:-stdlib} == "microsoft" ]]; then
with_msft_go
else
with_go
fi

with_mage

Expand Down
98 changes: 92 additions & 6 deletions internal/pkg/es/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ import (
"context"
"crypto/tls"
"crypto/x509"
_ "embed"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"time"

"github.com/elastic/elastic-agent-libs/transport/tlscommon"
"github.com/elastic/fleet-server/v7/internal/pkg/build"
"github.com/elastic/fleet-server/v7/internal/pkg/config"
"github.com/elastic/fleet-server/v7/internal/pkg/testing/certs"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -42,7 +45,7 @@ func TestClientCerts(t *testing.T) {
defer server.Close()

// client does not use client certs
client, err := NewClient(context.Background(), &config.Config{
client, err := NewClient(t.Context(), &config.Config{
Output: config.Output{
Elasticsearch: config.Elasticsearch{
Protocol: "https",
Expand All @@ -56,7 +59,7 @@ func TestClientCerts(t *testing.T) {
}, false)
require.NoError(t, err)

req, err := http.NewRequestWithContext(context.Background(), "GET", server.URL, nil)
req, err := http.NewRequestWithContext(t.Context(), "GET", server.URL, nil)
require.NoError(t, err)

resp, err := client.Perform(req)
Expand Down Expand Up @@ -87,7 +90,7 @@ func TestClientCerts(t *testing.T) {
cert := certs.GenCert(t, ca)

// client uses valid, matching certs
client, err := NewClient(context.Background(), &config.Config{
client, err := NewClient(t.Context(), &config.Config{
Output: config.Output{
Elasticsearch: config.Elasticsearch{
Protocol: "https",
Expand All @@ -105,7 +108,7 @@ func TestClientCerts(t *testing.T) {
}, false)
require.NoError(t, err)

req, err := http.NewRequestWithContext(context.Background(), "GET", server.URL, nil)
req, err := http.NewRequestWithContext(t.Context(), "GET", server.URL, nil)
require.NoError(t, err)

resp, err := client.Perform(req)
Expand Down Expand Up @@ -137,7 +140,7 @@ func TestClientCerts(t *testing.T) {
cert := certs.GenCert(t, certCA)

// client uses certs that are signed by a different CA
client, err := NewClient(context.Background(), &config.Config{
client, err := NewClient(t.Context(), &config.Config{
Output: config.Output{
Elasticsearch: config.Elasticsearch{
Protocol: "https",
Expand All @@ -155,10 +158,93 @@ func TestClientCerts(t *testing.T) {
}, false)
require.NoError(t, err)

req, err := http.NewRequestWithContext(context.Background(), "GET", server.URL, nil)
req, err := http.NewRequestWithContext(t.Context(), "GET", server.URL, nil)
require.NoError(t, err)

_, err = client.Perform(req) //nolint:bodyclose // no response is expected
require.Error(t, err)
})
}

// TestConnectionTLS tries to connect to a test HTTPS server (pretending
// to be an Elasticsearch cluster), that deliberately presents TLS options
// that are not FIPS-compliant.
// - If the test is running with a FIPS-capable build, the client, being FIPS-
// capable, should fail the TLS handshake. Concretely, the conn.Connect() method
// should return an error.
// - If the test is not running with a FIPS-capable build, the client should
// complete the TLS handshake successfully. Concretely, the conn.Connect() method
// should not return an error.
func TestConnectionTLS(t *testing.T) {
server := startTLSServer(t)
defer server.Close()

cfg := &config.Config{
Output: config.Output{
Elasticsearch: config.Elasticsearch{
Protocol: "https",
Hosts: []string{server.URL},
TLS: &tlscommon.Config{
Enabled: &enabled,
CAs: []string{string(caCertPEM)},
},
},
},
}

ctx, cancel := context.WithTimeout(t.Context(), 30*time.Second)
defer cancel()

client, err := NewClient(ctx, cfg, false)
require.NoError(t, err)

_, err = FetchESVersion(ctx, client)

if build.FIPSDistribution {
require.ErrorContains(t, err, "tls: internal error")
} else {
require.NoError(t, err)
}
}

//go:embed testdata/ca.crt
var caCertPEM []byte

//go:embed testdata/fips_invalid.key
var serverKeyPEM []byte // RSA key with length = 1024 bits

//go:embed testdata/fips_invalid.crt
var serverCertPEM []byte

//go:embed testdata/es_ping_response.json
var esPingResponse []byte

func startTLSServer(t *testing.T) *httptest.Server {
// Configure server and start it
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCertPEM)

// Create HTTPS server
server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Elastic-Product", "Elasticsearch")
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_, err := w.Write(esPingResponse)
require.NoError(t, err)
}))

serverCert, err := tls.X509KeyPair(serverCertPEM, serverKeyPEM)
require.NoError(t, err)

server.TLS = &tls.Config{
MinVersion: tls.VersionTLS12,
RootCAs: caCertPool,
Certificates: []tls.Certificate{serverCert},
ClientCAs: caCertPool,
ClientAuth: tls.NoClientCert,
}

server.StartTLS()

return server
}
23 changes: 23 additions & 0 deletions internal/pkg/es/testdata/ca.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIUA9Gphn0fTO3Vuo7ePJpfebnebtgwDQYJKoZIhvcNAQEL
BQAwZDELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE5ldyBZb3JrMSEwHwYDVQQKDBhJ
bnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxCzAJBgNVBAsMAkNBMRIwEAYDVQQDDAls
b2NhbGhvc3QwHhcNMjUwNDIyMjIwMTU2WhcNMzAwNDIxMjIwMTU2WjBkMQswCQYD
VQQGEwJVUzERMA8GA1UECAwITmV3IFlvcmsxITAfBgNVBAoMGEludGVybmV0IFdp
ZGdpdHMgUHR5IEx0ZDELMAkGA1UECwwCQ0ExEjAQBgNVBAMMCWxvY2FsaG9zdDCC
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIaR6W/pAoEFE5Hc6kgH2UTZ
cd0LOT5hp3xtomKfnNONS5WgXDZbOqCSUY1+ZrG6NDrzG64vDC+AdtW7Zji7s+VA
2hZ2DESbq+JBosAAyZbwzqosTCpp24on1VWXS+h8NT1nMGkvkkrKnM0fBK4Q9DVI
H9QAtKysPnLwbfyWrnAHtjMd0bIrBPlt26g16l1nJklTwm2clD0ixE4MKw7lPZWE
eJN+sK1CvA+r65huC7vDbNrL2OC+eNAiKtCH+AQR4HcB76kG9Qy/9+qfCGhizBlt
mwceLDhz6FWgxKSgXwSfmorZLc1ecBfuWjqr9rfaUhOd4oLkmfbaEPqNu2V/rw0C
AwEAAaNvMG0wHQYDVR0OBBYEFGzBvXdyHsVEY4bOAIiI3m4w7JfcMB8GA1UdIwQY
MBaAFGzBvXdyHsVEY4bOAIiI3m4w7JfcMA8GA1UdEwEB/wQFMAMBAf8wGgYDVR0R
BBMwEYIJbG9jYWxob3N0hwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBAQCEbCFPgfT4
DUkl/LozK8zUPEUV6mh53rTGQLhMbPfu7l1f6aSjvb1bIzYmrEFhlv/3yke+2/BC
lGPYZrzdy2S9Xqv2ZthBoqE7cUrUGcq6U4y9helsM4gMfokpgBuNqwFVOGtSAlYy
otUTRuIJeCLqAUV51wYROe9dOnY//ICEVrnRmLN4uXl64LMlBWbx76PS2s9dktr1
5oWeF8whEhzg41FGsd6QPulKgT9h8+RR10hc3F4IFCVjtnp11E22x0/YYONbuAEH
ZxL++PbvQRAvFGpTEmxH/AIq8yGQ90V94+HB7ocqz+3y0Nl93iNoanMOAJush3uL
oIhHS8L9ENUv
-----END CERTIFICATE-----
17 changes: 17 additions & 0 deletions internal/pkg/es/testdata/es_ping_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "instance-0000000000",
"cluster_name": "e8647d9cfc9e4e77a83554c5e6d5ee25",
"cluster_uuid": "25mwr5sGTZyXIGwWMcSGmQ",
"version": {
"number": "9.2.0-SNAPSHOT",
"build_flavor": "default",
"build_type": "docker",
"build_hash": "a6dfe646524f42869fc4820a67fffec2d76890dc",
"build_date": "2025-07-01T22:12:52.207781139Z",
"build_snapshot": true,
"lucene_version": "10.2.2",
"minimum_wire_compatibility_version": "8.19.0",
"minimum_index_compatibility_version": "8.0.0"
},
"tagline": "You Know, for Search"
}
20 changes: 20 additions & 0 deletions internal/pkg/es/testdata/fips_invalid.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDLzCCAhegAwIBAgIUIUHef0rqBRe0SWOxT/OwncexFiwwDQYJKoZIhvcNAQEL
BQAwZDELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE5ldyBZb3JrMSEwHwYDVQQKDBhJ
bnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxCzAJBgNVBAsMAkNBMRIwEAYDVQQDDAls
b2NhbGhvc3QwHhcNMjUwNDIyMjIwNjM1WhcNMzAwNDIxMjIwNjM1WjBYMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEQMA4GA1UECgwHRWxhc3RpYzEO
MAwGA1UECwwFQWdlbnQxEjAQBgNVBAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0B
AQEFAAOBjQAwgYkCgYEAo87+PNnpbu+hNkjPigLVKSmlDStd0OqcOmUlsegElMEk
CArXkS+nDkD+p6o6QgGZ65mevmbJ9AxTV4tHQZ8YE695BgVa/MixzWNa2CjZu4OY
CXJd1q8LfvkExXjp8+RVWuAh+FY5bZYGIlw2yLSHGbrE5k3F8YlfoL6ADkAf43kC
AwEAAaNpMGcwHwYDVR0jBBgwFoAUbMG9d3IexURjhs4AiIjebjDsl9wwCQYDVR0T
BAIwADAaBgNVHREEEzARgglsb2NhbGhvc3SHBH8AAAEwHQYDVR0OBBYEFFTZsQwH
ipBtdR1XTu9x3yUg7H9uMA0GCSqGSIb3DQEBCwUAA4IBAQAH4gJMyjTvGUBUuih9
VDcKsxxIGPhcBaoDRN7YX/qI5DapRA7/bP+1AIAoByrs6YTbMZYNB4hDEEywf59T
pHNFt+3IsWOO3RCP1IeJscKO79Ga5WeKYJyV5HeNRpgNMsjslh+shzz29Qm4voiE
Ab+x/CZYJu9Yw5JPENb035KWVAMCiN34afi3jgNcQVKYlyUwm27qVOLxTuUZU23a
RzsFIc3/DpxIUZ7hD0qgR00jOXWAynhRpptKW7/tJmnoUk5nZuJUz3XDvE4UPvHj
0KTf4RFfnNJbmO3ZVqj8QI9FdhOUYr/rJnrufyQBnCDEHmo9KIeIVynaijoBtem5
mPgS
-----END CERTIFICATE-----
16 changes: 16 additions & 0 deletions internal/pkg/es/testdata/fips_invalid.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKPO/jzZ6W7voTZI
z4oC1SkppQ0rXdDqnDplJbHoBJTBJAgK15Evpw5A/qeqOkIBmeuZnr5myfQMU1eL
R0GfGBOveQYFWvzIsc1jWtgo2buDmAlyXdavC375BMV46fPkVVrgIfhWOW2WBiJc
Nsi0hxm6xOZNxfGJX6C+gA5AH+N5AgMBAAECgYAD5fw6Zyge6Aeu4FGSTy7mC3WM
ydv+8DLR99nRx6V1qeyK3yfIiHxDn4CbLYoOJTyPZRqOtuj5iVvbTO3GbIwg09tW
4MMyS2AABIaO8Ke2MdXseI1Dt9sY7TnAPs8tz6KOEPksWXYOroqrzqXXmlG/yEei
Fk9Z/UZB3ue33oq+IQJBAMm53Bi7ck2A7O4ueaeX9SkC5XpFpaUAimY5h8m+J0aB
vXUjEX0BzEj7/+ocX+KaEXE0gfvQZHl2PUY5qCwnbdkCQQDP4YUknD+1lFH7l8tJ
1whZfPEKn7MYAAS9wI5q11CTeaSkvq3z+5gX0EwLBn7WSqfcR3vQOBmyz0uzZhws
e36hAkAP+Z4Kf12v8ZPR0PBla01I8CfIJRfXF1HegpPUUDDADqo4Soyp/6hz5zD/
Ezwsr9LNykC49mnejJSRqSM+S+kRAkEAhKEZBmueBia0S7XkIJ9OF3Isg5+ybwyL
+dihxK7NHNpOXkG90F1kA0WFTr99KxGEmXkOGKHCW6AAZ1wte3/rIQJASAjYaX8z
cvqU4hUIsh0A1fQDD4j1HYrkOdsThrAoWRPu2mBDsD6IWnVmHzRB8coTZllP+mBA
JL2QoEeSSdfniw==
-----END PRIVATE KEY-----
Loading