logstash-input-beats 6.0.10-java → 6.1.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (25) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/README.md +1 -1
  4. data/VERSION +1 -1
  5. data/docs/index.asciidoc +42 -5
  6. data/lib/logstash-input-beats_jars.rb +3 -4
  7. data/lib/logstash/inputs/beats.rb +87 -36
  8. data/lib/logstash/inputs/beats/decoded_event_transform.rb +10 -1
  9. data/lib/logstash/inputs/beats/event_transform_common.rb +2 -2
  10. data/lib/logstash/inputs/beats/message_listener.rb +30 -5
  11. data/logstash-input-beats.gemspec +1 -0
  12. data/spec/inputs/beats/decoded_event_transform_spec.rb +2 -1
  13. data/spec/inputs/beats/event_transform_common_spec.rb +2 -1
  14. data/spec/inputs/beats/message_listener_spec.rb +82 -54
  15. data/spec/inputs/beats/raw_event_transform_spec.rb +2 -1
  16. data/spec/inputs/beats_spec.rb +37 -12
  17. data/spec/integration/filebeat_spec.rb +2 -2
  18. data/spec/support/logstash_test.rb +7 -0
  19. data/spec/support/shared_examples.rb +33 -27
  20. data/vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-databind/{2.9.10.1/jackson-databind-2.9.10.1.jar → 2.9.10.4/jackson-databind-2.9.10.4.jar} +0 -0
  21. data/vendor/jar-dependencies/io/netty/netty-all/4.1.49.Final/netty-all-4.1.49.Final.jar +0 -0
  22. data/vendor/jar-dependencies/org/logstash/beats/logstash-input-beats/{6.0.10/logstash-input-beats-6.0.10.jar → 6.1.0/logstash-input-beats-6.1.0.jar} +0 -0
  23. metadata +19 -6
  24. data/vendor/jar-dependencies/io/netty/netty-all/4.1.30.Final/netty-all-4.1.30.Final.jar +0 -0
  25. data/vendor/jar-dependencies/io/netty/netty-tcnative-boringssl-static/2.0.12.Final/netty-tcnative-boringssl-static-2.0.12.Final.jar +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e0a57668d8737ad18f7f4399fd1d99a1d125d3ad3d358194d175d5ca0e9b9546
4
- data.tar.gz: 3d4e65c0798a8d66a8b803a7fa399166c8ac1f8569319de682faf92d178a6d3e
3
+ metadata.gz: 5924244575544fab0560730b5e773b170a04e6c25d1a72c683ea27c2cc47a597
4
+ data.tar.gz: 7e316315f18e4f33f821dc4c5655d78452e66d605b6db7edc1bc23b55ae3e1d4
5
5
  SHA512:
6
- metadata.gz: a885d465c14af1bef52498ab496e36c3f83932745f91f8e52980c25f1386844ad791db7bcd9ebe17cceaff6d5518805e30adadebb96719853ef3d0fb7f3fd89e
7
- data.tar.gz: e1837acabdd774915634ff99409a853a2863c46f216d250f20d8c16fc4b234587f7a7020e665bcc064e647531180bda4488c6e9afbd524028b0330e6d5d4eb84
6
+ metadata.gz: c17ac9a8663f465fd38282753f4cda55e6bf5d6ac7659ecafc4524193742dfc7f22ab325b6cdff36cb20daaf18448ff0a1f0345471d0467e023c68b924b70dc3
7
+ data.tar.gz: 422714a92f313e7f2d504c3b4927955759188a4246bb6417bbc4d77f24f1a5b4ce8ad403c7e059bc9c025ba97c9f3175bb5e186ff526dd34c850e7c97eb4befe
data/CHANGELOG.md CHANGED
@@ -1,3 +1,24 @@
1
+ ## 6.1.0
2
+ - ECS compatibility enablement, now an `ecs_compatibility` setting is used to declare the level of ECS compatibility
3
+ (`disabled` or `v1`) at plugin level. `disabled` let the plugin behave like before while `v1` does a rename of
4
+ `host` and `@metadata.ip_address` event fields. [404](https://github.com/logstash-plugins/logstash-input-beats/pull/404)
5
+
6
+ ## 6.0.14
7
+ - Feat: log + unwrap generic SSL context exceptions [#405](https://github.com/logstash-plugins/logstash-input-beats/pull/405)
8
+
9
+ ## 6.0.13
10
+ - [DOC] Update links to use shared attributes
11
+
12
+ ## 6.0.12
13
+ - Fix: log error when SSL context building fails [#402](https://github.com/logstash-plugins/logstash-input-beats/pull/402).
14
+ We've also made sure to log messages on configuration errors as LS 7.8/7.9 only prints details when level set to debug.
15
+
16
+ ## 6.0.11
17
+ - Updated jackson databind and Netty dependencies. Additionally, this release removes the dependency on `tcnative` +
18
+ `boringssl`, using JVM supplied ciphers instead. This may result in fewer ciphers being available if the JCE
19
+ unlimited strength jurisdiction policy is not installed. (This policy is installed by default on versions of the
20
+ JDK from u161 onwards)[#393](https://github.com/logstash-plugins/logstash-input-beats/pull/393)
21
+
1
22
  ## 6.0.10
2
23
  - Added error handling to detect if ssl certificate or key files can't be read [#394](https://github.com/logstash-plugins/logstash-input-beats/pull/394)
3
24
 
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Logstash Plugin
2
2
 
3
- [![Travis Build Status](https://travis-ci.org/logstash-plugins/logstash-input-beats.svg)](https://travis-ci.org/logstash-plugins/logstash-input-beats)
3
+ [![Travis Build Status](https://travis-ci.com/logstash-plugins/logstash-input-beats.svg)](https://travis-ci.com/logstash-plugins/logstash-input-beats)
4
4
 
5
5
  This is a plugin for [Logstash](https://github.com/elastic/logstash).
6
6
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 6.0.10
1
+ 6.1.0
data/docs/index.asciidoc CHANGED
@@ -56,11 +56,12 @@ NOTE: If ILM is not being used, set `index` to
56
56
  Logstash creates an index per day, based on the `@timestamp` value of the events
57
57
  coming from Beats.
58
58
 
59
- IMPORTANT: If you are shipping events that span multiple lines, you need to
60
- use the https://www.elastic.co/guide/en/beats/filebeat/current/multiline-examples.html[configuration options available in Filebeat] to handle multiline events
61
- before sending the event data to Logstash. You cannot use the
62
- {logstash-ref}/plugins-codecs-multiline.html[Multiline codec plugin] to handle multiline events. Doing so will
63
- result in the failure to start Logstash.
59
+ IMPORTANT: If you are shipping events that span multiple lines, you need to use
60
+ the {filebeat-ref}/multiline-examples.html[configuration options available in
61
+ Filebeat] to handle multiline events before sending the event data to Logstash.
62
+ You cannot use the {logstash-ref}/plugins-codecs-multiline.html[Multiline codec
63
+ plugin] to handle multiline events. Doing so will result in the failure to start
64
+ Logstash.
64
65
 
65
66
  [id="plugins-{type}s-{plugin}-versioned-indexes"]
66
67
  ==== Versioned Beats Indices
@@ -85,6 +86,14 @@ Logstash `@timestamp` field.
85
86
  This configuration results in daily index names like
86
87
  +filebeat-{logstash_version}-{localdate}+.
87
88
 
89
+
90
+ [id="plugins-{type}s-{plugin}-ecs_metadata"]
91
+ ==== Event Metadata and the Elastic Common Schema (ECS)
92
+ When decoding `beats` events, this plugin adds two fields related to the event: the deprecated `host`
93
+ which contains the `hostname` provided by beats and the `ip_address` containing the remote address
94
+ of the client's connection. When <<plugins-{type}s-{plugin}-ecs_compatibility,ECS compatibility mode>> is
95
+ enabled these are now moved in ECS compatible namespace.
96
+
88
97
  [id="plugins-{type}s-{plugin}-options"]
89
98
  ==== Beats Input Configuration Options
90
99
 
@@ -96,6 +105,7 @@ This plugin supports the following configuration options plus the <<plugins-{typ
96
105
  | <<plugins-{type}s-{plugin}-add_hostname>> |<<boolean,boolean>>|No
97
106
  | <<plugins-{type}s-{plugin}-cipher_suites>> |<<array,array>>|No
98
107
  | <<plugins-{type}s-{plugin}-client_inactivity_timeout>> |<<number,number>>|No
108
+ | <<plugins-{type}s-{plugin}-ecs_compatibility>> | <<string,string>>|No
99
109
  | <<plugins-{type}s-{plugin}-host>> |<<string,string>>|No
100
110
  | <<plugins-{type}s-{plugin}-include_codec_tag>> |<<boolean,boolean>>|No
101
111
  | <<plugins-{type}s-{plugin}-port>> |<<number,number>>|Yes
@@ -143,6 +153,33 @@ The list of ciphers suite to use, listed by priorities.
143
153
 
144
154
  Close Idle clients after X seconds of inactivity.
145
155
 
156
+ [id="plugins-{type}s-{plugin}-ecs_compatibility"]
157
+ ===== `ecs_compatibility`
158
+
159
+ * Value type is <<string,string>>
160
+ * Supported values are:
161
+ ** `disabled`: unstructured connection metadata added at root level
162
+ ** `v1`: structured connection metadata added under ECS compliant namespaces
163
+ * Default value depends on which version of Logstash is running:
164
+ ** When Logstash provides a `pipeline.ecs_compatibility` setting, its value is used as the default
165
+ ** Otherwise, the default value is `disabled`.
166
+
167
+ Controls this plugin's compatibility with the {ecs-ref}[Elastic Common Schema (ECS)].
168
+ The value of this setting affects the keys for the Beats connection's metadata on the event:
169
+
170
+ .Metadata Location by `ecs_compatibility` value
171
+ [cols="<l,<l,e,<e"]
172
+ |=======================================================================
173
+ |`disabled` |`v1` |Availability |Description
174
+
175
+ |[host] |[@metadata][input][beats][host][name] |Always |Name or address of the beat host
176
+ |[@metadata][ip_address] |[@metadata][input][beats][host][ip] |Always |IP address of the Beats client
177
+ |[@metadata][tls_peer][status] | [@metadata][tls_peer][status] | When SSL related fields are populated | Contains "verified"/"unverified" labels in `disabled`, `true`/`false` in `v1`
178
+ |[@metadata][tls_peer][protocol] | [@metadata][input][beats][tls][version_protocol] | When SSL status is "verified" | Contains the TLS version used (e.g. `TLSv1.2`)
179
+ |[@metadata][tls_peer][subject] | [@metadata][input][beats][tls][client][subject] | When SSL status is "verified" | Contains the identity name of the remote end (e.g. `CN=artifacts-no-kpi.elastic.co`)
180
+ |[@metadata][tls_peer][cipher_suite] | [@metadata][input][beats][tls][cipher] | When SSL status is "verified" | Contains the name of cipher suite used (e.g. `TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`)
181
+ |=======================================================================
182
+
146
183
  [id="plugins-{type}s-{plugin}-host"]
147
184
  ===== `host`
148
185
 
@@ -1,12 +1,11 @@
1
1
  # AUTOGENERATED BY THE GRADLE SCRIPT. DO NOT EDIT.
2
2
 
3
3
  require 'jar_dependencies'
4
- require_jar('io.netty', 'netty-all', '4.1.30.Final')
5
- require_jar('io.netty', 'netty-tcnative-boringssl-static', '2.0.12.Final')
4
+ require_jar('io.netty', 'netty-all', '4.1.49.Final')
6
5
  require_jar('org.javassist', 'javassist', '3.24.0-GA')
7
6
  require_jar('com.fasterxml.jackson.core', 'jackson-core', '2.9.10')
8
7
  require_jar('com.fasterxml.jackson.core', 'jackson-annotations', '2.9.10')
9
- require_jar('com.fasterxml.jackson.core', 'jackson-databind', '2.9.10.1')
8
+ require_jar('com.fasterxml.jackson.core', 'jackson-databind', '2.9.10.4')
10
9
  require_jar('com.fasterxml.jackson.module', 'jackson-module-afterburner', '2.9.10')
11
10
  require_jar('org.apache.logging.log4j', 'log4j-api', '2.11.1')
12
- require_jar('org.logstash.beats', 'logstash-input-beats', '6.0.10')
11
+ require_jar('org.logstash.beats', 'logstash-input-beats', '6.1.0')
@@ -5,6 +5,7 @@ require "logstash/timestamp"
5
5
  require "logstash/codecs/multiline"
6
6
  require "logstash/util"
7
7
  require "logstash-input-beats_jars"
8
+ require "logstash/plugin_mixins/ecs_compatibility_support"
8
9
  require_relative "beats/patch"
9
10
 
10
11
  # This input plugin enables Logstash to receive events from the
@@ -49,6 +50,9 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
49
50
  require "logstash/inputs/beats/message_listener"
50
51
  require "logstash/inputs/beats/tls"
51
52
 
53
+ # adds ecs_compatibility config which could be :disabled or :v1
54
+ include LogStash::PluginMixins::ECSCompatibilitySupport(:disabled,:v1)
55
+
52
56
  config_name "beats"
53
57
 
54
58
  default :codec, "plain"
@@ -114,14 +118,15 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
114
118
  config :tls_max_version, :validate => :number, :default => TLS.max.version
115
119
 
116
120
  # The list of ciphers suite to use, listed by priorities.
117
- config :cipher_suites, :validate => :array, :default => org.logstash.netty.SslContextBuilder::DEFAULT_CIPHERS
118
-
121
+ config :cipher_suites, :validate => :array, :default => org.logstash.netty.SslContextBuilder.getDefaultCiphers
119
122
  # Close Idle clients after X seconds of inactivity.
120
123
  config :client_inactivity_timeout, :validate => :number, :default => 60
121
124
 
122
125
  # Beats handler executor thread
123
126
  config :executor_threads, :validate => :number, :default => LogStash::Config::CpuCoreStrategy.maximum
124
127
 
128
+ attr_reader :field_hostname, :field_hostip
129
+
125
130
  def register
126
131
  # For Logstash 2.4 we need to make sure that the logger is correctly set for the
127
132
  # java classes before actually loading them.
@@ -132,27 +137,39 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
132
137
  LogStash::Logger.setup_log4j(@logger)
133
138
  end
134
139
 
135
- if !@ssl
136
- @logger.warn("Beats input: SSL Certificate will not be used") unless @ssl_certificate.nil?
137
- @logger.warn("Beats input: SSL Key will not be used") unless @ssl_key.nil?
138
- elsif !ssl_configured?
139
- raise LogStash::ConfigurationError, "Certificate or Certificate Key not configured"
140
- end
140
+ if @ssl
141
+ if @ssl_key.nil? || @ssl_key.empty?
142
+ configuration_error "ssl_key => is a required setting when ssl => true is configured"
143
+ end
144
+ if @ssl_certificate.nil? || @ssl_certificate.empty?
145
+ configuration_error "ssl_certificate => is a required setting when ssl => true is configured"
146
+ end
141
147
 
142
- if @ssl && require_certificate_authorities? && !client_authentification?
143
- raise LogStash::ConfigurationError, "Using `verify_mode` set to PEER or FORCE_PEER, requires the configuration of `certificate_authorities`"
144
- end
148
+ if require_certificate_authorities? && !client_authentification?
149
+ configuration_error "ssl_certificate_authorities => is a required setting when ssl_verify_mode => '#{@ssl_verify_mode}' is configured"
150
+ end
145
151
 
146
- if client_authentication_metadata? && !require_certificate_authorities?
147
- raise LogStash::ConfigurationError, "Enabling `peer_metadata` requires using `verify_mode` set to PEER or FORCE_PEER"
152
+ if client_authentication_metadata? && !require_certificate_authorities?
153
+ configuration_error "Configuring ssl_peer_metadata => true requires ssl_verify_mode => to be configured with 'peer' or 'force_peer'"
154
+ end
155
+ else
156
+ @logger.warn("configured ssl_certificate => #{@ssl_certificate.inspect} will not be used") if @ssl_certificate
157
+ @logger.warn("configured ssl_key => #{@ssl_key.inspect} will not be used") if @ssl_key
148
158
  end
149
159
 
150
160
  # Logstash 6.x breaking change (introduced with 4.0.0 of this gem)
151
161
  if @codec.kind_of? LogStash::Codecs::Multiline
152
- raise LogStash::ConfigurationError, "Multiline codec with beats input is not supported. Please refer to the beats documentation for how to best manage multiline data. See https://www.elastic.co/guide/en/beats/filebeat/current/multiline-examples.html"
162
+ configuration_error "Multiline codec with beats input is not supported. Please refer to the beats documentation for how to best manage multiline data. See https://www.elastic.co/guide/en/beats/filebeat/current/multiline-examples.html"
153
163
  end
154
164
 
155
- @logger.info("Beats inputs: Starting input listener", :address => "#{@host}:#{@port}")
165
+ # define ecs name mapping
166
+ @field_hostname = ecs_select[disabled: "host", v1: "[@metadata][input][beats][host][name]"]
167
+ @field_hostip = ecs_select[disabled: "[@metadata][ip_address]", v1: "[@metadata][input][beats][host][ip]"]
168
+ @field_tls_protocol_version = ecs_select[disabled: "[@metadata][tls_peer][protocol]", v1: "[@metadata][input][beats][tls][version_protocol]"]
169
+ @field_tls_peer_subject = ecs_select[disabled: "[@metadata][tls_peer][subject]", v1: "[@metadata][input][beats][tls][client][subject]"]
170
+ @field_tls_cipher = ecs_select[disabled: "[@metadata][tls_peer][cipher_suite]", v1: "[@metadata][input][beats][tls][cipher]"]
171
+
172
+ @logger.info("Starting input listener", :address => "#{@host}:#{@port}")
156
173
 
157
174
  @server = create_server
158
175
  end # def register
@@ -160,37 +177,20 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
160
177
  def create_server
161
178
  server = org.logstash.beats.Server.new(@host, @port, @client_inactivity_timeout, @executor_threads)
162
179
  if @ssl
163
-
164
- begin
165
- ssl_context_builder = org.logstash.netty.SslContextBuilder.new(@ssl_certificate, @ssl_key, @ssl_key_passphrase.nil? ? nil : @ssl_key_passphrase.value)
166
- .setProtocols(convert_protocols)
167
- .setCipherSuites(normalized_ciphers)
168
- rescue java.lang.IllegalArgumentException => e
169
- raise LogStash::ConfigurationError, e
170
- end
171
-
172
-
180
+ ssl_context_builder = new_ssl_context_builder
173
181
  if client_authentification?
174
- if @ssl_verify_mode.upcase == "FORCE_PEER"
182
+ if @ssl_verify_mode == "force_peer"
175
183
  ssl_context_builder.setVerifyMode(org.logstash.netty.SslContextBuilder::SslClientVerifyMode::FORCE_PEER)
176
- elsif @ssl_verify_mode.upcase == "PEER"
184
+ elsif @ssl_verify_mode == "peer"
177
185
  ssl_context_builder.setVerifyMode(org.logstash.netty.SslContextBuilder::SslClientVerifyMode::VERIFY_PEER)
178
186
  end
179
187
  ssl_context_builder.setCertificateAuthorities(@ssl_certificate_authorities)
180
188
  end
181
- server.setSslHandlerProvider(org.logstash.netty.SslHandlerProvider.new(ssl_context_builder.build_context, @ssl_handshake_timeout))
189
+ server.setSslHandlerProvider(new_ssl_handshake_provider(ssl_context_builder))
182
190
  end
183
191
  server
184
192
  end
185
193
 
186
- def ssl_configured?
187
- !(@ssl_certificate.nil? || @ssl_key.nil?)
188
- end
189
-
190
- def target_codec_on_field?
191
- !@target_codec_on_field.empty?
192
- end
193
-
194
194
  def run(output_queue)
195
195
  message_listener = MessageListener.new(output_queue, self)
196
196
  @server.setMessageListener(message_listener)
@@ -201,6 +201,14 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
201
201
  @server.stop unless @server.nil?
202
202
  end
203
203
 
204
+ def ssl_configured?
205
+ !(@ssl_certificate.nil? || @ssl_key.nil?)
206
+ end
207
+
208
+ def target_codec_on_field?
209
+ !@target_codec_on_field.empty?
210
+ end
211
+
204
212
  def client_authentification?
205
213
  @ssl_certificate_authorities && @ssl_certificate_authorities.size > 0
206
214
  end
@@ -217,6 +225,32 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
217
225
  @ssl_verify_mode == "force_peer" || @ssl_verify_mode == "peer"
218
226
  end
219
227
 
228
+ private
229
+
230
+ def new_ssl_handshake_provider(ssl_context_builder)
231
+ begin
232
+ org.logstash.netty.SslHandlerProvider.new(ssl_context_builder.build_context, @ssl_handshake_timeout)
233
+ rescue java.lang.IllegalArgumentException => e
234
+ @logger.error("SSL configuration invalid", error_details(e))
235
+ raise LogStash::ConfigurationError, e
236
+ rescue java.lang.Exception => e # java.security.GeneralSecurityException
237
+ @logger.error("SSL configuration failed", error_details(e, true))
238
+ raise e
239
+ end
240
+ end
241
+
242
+ def new_ssl_context_builder
243
+ passphrase = @ssl_key_passphrase.nil? ? nil : @ssl_key_passphrase.value
244
+ begin
245
+ org.logstash.netty.SslContextBuilder.new(@ssl_certificate, @ssl_key, passphrase)
246
+ .setProtocols(convert_protocols)
247
+ .setCipherSuites(normalized_ciphers)
248
+ rescue java.lang.IllegalArgumentException => e
249
+ @logger.error("SSL configuration invalid", error_details(e))
250
+ raise LogStash::ConfigurationError, e
251
+ end
252
+ end
253
+
220
254
  def normalized_ciphers
221
255
  @cipher_suites.map(&:upcase)
222
256
  end
@@ -224,4 +258,21 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
224
258
  def convert_protocols
225
259
  TLS.get_supported(@tls_min_version..@tls_max_version).map(&:name)
226
260
  end
261
+
262
+ def configuration_error(message)
263
+ @logger.error message
264
+ raise LogStash::ConfigurationError, message
265
+ end
266
+
267
+ def error_details(e, trace = false)
268
+ error_details = { :exception => e.class, :message => e.message }
269
+ error_details[:backtrace] = e.backtrace if trace || @logger.debug?
270
+ cause = e.cause
271
+ if cause && e != cause
272
+ error_details[:cause] = { :exception => cause.class, :message => cause.message }
273
+ error_details[:cause][:backtrace] = cause.backtrace if trace || @logger.debug?
274
+ end
275
+ error_details
276
+ end
277
+
227
278
  end
@@ -9,7 +9,16 @@ module LogStash module Inputs class Beats
9
9
  ts = coerce_ts(hash.delete("@timestamp"))
10
10
 
11
11
  event.set("@timestamp", ts) unless ts.nil?
12
- hash.each { |k, v| event.set(k, v) }
12
+ hash.each do |k, v|
13
+ #could be a nested map, so we need to merge and not overwrite
14
+ existing_value = event.get(k)
15
+ if existing_value.is_a?(Hash)
16
+ existing_value = existing_value.merge(v)
17
+ else
18
+ existing_value = v
19
+ end
20
+ event.set(k, existing_value)
21
+ end
13
22
  super(event)
14
23
  event.tag("beats_input_codec_#{codec_name}_applied") if include_codec_tag?
15
24
  event
@@ -15,8 +15,8 @@ module LogStash module Inputs class Beats
15
15
  return unless @input.add_hostname
16
16
  host = event.get("[beat][hostname]")
17
17
 
18
- if host && event.get("host").nil?
19
- event.set("host", host)
18
+ if host && event.get(@input.field_hostname).nil?
19
+ event.set(@input.field_hostname, host)
20
20
  end
21
21
  end
22
22
 
@@ -31,7 +31,9 @@ module LogStash module Inputs class Beats
31
31
  hash = message.getData
32
32
  ip_address = ip_address(ctx)
33
33
 
34
- hash['@metadata']['ip_address'] = ip_address unless ip_address.nil? || hash['@metadata'].nil?
34
+ unless ip_address.nil? || hash['@metadata'].nil?
35
+ set_nested(hash, @input.field_hostip, ip_address)
36
+ end
35
37
  target_field = extract_target_field(hash)
36
38
 
37
39
  extract_tls_peer(hash, ctx)
@@ -140,11 +142,12 @@ module LogStash module Inputs class Beats
140
142
  end
141
143
 
142
144
  if tls_verified
145
+ set_nested(hash, @field_tls_protocol_version, tls_session.getProtocol())
146
+ set_nested(hash, @field_tls_peer_subject, tls_session.getPeerPrincipal().getName())
147
+ set_nested(hash, @field_tls_cipher, tls_session.getCipherSuite())
148
+
143
149
  hash['@metadata']['tls_peer'] = {
144
- :status => "verified",
145
- :protocol => tls_session.getProtocol(),
146
- :subject => tls_session.getPeerPrincipal().getName(),
147
- :cipher_suite => tls_session.getCipherSuite()
150
+ :status => "verified"
148
151
  }
149
152
  else
150
153
  hash['@metadata']['tls_peer'] = {
@@ -154,6 +157,28 @@ module LogStash module Inputs class Beats
154
157
  end
155
158
  end
156
159
 
160
+ # set the value for field_name into the hash, nesting into sub-hashes and creating hashes where necessary
161
+ public #only to make it testable
162
+ def set_nested(hash, field_name, value)
163
+ field_ref = Java::OrgLogstash::FieldReference.from(field_name)
164
+ # create @metadata sub-hash if needed
165
+ if field_ref.type == Java::OrgLogstash::FieldReference::META_CHILD
166
+ unless hash.key?("@metadata")
167
+ hash["@metadata"] = {}
168
+ end
169
+ nesting_hash = hash["@metadata"]
170
+ else
171
+ nesting_hash = hash
172
+ end
173
+
174
+ field_ref.path.each do |token|
175
+ nesting_hash[token] = {} unless nesting_hash.key?(token)
176
+ nesting_hash = nesting_hash[token]
177
+ end
178
+ nesting_hash[field_ref.key] = value
179
+ end
180
+
181
+ private
157
182
  def extract_target_field(hash)
158
183
  if from_filebeat?(hash)
159
184
  hash.delete(FILEBEAT_LOG_LINE_FIELD).to_s
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
27
27
  s.add_runtime_dependency "thread_safe", "~> 0.3.5"
28
28
  s.add_runtime_dependency "logstash-codec-multiline", ">= 2.0.5"
29
29
  s.add_runtime_dependency 'jar-dependencies', '~> 0.3', '>= 0.3.4'
30
+ s.add_runtime_dependency 'logstash-mixin-ecs_compatibility_support', '~>1.1'
30
31
 
31
32
  s.add_development_dependency "flores", "~>0.0.6"
32
33
  s.add_development_dependency "rspec"
@@ -29,7 +29,8 @@ describe LogStash::Inputs::Beats::DecodedEventTransform do
29
29
 
30
30
  subject { described_class.new(input).transform(event, map) }
31
31
 
32
- include_examples "Common Event Transformation"
32
+ include_examples "Common Event Transformation", :disabled, "host"
33
+ include_examples "Common Event Transformation", :v1, "[@metadata][input][beats][host][name]"
33
34
 
34
35
  it "tags the event" do
35
36
  expect(subject.get("tags")).to include("beats_input_codec_plain_applied")
@@ -7,5 +7,6 @@ require "spec_helper"
7
7
  describe LogStash::Inputs::Beats::EventTransformCommon do
8
8
  subject { described_class.new(input).transform(event) }
9
9
 
10
- include_examples "Common Event Transformation"
10
+ include_examples "Common Event Transformation", :disabled, "host"
11
+ include_examples "Common Event Transformation", :v1, "[@metadata][input][beats][host][name]"
11
12
  end
@@ -52,10 +52,73 @@ class DummyCodec < LogStash::Codecs::Base
52
52
  end
53
53
  end
54
54
 
55
+ shared_examples "when the message is from any libbeat" do |ecs_compatibility, host_field_name|
56
+ let(:input) do
57
+ input = LogStash::Inputs::Beats.new({ "port" => 5555, "codec" => codec, "ecs_compatibility" => "#{ecs_compatibility}" })
58
+ input.register
59
+ input
60
+ end
61
+
62
+ #Requires data modeled as Java, not Ruby since the actual code pulls from Java backed (Netty) object
63
+ let(:data) do
64
+ d = HashMap.new
65
+ d.put('@metadata', HashMap.new)
66
+ d.put('metric', 1)
67
+ d.put('name', "super-stats")
68
+ d
69
+ end
70
+
71
+ let(:message) { MockMessage.new("abc", data)}
72
+
73
+ it "extract the event" do
74
+ subject.onNewMessage(ctx, message)
75
+ event = queue.pop
76
+ expect(event.get("message")).to be_nil
77
+ expect(event.get("metric")).to eq(1)
78
+ expect(event.get("name")).to eq("super-stats")
79
+ expect(event.get(host_field_name)).to eq(ip_address)
80
+ end
81
+
82
+ context 'when the remote address is nil' do
83
+ let(:ctx) { OngoingMethodMock.new("remoteAddress", nil)}
84
+
85
+ it 'extracts the event' do
86
+ subject.onNewMessage(ctx, message)
87
+ event = queue.pop
88
+ expect(event.get("message")).to be_nil
89
+ expect(event.get("metric")).to eq(1)
90
+ expect(event.get("name")).to eq("super-stats")
91
+ expect(event.get(host_field_name)).to eq(nil)
92
+ end
93
+ end
94
+
95
+ context 'when getting the remote address raises' do
96
+ let(:raising_ctx) { double("context")}
97
+
98
+ before do
99
+ allow(raising_ctx).to receive(:channel).and_raise("nope")
100
+ subject.onNewConnection(raising_ctx)
101
+ end
102
+
103
+ it 'extracts the event' do
104
+ subject.onNewMessage(raising_ctx, message)
105
+ event = queue.pop
106
+ expect(event.get("message")).to be_nil
107
+ expect(event.get("metric")).to eq(1)
108
+ expect(event.get("name")).to eq("super-stats")
109
+ expect(event.get(host_field_name)).to eq(nil)
110
+ end
111
+ end
112
+ end
113
+
55
114
  describe LogStash::Inputs::Beats::MessageListener do
56
115
  let(:queue) { Queue.new }
57
116
  let(:codec) { DummyCodec.new }
58
- let(:input) { LogStash::Inputs::Beats.new({ "port" => 5555, "codec" => codec }) }
117
+ let(:input) do
118
+ input = LogStash::Inputs::Beats.new({ "port" => 5555, "codec" => codec })
119
+ input.register
120
+ input
121
+ end
59
122
 
60
123
  let(:ip_address) { "10.0.0.1" }
61
124
  let(:remote_address) { OngoingMethodMock.new("getHostAddress", ip_address) }
@@ -146,59 +209,8 @@ describe LogStash::Inputs::Beats::MessageListener do
146
209
  end
147
210
  end
148
211
 
149
- context "when the message is from any libbeat" do
150
- #Requires data modeled as Java, not Ruby since the actual code pulls from Java backed (Netty) object
151
- let(:data) do
152
- d = HashMap.new
153
- d.put('@metadata', HashMap.new)
154
- d.put('metric', 1)
155
- d.put('name', "super-stats")
156
- d
157
- end
158
-
159
- let(:message) { MockMessage.new("abc", data)}
160
-
161
- it "extract the event" do
162
- subject.onNewMessage(ctx, message)
163
- event = queue.pop
164
- expect(event.get("message")).to be_nil
165
- expect(event.get("metric")).to eq(1)
166
- expect(event.get("name")).to eq("super-stats")
167
- expect(event.get("[@metadata][ip_address]")).to eq(ip_address)
168
- end
169
-
170
- context 'when the remote address is nil' do
171
- let(:ctx) { OngoingMethodMock.new("remoteAddress", nil)}
172
-
173
- it 'extracts the event' do
174
- subject.onNewMessage(ctx, message)
175
- event = queue.pop
176
- expect(event.get("message")).to be_nil
177
- expect(event.get("metric")).to eq(1)
178
- expect(event.get("name")).to eq("super-stats")
179
- expect(event.get("[@metadata][ip_address]")).to eq(nil)
180
- end
181
- end
182
-
183
- context 'when getting the remote address raises' do
184
- let(:raising_ctx) { double("context")}
185
-
186
- before do
187
- allow(raising_ctx).to receive(:channel).and_raise("nope")
188
- subject.onNewConnection(raising_ctx)
189
- end
190
-
191
- it 'extracts the event' do
192
- subject.onNewMessage(raising_ctx, message)
193
- event = queue.pop
194
- expect(event.get("message")).to be_nil
195
- expect(event.get("metric")).to eq(1)
196
- expect(event.get("name")).to eq("super-stats")
197
- expect(event.get("[@metadata][ip_address]")).to eq(nil)
198
- end
199
- end
200
-
201
- end
212
+ it_behaves_like "when the message is from any libbeat", :disabled, "[@metadata][ip_address]"
213
+ it_behaves_like "when the message is from any libbeat", :v1, "[@metadata][input][beats][host][ip]"
202
214
  end
203
215
 
204
216
  context "onException" do
@@ -222,4 +234,20 @@ describe LogStash::Inputs::Beats::MessageListener do
222
234
  expect(queue).not_to be_empty
223
235
  end
224
236
  end
237
+
238
+ context "set_nested" do
239
+ let(:hash) {{}}
240
+
241
+ it "creates correctly the nested maps" do
242
+ subject.set_nested(hash, "[root][inner][leaf]", 5)
243
+ expect(hash["root"]["inner"]["leaf"]).to eq(5)
244
+ end
245
+
246
+ it "doesn't overwrite existing the nested maps" do
247
+ hash = {"root" => {"foo" => {"bar" => "Hello"}}}
248
+ subject.set_nested(hash, "[root][inner][leaf]", 5)
249
+ expect(hash["root"]["inner"]["leaf"]).to eq(5)
250
+ expect(hash["root"]["foo"]["bar"]).to eq("Hello")
251
+ end
252
+ end
225
253
  end
@@ -18,7 +18,8 @@ describe LogStash::Inputs::Beats::RawEventTransform do
18
18
 
19
19
  subject { described_class.new(input).transform(event) }
20
20
 
21
- include_examples "Common Event Transformation"
21
+ include_examples "Common Event Transformation", :disabled, "host"
22
+ include_examples "Common Event Transformation", :v1, "[@metadata][input][beats][host][name]"
22
23
 
23
24
  it "tags the event" do
24
25
  expect(subject.get("tags")).to include("beats_input_raw_event")
@@ -13,11 +13,19 @@ describe LogStash::Inputs::Beats do
13
13
  let(:certificate) { BeatsInputTest.certificate }
14
14
  let(:port) { BeatsInputTest.random_port }
15
15
  let(:queue) { Queue.new }
16
- let(:config) { { "port" => 0, "ssl_certificate" => certificate.ssl_cert, "ssl_key" => certificate.ssl_key, "type" => "example", "tags" => "beats"} }
16
+ let(:config) do
17
+ {
18
+ "port" => 0,
19
+ "ssl_certificate" => certificate.ssl_cert,
20
+ "ssl_key" => certificate.ssl_key,
21
+ "type" => "example",
22
+ "tags" => "beats"
23
+ }
24
+ end
17
25
 
18
26
  context "#register" do
19
27
  context "host related configuration" do
20
- let(:config) { super.merge!({ "host" => host, "port" => port, "client_inactivity_timeout" => client_inactivity_timeout, "executor_threads" => threads }) }
28
+ let(:config) { super.merge("host" => host, "port" => port, "client_inactivity_timeout" => client_inactivity_timeout, "executor_threads" => threads) }
21
29
  let(:host) { "192.168.1.20" }
22
30
  let(:port) { 9000 }
23
31
  let(:client_inactivity_timeout) { 400 }
@@ -38,38 +46,55 @@ describe LogStash::Inputs::Beats do
38
46
 
39
47
  context "with ssl enabled" do
40
48
  context "without certificate configuration" do
41
- let(:config) {{ "port" => 0, "ssl" => true, "ssl_key" => certificate.ssl_key, "type" => "example", "tags" => "beats" }}
49
+ let(:config) { { "port" => 0, "ssl" => true, "ssl_key" => certificate.ssl_key, "type" => "example" } }
42
50
 
43
51
  it "should fail to register the plugin with ConfigurationError" do
44
52
  plugin = LogStash::Inputs::Beats.new(config)
45
- expect {plugin.register}.to raise_error(LogStash::ConfigurationError)
53
+ expect { plugin.register }.to raise_error(LogStash::ConfigurationError)
46
54
  end
47
55
  end
48
56
 
49
57
  context "without key configuration" do
50
- let(:config) { { "port" => 0, "ssl" => true, "ssl_certificate" => certificate.ssl_cert, "type" => "example", "tags" => "Beats"} }
58
+ let(:config) { { "port" => 0, "ssl" => true, "ssl_certificate" => certificate.ssl_cert, "type" => "example" } }
51
59
  it "should fail to register the plugin with ConfigurationError" do
52
60
  plugin = LogStash::Inputs::Beats.new(config)
53
- expect {plugin.register}.to raise_error(LogStash::ConfigurationError)
61
+ expect { plugin.register }.to raise_error(LogStash::ConfigurationError)
62
+ end
63
+ end
64
+
65
+ context "with invalid key configuration" do
66
+ let(:p12_key) { certificate.p12_key }
67
+ let(:config) { { "port" => 0, "ssl" => true, "ssl_certificate" => certificate.ssl_cert, "ssl_key" => p12_key } }
68
+ it "should fail to register the plugin" do
69
+ plugin = LogStash::Inputs::Beats.new(config)
70
+ expect( plugin.logger ).to receive(:error) do |msg, opts|
71
+ expect( msg ).to match /.*?configuration invalid/
72
+ expect( opts[:message] ).to match /does not contain valid private key/
73
+ end
74
+ expect { plugin.register }.to raise_error(LogStash::ConfigurationError)
54
75
  end
55
76
  end
56
77
 
57
78
  context "with invalid ciphers" do
58
- let(:config) { { "port" => 0, "ssl" => true, "ssl_certificate" => certificate.ssl_cert, "type" => "example", "tags" => "Beats", "cipher_suites" => "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA38"} }
79
+ let(:config) { super.merge("ssl" => true, "cipher_suites" => "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA38") }
59
80
 
60
81
  it "should raise a configuration error" do
61
82
  plugin = LogStash::Inputs::Beats.new(config)
83
+ expect( plugin.logger ).to receive(:error) do |msg, opts|
84
+ expect( msg ).to match /.*?configuration invalid/
85
+ expect( opts[:message] ).to match /TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA38.*? not available/
86
+ end
62
87
  expect { plugin.register }.to raise_error(LogStash::ConfigurationError)
63
88
  end
64
89
  end
65
90
 
66
91
  context "verify_mode" do
67
92
  context "verify_mode configured to PEER" do
68
- let(:config) { { "port" => 0, "ssl" => true, "ssl_verify_mode" => "peer", "ssl_certificate" => certificate.ssl_cert, "ssl_key" => certificate.ssl_key, "type" => "example", "tags" => "Beats"} }
93
+ let(:config) { super.merge("ssl" => true, "ssl_verify_mode" => "peer") }
69
94
 
70
95
  it "raise a ConfigurationError when certificate_authorities is not set" do
71
96
  plugin = LogStash::Inputs::Beats.new(config)
72
- expect {plugin.register}.to raise_error(LogStash::ConfigurationError, "Using `verify_mode` set to PEER or FORCE_PEER, requires the configuration of `certificate_authorities`")
97
+ expect {plugin.register}.to raise_error(LogStash::ConfigurationError, "ssl_certificate_authorities => is a required setting when ssl_verify_mode => 'peer' is configured")
73
98
  end
74
99
 
75
100
  it "doesn't raise a configuration error when certificate_authorities is set" do
@@ -80,11 +105,11 @@ describe LogStash::Inputs::Beats do
80
105
  end
81
106
 
82
107
  context "verify_mode configured to FORCE_PEER" do
83
- let(:config) { { "port" => 0, "ssl" => true, "ssl_verify_mode" => "force_peer", "ssl_certificate" => certificate.ssl_cert, "ssl_key" => certificate.ssl_key, "type" => "example", "tags" => "Beats"} }
108
+ let(:config) { super.merge("ssl" => true, "ssl_verify_mode" => "force_peer") }
84
109
 
85
110
  it "raise a ConfigurationError when certificate_authorities is not set" do
86
111
  plugin = LogStash::Inputs::Beats.new(config)
87
- expect {plugin.register}.to raise_error(LogStash::ConfigurationError, "Using `verify_mode` set to PEER or FORCE_PEER, requires the configuration of `certificate_authorities`")
112
+ expect {plugin.register}.to raise_error(LogStash::ConfigurationError, "ssl_certificate_authorities => is a required setting when ssl_verify_mode => 'force_peer' is configured")
88
113
  end
89
114
 
90
115
  it "doesn't raise a configuration error when certificate_authorities is set" do
@@ -98,7 +123,7 @@ describe LogStash::Inputs::Beats do
98
123
 
99
124
  context "with ssl disabled" do
100
125
  context "and certificate configuration" do
101
- let(:config) { { "port" => 0, "ssl" => false, "ssl_certificate" => certificate.ssl_cert, "type" => "example", "tags" => "Beats" } }
126
+ let(:config) { { "port" => 0, "ssl" => false, "ssl_certificate" => certificate.ssl_cert, "type" => "example", "tags" => "Beats" } }
102
127
 
103
128
  it "should not fail" do
104
129
  plugin = LogStash::Inputs::Beats.new(config)
@@ -166,8 +166,8 @@ describe "Filebeat", :integration => true do
166
166
  end
167
167
 
168
168
  context "when the cipher is not supported" do
169
- let(:beats_cipher) { "ECDHE-RSA-AES-128-GCM-SHA256" }
170
- let(:logstash_cipher) { "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"}
169
+ let(:beats_cipher) { "ECDHE-RSA-AES-256-GCM-SHA384" }
170
+ let(:logstash_cipher) { "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"}
171
171
 
172
172
  include_examples "doesn't send events"
173
173
  end
@@ -13,6 +13,13 @@ module BeatsInputTest
13
13
 
14
14
  system("openssl req -x509 -batch -nodes -newkey rsa:2048 -keyout #{ssl_key} -out #{ssl_cert} -subj /CN=localhost > /dev/null 2>&1")
15
15
  end
16
+
17
+ def p12_key
18
+ p12_key = Stud::Temporary.pathname("p12_key")
19
+ system "openssl pkcs12 -export -passout pass:123 -inkey #{ssl_key} -in #{ssl_cert} -out #{p12_key}"
20
+ p12_key
21
+ end
22
+
16
23
  end
17
24
 
18
25
  class << self
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
- shared_examples "Common Event Transformation" do
2
+ shared_examples "Common Event Transformation" do |ecs_compatibility, host_field_name|
3
3
  let(:tag) { "140-rpm-beats" }
4
4
  let(:config) do
5
5
  {
@@ -21,12 +21,18 @@ shared_examples "Common Event Transformation" do
21
21
  }
22
22
  end
23
23
 
24
+ def key_as_nested_maps(key, value)
25
+ evt = LogStash::Event.new
26
+ evt.set(key, value)
27
+ evt.to_hash_with_metadata
28
+ end
29
+
24
30
  it "adds configured tags to the event" do
25
31
  expect(subject.get("tags")).to include(tag)
26
32
  end
27
33
 
28
34
  context 'when add_hostname is true' do
29
- let(:config) { super.merge({'add_hostname' => true})}
35
+ let(:config) { super.merge({'add_hostname' => true, 'ecs_compatibility' => ecs_compatibility})}
30
36
 
31
37
  context 'when a host is provided in beat.host.name' do
32
38
  let(:already_exist) { "already_exist" }
@@ -53,35 +59,35 @@ shared_examples "Common Event Transformation" do
53
59
  let(:producer_host) { "newhost01" }
54
60
  let(:event_map) { super.merge({ "beat" => { "hostname" => producer_host }}) }
55
61
 
56
- context "when no `host` key already exists on the event" do
57
- it "copies the value in `beat.hostname` to `host`" do
58
- expect(subject.get("host")).to eq(producer_host)
62
+ context "when no `#{host_field_name}` key already exists on the event" do
63
+ it "copies the value in `beat.hostname` to `#{host_field_name}`" do
64
+ expect(subject.get(host_field_name)).to eq(producer_host)
59
65
  end
60
66
  end
61
67
 
62
- context "when `host` key exists on the event" do
68
+ context "when `#{host_field_name}` key exists on the event" do
63
69
  let(:already_exist) { "already_exist" }
64
- let(:event_map) { super.merge({ "host" => already_exist }) }
70
+ let(:event_map) { super.merge(key_as_nested_maps(host_field_name, already_exist)) }
65
71
 
66
72
  it "doesn't override it" do
67
- expect(subject.get("host")).to eq(already_exist)
73
+ expect(subject.get(host_field_name)).to eq(already_exist)
68
74
  end
69
75
  end
70
76
  end
71
77
 
72
78
  context "when no host is provided in beat" do
73
- context "when no `host` key already exists on the event" do
79
+ context "when no `#{host_field_name}` key already exists on the event" do
74
80
  it "does not set the host" do
75
- expect(subject.get("host")).to be_nil
81
+ expect(subject.get(host_field_name)).to be_nil
76
82
  end
77
83
  end
78
84
 
79
- context "when `host` key already exists on the event" do
85
+ context "when `#{host_field_name}` key already exists on the event" do
80
86
  let(:already_exist) { "already_exist" }
81
- let(:event_map) { super.merge({ "host" => already_exist }) }
87
+ let(:event_map) { super.merge(key_as_nested_maps(host_field_name, already_exist)) }
82
88
 
83
89
  it "doesn't override it" do
84
- expect(subject.get("host")).to eq(already_exist)
90
+ expect(subject.get(host_field_name)).to eq(already_exist)
85
91
  end
86
92
  end
87
93
  end
@@ -95,18 +101,18 @@ shared_examples "Common Event Transformation" do
95
101
  let(:producer_host) { "newhost01" }
96
102
  let(:event_map) { super.merge({ "beat" => { "host" => {"name" => producer_host }}}) }
97
103
 
98
- context "when no `host` key already exists on the event" do
104
+ context "when no `#{host_field_name}` key already exists on the event" do
99
105
  it "does not set the host" do
100
- expect(subject.get("host")).to be_nil
106
+ expect(subject.get(host_field_name)).to be_nil
101
107
  end
102
108
  end
103
109
 
104
- context "when `host` key already exists on the event" do
110
+ context "when `#{host_field_name}` key already exists on the event" do
105
111
  let(:already_exist) { "already_exist" }
106
- let(:event_map) { super.merge({ "host" => already_exist }) }
112
+ let(:event_map) { super.merge(key_as_nested_maps(host_field_name, already_exist)) }
107
113
 
108
114
  it "doesn't override it" do
109
- expect(subject.get("host")).to eq(already_exist)
115
+ expect(subject.get(host_field_name)).to eq(already_exist)
110
116
  end
111
117
  end
112
118
  end
@@ -115,35 +121,35 @@ shared_examples "Common Event Transformation" do
115
121
  let(:producer_host) { "newhost01" }
116
122
  let(:event_map) { super.merge({ "beat" => { "hostname" => producer_host }}) }
117
123
 
118
- context "when no `host` key already exists on the event" do
124
+ context "when no `#{host_field_name}` key already exists on the event" do
119
125
  it "does not set the host" do
120
- expect(subject.get("host")).to be_nil
126
+ expect(subject.get(host_field_name)).to be_nil
121
127
  end
122
128
  end
123
129
 
124
130
  context "when `host` key already exists on the event" do
125
131
  let(:already_exist) { "already_exist" }
126
- let(:event_map) { super.merge({ "host" => already_exist }) }
132
+ let(:event_map) { super.merge(key_as_nested_maps(host_field_name, already_exist)) }
127
133
 
128
134
  it "doesn't override it" do
129
- expect(subject.get("host")).to eq(already_exist)
135
+ expect(subject.get(host_field_name)).to eq(already_exist)
130
136
  end
131
137
  end
132
138
  end
133
139
 
134
140
  context "when no host is provided in beat" do
135
- context "when no `host` key already exists on the event" do
141
+ context "when no `#{host_field_name}` key already exists on the event" do
136
142
  it "does not set the host" do
137
- expect(subject.get("host")).to be_nil
143
+ expect(subject.get(host_field_name)).to be_nil
138
144
  end
139
145
  end
140
146
 
141
- context "when `host` key already exists on the event" do
147
+ context "when `#{host_field_name}` key already exists on the event" do
142
148
  let(:already_exist) { "already_exist" }
143
- let(:event_map) { super.merge({ "host" => already_exist }) }
149
+ let(:event_map) { super.merge(key_as_nested_maps(host_field_name, already_exist)) }
144
150
 
145
151
  it "doesn't override it" do
146
- expect(subject.get("host")).to eq(already_exist)
152
+ expect(subject.get(host_field_name)).to eq(already_exist)
147
153
  end
148
154
  end
149
155
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-input-beats
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.10
4
+ version: 6.1.0
5
5
  platform: java
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-12 00:00:00.000000000 Z
11
+ date: 2021-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -106,6 +106,20 @@ dependencies:
106
106
  - - ">="
107
107
  - !ruby/object:Gem::Version
108
108
  version: 0.3.4
109
+ - !ruby/object:Gem::Dependency
110
+ requirement: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - "~>"
113
+ - !ruby/object:Gem::Version
114
+ version: '1.1'
115
+ name: logstash-mixin-ecs_compatibility_support
116
+ prerelease: false
117
+ type: :runtime
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '1.1'
109
123
  - !ruby/object:Gem::Dependency
110
124
  requirement: !ruby/object:Gem::Requirement
111
125
  requirements:
@@ -266,13 +280,12 @@ files:
266
280
  - spec/support/shared_examples.rb
267
281
  - vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-annotations/2.9.10/jackson-annotations-2.9.10.jar
268
282
  - vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-core/2.9.10/jackson-core-2.9.10.jar
269
- - vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-databind/2.9.10.1/jackson-databind-2.9.10.1.jar
283
+ - vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-databind/2.9.10.4/jackson-databind-2.9.10.4.jar
270
284
  - vendor/jar-dependencies/com/fasterxml/jackson/module/jackson-module-afterburner/2.9.10/jackson-module-afterburner-2.9.10.jar
271
- - vendor/jar-dependencies/io/netty/netty-all/4.1.30.Final/netty-all-4.1.30.Final.jar
272
- - vendor/jar-dependencies/io/netty/netty-tcnative-boringssl-static/2.0.12.Final/netty-tcnative-boringssl-static-2.0.12.Final.jar
285
+ - vendor/jar-dependencies/io/netty/netty-all/4.1.49.Final/netty-all-4.1.49.Final.jar
273
286
  - vendor/jar-dependencies/org/apache/logging/log4j/log4j-api/2.11.1/log4j-api-2.11.1.jar
274
287
  - vendor/jar-dependencies/org/javassist/javassist/3.24.0-GA/javassist-3.24.0-GA.jar
275
- - vendor/jar-dependencies/org/logstash/beats/logstash-input-beats/6.0.10/logstash-input-beats-6.0.10.jar
288
+ - vendor/jar-dependencies/org/logstash/beats/logstash-input-beats/6.1.0/logstash-input-beats-6.1.0.jar
276
289
  homepage: http://www.elastic.co/guide/en/logstash/current/index.html
277
290
  licenses:
278
291
  - Apache License (2.0)