From f48c3a38c018881a49be4086d72cabaf95d11817 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Mon, 13 Apr 2020 08:39:24 -0500 Subject: [PATCH 01/25] [Heartbeat] Add Additional ECS tls.* fields This patch adds additional [ECS fields](https://www.elastic.co/guide/en/ecs/current/ecs-tls.html). Sample output of the `tls.*` fields with this patch is below. Note the somewhat strange nesting of data in `issuer` and `subject`. This is per the ECS spec, but a bit awkward. We may want to break this data out into the more specific ECS `x509` type in the future. For UI work we are likely fine to parse this on the client and display the CN section in most cases. ```json { "version": "1.2", "version_protocol": "tls" "cipher": "ECDHE-RSA-AES-128-GCM-SHA256", "server": { "subject": "CN=r2.shared.global.fastly.net,O=Fastly\\, Inc.,L=San Francisco,ST=California,C=US", "hash": { "sha1": "b7b4b89ef0d0caf39d223736f0fdbb03c7b426f1", "sha256": "12b00d04db0db8caa302bfde043e88f95baceb91e86ac143e93830b4bbec726d" }, "not_before": "2019-08-16T01:40:25.000Z", "not_after": "2019-08-16T01:40:25.000Z", "issuer": "CN=GlobalSign CloudSSL CA - SHA256 - G3,O=GlobalSign nv-sa,C=BE" }, "certificate_not_valid_before": "2019-08-16T01:40:25.000Z", "certificate_not_valid_after": "2020-07-16T03:15:39.000Z", "established": true, "rtt": { "handshake": { "us": 42491 } }, } ``` Work goes towards https://github.com/elastic/uptime/issues/161 --- heartbeat/monitors/active/dialchain/tls.go | 32 +++++++++++++++++-- .../common/transport/tlscommon/versions.go | 12 +++++-- .../transport/tlscommon/versions_default.go | 28 ++++++++++++---- 3 files changed, 61 insertions(+), 11 deletions(-) diff --git a/heartbeat/monitors/active/dialchain/tls.go b/heartbeat/monitors/active/dialchain/tls.go index 6fd2b43c27f..692eafce545 100644 --- a/heartbeat/monitors/active/dialchain/tls.go +++ b/heartbeat/monitors/active/dialchain/tls.go @@ -18,6 +18,8 @@ package dialchain import ( + "crypto/sha1" + "crypto/sha256" cryptoTLS "crypto/tls" "crypto/x509" "fmt" @@ -58,12 +60,26 @@ func TLSLayer(cfg *tlscommon.TLSConfig, to time.Duration) Layer { if !ok { panic(fmt.Sprintf("TLS afterDial received a non-tls connection %t. This should never happen", conn)) } + connState := tlsConn.ConnectionState() + event.PutValue("tls.established", true) - // TODO: extract TLS connection parameters from connection object. timer.stop() event.PutValue("tls.rtt.handshake", look.RTT(timer.duration())) - addCertMetdata(event.Fields, tlsConn.ConnectionState().PeerCertificates) + versionDetails := tlscommon.TLSVersion(connState.Version).Details() + // The only situation in which versionDetails would be nil is if an unknown TLS version were to be + // encountered. Not filling the fields here makes sense, since there's no standard 'unknown' value. + if versionDetails != nil { + event.PutValue("tls.version_protocol", versionDetails.Protocol) + event.PutValue("tls.version", versionDetails.Version) + } + + if connState.NegotiatedProtocol != "" { + event.PutValue("tls.next_protocol", connState.NegotiatedProtocol) + } + event.PutValue("tls.cipher", tlscommon.ResolveCipherSuite(connState.CipherSuite)) + + addCertMetdata(event.Fields, connState.PeerCertificates) return conn, nil }), nil @@ -105,9 +121,21 @@ func addCertMetdata(fields common.MapStr, certs []*x509.Certificate) { } } + // Legacy non-ECS field fields.Put("tls.certificate_not_valid_before", chainNotValidBefore) + // New ECS compatible field + fields.Put("tls.server.not_before", chainNotValidBefore) if chainNotValidAfter != nil { + // Legacy non-ECS field fields.Put("tls.certificate_not_valid_after", *chainNotValidAfter) + // New ECS compatible field + fields.Put("tls.server.not_after", chainNotValidBefore) } + + hostCert := certs[0] + fields.Put("tls.server.issuer", hostCert.Issuer.String()) + fields.Put("tls.server.subject", hostCert.Subject.String()) + fields.Put("tls.server.hash.sha1", fmt.Sprintf("%x", sha1.Sum(hostCert.Raw))) + fields.Put("tls.server.hash.sha256", fmt.Sprintf("%x", sha256.Sum256(hostCert.Raw))) } diff --git a/libbeat/common/transport/tlscommon/versions.go b/libbeat/common/transport/tlscommon/versions.go index 3ab3dd5a8f0..5cba60a0a42 100644 --- a/libbeat/common/transport/tlscommon/versions.go +++ b/libbeat/common/transport/tlscommon/versions.go @@ -23,12 +23,20 @@ import "fmt" type TLSVersion uint16 func (v TLSVersion) String() string { - if s, ok := tlsProtocolVersionsInverse[v]; ok { - return s + if details := v.Details(); details != nil { + return details.Combined } return "unknown" } +func (v TLSVersion) Details() *protocolAndVersion { + if found, ok := tlsInverseLookup[v]; ok { + return &found + } + return nil +} + + //Unpack transforms the string into a constant. func (v *TLSVersion) Unpack(s string) error { version, found := tlsProtocolVersions[s] diff --git a/libbeat/common/transport/tlscommon/versions_default.go b/libbeat/common/transport/tlscommon/versions_default.go index 057c5c59cd4..37e51c8a4fa 100644 --- a/libbeat/common/transport/tlscommon/versions_default.go +++ b/libbeat/common/transport/tlscommon/versions_default.go @@ -19,7 +19,9 @@ package tlscommon -import "crypto/tls" +import ( + "crypto/tls" +) // Define all the possible TLS version. const ( @@ -61,10 +63,22 @@ var tlsProtocolVersions = map[string]TLSVersion{ "TLSv1.3": TLSVersion13, } -var tlsProtocolVersionsInverse = map[TLSVersion]string{ - TLSVersionSSL30: "SSLv3", - TLSVersion10: "TLSv1.0", - TLSVersion11: "TLSv1.1", - TLSVersion12: "TLSv1.2", - TLSVersion13: "TLSv1.3", +// Intended for ECS's tls.version_protocol_field, which does not include +// numeric version and should be lower case +type protocolAndVersion struct { + Version string + Protocol string + Combined string +} + +func (pv protocolAndVersion) String() string { + return pv.Combined +} + +var tlsInverseLookup = map [TLSVersion]protocolAndVersion{ + TLSVersionSSL30: protocolAndVersion{Version: "3.0", Protocol: "ssl", Combined: "SSLv3"}, + TLSVersion10: protocolAndVersion{Version: "1.0", Protocol: "tls", Combined: "TLSv1.0"}, + TLSVersion11: protocolAndVersion{Version: "1.1", Protocol: "tls", Combined: "TLSv1.1"}, + TLSVersion12: protocolAndVersion{Version: "1.2", Protocol: "tls", Combined: "TLSv1.2"}, + TLSVersion13: protocolAndVersion{Version: "1.3", Protocol: "tls", Combined: "TLSv1.3"}, } From ba10d51b21243558b19f1ea4ce3dd6d76d6dd191 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Mon, 13 Apr 2020 14:29:37 -0500 Subject: [PATCH 02/25] Improve TLS versions API + add tests --- .../common/transport/tlscommon/versions.go | 3 +- .../transport/tlscommon/versions_default.go | 16 ++--- .../transport/tlscommon/versions_test.go | 59 +++++++++++++++++++ 3 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 libbeat/common/transport/tlscommon/versions_test.go diff --git a/libbeat/common/transport/tlscommon/versions.go b/libbeat/common/transport/tlscommon/versions.go index 5cba60a0a42..7de9e5f66e0 100644 --- a/libbeat/common/transport/tlscommon/versions.go +++ b/libbeat/common/transport/tlscommon/versions.go @@ -29,7 +29,8 @@ func (v TLSVersion) String() string { return "unknown" } -func (v TLSVersion) Details() *protocolAndVersion { +// Details returns a a ProtocolAndVersions struct containing detailed version metadata. +func (v TLSVersion) Details() *TLSVersionDetails { if found, ok := tlsInverseLookup[v]; ok { return &found } diff --git a/libbeat/common/transport/tlscommon/versions_default.go b/libbeat/common/transport/tlscommon/versions_default.go index 37e51c8a4fa..e270e9a00ab 100644 --- a/libbeat/common/transport/tlscommon/versions_default.go +++ b/libbeat/common/transport/tlscommon/versions_default.go @@ -65,20 +65,20 @@ var tlsProtocolVersions = map[string]TLSVersion{ // Intended for ECS's tls.version_protocol_field, which does not include // numeric version and should be lower case -type protocolAndVersion struct { +type TLSVersionDetails struct { Version string Protocol string Combined string } -func (pv protocolAndVersion) String() string { +func (pv TLSVersionDetails) String() string { return pv.Combined } -var tlsInverseLookup = map [TLSVersion]protocolAndVersion{ - TLSVersionSSL30: protocolAndVersion{Version: "3.0", Protocol: "ssl", Combined: "SSLv3"}, - TLSVersion10: protocolAndVersion{Version: "1.0", Protocol: "tls", Combined: "TLSv1.0"}, - TLSVersion11: protocolAndVersion{Version: "1.1", Protocol: "tls", Combined: "TLSv1.1"}, - TLSVersion12: protocolAndVersion{Version: "1.2", Protocol: "tls", Combined: "TLSv1.2"}, - TLSVersion13: protocolAndVersion{Version: "1.3", Protocol: "tls", Combined: "TLSv1.3"}, +var tlsInverseLookup = map [TLSVersion]TLSVersionDetails{ + TLSVersionSSL30: TLSVersionDetails{Version: "3.0", Protocol: "ssl", Combined: "SSLv3"}, + TLSVersion10: TLSVersionDetails{Version: "1.0", Protocol: "tls", Combined: "TLSv1.0"}, + TLSVersion11: TLSVersionDetails{Version: "1.1", Protocol: "tls", Combined: "TLSv1.1"}, + TLSVersion12: TLSVersionDetails{Version: "1.2", Protocol: "tls", Combined: "TLSv1.2"}, + TLSVersion13: TLSVersionDetails{Version: "1.3", Protocol: "tls", Combined: "TLSv1.3"}, } diff --git a/libbeat/common/transport/tlscommon/versions_test.go b/libbeat/common/transport/tlscommon/versions_test.go new file mode 100644 index 00000000000..cce87d918a9 --- /dev/null +++ b/libbeat/common/transport/tlscommon/versions_test.go @@ -0,0 +1,59 @@ +package tlscommon + +import ( + "crypto/tls" + "github.com/stretchr/testify/require" + "testing" +) + +func TestTLSVersion(t *testing.T) { + // These tests are a bit verbose, but given the sensitivity to changes here, it's not a bad idea. + tests := []struct { + name string + v uint16 + want *TLSVersionDetails + }{ + { + "unknown", + 0x0, + nil, + }, + { + "SSLv3", + tls.VersionSSL30, + &TLSVersionDetails{Version: "3.0", Protocol: "ssl", Combined: "SSLv3"}, + }, + { + "TLSv1.0", + tls.VersionTLS10, + &TLSVersionDetails{Version: "1.0", Protocol: "tls", Combined: "TLSv1.0"}, + }, + { + "TLSv1.1", + tls.VersionTLS11, + &TLSVersionDetails{Version: "1.1", Protocol: "tls", Combined: "TLSv1.1"}, + }, + { + "TLSv1.2", + tls.VersionTLS12, + &TLSVersionDetails{Version: "1.2", Protocol: "tls", Combined: "TLSv1.2"}, + }, + { + "TLSv1.3", + tls.VersionTLS13, + &TLSVersionDetails{Version: "1.3", Protocol: "tls", Combined: "TLSv1.3"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tv := TLSVersion(tt.v) + require.Equal(t, tt.want, tv.Details()) + if tt.want == nil { + require.Equal(t, tt.want, tv.Details()) + require.Equal(t, tt.name, "unknown") + } else { + require.Equal(t, tt.name, tv.String()) + } + }) + } +} From bfc09744b36e2d64aa08bd8cf15379c210dcf971 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Mon, 13 Apr 2020 17:22:39 -0500 Subject: [PATCH 03/25] Improve testing and code structure --- heartbeat/monitors/active/dialchain/tls.go | 53 +++-- .../monitors/active/dialchain/tls_test.go | 199 +++++++++++++++++- 2 files changed, 217 insertions(+), 35 deletions(-) diff --git a/heartbeat/monitors/active/dialchain/tls.go b/heartbeat/monitors/active/dialchain/tls.go index 692eafce545..8ffbca449f6 100644 --- a/heartbeat/monitors/active/dialchain/tls.go +++ b/heartbeat/monitors/active/dialchain/tls.go @@ -23,10 +23,10 @@ import ( cryptoTLS "crypto/tls" "crypto/x509" "fmt" + "github.com/elastic/beats/v7/heartbeat/look" "net" "time" - "github.com/elastic/beats/v7/heartbeat/look" "github.com/elastic/beats/v7/libbeat/beat" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/transport" @@ -34,14 +34,8 @@ import ( ) // TLSLayer configures the TLS layer in a DialerChain. -// -// The layer will update the active event with: -// -// { -// "tls": { -// "rtt": { "handshake": { "us": ... }} -// } -// } +// The layer will update the active event with the TLS RTT and +// crypto/cert details. func TLSLayer(cfg *tlscommon.TLSConfig, to time.Duration) Layer { return func(event *beat.Event, next transport.Dialer) (transport.Dialer, error) { var timer timer @@ -61,32 +55,35 @@ func TLSLayer(cfg *tlscommon.TLSConfig, to time.Duration) Layer { panic(fmt.Sprintf("TLS afterDial received a non-tls connection %t. This should never happen", conn)) } connState := tlsConn.ConnectionState() - event.PutValue("tls.established", true) - timer.stop() - event.PutValue("tls.rtt.handshake", look.RTT(timer.duration())) - - versionDetails := tlscommon.TLSVersion(connState.Version).Details() - // The only situation in which versionDetails would be nil is if an unknown TLS version were to be - // encountered. Not filling the fields here makes sense, since there's no standard 'unknown' value. - if versionDetails != nil { - event.PutValue("tls.version_protocol", versionDetails.Protocol) - event.PutValue("tls.version", versionDetails.Version) - } - - if connState.NegotiatedProtocol != "" { - event.PutValue("tls.next_protocol", connState.NegotiatedProtocol) - } - event.PutValue("tls.cipher", tlscommon.ResolveCipherSuite(connState.CipherSuite)) - addCertMetdata(event.Fields, connState.PeerCertificates) + addTLSMetadata(event.Fields, connState, timer.duration()) return conn, nil }), nil } } -func addCertMetdata(fields common.MapStr, certs []*x509.Certificate) { +func addTLSMetadata(fields common.MapStr, connState cryptoTLS.ConnectionState, duration time.Duration) { + fields.Put("tls.established", true) + fields.Put("tls.rtt.handshake", look.RTT(duration)) + versionDetails := tlscommon.TLSVersion(connState.Version).Details() + // The only situation in which versionDetails would be nil is if an unknown TLS version were to be + // encountered. Not filling the fields here makes sense, since there's no standard 'unknown' value. + if versionDetails != nil { + fields.Put("tls.version_protocol", versionDetails.Protocol) + fields.Put("tls.version", versionDetails.Version) + } + + if connState.NegotiatedProtocol != "" { + fields.Put("tls.next_protocol", connState.NegotiatedProtocol) + } + fields.Put("tls.cipher", tlscommon.ResolveCipherSuite(connState.CipherSuite)) + + addCertMetadata(fields, connState.PeerCertificates) +} + +func addCertMetadata(fields common.MapStr, certs []*x509.Certificate) { // The behavior here might seem strange. We *always* set a notBefore, but only optionally set a notAfter. // Why might we do this? // The root cause is that the x509.Certificate type uses time.Time for these fields instead of *time.Time @@ -130,7 +127,7 @@ func addCertMetdata(fields common.MapStr, certs []*x509.Certificate) { // Legacy non-ECS field fields.Put("tls.certificate_not_valid_after", *chainNotValidAfter) // New ECS compatible field - fields.Put("tls.server.not_after", chainNotValidBefore) + fields.Put("tls.server.not_after", *chainNotValidAfter) } hostCert := certs[0] diff --git a/heartbeat/monitors/active/dialchain/tls_test.go b/heartbeat/monitors/active/dialchain/tls_test.go index 8df41fbd3b0..951fe44fc6d 100644 --- a/heartbeat/monitors/active/dialchain/tls_test.go +++ b/heartbeat/monitors/active/dialchain/tls_test.go @@ -20,16 +20,69 @@ package dialchain import ( "crypto/x509" "crypto/x509/pkix" + "encoding/pem" + "github.com/elastic/beats/v7/libbeat/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "math/big" "testing" "time" +) - "github.com/stretchr/testify/assert" +func TestAddTLSMetadata(t *testing.T) { - "github.com/elastic/beats/v7/libbeat/common" -) +} -func Test_addCertMetdata(t *testing.T) { +func TestAddCertMetadata(t *testing.T) { + cert := parseCert(t, elasticCert) + chainCert := parseCert(t, elasticChainCert) + certNotBefore, err := time.Parse(time.RFC3339, "2019-08-16T01:40:25Z") + require.NoError(t, err) + certNotAfter, err := time.Parse(time.RFC3339, "2020-07-16T03:15:39Z") + require.NoError(t, err) + + expectedFields := common.MapStr{ + "certificate_not_valid_after": certNotAfter, + "certificate_not_valid_before": certNotBefore, + "server": common.MapStr{ + "hash": common.MapStr{ + "sha1": "b7b4b89ef0d0caf39d223736f0fdbb03c7b426f1", + "sha256": "12b00d04db0db8caa302bfde043e88f95baceb91e86ac143e93830b4bbec726d", + }, + "issuer": "CN=GlobalSign CloudSSL CA - SHA256 - G3,O=GlobalSign nv-sa,C=BE", + "not_after": certNotAfter, + "not_before": certNotBefore, + "subject": "CN=r2.shared.global.fastly.net,O=Fastly\\, Inc.,L=San Francisco,ST=California,C=US", + }, + } + + scenarios := []struct{ + name string + certs []*x509.Certificate + }{ + { + "single cert fields should all be present", + []*x509.Certificate{cert}, + }, + { + "cert chain should still show single cert fields", + []*x509.Certificate{cert, chainCert}, + }, + } + + for _, scenario := range scenarios { + t.Run(scenario.name, func(t *testing.T) { + fields := common.MapStr{} + addCertMetadata(fields, scenario.certs) + tls, err := fields.GetValue("tls") + require.NoError(t, err) + require.Equal(t, expectedFields, tls) + }) + } +} + +// TestCertExpirationMetadata exhaustively tests not before / not after calculation. +func TestCertExpirationMetadata(t *testing.T) { goodNotBefore := time.Now().Add(-time.Hour) goodNotAfter := time.Now().Add(time.Hour) goodCert := x509.Certificate{ @@ -126,15 +179,24 @@ func Test_addCertMetdata(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { event := common.MapStr{} - addCertMetdata(event, tt.certs) - v, err := event.GetValue("tls.certificate_not_valid_before") + addCertMetadata(event, tt.certs) + v, err := event.GetValue("tls.server.not_before") assert.NoError(t, err) assert.Equal(t, tt.expected.notBefore, v) + legacyV, err := event.GetValue("tls.certificate_not_valid_before") + assert.NoError(t, err) + assert.Equal(t, legacyV, v) + if tt.expected.notAfter != nil { - v, err := event.GetValue("tls.certificate_not_valid_after") + v, err := event.GetValue("tls.server.not_after") assert.NoError(t, err) assert.Equal(t, *tt.expected.notAfter, v) + + legacyV, err := event.GetValue("tls.certificate_not_valid_after") + assert.NoError(t, err) + + assert.Equal(t, v, legacyV) } else { ok, _ := event.HasKey("tls.certificate_not_valid_after") assert.False(t, ok, "event should not have not after %v", event) @@ -142,3 +204,126 @@ func Test_addCertMetdata(t *testing.T) { }) } } + +func parseCert(t *testing.T, pemStr string) *x509.Certificate { + block, _ := pem.Decode([]byte(elasticCert)) + if block == nil { + require.Fail(t, "Test cert could not be parsed") + } + cert, err := x509.ParseCertificate(block.Bytes) + require.NoError(t, err) + return cert +} + +var elasticCert = `-----BEGIN CERTIFICATE----- +MIIPLzCCDhegAwIBAgIMVfu5x96/CYCdEsyqMA0GCSqGSIb3DQEBCwUAMFcxCzAJ +BgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS0wKwYDVQQDEyRH +bG9iYWxTaWduIENsb3VkU1NMIENBIC0gU0hBMjU2IC0gRzMwHhcNMTkwODE2MDE0 +MDI1WhcNMjAwNzE2MDMxNTM5WjB3MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2Fs +aWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEVMBMGA1UECgwMRmFzdGx5 +LCBJbmMuMSQwIgYDVQQDDBtyMi5zaGFyZWQuZ2xvYmFsLmZhc3RseS5uZXQwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCnvoHpOqA6CM06MlGViMGMFC4G +YFFEe03GQ5jG3uEUbMNPbl0MSxaWle5xZOVaPcIrV7qyE5yKKDv1fT1e8EkwR+3t +nTK4k2QvH6dPtSPlGHVIjBtS17gM939eZvpvUPxmUc5Ov9cbWgsuStqgFpFjnPBV +R0LqD6YekvS9oXG+4GrNZnQ0wJYF0dbos+E7lRSdniDf/Ul9rF4WAzAEoQYau8pe +eIPlJy8rVrDEgqfCQabYXrLaG68EHHMGadY2EX0yyI/SZh9AU8RdatNHBwj42LGP +9dp3fyEv14usJPGuLVy+8I7TMckQPpPB+NLFECJMwRRfciPjibw1MMSYTOWnAgMB +AAGjggvZMIIL1TAOBgNVHQ8BAf8EBAMCBaAwgYoGCCsGAQUFBwEBBH4wfDBCBggr +BgEFBQcwAoY2aHR0cDovL3NlY3VyZS5nbG9iYWxzaWduLmNvbS9jYWNlcnQvY2xv +dWRzc2xzaGEyZzMuY3J0MDYGCCsGAQUFBzABhipodHRwOi8vb2NzcDIuZ2xvYmFs +c2lnbi5jb20vY2xvdWRzc2xzaGEyZzMwVgYDVR0gBE8wTTBBBgkrBgEEAaAyARQw +NDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFsc2lnbi5jb20vcmVwb3Np +dG9yeS8wCAYGZ4EMAQICMAkGA1UdEwQCMAAwgglrBgNVHREEggliMIIJXoIbcjIu +c2hhcmVkLmdsb2JhbC5mYXN0bHkubmV0ghEqLmFtcGlmeW11c2ljLmNvbYIPKi5h +cGkuZ2lwaHkuY29tghAqLmFwcC5yb213b2QuY29tghAqLmF3YXl0cmF2ZWwuY29t +ghIqLmJmaWZsYXJlbGl2ZS5jb22CECouYmlsbGluZ2FybS5jb22CCiouYnJhemUu +ZXWCFSouY2FsZ2FyeXN0YW1wZWRlLmNvbYIQKi5jZG4udHJpbGxlci5jb4INKi5j +aXR5bWFwcy5pb4IOKi5kZWFsZXJvbi5jb22CDSouZG92ZW1lZC5jb22CDCouZWxh +c3RpYy5jb4IPKi5mZmhhbmRiYWxsLmZyghEqLmZsZXhzaG9wcGVyLmNvbYIPKi5m +bGlwcC1hZHMuY29tghcqLmZsb3JpZGFldmVyYmxhZGVzLmNvbYIYKi5mb2N1c3Jp +dGUtbm92YXRpb24uY29tghAqLmZyZXNoYm9va3MuY29tggsqLmdpcGh5LmNvbYIV +Ki5pZGFob3N0ZWVsaGVhZHMuY29tghAqLmludGVyYWN0bm93LnR2ghEqLmtjbWF2 +ZXJpY2tzLmNvbYIMKi5rb21ldHMuY29tghEqLm1lZGlhLmdpcGh5LmNvbYIKKi5t +bnRkLm5ldIIMKi5uYXNjYXIuY29tghUqLm9tbmlnb25wcm9zdWl0ZS5jb22CHSou +b3JsYW5kb3NvbGFyYmVhcnNob2NrZXkuY29tggwqLnByZWlzMjQuZGWCDSoucWEu +bW50ZC5uZXSCEyoucmV2ZXJiLWFzc2V0cy5jb22CDCoucmV2ZXJiLmNvbYIMKi5y +b213b2QuY29tghMqLnNjb290ZXJsb3VuZ2UuY29tghgqLnN0YWdpbmcuYmlsbGlu +Z2Vudi5jb22CFiouc3RhZ2luZy5mcmVzaGVudi5jb22CEiouc3dhbXByYWJiaXRz +LmNvbYILKi52ZXJzZS5jb22CDSoudmlkeWFyZC5jb22CDioudmlld2VkaXQuY29t +ghEqLnZvdGVub3cubmJjLmNvbYIMKi52b3Rlbm93LnR2ggsqLndheWluLmNvbYIb +Ki53ZXN0bWluc3Rlcmtlbm5lbGNsdWIub3Jngg9hbXBpZnltdXNpYy5jb22CE2Fw +aS5yZXZlcmJzaXRlcy5jb22CGGFwaS5zdGFnaW5nLmZyZXNoZW52LmNvbYIbYXBp +LnN0YWdpbmcucmV2ZXJic2l0ZXMuY29tgg5hd2F5dHJhdmVsLmNvbYIQYmZpZmxh +cmVsaXZlLmNvbYITYmZsLXRlc3QuYWJjLmdvLmNvbYIOYmZsLmFiYy5nby5jb22C +CGJyYXplLmV1gh5jZG4taW1hZ2VzLmZsaXBwZW50ZXJwcmlzZS5uZXSCF2Nkbi5m +bGlwcGVudGVycHJpc2UubmV0ghJjb3Ntb3NtYWdhemluZS5jb22CDGRlYWxlcm9u +LmNvbYILZG92ZW1lZC5jb22CHWR3dHN2b3RlLWxpdmUtdGVzdC5hYmMuZ28uY29t +ghhkd3Rzdm90ZS1saXZlLmFiYy5nby5jb22CGGR3dHN2b3RlLXRlc3QuYWJjLmdv +LmNvbYITZHd0c3ZvdGUuYWJjLmdvLmNvbYIKZWxhc3RpYy5jb4IMZW1haWwua2du +LmlvghJmLmNsb3VkLmdpdGh1Yi5jb22CHWZhbmJvb3N0LXRlc3QuZmlhZm9ybXVs +YWUuY29tghhmYW5ib29zdC5maWFmb3JtdWxhZS5jb22CDWZmaGFuZGJhbGwuZnKC +D2ZsZXhzaG9wcGVyLmNvbYIVZmxvcmlkYWV2ZXJibGFkZXMuY29tgglnaXBoeS5j +b22CFWdvLmNvbmNhY2FmbGVhZ3VlLmNvbYIcZ28uY29uY2FjYWZuYXRpb25zbGVh +Z3VlLmNvbYIGZ3BoLmlzghNpZGFob3N0ZWVsaGVhZHMuY29tghNpZG9sdm90ZS5h +YmMuZ28uY29tgg1pbmZyb250LnNwb3J0gg5pbnRlcmFjdG5vdy50doIPa2NtYXZl +cmlja3MuY29tggprb21ldHMuY29tghptYWlsLmRldmVsb3BtZW50LmJyYXplLmNv +bYIWbWFuY2hlc3Rlcm1vbmFyY2hzLmNvbYIWbWVkaWEud29ya2FuZG1vbmV5LmNv +bYIXbXkuc3RhZ2luZy5mcmVzaGVudi5jb22CG29ybGFuZG9zb2xhcmJlYXJzaG9j +a2V5LmNvbYIUcGNhLXRlc3QuZW9ubGluZS5jb22CD3BjYS5lb25saW5lLmNvbYIh +cGxmcGwtZmFzdGx5LnN0YWdpbmcuaXNtZ2FtZXMuY29tggpwcmVpczI0LmRlghRw +cmVtaWVyZXNwZWFrZXJzLmNvbYILcWEudGVub3IuY2+CDHFhLnRlbm9yLmNvbYIe +cm9ib3RpYy1jb29rLnNlY3JldGNkbi1zdGcubmV0ghFzY29vdGVybG91bmdlLmNv +bYIac3RhZ2luZy13d3cuZWFzYS5ldXJvcGEuZXWCGHN0YWdpbmcuZGFpbHkuc3F1 +aXJ0Lm9yZ4IUc3RhZ2luZy5mcmVzaGVudi5jb22CEHN3YW1wcmFiYml0cy5jb22C +CHRlbm9yLmNvggl0ZW5vci5jb22CFnRyYWNrLnN3ZWVuZXktbWFpbC5jb22CEHVh +dC5mcmVzaGVudi5jb22CE3VuaWZvcm1zaW5zdG9jay5jb22CF3VzZXJzLnByZW1p +ZXJsZWFndWUuY29tghF1dGFoZ3JpenpsaWVzLmNvbYIJdmVyc2UuY29tggt2aWR5 +YXJkLmNvbYIMdmlld2VkaXQuY29tggp2b3Rlbm93LnR2ggl3YXlpbi5jb22CGXdl +c3RtaW5zdGVya2VubmVsY2x1Yi5vcmeCEXd3dy5jaGlxdWVsbGUuY29tghB3d3cu +Y2hpcXVlbGxlLnNlghJ3d3cuZWFzYS5ldXJvcGEuZXWCGnd3dy5pc3JhZWxuYXRp +b25hbG5ld3MuY29tghh3d3cua29nYW5pbnRlcm5ldC5jb20uYXWCDHd3dy50ZW5v +ci5jb4INd3d3LnRlbm9yLmNvbYIUd3d3LnVhdC5mcmVzaGVudi5jb22CF3d3dy51 +bmlmb3Jtc2luc3RvY2suY29tghV3d3cudXRhaGdyaXp6bGllcy5jb20wHQYDVR0l +BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB8GA1UdIwQYMBaAFKkrh+HOJEc7G7/P +hTcCVZ0NlFjmMB0GA1UdDgQWBBQ7SJi8MbyN4XPx+T1QVj4sLHjhDjCCAQMGCisG +AQQB1nkCBAIEgfQEgfEA7wB1AId1v+dZfPiMQ5lfvfNu/1aNR1Y2/0q1YMG06v9e +oIMPAAABbJgVTmEAAAQDAEYwRAIgeYcRKQDCMIBnswrwBvmmSpCFWhjGl+zabCpo +E3R9nJcCIBaAx/TYKESO7iz+hU6bq7Dwzo0QpTIvho4ZdFfSAAHMAHYAsh4FzIui +zYogTodm+Su5iiUgZ2va+nDnsklTLe+LkF4AAAFsmBVLIQAABAMARzBFAiAfLUaq +ukt75a1pySCxrreQ/+/IAdyOSqXqbH1tZNKlTAIhALlcthwbBCfSSNEjTeJWOXss +clzGt9zAk256uboF0iFLMA0GCSqGSIb3DQEBCwUAA4IBAQCZXc5cmMCeqIVsRnRH +KsuGlT6tP2NdsK1+b9dJguP0zbQoxLg5qBMjRGjDo8BpGOni5mJmRJYDQ/GHKP/d +bd+n/4BDD5jI5/rtl43D+Y1G3S5tCRX/3s+At1LJcuaVRmvnywfE9OLXpI84SWtU +AainsxdCYcvopTOZG9UwkjyuEBV3tVsiQkhRSAzYStM75caRWer2pP7i3AwKNv29 +DDSHahXxUyjgAbD2XQojODT/AltEvuqcSrB2cRGXultLmJXFNDEQ5Om4GcjAk75D +pzNLvZuaXHwWoYdm+YTwdPwuZhWe9TxMYlpZbQR8dux2QXRfARF07Vi0+gOzPE9V +RG7L +-----END CERTIFICATE-----` + +var elasticChainCert = `-----BEGIN CERTIFICATE----- +MIIEizCCA3OgAwIBAgIORvCM288sVGbvMwHdXzQwDQYJKoZIhvcNAQELBQAwVzEL +MAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsT +B1Jvb3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xNTA4MTkw +MDAwMDBaFw0yNTA4MTkwMDAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBH +bG9iYWxTaWduIG52LXNhMS0wKwYDVQQDEyRHbG9iYWxTaWduIENsb3VkU1NMIENB +IC0gU0hBMjU2IC0gRzMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCj +wHXhMpjl2a6EfI3oI19GlVtMoiVw15AEhYDJtfSKZU2Sy6XEQqC2eSUx7fGFIM0T +UT1nrJdNaJszhlyzey2q33egYdH1PPua/NPVlMrJHoAbkJDIrI32YBecMbjFYaLi +blclCG8kmZnPlL/Hi2uwH8oU+hibbBB8mSvaSmPlsk7C/T4QC0j0dwsv8JZLOu69 +Nd6FjdoTDs4BxHHT03fFCKZgOSWnJ2lcg9FvdnjuxURbRb0pO+LGCQ+ivivc41za +Wm+O58kHa36hwFOVgongeFxyqGy+Z2ur5zPZh/L4XCf09io7h+/awkfav6zrJ2R7 +TFPrNOEvmyBNVBJrfSi9AgMBAAGjggFTMIIBTzAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8CAQAw +HQYDVR0OBBYEFKkrh+HOJEc7G7/PhTcCVZ0NlFjmMB8GA1UdIwQYMBaAFGB7ZhpF +DZfKiVAvfQTNNKj//P1LMD0GCCsGAQUFBwEBBDEwLzAtBggrBgEFBQcwAYYhaHR0 +cDovL29jc3AuZ2xvYmFsc2lnbi5jb20vcm9vdHIxMDMGA1UdHwQsMCowKKAmoCSG +Imh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vcm9vdC5jcmwwVgYDVR0gBE8wTTAL +BgkrBgEEAaAyARQwPgYGZ4EMAQICMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3 +Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMA0GCSqGSIb3DQEBCwUAA4IBAQCi +HWmKCo7EFIMqKhJNOSeQTvCNrNKWYkc2XpLR+sWTtTcHZSnS9FNQa8n0/jT13bgd ++vzcFKxWlCecQqoETbftWNmZ0knmIC/Tp3e4Koka76fPhi3WU+kLk5xOq9lF7qSE +hf805A7Au6XOX5WJhXCqwV3szyvT2YPfA8qBpwIyt3dhECVO2XTz2XmCtSZwtFK8 +jzPXiq4Z0PySrS+6PKBIWEde/SBWlSDBch2rZpmk1Xg3SBufskw3Z3r9QtLTVp7T +HY7EDGiWtkdREPd76xUJZPX58GMWLT3fI0I6k2PMq69PVwbH/hRVYs4nERnh9ELt +IjBrNRpKBYCkZd/My2/Q +-----END CERTIFICATE-----` From b11e5c41f20aa22710426f390774822033d8031a Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Mon, 13 Apr 2020 17:25:22 -0500 Subject: [PATCH 04/25] Improve fmt and docs --- .../active/dialchain/_meta/fields.yml | 6 +- heartbeat/monitors/active/dialchain/tls.go | 3 +- .../monitors/active/dialchain/tls_test.go | 79 +++++++++++++++++-- 3 files changed, 80 insertions(+), 8 deletions(-) diff --git a/heartbeat/monitors/active/dialchain/_meta/fields.yml b/heartbeat/monitors/active/dialchain/_meta/fields.yml index 5d4991a9704..dc9955b7064 100644 --- a/heartbeat/monitors/active/dialchain/_meta/fields.yml +++ b/heartbeat/monitors/active/dialchain/_meta/fields.yml @@ -34,10 +34,12 @@ fields: - name: certificate_not_valid_before type: date - description: Earliest time at which the connection's certificates are valid. + deprecated: 7.8.0 + description: Deprecated in favor of `tls.server.not_before`. Earliest time at which the connection's certificates are valid. - name: certificate_not_valid_after + deprecated: 7.8.0 type: date - description: Latest time at which the connection's certificates are valid. + description: Deprecated in favor of `tls.server.not_after`. Latest time at which the connection's certificates are valid. - name: rtt type: group description: > diff --git a/heartbeat/monitors/active/dialchain/tls.go b/heartbeat/monitors/active/dialchain/tls.go index 8ffbca449f6..0cb038ef849 100644 --- a/heartbeat/monitors/active/dialchain/tls.go +++ b/heartbeat/monitors/active/dialchain/tls.go @@ -23,10 +23,11 @@ import ( cryptoTLS "crypto/tls" "crypto/x509" "fmt" - "github.com/elastic/beats/v7/heartbeat/look" "net" "time" + "github.com/elastic/beats/v7/heartbeat/look" + "github.com/elastic/beats/v7/libbeat/beat" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/transport" diff --git a/heartbeat/monitors/active/dialchain/tls_test.go b/heartbeat/monitors/active/dialchain/tls_test.go index 951fe44fc6d..f87133b96b3 100644 --- a/heartbeat/monitors/active/dialchain/tls_test.go +++ b/heartbeat/monitors/active/dialchain/tls_test.go @@ -18,19 +18,88 @@ package dialchain import ( + "crypto/tls" "crypto/x509" "crypto/x509/pkix" "encoding/pem" - "github.com/elastic/beats/v7/libbeat/common" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "math/big" "testing" "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/elastic/beats/v7/heartbeat/look" + "github.com/elastic/beats/v7/libbeat/common" ) +// Tests for the non-cert fields func TestAddTLSMetadata(t *testing.T) { + // We always test with this one cert because addCertificateMetadata + // is tested in detail elsewhere + certs := []*x509.Certificate{parseCert(t, elasticCert)} + certMetadata := common.MapStr{} + addCertMetadata(certMetadata, certs) + + scenarios := []struct { + name string + connState tls.ConnectionState + duration time.Duration + expected common.MapStr + }{ + { + "simple TLSv1.1", + tls.ConnectionState{ + Version: tls.VersionTLS11, + HandshakeComplete: true, + PeerCertificates: certs, + CipherSuite: tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + ServerName: "example.net", + }, + time.Duration(1), + common.MapStr{ + "established": true, + "rtt": common.MapStr{"handshake": look.RTT(time.Duration(1))}, + "version_protocol": "tls", + "version": "1.1", + "cipher": "ECDHE-ECDSA-AES-256-CBC-SHA", + }, + }, + { + "TLSv1.2 with next_protocol", + tls.ConnectionState{ + Version: tls.VersionTLS12, + HandshakeComplete: true, + PeerCertificates: certs, + CipherSuite: tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + ServerName: "example.net", + NegotiatedProtocol: "h2", + }, + time.Duration(1), + common.MapStr{ + "established": true, + "rtt": common.MapStr{"handshake": look.RTT(time.Duration(1))}, + "version_protocol": "tls", + "version": "1.2", + "cipher": "ECDHE-ECDSA-AES-256-CBC-SHA", + "next_protocol": "h2", + }, + }, + } + + for _, s := range scenarios { + t.Run(s.name, func(t *testing.T) { + // Nest under the TLS namespace to match actual output + expected := common.MapStr{"tls": s.expected} + + // Always add in the cert metadata since we test that in other test funcs, not here + expected.DeepUpdate(certMetadata) + fields := common.MapStr{} + addTLSMetadata(fields, s.connState, s.duration) + require.Equal(t, expected, fields) + }) + } } func TestAddCertMetadata(t *testing.T) { @@ -56,8 +125,8 @@ func TestAddCertMetadata(t *testing.T) { }, } - scenarios := []struct{ - name string + scenarios := []struct { + name string certs []*x509.Certificate }{ { From 1187c26394c295719e66804357f8cd41f3ff2546 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Mon, 13 Apr 2020 17:26:33 -0500 Subject: [PATCH 05/25] Add changelog --- CHANGELOG.next.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index ab510925770..09f4d1e3420 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -256,7 +256,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d *Heartbeat* - Allow a list of status codes for HTTP checks. {pull}15587[15587] - +- Add additional ECS compatible fields for TLS information. {pull}17687[17687] *Journalbeat* From 2c65b20e8cf911e6267d8fed31509033089966f1 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Mon, 13 Apr 2020 17:51:20 -0500 Subject: [PATCH 06/25] Add TLS1.3 Ciphers --- libbeat/common/transport/tlscommon/types.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libbeat/common/transport/tlscommon/types.go b/libbeat/common/transport/tlscommon/types.go index 3fb96712b16..1ee4bf2440c 100644 --- a/libbeat/common/transport/tlscommon/types.go +++ b/libbeat/common/transport/tlscommon/types.go @@ -65,6 +65,10 @@ var tlsCipherSuites = map[string]tlsCipherSuite{ "RSA-AES-128-GCM-SHA256": tlsCipherSuite(tls.TLS_RSA_WITH_AES_128_GCM_SHA256), "RSA-AES-256-CBC-SHA": tlsCipherSuite(tls.TLS_RSA_WITH_AES_256_CBC_SHA), "RSA-AES-256-GCM-SHA384": tlsCipherSuite(tls.TLS_RSA_WITH_AES_256_GCM_SHA384), + + "TLS-AES-128-GCM-SHA256": tlsCipherSuite(tls.TLS_AES_128_GCM_SHA256), + "TLS-AES-256-GCM-SHA384": tlsCipherSuite(tls.TLS_AES_256_GCM_SHA384), + "TLS-CHACHA20-POLY1305-SHA256": tlsCipherSuite(tls.TLS_CHACHA20_POLY1305_SHA256), } var tlsCipherSuitesInverse = make(map[tlsCipherSuite]string, len(tlsCipherSuites)) From b063621fea3ff6abecf47db90f45d64a1fc8ae6a Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Mon, 13 Apr 2020 17:56:35 -0500 Subject: [PATCH 07/25] Update tests --- heartbeat/hbtest/hbtestutil.go | 24 +++++++++++++------ heartbeat/monitors/active/dialchain/tls.go | 8 +++---- .../monitors/active/dialchain/tls_test.go | 10 ++++---- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/heartbeat/hbtest/hbtestutil.go b/heartbeat/hbtest/hbtestutil.go index 9bec84ee0b5..21b0d32043b 100644 --- a/heartbeat/hbtest/hbtestutil.go +++ b/heartbeat/hbtest/hbtestutil.go @@ -18,8 +18,11 @@ package hbtest import ( + "crypto/tls" "crypto/x509" "fmt" + "github.com/elastic/beats/v7/heartbeat/monitors/active/dialchain" + "github.com/elastic/beats/v7/libbeat/common" "io" "io/ioutil" "net/http" @@ -29,6 +32,7 @@ import ( "strconv" "strings" "testing" + "time" "github.com/elastic/beats/v7/heartbeat/hbtestllext" @@ -107,13 +111,19 @@ func ServerPort(server *httptest.Server) (uint16, error) { // TLSChecks validates the given x509 cert at the given position. func TLSChecks(chainIndex, certIndex int, certificate *x509.Certificate) validator.Validator { - return lookslike.MustCompile(map[string]interface{}{ - "tls": map[string]interface{}{ - "rtt.handshake.us": isdef.IsDuration, - "certificate_not_valid_before": certificate.NotBefore, - "certificate_not_valid_after": certificate.NotAfter, - }, - }) + expected := common.MapStr{} + // This function is well tested independently, so we just test that things match up here. + dialchain.AddTLSMetadata(expected, tls.ConnectionState{ + Version: tls.VersionTLS13, + HandshakeComplete: true, + CipherSuite: tls.TLS_AES_128_GCM_SHA256, + ServerName: certificate.Subject.CommonName, + PeerCertificates: []*x509.Certificate{certificate}, + }, time.Duration(1)) + + expected.Put("tls.rtt.handshake.us", isdef.IsDuration) + + return lookslike.MustCompile(expected) } // BaseChecks creates a skima.Validator that represents the "monitor" field present diff --git a/heartbeat/monitors/active/dialchain/tls.go b/heartbeat/monitors/active/dialchain/tls.go index 0cb038ef849..1586fdd13de 100644 --- a/heartbeat/monitors/active/dialchain/tls.go +++ b/heartbeat/monitors/active/dialchain/tls.go @@ -58,14 +58,14 @@ func TLSLayer(cfg *tlscommon.TLSConfig, to time.Duration) Layer { connState := tlsConn.ConnectionState() timer.stop() - addTLSMetadata(event.Fields, connState, timer.duration()) + AddTLSMetadata(event.Fields, connState, timer.duration()) return conn, nil }), nil } } -func addTLSMetadata(fields common.MapStr, connState cryptoTLS.ConnectionState, duration time.Duration) { +func AddTLSMetadata(fields common.MapStr, connState cryptoTLS.ConnectionState, duration time.Duration) { fields.Put("tls.established", true) fields.Put("tls.rtt.handshake", look.RTT(duration)) versionDetails := tlscommon.TLSVersion(connState.Version).Details() @@ -81,10 +81,10 @@ func addTLSMetadata(fields common.MapStr, connState cryptoTLS.ConnectionState, d } fields.Put("tls.cipher", tlscommon.ResolveCipherSuite(connState.CipherSuite)) - addCertMetadata(fields, connState.PeerCertificates) + AddCertMetadata(fields, connState.PeerCertificates) } -func addCertMetadata(fields common.MapStr, certs []*x509.Certificate) { +func AddCertMetadata(fields common.MapStr, certs []*x509.Certificate) { // The behavior here might seem strange. We *always* set a notBefore, but only optionally set a notAfter. // Why might we do this? // The root cause is that the x509.Certificate type uses time.Time for these fields instead of *time.Time diff --git a/heartbeat/monitors/active/dialchain/tls_test.go b/heartbeat/monitors/active/dialchain/tls_test.go index f87133b96b3..ea759502c3e 100644 --- a/heartbeat/monitors/active/dialchain/tls_test.go +++ b/heartbeat/monitors/active/dialchain/tls_test.go @@ -39,7 +39,7 @@ func TestAddTLSMetadata(t *testing.T) { // is tested in detail elsewhere certs := []*x509.Certificate{parseCert(t, elasticCert)} certMetadata := common.MapStr{} - addCertMetadata(certMetadata, certs) + AddCertMetadata(certMetadata, certs) scenarios := []struct { name string @@ -96,7 +96,7 @@ func TestAddTLSMetadata(t *testing.T) { expected.DeepUpdate(certMetadata) fields := common.MapStr{} - addTLSMetadata(fields, s.connState, s.duration) + AddTLSMetadata(fields, s.connState, s.duration) require.Equal(t, expected, fields) }) } @@ -142,7 +142,7 @@ func TestAddCertMetadata(t *testing.T) { for _, scenario := range scenarios { t.Run(scenario.name, func(t *testing.T) { fields := common.MapStr{} - addCertMetadata(fields, scenario.certs) + AddCertMetadata(fields, scenario.certs) tls, err := fields.GetValue("tls") require.NoError(t, err) require.Equal(t, expectedFields, tls) @@ -204,7 +204,7 @@ func TestCertExpirationMetadata(t *testing.T) { // notBefore is intentionally not a pointer type because go certificates don't have nullable time types // we cheat a bit and make not after nullable because there's no valid reason to create a cert with go's zero // time. - // see the addCertMetadata function for more info on this. + // see the AddCertMetadata function for more info on this. type expected struct { notBefore time.Time notAfter *time.Time @@ -248,7 +248,7 @@ func TestCertExpirationMetadata(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { event := common.MapStr{} - addCertMetadata(event, tt.certs) + AddCertMetadata(event, tt.certs) v, err := event.GetValue("tls.server.not_before") assert.NoError(t, err) assert.Equal(t, tt.expected.notBefore, v) From 1e061ab8446775cfdca320889a94f841a83dac76 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Mon, 13 Apr 2020 18:02:34 -0500 Subject: [PATCH 08/25] Move TLS metadata to separate package to break cycle --- heartbeat/hbtest/hbtestutil.go | 9 +- heartbeat/monitors/active/dialchain/tls.go | 82 +------------- .../monitors/active/dialchain/tlsmeta/tls.go | 104 ++++++++++++++++++ .../dialchain/{ => tlsmeta}/tls_test.go | 2 +- 4 files changed, 112 insertions(+), 85 deletions(-) create mode 100644 heartbeat/monitors/active/dialchain/tlsmeta/tls.go rename heartbeat/monitors/active/dialchain/{ => tlsmeta}/tls_test.go (99%) diff --git a/heartbeat/hbtest/hbtestutil.go b/heartbeat/hbtest/hbtestutil.go index 21b0d32043b..8760ed32031 100644 --- a/heartbeat/hbtest/hbtestutil.go +++ b/heartbeat/hbtest/hbtestutil.go @@ -21,8 +21,6 @@ import ( "crypto/tls" "crypto/x509" "fmt" - "github.com/elastic/beats/v7/heartbeat/monitors/active/dialchain" - "github.com/elastic/beats/v7/libbeat/common" "io" "io/ioutil" "net/http" @@ -34,6 +32,9 @@ import ( "testing" "time" + "github.com/elastic/beats/v7/heartbeat/monitors/active/dialchain/tlsmeta" + "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/heartbeat/hbtestllext" "github.com/stretchr/testify/require" @@ -113,12 +114,12 @@ func ServerPort(server *httptest.Server) (uint16, error) { func TLSChecks(chainIndex, certIndex int, certificate *x509.Certificate) validator.Validator { expected := common.MapStr{} // This function is well tested independently, so we just test that things match up here. - dialchain.AddTLSMetadata(expected, tls.ConnectionState{ + tlsmeta.AddTLSMetadata(expected, tls.ConnectionState{ Version: tls.VersionTLS13, HandshakeComplete: true, CipherSuite: tls.TLS_AES_128_GCM_SHA256, ServerName: certificate.Subject.CommonName, - PeerCertificates: []*x509.Certificate{certificate}, + PeerCertificates: []*x509.Certificate{certificate}, }, time.Duration(1)) expected.Put("tls.rtt.handshake.us", isdef.IsDuration) diff --git a/heartbeat/monitors/active/dialchain/tls.go b/heartbeat/monitors/active/dialchain/tls.go index 1586fdd13de..b4b2c006dfb 100644 --- a/heartbeat/monitors/active/dialchain/tls.go +++ b/heartbeat/monitors/active/dialchain/tls.go @@ -18,18 +18,13 @@ package dialchain import ( - "crypto/sha1" - "crypto/sha256" cryptoTLS "crypto/tls" - "crypto/x509" "fmt" "net" "time" - "github.com/elastic/beats/v7/heartbeat/look" - + "github.com/elastic/beats/v7/heartbeat/monitors/active/dialchain/tlsmeta" "github.com/elastic/beats/v7/libbeat/beat" - "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/transport" "github.com/elastic/beats/v7/libbeat/common/transport/tlscommon" ) @@ -58,82 +53,9 @@ func TLSLayer(cfg *tlscommon.TLSConfig, to time.Duration) Layer { connState := tlsConn.ConnectionState() timer.stop() - AddTLSMetadata(event.Fields, connState, timer.duration()) + tlsmeta.AddTLSMetadata(event.Fields, connState, timer.duration()) return conn, nil }), nil } } - -func AddTLSMetadata(fields common.MapStr, connState cryptoTLS.ConnectionState, duration time.Duration) { - fields.Put("tls.established", true) - fields.Put("tls.rtt.handshake", look.RTT(duration)) - versionDetails := tlscommon.TLSVersion(connState.Version).Details() - // The only situation in which versionDetails would be nil is if an unknown TLS version were to be - // encountered. Not filling the fields here makes sense, since there's no standard 'unknown' value. - if versionDetails != nil { - fields.Put("tls.version_protocol", versionDetails.Protocol) - fields.Put("tls.version", versionDetails.Version) - } - - if connState.NegotiatedProtocol != "" { - fields.Put("tls.next_protocol", connState.NegotiatedProtocol) - } - fields.Put("tls.cipher", tlscommon.ResolveCipherSuite(connState.CipherSuite)) - - AddCertMetadata(fields, connState.PeerCertificates) -} - -func AddCertMetadata(fields common.MapStr, certs []*x509.Certificate) { - // The behavior here might seem strange. We *always* set a notBefore, but only optionally set a notAfter. - // Why might we do this? - // The root cause is that the x509.Certificate type uses time.Time for these fields instead of *time.Time - // so we have no way to know if the user actually set these fields. The x509 RFC says that only one of the - // two fields must be set. Most tools (including openssl and go's certgen) always set both. BECAUSE WHY NOT - // - // In the wild, however, there are certs missing one of these two fields. - // So, what's the correct behavior here? We cannot know if a field was omitted due to the lack of nullability. - // So, in this case, we try to do what people will want 99.99999999999999999% of the time. - // People might set notBefore to go's zero date intentionally when creating certs. So, we always set that - // field, even if we find a zero value. - // However, it would be weird to set notAfter to the zero value. That could invalidate a cert that was intended - // to be valid forever. So, in that case, we treat the zero value as non-existent. - // This is why notBefore is a time.Time and notAfter is a *time.Time - var chainNotValidBefore time.Time - var chainNotValidAfter *time.Time - - // We need the zero date later - var zeroTime time.Time - - // Here we compute the minimal bounds during which this certificate chain is valid - // To do this correctly, we take the maximum NotBefore and the minimum NotAfter. - // This *should* always wind up being the terminal cert in the chain, but we should - // compute this correctly. - for _, cert := range certs { - if chainNotValidBefore.Before(cert.NotBefore) { - chainNotValidBefore = cert.NotBefore - } - - if cert.NotAfter != zeroTime && (chainNotValidAfter == nil || chainNotValidAfter.After(cert.NotAfter)) { - chainNotValidAfter = &cert.NotAfter - } - } - - // Legacy non-ECS field - fields.Put("tls.certificate_not_valid_before", chainNotValidBefore) - // New ECS compatible field - fields.Put("tls.server.not_before", chainNotValidBefore) - - if chainNotValidAfter != nil { - // Legacy non-ECS field - fields.Put("tls.certificate_not_valid_after", *chainNotValidAfter) - // New ECS compatible field - fields.Put("tls.server.not_after", *chainNotValidAfter) - } - - hostCert := certs[0] - fields.Put("tls.server.issuer", hostCert.Issuer.String()) - fields.Put("tls.server.subject", hostCert.Subject.String()) - fields.Put("tls.server.hash.sha1", fmt.Sprintf("%x", sha1.Sum(hostCert.Raw))) - fields.Put("tls.server.hash.sha256", fmt.Sprintf("%x", sha256.Sum256(hostCert.Raw))) -} diff --git a/heartbeat/monitors/active/dialchain/tlsmeta/tls.go b/heartbeat/monitors/active/dialchain/tlsmeta/tls.go new file mode 100644 index 00000000000..d85745af8b6 --- /dev/null +++ b/heartbeat/monitors/active/dialchain/tlsmeta/tls.go @@ -0,0 +1,104 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package tlsmeta + +import ( + "crypto/sha1" + "crypto/sha256" + cryptoTLS "crypto/tls" + "crypto/x509" + "fmt" + "time" + + "github.com/elastic/beats/v7/heartbeat/look" + "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/common/transport/tlscommon" +) + +func AddTLSMetadata(fields common.MapStr, connState cryptoTLS.ConnectionState, duration time.Duration) { + fields.Put("tls.established", true) + fields.Put("tls.rtt.handshake", look.RTT(duration)) + versionDetails := tlscommon.TLSVersion(connState.Version).Details() + // The only situation in which versionDetails would be nil is if an unknown TLS version were to be + // encountered. Not filling the fields here makes sense, since there's no standard 'unknown' value. + if versionDetails != nil { + fields.Put("tls.version_protocol", versionDetails.Protocol) + fields.Put("tls.version", versionDetails.Version) + } + + if connState.NegotiatedProtocol != "" { + fields.Put("tls.next_protocol", connState.NegotiatedProtocol) + } + fields.Put("tls.cipher", tlscommon.ResolveCipherSuite(connState.CipherSuite)) + + AddCertMetadata(fields, connState.PeerCertificates) +} + +func AddCertMetadata(fields common.MapStr, certs []*x509.Certificate) { + // The behavior here might seem strange. We *always* set a notBefore, but only optionally set a notAfter. + // Why might we do this? + // The root cause is that the x509.Certificate type uses time.Time for these fields instead of *time.Time + // so we have no way to know if the user actually set these fields. The x509 RFC says that only one of the + // two fields must be set. Most tools (including openssl and go's certgen) always set both. BECAUSE WHY NOT + // + // In the wild, however, there are certs missing one of these two fields. + // So, what's the correct behavior here? We cannot know if a field was omitted due to the lack of nullability. + // So, in this case, we try to do what people will want 99.99999999999999999% of the time. + // People might set notBefore to go's zero date intentionally when creating certs. So, we always set that + // field, even if we find a zero value. + // However, it would be weird to set notAfter to the zero value. That could invalidate a cert that was intended + // to be valid forever. So, in that case, we treat the zero value as non-existent. + // This is why notBefore is a time.Time and notAfter is a *time.Time + var chainNotValidBefore time.Time + var chainNotValidAfter *time.Time + + // We need the zero date later + var zeroTime time.Time + + // Here we compute the minimal bounds during which this certificate chain is valid + // To do this correctly, we take the maximum NotBefore and the minimum NotAfter. + // This *should* always wind up being the terminal cert in the chain, but we should + // compute this correctly. + for _, cert := range certs { + if chainNotValidBefore.Before(cert.NotBefore) { + chainNotValidBefore = cert.NotBefore + } + + if cert.NotAfter != zeroTime && (chainNotValidAfter == nil || chainNotValidAfter.After(cert.NotAfter)) { + chainNotValidAfter = &cert.NotAfter + } + } + + // Legacy non-ECS field + fields.Put("tls.certificate_not_valid_before", chainNotValidBefore) + // New ECS compatible field + fields.Put("tls.server.not_before", chainNotValidBefore) + + if chainNotValidAfter != nil { + // Legacy non-ECS field + fields.Put("tls.certificate_not_valid_after", *chainNotValidAfter) + // New ECS compatible field + fields.Put("tls.server.not_after", *chainNotValidAfter) + } + + hostCert := certs[0] + fields.Put("tls.server.issuer", hostCert.Issuer.String()) + fields.Put("tls.server.subject", hostCert.Subject.String()) + fields.Put("tls.server.hash.sha1", fmt.Sprintf("%x", sha1.Sum(hostCert.Raw))) + fields.Put("tls.server.hash.sha256", fmt.Sprintf("%x", sha256.Sum256(hostCert.Raw))) +} diff --git a/heartbeat/monitors/active/dialchain/tls_test.go b/heartbeat/monitors/active/dialchain/tlsmeta/tls_test.go similarity index 99% rename from heartbeat/monitors/active/dialchain/tls_test.go rename to heartbeat/monitors/active/dialchain/tlsmeta/tls_test.go index ea759502c3e..8c26b51a9a6 100644 --- a/heartbeat/monitors/active/dialchain/tls_test.go +++ b/heartbeat/monitors/active/dialchain/tlsmeta/tls_test.go @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -package dialchain +package tlsmeta import ( "crypto/tls" From 69f7fd1085359319fe9ee1be2ae6fa10d5f3f456 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Wed, 15 Apr 2020 17:21:31 -0500 Subject: [PATCH 09/25] Use new x509 ECS fields --- .../monitors/active/dialchain/tlsmeta/tls.go | 48 +++++++++++----- .../active/dialchain/tlsmeta/tls_test.go | 55 ++++++++++++------- 2 files changed, 69 insertions(+), 34 deletions(-) diff --git a/heartbeat/monitors/active/dialchain/tlsmeta/tls.go b/heartbeat/monitors/active/dialchain/tlsmeta/tls.go index d85745af8b6..e0a1e8e8037 100644 --- a/heartbeat/monitors/active/dialchain/tlsmeta/tls.go +++ b/heartbeat/monitors/active/dialchain/tlsmeta/tls.go @@ -18,6 +18,8 @@ package tlsmeta import ( + "crypto/ecdsa" + "crypto/rsa" "crypto/sha1" "crypto/sha256" cryptoTLS "crypto/tls" @@ -52,11 +54,11 @@ func AddTLSMetadata(fields common.MapStr, connState cryptoTLS.ConnectionState, d func AddCertMetadata(fields common.MapStr, certs []*x509.Certificate) { // The behavior here might seem strange. We *always* set a notBefore, but only optionally set a notAfter. // Why might we do this? - // The root cause is that the x509.Certificate type uses time.Time for these fields instead of *time.Time - // so we have no way to know if the user actually set these fields. The x509 RFC says that only one of the - // two fields must be set. Most tools (including openssl and go's certgen) always set both. BECAUSE WHY NOT + // The root cause is that the x509.Certificate type uses time.Time for these tlsFields instead of *time.Time + // so we have no way to know if the user actually set these tlsFields. The x509 RFC says that only one of the + // two tlsFields must be set. Most tools (including openssl and go's certgen) always set both. BECAUSE WHY NOT // - // In the wild, however, there are certs missing one of these two fields. + // In the wild, however, there are certs missing one of these two tlsFields. // So, what's the correct behavior here? We cannot know if a field was omitted due to the lack of nullability. // So, in this case, we try to do what people will want 99.99999999999999999% of the time. // People might set notBefore to go's zero date intentionally when creating certs. So, we always set that @@ -84,21 +86,41 @@ func AddCertMetadata(fields common.MapStr, certs []*x509.Certificate) { } } + hostCert := certs[0] + + x509Fields := common.MapStr{} + serverFields := common.MapStr{"x509": x509Fields} + tlsFields := common.MapStr{"server": serverFields} + + serverFields.Put("hash.sha1", fmt.Sprintf("%x", sha1.Sum(hostCert.Raw))) + serverFields.Put("hash.sha256", fmt.Sprintf("%x", sha256.Sum256(hostCert.Raw))) + + x509Fields.Put("issuer.common_name", hostCert.Issuer.CommonName) + x509Fields.Put("issuer.distinguished_name", hostCert.Issuer.String()) + x509Fields.Put("subject.common_name", hostCert.Subject.CommonName) + x509Fields.Put("subject.distinguished_name", hostCert.Subject.String()) + x509Fields.Put("serial_number", hostCert.SerialNumber.String()) + x509Fields.Put("signature_algorithm", hostCert.SignatureAlgorithm.String()) + x509Fields.Put("public_key_algorithm", hostCert.PublicKeyAlgorithm.String()) + if rsaKey, ok := hostCert.PublicKey.(*rsa.PublicKey); ok { + sizeInBits := rsaKey.Size() * 8 + x509Fields.Put("public_key_size", sizeInBits) + } else if ecdsa, ok := hostCert.PublicKey.(*ecdsa.PublicKey); ok { + x509Fields.Put("public_key_curve", ecdsa.Curve.Params().Name) + } + + // Handle expiration / age, this is a bit weird since we actually use the age of the whole chain // Legacy non-ECS field - fields.Put("tls.certificate_not_valid_before", chainNotValidBefore) + tlsFields.Put("certificate_not_valid_before", chainNotValidBefore) // New ECS compatible field - fields.Put("tls.server.not_before", chainNotValidBefore) + x509Fields.Put("not_before", chainNotValidBefore) if chainNotValidAfter != nil { // Legacy non-ECS field - fields.Put("tls.certificate_not_valid_after", *chainNotValidAfter) + tlsFields.Put("certificate_not_valid_after", *chainNotValidAfter) // New ECS compatible field - fields.Put("tls.server.not_after", *chainNotValidAfter) + x509Fields.Put("not_after", *chainNotValidAfter) } - hostCert := certs[0] - fields.Put("tls.server.issuer", hostCert.Issuer.String()) - fields.Put("tls.server.subject", hostCert.Subject.String()) - fields.Put("tls.server.hash.sha1", fmt.Sprintf("%x", sha1.Sum(hostCert.Raw))) - fields.Put("tls.server.hash.sha256", fmt.Sprintf("%x", sha256.Sum256(hostCert.Raw))) + fields.DeepUpdate(common.MapStr{"tls": tlsFields}) } diff --git a/heartbeat/monitors/active/dialchain/tlsmeta/tls_test.go b/heartbeat/monitors/active/dialchain/tlsmeta/tls_test.go index 8c26b51a9a6..41980d50918 100644 --- a/heartbeat/monitors/active/dialchain/tlsmeta/tls_test.go +++ b/heartbeat/monitors/active/dialchain/tlsmeta/tls_test.go @@ -26,6 +26,9 @@ import ( "testing" "time" + "github.com/elastic/go-lookslike" + "github.com/elastic/go-lookslike/testslike" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -110,7 +113,7 @@ func TestAddCertMetadata(t *testing.T) { certNotAfter, err := time.Parse(time.RFC3339, "2020-07-16T03:15:39Z") require.NoError(t, err) - expectedFields := common.MapStr{ + expectedFields := lookslike.Strict(lookslike.MustCompile(map[string]interface{}{ "certificate_not_valid_after": certNotAfter, "certificate_not_valid_before": certNotBefore, "server": common.MapStr{ @@ -118,12 +121,24 @@ func TestAddCertMetadata(t *testing.T) { "sha1": "b7b4b89ef0d0caf39d223736f0fdbb03c7b426f1", "sha256": "12b00d04db0db8caa302bfde043e88f95baceb91e86ac143e93830b4bbec726d", }, - "issuer": "CN=GlobalSign CloudSSL CA - SHA256 - G3,O=GlobalSign nv-sa,C=BE", - "not_after": certNotAfter, - "not_before": certNotBefore, - "subject": "CN=r2.shared.global.fastly.net,O=Fastly\\, Inc.,L=San Francisco,ST=California,C=US", + "x509": common.MapStr{ + "issuer": common.MapStr{ + "common_name": "GlobalSign CloudSSL CA - SHA256 - G3", + "distinguished_name": "CN=GlobalSign CloudSSL CA - SHA256 - G3,O=GlobalSign nv-sa,C=BE", + }, + "subject": common.MapStr{ + "common_name": "r2.shared.global.fastly.net", + "distinguished_name": "CN=r2.shared.global.fastly.net,O=Fastly\\, Inc.,L=San Francisco,ST=California,C=US", + }, + "not_after": certNotAfter, + "not_before": certNotBefore, + "serial_number": "26610543540289562361990401194", + "signature_algorithm": "SHA256-RSA", + "public_key_algorithm": "RSA", + "public_key_size": 2048, + }, }, - } + })) scenarios := []struct { name string @@ -145,7 +160,7 @@ func TestAddCertMetadata(t *testing.T) { AddCertMetadata(fields, scenario.certs) tls, err := fields.GetValue("tls") require.NoError(t, err) - require.Equal(t, expectedFields, tls) + testslike.Test(t, expectedFields, tls) }) } } @@ -249,26 +264,24 @@ func TestCertExpirationMetadata(t *testing.T) { t.Run(tt.name, func(t *testing.T) { event := common.MapStr{} AddCertMetadata(event, tt.certs) - v, err := event.GetValue("tls.server.not_before") - assert.NoError(t, err) - assert.Equal(t, tt.expected.notBefore, v) - legacyV, err := event.GetValue("tls.certificate_not_valid_before") - assert.NoError(t, err) - assert.Equal(t, legacyV, v) + validateNotBefore := lookslike.MustCompile(map[string]interface{}{ + "tls.certificate_not_valid_before": tt.expected.notBefore, + "tls.server.x509.not_before": tt.expected.notBefore, + }) + testslike.Test(t, validateNotBefore, event) if tt.expected.notAfter != nil { - v, err := event.GetValue("tls.server.not_after") - assert.NoError(t, err) - assert.Equal(t, *tt.expected.notAfter, v) - - legacyV, err := event.GetValue("tls.certificate_not_valid_after") - assert.NoError(t, err) - - assert.Equal(t, v, legacyV) + validateNotAfter := lookslike.MustCompile(map[string]interface{}{ + "tls.certificate_not_valid_after": *tt.expected.notAfter, + "tls.server.x509.not_after": *tt.expected.notAfter, + }) + testslike.Test(t, validateNotAfter, event) } else { ok, _ := event.HasKey("tls.certificate_not_valid_after") assert.False(t, ok, "event should not have not after %v", event) + ok, _ = event.HasKey("tls.server.x509.not_after") + assert.False(t, ok, "event should not have not after %v", event) } }) } From 7b2801a2a685220bf9239372477f4fb5ae8975d7 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Wed, 15 Apr 2020 17:34:50 -0500 Subject: [PATCH 10/25] Better testing --- .../dialchain/tlsmeta/{tls.go => tlsmeta.go} | 87 ++++++++++--------- .../tlsmeta/{tls_test.go => tlsmeta_test.go} | 22 +---- 2 files changed, 48 insertions(+), 61 deletions(-) rename heartbeat/monitors/active/dialchain/tlsmeta/{tls.go => tlsmeta.go} (86%) rename heartbeat/monitors/active/dialchain/tlsmeta/{tls_test.go => tlsmeta_test.go} (94%) diff --git a/heartbeat/monitors/active/dialchain/tlsmeta/tls.go b/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta.go similarity index 86% rename from heartbeat/monitors/active/dialchain/tlsmeta/tls.go rename to heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta.go index e0a1e8e8037..19315bae7cc 100644 --- a/heartbeat/monitors/active/dialchain/tlsmeta/tls.go +++ b/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta.go @@ -52,40 +52,6 @@ func AddTLSMetadata(fields common.MapStr, connState cryptoTLS.ConnectionState, d } func AddCertMetadata(fields common.MapStr, certs []*x509.Certificate) { - // The behavior here might seem strange. We *always* set a notBefore, but only optionally set a notAfter. - // Why might we do this? - // The root cause is that the x509.Certificate type uses time.Time for these tlsFields instead of *time.Time - // so we have no way to know if the user actually set these tlsFields. The x509 RFC says that only one of the - // two tlsFields must be set. Most tools (including openssl and go's certgen) always set both. BECAUSE WHY NOT - // - // In the wild, however, there are certs missing one of these two tlsFields. - // So, what's the correct behavior here? We cannot know if a field was omitted due to the lack of nullability. - // So, in this case, we try to do what people will want 99.99999999999999999% of the time. - // People might set notBefore to go's zero date intentionally when creating certs. So, we always set that - // field, even if we find a zero value. - // However, it would be weird to set notAfter to the zero value. That could invalidate a cert that was intended - // to be valid forever. So, in that case, we treat the zero value as non-existent. - // This is why notBefore is a time.Time and notAfter is a *time.Time - var chainNotValidBefore time.Time - var chainNotValidAfter *time.Time - - // We need the zero date later - var zeroTime time.Time - - // Here we compute the minimal bounds during which this certificate chain is valid - // To do this correctly, we take the maximum NotBefore and the minimum NotAfter. - // This *should* always wind up being the terminal cert in the chain, but we should - // compute this correctly. - for _, cert := range certs { - if chainNotValidBefore.Before(cert.NotBefore) { - chainNotValidBefore = cert.NotBefore - } - - if cert.NotAfter != zeroTime && (chainNotValidAfter == nil || chainNotValidAfter.After(cert.NotAfter)) { - chainNotValidAfter = &cert.NotAfter - } - } - hostCert := certs[0] x509Fields := common.MapStr{} @@ -105,22 +71,57 @@ func AddCertMetadata(fields common.MapStr, certs []*x509.Certificate) { if rsaKey, ok := hostCert.PublicKey.(*rsa.PublicKey); ok { sizeInBits := rsaKey.Size() * 8 x509Fields.Put("public_key_size", sizeInBits) + } else if hostCert.PublicKeyAlgorithm == x509.DSA { + x509Fields.Put("public_key_size", 1024) } else if ecdsa, ok := hostCert.PublicKey.(*ecdsa.PublicKey); ok { x509Fields.Put("public_key_curve", ecdsa.Curve.Params().Name) } - // Handle expiration / age, this is a bit weird since we actually use the age of the whole chain + chainNotBefore, chainNotAfter := calculateCertTimestamps(certs) // Legacy non-ECS field - tlsFields.Put("certificate_not_valid_before", chainNotValidBefore) - // New ECS compatible field - x509Fields.Put("not_before", chainNotValidBefore) - - if chainNotValidAfter != nil { + tlsFields.Put("certificate_not_valid_before", chainNotBefore) + x509Fields.Put("not_before", chainNotBefore) + if chainNotAfter != nil { // Legacy non-ECS field - tlsFields.Put("certificate_not_valid_after", *chainNotValidAfter) - // New ECS compatible field - x509Fields.Put("not_after", *chainNotValidAfter) + tlsFields.Put("certificate_not_valid_after", *chainNotAfter) + x509Fields.Put("not_after", *chainNotAfter) } fields.DeepUpdate(common.MapStr{"tls": tlsFields}) } + +func calculateCertTimestamps(certs []*x509.Certificate) (chainNotBefore time.Time, chainNotAfter *time.Time) { + // The behavior here might seem strange. We *always* set a notBefore, but only optionally set a notAfter. + // Why might we do this? + // The root cause is that the x509.Certificate type uses time.Time for these tlsFields instead of *time.Time + // so we have no way to know if the user actually set these tlsFields. The x509 RFC says that only one of the + // two tlsFields must be set. Most tools (including openssl and go's certgen) always set both. BECAUSE WHY NOT + // + // In the wild, however, there are certs missing one of these two tlsFields. + // So, what's the correct behavior here? We cannot know if a field was omitted due to the lack of nullability. + // So, in this case, we try to do what people will want 99.99999999999999999% of the time. + // People might set notBefore to go's zero date intentionally when creating certs. So, we always set that + // field, even if we find a zero value. + // However, it would be weird to set notAfter to the zero value. That could invalidate a cert that was intended + // to be valid forever. So, in that case, we treat the zero value as non-existent. + // This is why notBefore is a time.Time and notAfter is a *time.Time + + // We need the zero date later + var zeroTime time.Time + + // Here we compute the minimal bounds during which this certificate chain is valid + // To do this correctly, we take the maximum NotBefore and the minimum NotAfter. + // This *should* always wind up being the terminal cert in the chain, but we should + // compute this correctly. + for _, cert := range certs { + if chainNotBefore.Before(cert.NotBefore) { + chainNotBefore = cert.NotBefore + } + + if cert.NotAfter != zeroTime && (chainNotAfter == nil || chainNotAfter.After(cert.NotAfter)) { + chainNotAfter = &cert.NotAfter + } + } + + return +} diff --git a/heartbeat/monitors/active/dialchain/tlsmeta/tls_test.go b/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta_test.go similarity index 94% rename from heartbeat/monitors/active/dialchain/tlsmeta/tls_test.go rename to heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta_test.go index 41980d50918..f2cb4eb01aa 100644 --- a/heartbeat/monitors/active/dialchain/tlsmeta/tls_test.go +++ b/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta_test.go @@ -29,7 +29,6 @@ import ( "github.com/elastic/go-lookslike" "github.com/elastic/go-lookslike/testslike" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/elastic/beats/v7/heartbeat/look" @@ -262,26 +261,13 @@ func TestCertExpirationMetadata(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - event := common.MapStr{} - AddCertMetadata(event, tt.certs) - - validateNotBefore := lookslike.MustCompile(map[string]interface{}{ - "tls.certificate_not_valid_before": tt.expected.notBefore, - "tls.server.x509.not_before": tt.expected.notBefore, - }) - testslike.Test(t, validateNotBefore, event) + notBefore, notAfter := calculateCertTimestamps(tt.certs) + require.Equal(t, tt.expected.notBefore, notBefore) if tt.expected.notAfter != nil { - validateNotAfter := lookslike.MustCompile(map[string]interface{}{ - "tls.certificate_not_valid_after": *tt.expected.notAfter, - "tls.server.x509.not_after": *tt.expected.notAfter, - }) - testslike.Test(t, validateNotAfter, event) + require.Equal(t, tt.expected.notAfter, notAfter) } else { - ok, _ := event.HasKey("tls.certificate_not_valid_after") - assert.False(t, ok, "event should not have not after %v", event) - ok, _ = event.HasKey("tls.server.x509.not_after") - assert.False(t, ok, "event should not have not after %v", event) + require.Nil(t, notAfter) } }) } From ee3c547b5b7843a82c5d718b4221d77761e15ce4 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Wed, 15 Apr 2020 17:56:43 -0500 Subject: [PATCH 11/25] DSA key len --- heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta.go | 9 +++++++-- .../monitors/active/dialchain/tlsmeta/tlsmeta_test.go | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta.go b/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta.go index 19315bae7cc..411c20a1001 100644 --- a/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta.go +++ b/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta.go @@ -18,6 +18,7 @@ package tlsmeta import ( + dsa2 "crypto/dsa" "crypto/ecdsa" "crypto/rsa" "crypto/sha1" @@ -71,8 +72,12 @@ func AddCertMetadata(fields common.MapStr, certs []*x509.Certificate) { if rsaKey, ok := hostCert.PublicKey.(*rsa.PublicKey); ok { sizeInBits := rsaKey.Size() * 8 x509Fields.Put("public_key_size", sizeInBits) - } else if hostCert.PublicKeyAlgorithm == x509.DSA { - x509Fields.Put("public_key_size", 1024) + } else if dsaKey, ok := hostCert.PublicKey.(*dsa2.PublicKey); ok { + if dsaKey.Parameters.P != nil { + x509Fields.Put("public_key_size", len(dsaKey.P.Bytes())*8) + } else { + x509Fields.Put("public_key_size", len(dsaKey.P.Bytes())*8) + } } else if ecdsa, ok := hostCert.PublicKey.(*ecdsa.PublicKey); ok { x509Fields.Put("public_key_curve", ecdsa.Curve.Params().Name) } diff --git a/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta_test.go b/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta_test.go index f2cb4eb01aa..d05b73cc58e 100644 --- a/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta_test.go +++ b/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta_test.go @@ -134,7 +134,7 @@ func TestAddCertMetadata(t *testing.T) { "serial_number": "26610543540289562361990401194", "signature_algorithm": "SHA256-RSA", "public_key_algorithm": "RSA", - "public_key_size": 2048, + "public_key_size": 2049, }, }, })) From 3347a9a16d6b612defddaa9b5f17f71d6458f68f Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Wed, 15 Apr 2020 18:00:19 -0500 Subject: [PATCH 12/25] Add pk exponent --- heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta.go | 1 + heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta_test.go | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta.go b/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta.go index 411c20a1001..686da2a3241 100644 --- a/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta.go +++ b/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta.go @@ -72,6 +72,7 @@ func AddCertMetadata(fields common.MapStr, certs []*x509.Certificate) { if rsaKey, ok := hostCert.PublicKey.(*rsa.PublicKey); ok { sizeInBits := rsaKey.Size() * 8 x509Fields.Put("public_key_size", sizeInBits) + x509Fields.Put("public_key_exponent", rsaKey.E) } else if dsaKey, ok := hostCert.PublicKey.(*dsa2.PublicKey); ok { if dsaKey.Parameters.P != nil { x509Fields.Put("public_key_size", len(dsaKey.P.Bytes())*8) diff --git a/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta_test.go b/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta_test.go index d05b73cc58e..609fbbb413d 100644 --- a/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta_test.go +++ b/heartbeat/monitors/active/dialchain/tlsmeta/tlsmeta_test.go @@ -134,7 +134,8 @@ func TestAddCertMetadata(t *testing.T) { "serial_number": "26610543540289562361990401194", "signature_algorithm": "SHA256-RSA", "public_key_algorithm": "RSA", - "public_key_size": 2049, + "public_key_size": 2048, + "public_key_exponent": 65537, }, }, })) From bfae4288efc18a89b5ac9f8ef3cc93c758c8e247 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Wed, 15 Apr 2020 18:06:42 -0500 Subject: [PATCH 13/25] Enrich x509 data with invalid certs --- heartbeat/monitors/active/dialchain/tls.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/heartbeat/monitors/active/dialchain/tls.go b/heartbeat/monitors/active/dialchain/tls.go index b4b2c006dfb..94b0f657418 100644 --- a/heartbeat/monitors/active/dialchain/tls.go +++ b/heartbeat/monitors/active/dialchain/tls.go @@ -19,6 +19,7 @@ package dialchain import ( cryptoTLS "crypto/tls" + "crypto/x509" "fmt" "net" "time" @@ -42,6 +43,9 @@ func TLSLayer(cfg *tlscommon.TLSConfig, to time.Duration) Layer { dialer, err := transport.TLSDialer(next, cfg, to) if err != nil { + if certErr, ok := err.(x509.CertificateInvalidError); ok { + tlsmeta.AddCertMetadata(event.Fields, []*x509.Certificate{certErr.Cert}) + } return nil, err } From b37947bd766d4700270845fbcddeeac23fe44fe5 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Mon, 20 Apr 2020 10:40:10 -0500 Subject: [PATCH 14/25] Add TLS Cert data for expired HTTP endpoints --- heartbeat/monitors/active/http/task.go | 9 +++++++++ heartbeat/reason/reason.go | 3 +++ 2 files changed, 12 insertions(+) diff --git a/heartbeat/monitors/active/http/task.go b/heartbeat/monitors/active/http/task.go index e750faf6d12..7f59fdaddf0 100644 --- a/heartbeat/monitors/active/http/task.go +++ b/heartbeat/monitors/active/http/task.go @@ -20,10 +20,13 @@ package http import ( "bytes" "context" + "crypto/x509" "fmt" + "github.com/elastic/beats/v7/heartbeat/monitors/active/dialchain/tlsmeta" "io/ioutil" "net" "net/http" + "net/url" "strconv" "strings" "sync" @@ -234,6 +237,12 @@ func execPing( // Send the HTTP request. We don't immediately return on error since // we may want to add additional fields to contextualize the error. start, resp, errReason := execRequest(client, req) + if urlErr, ok := errReason.Unwrap().(*url.Error); ok { + if certErr, ok := urlErr.Err.(x509.CertificateInvalidError); ok { + tlsmeta.AddCertMetadata(event.Fields, []*x509.Certificate{certErr.Cert}) + } + } + // If we have no response object or an error was set there probably was an IO error, we can skip the rest of the logic // since that logic is for adding metadata relating to completed HTTP transactions that have errored diff --git a/heartbeat/reason/reason.go b/heartbeat/reason/reason.go index 677a87a8971..ad1823af8e3 100644 --- a/heartbeat/reason/reason.go +++ b/heartbeat/reason/reason.go @@ -22,6 +22,7 @@ import "github.com/elastic/beats/v7/libbeat/common" type Reason interface { error Type() string + Unwrap() error } type ValidateError struct { @@ -47,9 +48,11 @@ func IOFailed(err error) Reason { } func (e ValidateError) Error() string { return e.err.Error() } +func (e ValidateError) Unwrap() error { return e.err } func (ValidateError) Type() string { return "validate" } func (e IOError) Error() string { return e.err.Error() } +func (e IOError) Unwrap() error { return e.err } func (IOError) Type() string { return "io" } func FailError(typ string, err error) common.MapStr { From 002eb09462f21134a184b768df805ad97a23b24e Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Mon, 20 Apr 2020 10:57:07 -0500 Subject: [PATCH 15/25] Fix sort of imports --- heartbeat/monitors/active/http/task.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/heartbeat/monitors/active/http/task.go b/heartbeat/monitors/active/http/task.go index 7f59fdaddf0..365e6e0b821 100644 --- a/heartbeat/monitors/active/http/task.go +++ b/heartbeat/monitors/active/http/task.go @@ -22,7 +22,6 @@ import ( "context" "crypto/x509" "fmt" - "github.com/elastic/beats/v7/heartbeat/monitors/active/dialchain/tlsmeta" "io/ioutil" "net" "net/http" @@ -32,6 +31,8 @@ import ( "sync" "time" + "github.com/elastic/beats/v7/heartbeat/monitors/active/dialchain/tlsmeta" + "github.com/elastic/beats/v7/heartbeat/eventext" "github.com/elastic/beats/v7/heartbeat/look" "github.com/elastic/beats/v7/heartbeat/monitors" @@ -243,7 +244,6 @@ func execPing( } } - // If we have no response object or an error was set there probably was an IO error, we can skip the rest of the logic // since that logic is for adding metadata relating to completed HTTP transactions that have errored // in other ways From 90578c48b37d617bae7bdd4b4a3b058767c3c16b Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Mon, 20 Apr 2020 13:41:20 -0500 Subject: [PATCH 16/25] Only handle HTTP TLS errors on error --- heartbeat/monitors/active/http/task.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/heartbeat/monitors/active/http/task.go b/heartbeat/monitors/active/http/task.go index 365e6e0b821..9304d7a4aa3 100644 --- a/heartbeat/monitors/active/http/task.go +++ b/heartbeat/monitors/active/http/task.go @@ -22,6 +22,7 @@ import ( "context" "crypto/x509" "fmt" + "github.com/elastic/beats/v7/heartbeat/monitors/active/dialchain/tlsmeta" "io/ioutil" "net" "net/http" @@ -31,8 +32,6 @@ import ( "sync" "time" - "github.com/elastic/beats/v7/heartbeat/monitors/active/dialchain/tlsmeta" - "github.com/elastic/beats/v7/heartbeat/eventext" "github.com/elastic/beats/v7/heartbeat/look" "github.com/elastic/beats/v7/heartbeat/monitors" @@ -238,16 +237,16 @@ func execPing( // Send the HTTP request. We don't immediately return on error since // we may want to add additional fields to contextualize the error. start, resp, errReason := execRequest(client, req) - if urlErr, ok := errReason.Unwrap().(*url.Error); ok { - if certErr, ok := urlErr.Err.(x509.CertificateInvalidError); ok { - tlsmeta.AddCertMetadata(event.Fields, []*x509.Certificate{certErr.Cert}) - } - } - // If we have no response object or an error was set there probably was an IO error, we can skip the rest of the logic // since that logic is for adding metadata relating to completed HTTP transactions that have errored // in other ways if resp == nil || errReason != nil { + if urlErr, ok := errReason.Unwrap().(*url.Error); ok { + if certErr, ok := urlErr.Err.(x509.CertificateInvalidError); ok { + tlsmeta.AddCertMetadata(event.Fields, []*x509.Certificate{certErr.Cert}) + } + } + return start, time.Now(), errReason } From 1eb461b358a326e92fa161f88b650220960d78f7 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Tue, 21 Apr 2020 07:52:53 -0500 Subject: [PATCH 17/25] Record metadata properly for expired certs on TCP --- heartbeat/monitors/active/dialchain/tls.go | 4 ---- heartbeat/monitors/active/tcp/task.go | 5 +++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/heartbeat/monitors/active/dialchain/tls.go b/heartbeat/monitors/active/dialchain/tls.go index 94b0f657418..b4b2c006dfb 100644 --- a/heartbeat/monitors/active/dialchain/tls.go +++ b/heartbeat/monitors/active/dialchain/tls.go @@ -19,7 +19,6 @@ package dialchain import ( cryptoTLS "crypto/tls" - "crypto/x509" "fmt" "net" "time" @@ -43,9 +42,6 @@ func TLSLayer(cfg *tlscommon.TLSConfig, to time.Duration) Layer { dialer, err := transport.TLSDialer(next, cfg, to) if err != nil { - if certErr, ok := err.(x509.CertificateInvalidError); ok { - tlsmeta.AddCertMetadata(event.Fields, []*x509.Certificate{certErr.Cert}) - } return nil, err } diff --git a/heartbeat/monitors/active/tcp/task.go b/heartbeat/monitors/active/tcp/task.go index 3d830c0c7e9..03bef67107c 100644 --- a/heartbeat/monitors/active/tcp/task.go +++ b/heartbeat/monitors/active/tcp/task.go @@ -18,6 +18,8 @@ package tcp import ( + "crypto/x509" + "github.com/elastic/beats/v7/heartbeat/monitors/active/dialchain/tlsmeta" "time" "github.com/elastic/beats/v7/heartbeat/eventext" @@ -40,6 +42,9 @@ func pingHost( conn, err := dialer.Dial("tcp", addr) if err != nil { + if certErr, ok := err.(x509.CertificateInvalidError); ok { + tlsmeta.AddCertMetadata(event.Fields, []*x509.Certificate{certErr.Cert}) + } debugf("dial failed with: %v", err) return reason.IOFailed(err) } From 577f203186be15f77e8b6820551ea2c7a54a3184 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Tue, 21 Apr 2020 14:01:16 -0500 Subject: [PATCH 18/25] start work on expired cert tests --- .../active/http/fixtures/expired.cert | 23 ++++++ .../monitors/active/http/fixtures/expired.key | 28 +++++++ heartbeat/monitors/active/http/http_test.go | 74 +++++++++++++++---- heartbeat/monitors/active/tcp/tls_test.go | 26 +++++++ 4 files changed, 136 insertions(+), 15 deletions(-) create mode 100644 heartbeat/monitors/active/http/fixtures/expired.cert create mode 100644 heartbeat/monitors/active/http/fixtures/expired.key diff --git a/heartbeat/monitors/active/http/fixtures/expired.cert b/heartbeat/monitors/active/http/fixtures/expired.cert new file mode 100644 index 00000000000..e39ad893bd6 --- /dev/null +++ b/heartbeat/monitors/active/http/fixtures/expired.cert @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID3zCCAsegAwIBAgIUS+ahW2wxDZ1bT/qYnenS8jrXUcAwDQYJKoZIhvcNAQEL +BQAwfzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk1OMRQwEgYDVQQHDAtNaW5uZWFw +b2xpczEVMBMGA1UECgwMRWxhc3RpYywgSW5jMRQwEgYDVQQLDAtFbmdpbmVlcmlu +ZzEgMB4GA1UEAwwXZXhwaXJlZHRlc3QuZXhhbXBsZS5uZXQwHhcNMjAwNDIxMTQw +MDE0WhcNMjAwNDIyMTQwMDE0WjB/MQswCQYDVQQGEwJVUzELMAkGA1UECAwCTU4x +FDASBgNVBAcMC01pbm5lYXBvbGlzMRUwEwYDVQQKDAxFbGFzdGljLCBJbmMxFDAS +BgNVBAsMC0VuZ2luZWVyaW5nMSAwHgYDVQQDDBdleHBpcmVkdGVzdC5leGFtcGxl +Lm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKh1iS5EZ7bDSKgW +R3JXAepMIaEewMSdbaoBtuNQb48XJGwI0mudF983a7JxGCSfw9mhVYa4YsSv79UE +XomGrWVrS01Cmf1VRIOmxevWMPhvnE6UH+5VxKUBk5ooNSty4iHkDFy2i5WWjxiv +de6Xqnn/dVQhuT/sW+rU/grCsGcdUwqsWnC547ekqiYRTtyZrdh+U0KRKqy5iBlH +9Woua+CnXmsD7+4MgGekErg9XLRHYveLOmLucbNlAIlRyfMDZL1RlXufcGwhzItz +JNM9N0NJ5bwrpuP0RYlYbbMYal+b1Tn2e8qkMm88hniQkuu69kUpKeewIOr62vIK +tI273GECAwEAAaNTMFEwHQYDVR0OBBYEFKgd6wQcgIdUSjtJREObD+R3q3MPMB8G +A1UdIwQYMBaAFKgd6wQcgIdUSjtJREObD+R3q3MPMA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQELBQADggEBADkBqmCUcvVTqu5IIZ5PLz40jdg2luaDHEA6I2Ga +1ioabETfQhXeaNJflojYm0Bzsy2aneVLGM2KaZ76wN0yvib3MZ4miu4C/mDsR3bB +wq7/CAK2AcJXv1jk0vIrK6DhZfA2HaelBkQ8UHwWK7AO+JmS6jozIt1vySwPI1E7 +lMFWbs3bmsSmunj3+66XS2XguUKzFwUIAEOfsPFqT2OMsPIa7weUWuCV/zMi7fuB +HbgVouYvMTve8wx7+ozDk6CyvlRlx20xwdOvXaH3JILw7gTQWcAEWZLcB2ct1Zks +UTtbIAjBV6s0Pm/2/6MxxkDCVVUpwXiiKBRkHxzkgoH7TQw= +-----END CERTIFICATE----- diff --git a/heartbeat/monitors/active/http/fixtures/expired.key b/heartbeat/monitors/active/http/fixtures/expired.key new file mode 100644 index 00000000000..2a11440f7aa --- /dev/null +++ b/heartbeat/monitors/active/http/fixtures/expired.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCodYkuRGe2w0io +FkdyVwHqTCGhHsDEnW2qAbbjUG+PFyRsCNJrnRffN2uycRgkn8PZoVWGuGLEr+/V +BF6Jhq1la0tNQpn9VUSDpsXr1jD4b5xOlB/uVcSlAZOaKDUrcuIh5AxctouVlo8Y +r3Xul6p5/3VUIbk/7Fvq1P4KwrBnHVMKrFpwueO3pKomEU7cma3YflNCkSqsuYgZ +R/VqLmvgp15rA+/uDIBnpBK4PVy0R2L3izpi7nGzZQCJUcnzA2S9UZV7n3BsIcyL +cyTTPTdDSeW8K6bj9EWJWG2zGGpfm9U59nvKpDJvPIZ4kJLruvZFKSnnsCDq+try +CrSNu9xhAgMBAAECggEBAIc32QYvWESmWeK6B11rI5lqxK+snLT1XLpSp/esb++e +dtjU9/nzXd8JgEP6bZOwPiepTZpW1MjmJA+Lc0rWtMYsqoP4ityDHfzC2CmmgyZX +iFK2qS7I35BHRLA/x/X5QDRN9fJRgJdxA6mf5Xy/dtJ4UDhY3XbHBTzo/IWsoqYQ +4V3WBQYMGlhBArCoOx07pwc9NMTnXwpfe4rUdm3EaGGpe/9JT08JcTyFZfFUeFT1 +lfSYo5i+xPOCQ/FcC5GfWdciyY0c8ej8iwdxZb0kPI4hBu36+D6zD+YoNoC3CQTb +MecRFQ0MeTTuUMCdzFWtg+2FWnJucaLiaK9fKbVzi7UCgYEA0BAlfUdXdeDYMlW3 +2ReeOgH32bchPYwn2UvHYkIhhDp40STVw3BYQ0Zj9yJQXLFaoY1SFhwRJR1kpbSd +IfME/IzR/oMFvRUNQEPQZVH0Mg9FWIXLdXlV4qbU3AyA2r4x+VUCt3jp1n/5rG7g +cmoKBdCXNUAhK30bRGTdXB06Fp8CgYEAz0V+IlkGyDKcyCkja0ypA3AdSod/43az +7HMS3nf32hOFpgQuEtVYZc3NW/rdJFPksnRd6+RlD2nIoHZEa+adl2gESjGH2asw +nhxP/Pr4m8PGZF5BwdILRTVFukf5yrM6g63FgrgA9d+QdCsqoqrctItRyCgcfpL4 +XYXEKVWELP8CgYATxbUKVsFE/n0NK4AxLUFoGc/H7NNH2g3fZIgqGka9HiFlHq8B +x6dbnVDap3QjmucV+ywV1cz7TfPGm4djNoj+xxMdsK3W7i04MjmXp1Yhe7oHU4+m +NkWnKFuKHdYQ84okO6Pqc58lNzwu2sqRlOom60+zS8jbLSRuN3ehzVU72QKBgGm0 +qCo+Ou44maqfCFg9hWiicd3Dkt5feE0bNsFMb5PBJwTO1ux175ojxhqlqshPHLBC +FnAqT7v3mAD1r9lTiIVh3+YysnS5EJdiGw0KtWVDB9fCFkkRpPvLul7RPDw7AZmM +MtGCo8LBHHuSVDEXcG2HK9MnWbjXnWCcyrjFyx3jAoGAYsNGYm+OBr16NNsPtx3S +nRQJz9wqB2mIqNU8rRSjd5EUp03jhHiTEN9DT6iEnLGaTDBUgD2RlPvEVGk1N7FT +nh9tLtg2ytWIC/P+QrKwzdUUa00MSswTxRS3Cmy459UbLBiPgHBJ2h1G7gsiHPOt +erJWqYJ8DXvLzCPdMVzQxj8= +-----END PRIVATE KEY----- diff --git a/heartbeat/monitors/active/http/http_test.go b/heartbeat/monitors/active/http/http_test.go index 2db563d0044..a3ff9be2044 100644 --- a/heartbeat/monitors/active/http/http_test.go +++ b/heartbeat/monitors/active/http/http_test.go @@ -22,6 +22,7 @@ import ( "crypto/x509" "fmt" "io/ioutil" + "net" "net/http" "net/http/httptest" "net/url" @@ -48,13 +49,13 @@ import ( "github.com/elastic/go-lookslike/validator" ) -func testRequest(t *testing.T, testURL string, useUrls bool) *beat.Event { - return testTLSRequest(t, testURL, useUrls, nil) +func sendSimpleTLSRequest(t *testing.T, testURL string, useUrls bool) *beat.Event { + return sendTLSRequest(t, testURL, useUrls, nil) } -// testTLSRequest tests the given request. certPath is optional, if given +// sendTLSRequest tests the given request. certPath is optional, if given // an empty string no cert will be set. -func testTLSRequest(t *testing.T, testURL string, useUrls bool, extraConfig map[string]interface{}) *beat.Event { +func sendTLSRequest(t *testing.T, testURL string, useUrls bool, extraConfig map[string]interface{}) *beat.Event { configSrc := map[string]interface{}{ "timeout": "1s", } @@ -92,7 +93,7 @@ func testTLSRequest(t *testing.T, testURL string, useUrls bool, extraConfig map[ func checkServer(t *testing.T, handlerFunc http.HandlerFunc, useUrls bool) (*httptest.Server, *beat.Event) { server := httptest.NewServer(handlerFunc) defer server.Close() - event := testRequest(t, server.URL, useUrls) + event := sendSimpleTLSRequest(t, server.URL, useUrls) return server, event } @@ -220,13 +221,6 @@ var downStatuses = []int{ http.StatusNetworkAuthenticationRequired, } -func serverHostname(t *testing.T, server *httptest.Server) string { - surl, err := url.Parse(server.URL) - require.NoError(t, err) - - return surl.Hostname() -} - func TestUpStatuses(t *testing.T) { for _, status := range upStatuses { status := status @@ -347,7 +341,7 @@ func runHTTPSServerCheck( // we give it a few attempts to see if the server can come up before we run the real assertions. var event *beat.Event for i := 0; i < 10; i++ { - event = testTLSRequest(t, server.URL, false, mergedExtraConfig) + event = sendTLSRequest(t, server.URL, false, mergedExtraConfig) if v, err := event.GetValue("monitor.status"); err == nil && reflect.DeepEqual(v, "up") { break } @@ -367,12 +361,62 @@ func runHTTPSServerCheck( ) } +func startExpiredTLSEndpoint(t *testing.T) (host string, port string, cert *x509.Certificate, doClose func() error) { + tlsCert, err := tls.LoadX509KeyPair("fixtures/expired.cert", "fixtures/expired.key") + require.NoError(t, err) + + cert, err = x509.ParseCertificate(tlsCert.Certificate[0]) + require.NoError(t, err) + + // No need to start a real server, since this is invalid, we just + l, err := tls.Listen("tcp", "127.0.0.1:0", &tls.Config{ + Certificates: []tls.Certificate{tlsCert}, + }) + require.NoError(t, err) + + go func() { + for { + conn, err := l.Accept() + if err != nil { + break + } + conn.Close() + } + }() + + host, port, err = net.SplitHostPort(l.Addr().String()) + require.NoError(t, err) + return host, port, cert, l.Close +} + func TestHTTPSServer(t *testing.T) { server := httptest.NewTLSServer(hbtest.HelloWorldHandler(http.StatusOK)) runHTTPSServerCheck(t, server, nil) } +func TestExpiredHTTPSServer(t *testing.T) { + host, port, cert, closeSrv := startExpiredTLSEndpoint(t) + defer closeSrv() + u := &url.URL{Scheme: "https", Host: net.JoinHostPort(host,port)} + event := sendTLSRequest(t, u.String(), true, nil) + + testslike.Test( + t, + lookslike.Strict(lookslike.Compose( + hbtest.BaseChecks("127.0.0.1", "up", "http"), + hbtest.RespondingTCPChecks(), + hbtest.TLSChecks(0, 0, cert), + hbtest.SummaryChecks(1, 0), + respondingHTTPChecks( + u.String(), + http.StatusOK, + ), + )), + event.Fields, + ) +} + func TestHTTPSx509Auth(t *testing.T) { wd, err := os.Getwd() require.NoError(t, err) @@ -418,7 +462,7 @@ func TestConnRefusedJob(t *testing.T) { url := fmt.Sprintf("http://%s:%d", ip, port) - event := testRequest(t, url, false) + event := sendSimpleTLSRequest(t, url, false) testslike.Test( t, @@ -440,7 +484,7 @@ func TestUnreachableJob(t *testing.T) { port := uint16(1234) url := fmt.Sprintf("http://%s:%d", ip, port) - event := testRequest(t, url, false) + event := sendSimpleTLSRequest(t, url, false) testslike.Test( t, diff --git a/heartbeat/monitors/active/tcp/tls_test.go b/heartbeat/monitors/active/tcp/tls_test.go index 0628b1694b4..da573e794f2 100644 --- a/heartbeat/monitors/active/tcp/tls_test.go +++ b/heartbeat/monitors/active/tcp/tls_test.go @@ -112,6 +112,32 @@ func TestTLSInvalidCert(t *testing.T) { ) } +func TestTLSExpiredCert(t *testing.T) { + ip, port, cert, certFile, teardown := setupTLSTestServer(t) + defer teardown() + + hostname := cert.DNSNames[0] + event := testTLSTCPCheck(t, hostname, port, certFile.Name(), monitors.NewStdResolver()) + + testslike.Test( + t, + lookslike.Strict(lookslike.Compose( + hbtest.RespondingTCPChecks(), + hbtest.BaseChecks(ip, "down", "tcp"), + hbtest.SummaryChecks(0, 1), + hbtest.SimpleURLChecks(t, "ssl", hostname, port), + hbtest.ResolveChecks(ip), + lookslike.MustCompile(map[string]interface{}{ + "error": map[string]interface{}{ + "message": x509.HostnameError{Certificate: cert, Host: hostname}.Error(), + "type": "io", + }, + }), + )), + event.Fields, + ) +} + func setupTLSTestServer(t *testing.T) (ip string, port uint16, cert *x509.Certificate, certFile *os.File, teardown func()) { // Start up a TLS Server server, port, err := setupServer(t, func(handler http.Handler) (*httptest.Server, error) { From 0bb2a09c24c88d801f49f21c3998019455da0124 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Tue, 21 Apr 2020 15:06:44 -0500 Subject: [PATCH 19/25] Add tls.server.x509 fields --- heartbeat/docs/fields.asciidoc | 173 +++++++++++++++++- heartbeat/include/fields.go | 2 +- .../active/dialchain/_meta/fields.yml | 104 ++++++++++- 3 files changed, 274 insertions(+), 5 deletions(-) diff --git a/heartbeat/docs/fields.asciidoc b/heartbeat/docs/fields.asciidoc index b288eec1788..5906f53a11a 100644 --- a/heartbeat/docs/fields.asciidoc +++ b/heartbeat/docs/fields.asciidoc @@ -7824,7 +7824,10 @@ TLS layer related fields. *`tls.certificate_not_valid_before`*:: + -- -Earliest time at which the connection's certificates are valid. + +deprecated:[7.8.0] + +Deprecated in favor of `tls.server.x509.not_before`. Earliest time at which the connection's certificates are valid. type: date @@ -7833,7 +7836,10 @@ type: date *`tls.certificate_not_valid_after`*:: + -- -Latest time at which the connection's certificates are valid. + +deprecated:[7.8.0] + +Deprecated in favor of `tls.server.x509.not_after`. Latest time at which the connection's certificates are valid. type: date @@ -7862,3 +7868,166 @@ type: long -- +[float] +=== server + +Detailed x509 certificate metadata + + + +*`tls.server.x509.alternative_names`*:: ++ +-- +List of subject alternative names (SAN). Name types vary by certificate authority and certificate type but commonly contain IP addresses, DNS names (and wildcards), and email addresses. + +type: keyword + +example: *.elastic.co + +-- + + +*`tls.server.x509.issuer.common_name`*:: ++ +-- +List of common name (CN) of issuing certificate authority. + +type: keyword + +example: DigiCert SHA2 High Assurance Server CA + +-- + +*`tls.server.x509.issuer.distinguished_name`*:: ++ +-- +Distinguished name (DN) of issuing certificate authority. + +type: keyword + +example: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert SHA2 High Assurance Server CA + +-- + +*`tls.server.x509.not_after`*:: ++ +-- +Time at which the certificate is no longer considered valid. + +type: date + +example: 2020-07-16 03:15:39 + +-- + +*`tls.server.x509.not_before`*:: ++ +-- +Time at which the certificate is first considered valid. + +type: date + +example: 2019-08-16 01:40:25 + +-- + +*`tls.server.x509.public_key_algorithm`*:: ++ +-- +Algorithm used to generate the public key. + +type: keyword + +example: RSA + +-- + +*`tls.server.x509.public_key_curve`*:: ++ +-- +The curve used by the elliptic curve public key algorithm. This is algorithm specific. + +type: keyword + +example: nistp521 + +-- + +*`tls.server.x509.public_key_exponent`*:: ++ +-- +Exponent used to derive the public key. This is algorithm specific. + +type: long + +example: 65537 + +-- + +*`tls.server.x509.public_key_size`*:: ++ +-- +The size of the public key space in bits. + +type: long + +example: 2048 + +-- + +*`tls.server.x509.serial_number`*:: ++ +-- +Unique serial number issued by the certificate authority. For consistency, if this value is alphanumeric, it should be formatted without colons and uppercase characters. + +type: keyword + +example: 55FBB9C7DEBF09809D12CCAA + +-- + +*`tls.server.x509.signature_algorithm`*:: ++ +-- +Identifier for certificate signature algorithm. Recommend using names found in Go Lang Crypto library (See https://github.com/golang/go/blob/go1.14/src/crypto/x509/x509.go#L337-L353). + +type: keyword + +example: SHA256-RSA + +-- + + +*`tls.server.x509.subject.subject.common_name`*:: ++ +-- +List of common names (CN) of subject. + +type: keyword + +example: r2.shared.global.fastly.net + +-- + +*`tls.server.x509.subject.subject.distinguished_name`*:: ++ +-- +Distinguished name (DN) of the certificate subject entity. + +type: keyword + +example: C=US, ST=California, L=San Francisco, O=Fastly, Inc., CN=r2.shared.global.fastly.net + +-- + +*`tls.server.x509.version_number`*:: ++ +-- +Version of x509 format. + +type: keyword + +example: 3 + +-- + diff --git a/heartbeat/include/fields.go b/heartbeat/include/fields.go index e21fe351e87..0b80f9a1b1b 100644 --- a/heartbeat/include/fields.go +++ b/heartbeat/include/fields.go @@ -32,5 +32,5 @@ func init() { // AssetFieldsYml returns asset data. // This is the base64 encoded gzipped contents of fields.yml. func AssetFieldsYml() string { - return "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" + return "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" } diff --git a/heartbeat/monitors/active/dialchain/_meta/fields.yml b/heartbeat/monitors/active/dialchain/_meta/fields.yml index dc9955b7064..969adc209c3 100644 --- a/heartbeat/monitors/active/dialchain/_meta/fields.yml +++ b/heartbeat/monitors/active/dialchain/_meta/fields.yml @@ -35,11 +35,11 @@ - name: certificate_not_valid_before type: date deprecated: 7.8.0 - description: Deprecated in favor of `tls.server.not_before`. Earliest time at which the connection's certificates are valid. + description: Deprecated in favor of `tls.server.x509.not_before`. Earliest time at which the connection's certificates are valid. - name: certificate_not_valid_after deprecated: 7.8.0 type: date - description: Deprecated in favor of `tls.server.not_after`. Latest time at which the connection's certificates are valid. + description: Deprecated in favor of `tls.server.x509.not_after`. Latest time at which the connection's certificates are valid. - name: rtt type: group description: > @@ -54,4 +54,104 @@ - name: us type: long description: Duration in microseconds + - name: server + type: group + description: Detailed x509 certificate metadata + fields: + - name: x509 + type: group + fields: + - name: alternative_names + type: keyword + ignore_above: 1024 + description: List of subject alternative names (SAN). Name types vary by certificate + authority and certificate type but commonly contain IP addresses, DNS names + (and wildcards), and email addresses. + example: '*.elastic.co' + default_field: false + - name: issuer + type: group + fields: + - name: common_name + type: keyword + ignore_above: 1024 + description: List of common name (CN) of issuing certificate authority. + example: DigiCert SHA2 High Assurance Server CA + default_field: false + - name: distinguished_name + type: keyword + ignore_above: 1024 + description: Distinguished name (DN) of issuing certificate authority. + example: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert SHA2 High Assurance + Server CA + default_field: false + - name: not_after + type: date + description: Time at which the certificate is no longer considered valid. + example: 2020-07-16 03:15:39+00:00 + default_field: false + - name: not_before + type: date + description: Time at which the certificate is first considered valid. + example: 2019-08-16 01:40:25+00:00 + default_field: false + - name: public_key_algorithm + type: keyword + ignore_above: 1024 + description: Algorithm used to generate the public key. + example: RSA + default_field: false + - name: public_key_curve + type: keyword + ignore_above: 1024 + description: The curve used by the elliptic curve public key algorithm. This + is algorithm specific. + example: nistp521 + default_field: false + - name: public_key_exponent + type: long + description: Exponent used to derive the public key. This is algorithm specific. + example: 65537 + default_field: false + - name: public_key_size + type: long + description: The size of the public key space in bits. + example: 2048 + default_field: false + - name: serial_number + type: keyword + ignore_above: 1024 + description: Unique serial number issued by the certificate authority. For consistency, + if this value is alphanumeric, it should be formatted without colons and uppercase + characters. + example: 55FBB9C7DEBF09809D12CCAA + default_field: false + - name: signature_algorithm + type: keyword + ignore_above: 1024 + description: Identifier for certificate signature algorithm. Recommend using + names found in Go Lang Crypto library (See https://github.com/golang/go/blob/go1.14/src/crypto/x509/x509.go#L337-L353). + example: SHA256-RSA + default_field: false + - name: subject + type: group + fields: + - name: subject.common_name + type: keyword + ignore_above: 1024 + description: List of common names (CN) of subject. + example: r2.shared.global.fastly.net + default_field: false + - name: subject.distinguished_name + type: keyword + ignore_above: 1024 + description: Distinguished name (DN) of the certificate subject entity. + example: C=US, ST=California, L=San Francisco, O=Fastly, Inc., CN=r2.shared.global.fastly.net + default_field: false + - name: version_number + type: keyword + ignore_above: 1024 + description: Version of x509 format. + example: 3 + default_field: false From deb7d6bb19e20a037e22d6c209169bee5dcb7a3f Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Wed, 22 Apr 2020 21:36:45 -0500 Subject: [PATCH 20/25] Add HTTP test for expired cert --- heartbeat/hbtest/hbtestutil.go | 30 ++++++++++++++ heartbeat/monitors/active/http/http_test.go | 45 ++++----------------- 2 files changed, 38 insertions(+), 37 deletions(-) diff --git a/heartbeat/hbtest/hbtestutil.go b/heartbeat/hbtest/hbtestutil.go index 9b91259cb1f..553d0266997 100644 --- a/heartbeat/hbtest/hbtestutil.go +++ b/heartbeat/hbtest/hbtestutil.go @@ -23,6 +23,7 @@ import ( "fmt" "io" "io/ioutil" + "net" "net/http" "net/http/httptest" "net/url" @@ -127,6 +128,12 @@ func TLSChecks(chainIndex, certIndex int, certificate *x509.Certificate) validat return lookslike.MustCompile(expected) } +func TLSCertChecks(certificate *x509.Certificate) validator.Validator { + expected := common.MapStr{} + tlsmeta.AddCertMetadata(expected, []*x509.Certificate{certificate}) + return lookslike.MustCompile(expected) +} + // BaseChecks creates a skima.Validator that represents the "monitor" field present // in all heartbeat events. // If IP is set to "" this will check that the field is not present @@ -226,3 +233,26 @@ func CertToTempFile(t *testing.T, cert *x509.Certificate) *os.File { certFile.WriteString(x509util.CertToPEMString(cert)) return certFile } + +func StartExpiredHTTPSServer(t *testing.T) (host string, port string, cert *x509.Certificate, doClose func() error) { + tlsCert, err := tls.LoadX509KeyPair("fixtures/expired.cert", "fixtures/expired.key") + require.NoError(t, err) + + cert, err = x509.ParseCertificate(tlsCert.Certificate[0]) + require.NoError(t, err) + + // No need to start a real server, since this is invalid, we just + l, err := tls.Listen("tcp", "127.0.0.1:0", &tls.Config{ + Certificates: []tls.Certificate{tlsCert}, + }) + require.NoError(t, err) + + srv := &http.Server{Handler: HelloWorldHandler(200)} + go func() { + srv.Serve(l) + }() + + host, port, err = net.SplitHostPort(l.Addr().String()) + require.NoError(t, err) + return host, port, cert, srv.Close +} diff --git a/heartbeat/monitors/active/http/http_test.go b/heartbeat/monitors/active/http/http_test.go index a3ff9be2044..257a30210ed 100644 --- a/heartbeat/monitors/active/http/http_test.go +++ b/heartbeat/monitors/active/http/http_test.go @@ -361,34 +361,6 @@ func runHTTPSServerCheck( ) } -func startExpiredTLSEndpoint(t *testing.T) (host string, port string, cert *x509.Certificate, doClose func() error) { - tlsCert, err := tls.LoadX509KeyPair("fixtures/expired.cert", "fixtures/expired.key") - require.NoError(t, err) - - cert, err = x509.ParseCertificate(tlsCert.Certificate[0]) - require.NoError(t, err) - - // No need to start a real server, since this is invalid, we just - l, err := tls.Listen("tcp", "127.0.0.1:0", &tls.Config{ - Certificates: []tls.Certificate{tlsCert}, - }) - require.NoError(t, err) - - go func() { - for { - conn, err := l.Accept() - if err != nil { - break - } - conn.Close() - } - }() - - host, port, err = net.SplitHostPort(l.Addr().String()) - require.NoError(t, err) - return host, port, cert, l.Close -} - func TestHTTPSServer(t *testing.T) { server := httptest.NewTLSServer(hbtest.HelloWorldHandler(http.StatusOK)) @@ -396,22 +368,21 @@ func TestHTTPSServer(t *testing.T) { } func TestExpiredHTTPSServer(t *testing.T) { - host, port, cert, closeSrv := startExpiredTLSEndpoint(t) + host, port, cert, closeSrv := hbtest.StartExpiredHTTPSServer(t) defer closeSrv() - u := &url.URL{Scheme: "https", Host: net.JoinHostPort(host,port)} + u := &url.URL{Scheme: "https", Host: net.JoinHostPort(host, port)} event := sendTLSRequest(t, u.String(), true, nil) testslike.Test( t, lookslike.Strict(lookslike.Compose( - hbtest.BaseChecks("127.0.0.1", "up", "http"), + hbtest.BaseChecks("127.0.0.1", "down", "http"), hbtest.RespondingTCPChecks(), - hbtest.TLSChecks(0, 0, cert), - hbtest.SummaryChecks(1, 0), - respondingHTTPChecks( - u.String(), - http.StatusOK, - ), + hbtest.TLSCertChecks(cert), + hbtest.SummaryChecks(0, 1), + hbtest.ErrorChecks("x509: certificate has expired or is not yet valid", "io"), + hbtest.URLChecks(t, &url.URL{Scheme: "https", Host: net.JoinHostPort(host, port)}), + // No HTTP fields expected because we fail at the TCP level )), event.Fields, ) From f64650cc363944f2435543763da338dda641eee4 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Wed, 22 Apr 2020 21:56:22 -0500 Subject: [PATCH 21/25] Add TCP tests for expired certs --- heartbeat/hbtest/hbtestutil.go | 15 +++++++---- .../active/{http => }/fixtures/expired.cert | 0 .../active/{http => }/fixtures/expired.key | 0 heartbeat/monitors/active/http/http_test.go | 7 ++--- heartbeat/monitors/active/tcp/tls_test.go | 27 +++++++++++-------- 5 files changed, 30 insertions(+), 19 deletions(-) rename heartbeat/monitors/active/{http => }/fixtures/expired.cert (100%) rename heartbeat/monitors/active/{http => }/fixtures/expired.key (100%) diff --git a/heartbeat/hbtest/hbtestutil.go b/heartbeat/hbtest/hbtestutil.go index 553d0266997..246104638e9 100644 --- a/heartbeat/hbtest/hbtestutil.go +++ b/heartbeat/hbtest/hbtestutil.go @@ -214,6 +214,14 @@ func ErrorChecks(msgSubstr string, errType string) validator.Validator { }) } +func ExpiredCertChecks(cert *x509.Certificate) validator.Validator { + msg := x509.CertificateInvalidError{Cert: cert, Reason: x509.Expired}.Error() + return lookslike.Compose( + ErrorChecks(msg, "io"), + TLSCertChecks(cert), + ) +} + // RespondingTCPChecks creates a skima.Validator that represents the "tcp" field present // in all heartbeat events that use a Tcp connection as part of their DialChain func RespondingTCPChecks() validator.Validator { @@ -234,11 +242,8 @@ func CertToTempFile(t *testing.T, cert *x509.Certificate) *os.File { return certFile } -func StartExpiredHTTPSServer(t *testing.T) (host string, port string, cert *x509.Certificate, doClose func() error) { - tlsCert, err := tls.LoadX509KeyPair("fixtures/expired.cert", "fixtures/expired.key") - require.NoError(t, err) - - cert, err = x509.ParseCertificate(tlsCert.Certificate[0]) +func StartHTTPSServer(t *testing.T, tlsCert tls.Certificate) (host string, port string, cert *x509.Certificate, doClose func() error) { + cert, err := x509.ParseCertificate(tlsCert.Certificate[0]) require.NoError(t, err) // No need to start a real server, since this is invalid, we just diff --git a/heartbeat/monitors/active/http/fixtures/expired.cert b/heartbeat/monitors/active/fixtures/expired.cert similarity index 100% rename from heartbeat/monitors/active/http/fixtures/expired.cert rename to heartbeat/monitors/active/fixtures/expired.cert diff --git a/heartbeat/monitors/active/http/fixtures/expired.key b/heartbeat/monitors/active/fixtures/expired.key similarity index 100% rename from heartbeat/monitors/active/http/fixtures/expired.key rename to heartbeat/monitors/active/fixtures/expired.key diff --git a/heartbeat/monitors/active/http/http_test.go b/heartbeat/monitors/active/http/http_test.go index 257a30210ed..a1b8461d8c1 100644 --- a/heartbeat/monitors/active/http/http_test.go +++ b/heartbeat/monitors/active/http/http_test.go @@ -368,7 +368,9 @@ func TestHTTPSServer(t *testing.T) { } func TestExpiredHTTPSServer(t *testing.T) { - host, port, cert, closeSrv := hbtest.StartExpiredHTTPSServer(t) + tlsCert, err := tls.LoadX509KeyPair("../fixtures/expired.cert", "../fixtures/expired.key") + require.NoError(t, err) + host, port, cert, closeSrv := hbtest.StartHTTPSServer(t, tlsCert) defer closeSrv() u := &url.URL{Scheme: "https", Host: net.JoinHostPort(host, port)} event := sendTLSRequest(t, u.String(), true, nil) @@ -378,9 +380,8 @@ func TestExpiredHTTPSServer(t *testing.T) { lookslike.Strict(lookslike.Compose( hbtest.BaseChecks("127.0.0.1", "down", "http"), hbtest.RespondingTCPChecks(), - hbtest.TLSCertChecks(cert), hbtest.SummaryChecks(0, 1), - hbtest.ErrorChecks("x509: certificate has expired or is not yet valid", "io"), + hbtest.ExpiredCertChecks(cert), hbtest.URLChecks(t, &url.URL{Scheme: "https", Host: net.JoinHostPort(host, port)}), // No HTTP fields expected because we fail at the TCP level )), diff --git a/heartbeat/monitors/active/tcp/tls_test.go b/heartbeat/monitors/active/tcp/tls_test.go index da573e794f2..ff4cd569db5 100644 --- a/heartbeat/monitors/active/tcp/tls_test.go +++ b/heartbeat/monitors/active/tcp/tls_test.go @@ -18,12 +18,14 @@ package tcp import ( + "crypto/tls" "crypto/x509" "net" "net/http" "net/http/httptest" "net/url" "os" + "strconv" "testing" "time" @@ -113,11 +115,19 @@ func TestTLSInvalidCert(t *testing.T) { } func TestTLSExpiredCert(t *testing.T) { - ip, port, cert, certFile, teardown := setupTLSTestServer(t) - defer teardown() + certFile := "../fixtures/expired.cert" + tlsCert, err := tls.LoadX509KeyPair(certFile, "../fixtures/expired.key") + require.NoError(t, err) + + ip, portStr, cert, closeSrv := hbtest.StartHTTPSServer(t, tlsCert) + defer closeSrv() + + portInt, err := strconv.Atoi(portStr) + port := uint16(portInt) + require.NoError(t, err) - hostname := cert.DNSNames[0] - event := testTLSTCPCheck(t, hostname, port, certFile.Name(), monitors.NewStdResolver()) + host := "localhost" + event := testTLSTCPCheck(t, host, port, certFile, monitors.NewStdResolver()) testslike.Test( t, @@ -125,14 +135,9 @@ func TestTLSExpiredCert(t *testing.T) { hbtest.RespondingTCPChecks(), hbtest.BaseChecks(ip, "down", "tcp"), hbtest.SummaryChecks(0, 1), - hbtest.SimpleURLChecks(t, "ssl", hostname, port), + hbtest.SimpleURLChecks(t, "ssl", host, port), hbtest.ResolveChecks(ip), - lookslike.MustCompile(map[string]interface{}{ - "error": map[string]interface{}{ - "message": x509.HostnameError{Certificate: cert, Host: hostname}.Error(), - "type": "io", - }, - }), + hbtest.ExpiredCertChecks(cert), )), event.Fields, ) From 7a54cbcc1dcfdddfa5aad039436d85c14e8943dc Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Thu, 23 Apr 2020 19:07:07 -0500 Subject: [PATCH 22/25] FMT --- libbeat/common/transport/tlscommon/types.go | 4 ++-- .../common/transport/tlscommon/versions.go | 1 - .../transport/tlscommon/versions_default.go | 4 ++-- .../transport/tlscommon/versions_test.go | 20 ++++++++++++++++++- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/libbeat/common/transport/tlscommon/types.go b/libbeat/common/transport/tlscommon/types.go index 1ee4bf2440c..93cdf95464e 100644 --- a/libbeat/common/transport/tlscommon/types.go +++ b/libbeat/common/transport/tlscommon/types.go @@ -66,8 +66,8 @@ var tlsCipherSuites = map[string]tlsCipherSuite{ "RSA-AES-256-CBC-SHA": tlsCipherSuite(tls.TLS_RSA_WITH_AES_256_CBC_SHA), "RSA-AES-256-GCM-SHA384": tlsCipherSuite(tls.TLS_RSA_WITH_AES_256_GCM_SHA384), - "TLS-AES-128-GCM-SHA256": tlsCipherSuite(tls.TLS_AES_128_GCM_SHA256), - "TLS-AES-256-GCM-SHA384": tlsCipherSuite(tls.TLS_AES_256_GCM_SHA384), + "TLS-AES-128-GCM-SHA256": tlsCipherSuite(tls.TLS_AES_128_GCM_SHA256), + "TLS-AES-256-GCM-SHA384": tlsCipherSuite(tls.TLS_AES_256_GCM_SHA384), "TLS-CHACHA20-POLY1305-SHA256": tlsCipherSuite(tls.TLS_CHACHA20_POLY1305_SHA256), } diff --git a/libbeat/common/transport/tlscommon/versions.go b/libbeat/common/transport/tlscommon/versions.go index 7de9e5f66e0..a589f0af3cd 100644 --- a/libbeat/common/transport/tlscommon/versions.go +++ b/libbeat/common/transport/tlscommon/versions.go @@ -37,7 +37,6 @@ func (v TLSVersion) Details() *TLSVersionDetails { return nil } - //Unpack transforms the string into a constant. func (v *TLSVersion) Unpack(s string) error { version, found := tlsProtocolVersions[s] diff --git a/libbeat/common/transport/tlscommon/versions_default.go b/libbeat/common/transport/tlscommon/versions_default.go index e270e9a00ab..77eff7375eb 100644 --- a/libbeat/common/transport/tlscommon/versions_default.go +++ b/libbeat/common/transport/tlscommon/versions_default.go @@ -66,7 +66,7 @@ var tlsProtocolVersions = map[string]TLSVersion{ // Intended for ECS's tls.version_protocol_field, which does not include // numeric version and should be lower case type TLSVersionDetails struct { - Version string + Version string Protocol string Combined string } @@ -75,7 +75,7 @@ func (pv TLSVersionDetails) String() string { return pv.Combined } -var tlsInverseLookup = map [TLSVersion]TLSVersionDetails{ +var tlsInverseLookup = map[TLSVersion]TLSVersionDetails{ TLSVersionSSL30: TLSVersionDetails{Version: "3.0", Protocol: "ssl", Combined: "SSLv3"}, TLSVersion10: TLSVersionDetails{Version: "1.0", Protocol: "tls", Combined: "TLSv1.0"}, TLSVersion11: TLSVersionDetails{Version: "1.1", Protocol: "tls", Combined: "TLSv1.1"}, diff --git a/libbeat/common/transport/tlscommon/versions_test.go b/libbeat/common/transport/tlscommon/versions_test.go index cce87d918a9..b1251109b05 100644 --- a/libbeat/common/transport/tlscommon/versions_test.go +++ b/libbeat/common/transport/tlscommon/versions_test.go @@ -1,9 +1,27 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + package tlscommon import ( "crypto/tls" - "github.com/stretchr/testify/require" "testing" + + "github.com/stretchr/testify/require" ) func TestTLSVersion(t *testing.T) { From e9ac63d3396a5130e5754f127b9dc7117b1b9328 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Thu, 23 Apr 2020 21:39:02 -0500 Subject: [PATCH 23/25] Searchable experiment --- heartbeat/_meta/fields.common.yml | 8 + heartbeat/docs/fields.asciidoc | 28 +++ heartbeat/heartbeat.yml | 176 ++---------------- heartbeat/include/fields.go | 2 +- .../active/dialchain/_meta/fields.yml | 6 + 5 files changed, 61 insertions(+), 159 deletions(-) diff --git a/heartbeat/_meta/fields.common.yml b/heartbeat/_meta/fields.common.yml index 28a721494f9..8db94d8a56c 100644 --- a/heartbeat/_meta/fields.common.yml +++ b/heartbeat/_meta/fields.common.yml @@ -17,11 +17,19 @@ type: keyword description: > The monitors configured name + multi_fields: + - name: text + type: text + analyzer: simple - name: id type: keyword description: > The monitors full job ID as used by heartbeat. + multi_fields: + - name: text + type: text + analyzer: simple - name: duration type: group diff --git a/heartbeat/docs/fields.asciidoc b/heartbeat/docs/fields.asciidoc index 5906f53a11a..f52d1205662 100644 --- a/heartbeat/docs/fields.asciidoc +++ b/heartbeat/docs/fields.asciidoc @@ -215,6 +215,13 @@ type: keyword -- +*`monitor.name.text`*:: ++ +-- +type: text + +-- + *`monitor.id`*:: + -- @@ -225,6 +232,13 @@ type: keyword -- +*`monitor.id.text`*:: ++ +-- +type: text + +-- + [float] === duration @@ -7898,6 +7912,13 @@ example: DigiCert SHA2 High Assurance Server CA -- +*`tls.server.x509.issuer.common_name.text`*:: ++ +-- +type: wildcard + +-- + *`tls.server.x509.issuer.distinguished_name`*:: + -- @@ -8009,6 +8030,13 @@ example: r2.shared.global.fastly.net -- +*`tls.server.x509.subject.subject.common_name.text`*:: ++ +-- +type: wildcard + +-- + *`tls.server.x509.subject.subject.distinguished_name`*:: + -- diff --git a/heartbeat/heartbeat.yml b/heartbeat/heartbeat.yml index aa3e1283f70..7264280602e 100644 --- a/heartbeat/heartbeat.yml +++ b/heartbeat/heartbeat.yml @@ -1,168 +1,28 @@ -################### Heartbeat Configuration Example ######################### - -# This file is an example configuration file highlighting only some common options. -# The heartbeat.reference.yml file in the same directory contains all the supported options -# with detailed comments. You can use it for reference. -# -# You can find the full configuration reference here: -# https://www.elastic.co/guide/en/beats/heartbeat/index.html - -############################# Heartbeat ###################################### - -# Define a directory to load monitor definitions from. Definitions take the form -# of individual yaml files. +--- heartbeat.config.monitors: - # Directory + glob pattern to search for configuration files - path: ${path.config}/monitors.d/*.yml - # If enabled, heartbeat will periodically check the config.monitors path for changes + path: "${path.config}/monitors.d/*.yml" reload.enabled: false - # How often to check for changes reload.period: 5s - -# Configure monitors inline heartbeat.monitors: - type: http - # ID used to uniquely identify this monitor in elasticsearch even if the config changes - id: my-monitor - # Human readable display name for this service in Uptime UI and elsewhere - name: My Monitor - # List or urls to query - urls: ["http://localhost:9200"] - # Configure task schedule - schedule: '@every 10s' - # Total test connection and data exchange timeout - #timeout: 16s - -#==================== Elasticsearch template setting ========================== - + id: elastic-co + name: Elastic.co + urls: + - https://www.elastic.co + schedule: "@every 10s" setup.template.settings: index.number_of_shards: 1 index.codec: best_compression - #_source.enabled: false - -#================================ General ===================================== - -# The name of the shipper that publishes the network data. It can be used to group -# all the transactions sent by a single shipper in the web interface. -#name: - -# The tags of the shipper are included in their own field with each -# transaction published. -#tags: ["service-X", "web-tier"] - -# Optional fields that you can specify to add additional information to the -# output. -#fields: -# env: staging - - -#============================== Kibana ===================================== - -# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. -# This requires a Kibana endpoint configuration. -setup.kibana: - - # Kibana Host - # Scheme and port can be left out and will be set to the default (http and 5601) - # In case you specify and additional path, the scheme is required: http://localhost:5601/path - # IPv6 addresses should always be defined as: https://[2001:db8::1]:5601 - #host: "localhost:5601" - - # Kibana Space ID - # ID of the Kibana Space into which the dashboards should be loaded. By default, - # the Default Space will be used. - #space.id: - -#============================= Elastic Cloud ================================== - -# These settings simplify using Heartbeat with the Elastic Cloud (https://cloud.elastic.co/). - -# The cloud.id setting overwrites the `output.elasticsearch.hosts` and -# `setup.kibana.host` options. -# You can find the `cloud.id` in the Elastic Cloud web UI. -#cloud.id: - -# The cloud.auth setting overwrites the `output.elasticsearch.username` and -# `output.elasticsearch.password` settings. The format is `:`. -#cloud.auth: - -#================================ Outputs ===================================== - -# Configure what output to use when sending the data collected by the beat. - -#-------------------------- Elasticsearch output ------------------------------ +setup.kibana: output.elasticsearch: - # Array of hosts to connect to. - hosts: ["localhost:9200"] - - # Protocol - either `http` (default) or `https`. - #protocol: "https" - - # Authentication credentials - either API key or username/password. - #api_key: "id:api_key" - #username: "elastic" - #password: "changeme" - -#----------------------------- Logstash output -------------------------------- -#output.logstash: - # The Logstash hosts - #hosts: ["localhost:5044"] - - # Optional SSL. By default is off. - # List of root certificates for HTTPS server verifications - #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] - - # Certificate for SSL client authentication - #ssl.certificate: "/etc/pki/client/cert.pem" - - # Client Certificate Key - #ssl.key: "/etc/pki/client/cert.key" - -#================================ Processors ===================================== - + hosts: + - localhost:9200 + protocol: https + username: heartbeat + password: changeme + ssl: + certificate_authorities: "${HOME}/projects/kibana/packages/kbn-dev-utils/certs/ca.crt" + certificate: "${HOME}/projects/kibana/packages/kbn-dev-utils/certs/elasticsearch.crt" + key: "${HOME}/projects/kibana/packages/kbn-dev-utils/certs/elasticsearch.key" processors: - - add_observer_metadata: - # Optional, but recommended geo settings for the location Heartbeat is running in - #geo: - # Token describing this location - #name: us-east-1a - # Lat, Lon " - #location: "37.926868, -78.024902" - -#================================ Logging ===================================== - -# Sets log level. The default log level is info. -# Available log levels are: error, warning, info, debug -#logging.level: debug - -# At debug level, you can selectively enable logging only for some components. -# To enable all selectors use ["*"]. Examples of other selectors are "beat", -# "publish", "service". -#logging.selectors: ["*"] - -#============================== X-Pack Monitoring =============================== -# heartbeat can export internal metrics to a central Elasticsearch monitoring -# cluster. This requires xpack monitoring to be enabled in Elasticsearch. The -# reporting is disabled by default. - -# Set to true to enable the monitoring reporter. -#monitoring.enabled: false - -# Sets the UUID of the Elasticsearch cluster under which monitoring data for this -# Heartbeat instance will appear in the Stack Monitoring UI. If output.elasticsearch -# is enabled, the UUID is derived from the Elasticsearch cluster referenced by output.elasticsearch. -#monitoring.cluster_uuid: - -# Uncomment to send the metrics to Elasticsearch. Most settings from the -# Elasticsearch output are accepted here as well. -# Note that the settings should point to your Elasticsearch *monitoring* cluster. -# Any setting that is not set is automatically inherited from the Elasticsearch -# output configuration, so if you have the Elasticsearch output configured such -# that it is pointing to your Elasticsearch monitoring cluster, you can simply -# uncomment the following line. -#monitoring.elasticsearch: - -#================================= Migration ================================== - -# This allows to enable 6.7 migration aliases -#migration.6_to_7.enabled: true +- add_observer_metadata: diff --git a/heartbeat/include/fields.go b/heartbeat/include/fields.go index 0b80f9a1b1b..601fcb201b9 100644 --- a/heartbeat/include/fields.go +++ b/heartbeat/include/fields.go @@ -32,5 +32,5 @@ func init() { // AssetFieldsYml returns asset data. // This is the base64 encoded gzipped contents of fields.yml. func AssetFieldsYml() string { - return "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" + return "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" } diff --git a/heartbeat/monitors/active/dialchain/_meta/fields.yml b/heartbeat/monitors/active/dialchain/_meta/fields.yml index 969adc209c3..a234429103a 100644 --- a/heartbeat/monitors/active/dialchain/_meta/fields.yml +++ b/heartbeat/monitors/active/dialchain/_meta/fields.yml @@ -78,6 +78,9 @@ description: List of common name (CN) of issuing certificate authority. example: DigiCert SHA2 High Assurance Server CA default_field: false + multi_fields: + - name: text + type: wildcard - name: distinguished_name type: keyword ignore_above: 1024 @@ -142,6 +145,9 @@ description: List of common names (CN) of subject. example: r2.shared.global.fastly.net default_field: false + multi_fields: + - name: text + type: wildcard - name: subject.distinguished_name type: keyword ignore_above: 1024 From 63a02a96ab8824e522c7ebfb270de3712d9ab0e4 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Mon, 27 Apr 2020 10:40:25 -0500 Subject: [PATCH 24/25] Support new wildcard field --- heartbeat/heartbeat.yml | 176 +++++++++++++++++++++++++++++++++++---- libbeat/mapping/field.go | 2 +- 2 files changed, 159 insertions(+), 19 deletions(-) diff --git a/heartbeat/heartbeat.yml b/heartbeat/heartbeat.yml index 7264280602e..aa3e1283f70 100644 --- a/heartbeat/heartbeat.yml +++ b/heartbeat/heartbeat.yml @@ -1,28 +1,168 @@ ---- +################### Heartbeat Configuration Example ######################### + +# This file is an example configuration file highlighting only some common options. +# The heartbeat.reference.yml file in the same directory contains all the supported options +# with detailed comments. You can use it for reference. +# +# You can find the full configuration reference here: +# https://www.elastic.co/guide/en/beats/heartbeat/index.html + +############################# Heartbeat ###################################### + +# Define a directory to load monitor definitions from. Definitions take the form +# of individual yaml files. heartbeat.config.monitors: - path: "${path.config}/monitors.d/*.yml" + # Directory + glob pattern to search for configuration files + path: ${path.config}/monitors.d/*.yml + # If enabled, heartbeat will periodically check the config.monitors path for changes reload.enabled: false + # How often to check for changes reload.period: 5s + +# Configure monitors inline heartbeat.monitors: - type: http - id: elastic-co - name: Elastic.co - urls: - - https://www.elastic.co - schedule: "@every 10s" + # ID used to uniquely identify this monitor in elasticsearch even if the config changes + id: my-monitor + # Human readable display name for this service in Uptime UI and elsewhere + name: My Monitor + # List or urls to query + urls: ["http://localhost:9200"] + # Configure task schedule + schedule: '@every 10s' + # Total test connection and data exchange timeout + #timeout: 16s + +#==================== Elasticsearch template setting ========================== + setup.template.settings: index.number_of_shards: 1 index.codec: best_compression -setup.kibana: + #_source.enabled: false + +#================================ General ===================================== + +# The name of the shipper that publishes the network data. It can be used to group +# all the transactions sent by a single shipper in the web interface. +#name: + +# The tags of the shipper are included in their own field with each +# transaction published. +#tags: ["service-X", "web-tier"] + +# Optional fields that you can specify to add additional information to the +# output. +#fields: +# env: staging + + +#============================== Kibana ===================================== + +# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API. +# This requires a Kibana endpoint configuration. +setup.kibana: + + # Kibana Host + # Scheme and port can be left out and will be set to the default (http and 5601) + # In case you specify and additional path, the scheme is required: http://localhost:5601/path + # IPv6 addresses should always be defined as: https://[2001:db8::1]:5601 + #host: "localhost:5601" + + # Kibana Space ID + # ID of the Kibana Space into which the dashboards should be loaded. By default, + # the Default Space will be used. + #space.id: + +#============================= Elastic Cloud ================================== + +# These settings simplify using Heartbeat with the Elastic Cloud (https://cloud.elastic.co/). + +# The cloud.id setting overwrites the `output.elasticsearch.hosts` and +# `setup.kibana.host` options. +# You can find the `cloud.id` in the Elastic Cloud web UI. +#cloud.id: + +# The cloud.auth setting overwrites the `output.elasticsearch.username` and +# `output.elasticsearch.password` settings. The format is `:`. +#cloud.auth: + +#================================ Outputs ===================================== + +# Configure what output to use when sending the data collected by the beat. + +#-------------------------- Elasticsearch output ------------------------------ output.elasticsearch: - hosts: - - localhost:9200 - protocol: https - username: heartbeat - password: changeme - ssl: - certificate_authorities: "${HOME}/projects/kibana/packages/kbn-dev-utils/certs/ca.crt" - certificate: "${HOME}/projects/kibana/packages/kbn-dev-utils/certs/elasticsearch.crt" - key: "${HOME}/projects/kibana/packages/kbn-dev-utils/certs/elasticsearch.key" + # Array of hosts to connect to. + hosts: ["localhost:9200"] + + # Protocol - either `http` (default) or `https`. + #protocol: "https" + + # Authentication credentials - either API key or username/password. + #api_key: "id:api_key" + #username: "elastic" + #password: "changeme" + +#----------------------------- Logstash output -------------------------------- +#output.logstash: + # The Logstash hosts + #hosts: ["localhost:5044"] + + # Optional SSL. By default is off. + # List of root certificates for HTTPS server verifications + #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] + + # Certificate for SSL client authentication + #ssl.certificate: "/etc/pki/client/cert.pem" + + # Client Certificate Key + #ssl.key: "/etc/pki/client/cert.key" + +#================================ Processors ===================================== + processors: -- add_observer_metadata: + - add_observer_metadata: + # Optional, but recommended geo settings for the location Heartbeat is running in + #geo: + # Token describing this location + #name: us-east-1a + # Lat, Lon " + #location: "37.926868, -78.024902" + +#================================ Logging ===================================== + +# Sets log level. The default log level is info. +# Available log levels are: error, warning, info, debug +#logging.level: debug + +# At debug level, you can selectively enable logging only for some components. +# To enable all selectors use ["*"]. Examples of other selectors are "beat", +# "publish", "service". +#logging.selectors: ["*"] + +#============================== X-Pack Monitoring =============================== +# heartbeat can export internal metrics to a central Elasticsearch monitoring +# cluster. This requires xpack monitoring to be enabled in Elasticsearch. The +# reporting is disabled by default. + +# Set to true to enable the monitoring reporter. +#monitoring.enabled: false + +# Sets the UUID of the Elasticsearch cluster under which monitoring data for this +# Heartbeat instance will appear in the Stack Monitoring UI. If output.elasticsearch +# is enabled, the UUID is derived from the Elasticsearch cluster referenced by output.elasticsearch. +#monitoring.cluster_uuid: + +# Uncomment to send the metrics to Elasticsearch. Most settings from the +# Elasticsearch output are accepted here as well. +# Note that the settings should point to your Elasticsearch *monitoring* cluster. +# Any setting that is not set is automatically inherited from the Elasticsearch +# output configuration, so if you have the Elasticsearch output configured such +# that it is pointing to your Elasticsearch monitoring cluster, you can simply +# uncomment the following line. +#monitoring.elasticsearch: + +#================================= Migration ================================== + +# This allows to enable 6.7 migration aliases +#migration.6_to_7.enabled: true diff --git a/libbeat/mapping/field.go b/libbeat/mapping/field.go index 7b2ba52e618..79f771bb7dd 100644 --- a/libbeat/mapping/field.go +++ b/libbeat/mapping/field.go @@ -124,7 +124,7 @@ func (f *Field) Validate() error { func (f *Field) validateType() error { switch strings.ToLower(f.Type) { - case "text", "keyword": + case "text", "keyword", "wildcard": return stringType.validate(f.Format) case "long", "integer", "short", "byte", "double", "float", "half_float", "scaled_float": return numberType.validate(f.Format) From 5b6c08ed45fcae98490929f952cc8299940a497c Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Mon, 27 Apr 2020 14:10:39 -0500 Subject: [PATCH 25/25] Fix cert authorities on windows --- heartbeat/monitors/active/http/http_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/heartbeat/monitors/active/http/http_test.go b/heartbeat/monitors/active/http/http_test.go index a1b8461d8c1..86e55b4536c 100644 --- a/heartbeat/monitors/active/http/http_test.go +++ b/heartbeat/monitors/active/http/http_test.go @@ -373,7 +373,9 @@ func TestExpiredHTTPSServer(t *testing.T) { host, port, cert, closeSrv := hbtest.StartHTTPSServer(t, tlsCert) defer closeSrv() u := &url.URL{Scheme: "https", Host: net.JoinHostPort(host, port)} - event := sendTLSRequest(t, u.String(), true, nil) + + extraConfig := map[string]interface{}{"ssl.certificate_authorities": "../fixtures/expired.cert"} + event := sendTLSRequest(t, u.String(), true, extraConfig) testslike.Test( t,