logstash-input-syslog 3.4.5 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 78d3ae407146832319799963b5ca4a436fda4936a75e1985261c8b4439acedec
4
- data.tar.gz: a59e5ea7f49ced6e7a9c75d4f30154733e4ad9413a1be01e309848e5802b7fac
3
+ metadata.gz: 6f54c37d7c50508f001a49df641a45df74cf61cf4c4a4fcebafef442e380df68
4
+ data.tar.gz: 8c269bbad63b3ee0b022e7e206fc0884ed213b38380b15bdda9ee421e7f8ebeb
5
5
  SHA512:
6
- metadata.gz: 3e9d73ad662d26e0a1a49b6700e8da99050982da9c36766473eb21742279e8117091fbfa1b6ab7d11958d6e015754eb7a4547c2795782fcd9081557510ca8097
7
- data.tar.gz: 2cf5e512229804e7dc0f99cded9070cf48d5f2d4ac73c107e60c242b453b55fce8832b6b71ee1766778d61719da39687806bd57c913d784556684c98f32a144f
6
+ metadata.gz: 8c886952d2095e9cefddeaaebbefa8495b78732b74350a6579849dd22da8f85f3065a35b411ce8952cd2cb12a80d49468cb44eeabfac4d93d8610663f7536366
7
+ data.tar.gz: a254785ecca431fc409bd2ebd031a14b2901295f2293913c6d7f92629327e8694e1ee2e13e7e04898cdc7c1939f29b1a6bb674e5dbc183b7c5c1487146d47284
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ ## 3.5.0
2
+ - Feat: ECS compatibility support [#63](https://github.com/logstash-plugins/logstash-input-syslog/pull/63)
3
+
1
4
  ## 3.4.5
2
5
  - Added support for listening on IPv6 addresses
3
6
 
data/docs/index.asciidoc CHANGED
@@ -47,6 +47,7 @@ This plugin supports the following configuration options plus the <<plugins-{typ
47
47
  [cols="<,<,<",options="header",]
48
48
  |=======================================================================
49
49
  |Setting |Input type|Required
50
+ | <<plugins-{type}s-{plugin}-ecs_compatibility>> | <<string,string>>|No
50
51
  | <<plugins-{type}s-{plugin}-facility_labels>> |<<array,array>>|No
51
52
  | <<plugins-{type}s-{plugin}-grok_pattern>> |<<string,string>>|No
52
53
  | <<plugins-{type}s-{plugin}-host>> |<<string,string>>|No
@@ -64,6 +65,20 @@ input plugins.
64
65
 
65
66
  &nbsp;
66
67
 
68
+ [id="plugins-{type}s-{plugin}-ecs_compatibility"]
69
+ ===== `ecs_compatibility`
70
+
71
+ * Value type is <<string,string>>
72
+ * Supported values are:
73
+ ** `disabled`: does not use ECS-compatible field names (for example, `priority` for syslog priority)
74
+ ** `v1`: uses fields that are compatible with Elastic Common Schema (for example, `[log][syslog][priority]`)
75
+ * Default value depends on which version of Logstash is running:
76
+ ** When Logstash provides a `pipeline.ecs_compatibility` setting, its value is used as the default
77
+ ** Otherwise, the default value is `disabled`.
78
+
79
+ Controls this plugin's compatibility with the
80
+ {ecs-ref}[Elastic Common Schema (ECS)].
81
+
67
82
  [id="plugins-{type}s-{plugin}-facility_labels"]
68
83
  ===== `facility_labels`
69
84
 
@@ -84,6 +99,9 @@ the facility_label is not added to the event.
84
99
 
85
100
  * Value type is <<string,string>>
86
101
  * Default value is `"<%{POSINT:priority}>%{SYSLOGLINE}"`
102
+ * Default value depends on whether <<plugins-{type}s-{plugin}-ecs_compatibility>> is enabled:
103
+ ** ECS Compatibility disabled: `"<%{POSINT:priority}>%{SYSLOGLINE}"`
104
+ ** ECS Compatibility enabled: `"<%{POSINT:[log][syslog][priority]:int}>%{SYSLOGLINE}"`
87
105
 
88
106
  The default value should read and properly parse syslog lines which are
89
107
  fully compliant with http://www.ietf.org/rfc/rfc3164.txt[RFC3164].
@@ -6,6 +6,7 @@ require "logstash/filters/grok"
6
6
  require "logstash/filters/date"
7
7
  require "logstash/inputs/base"
8
8
  require "logstash/namespace"
9
+ require 'logstash/plugin_mixins/ecs_compatibility_support'
9
10
  require "stud/interval"
10
11
 
11
12
  # Read syslog messages as events over the network.
@@ -25,6 +26,8 @@ require "stud/interval"
25
26
  # Note: This input will start listeners on both TCP and UDP.
26
27
  #
27
28
  class LogStash::Inputs::Syslog < LogStash::Inputs::Base
29
+ include LogStash::PluginMixins::ECSCompatibilitySupport(:disabled, :v1)
30
+
28
31
  config_name "syslog"
29
32
 
30
33
  default :codec, "plain"
@@ -42,7 +45,7 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
42
45
 
43
46
  # Set custom grok pattern to parse the syslog, in case the format differs
44
47
  # from the defined standard. This is common in security and other appliances
45
- config :grok_pattern, :validate => :string, :default => "<%{POSINT:priority}>%{SYSLOGLINE}"
48
+ config :grok_pattern, :validate => :string
46
49
 
47
50
  # Proxy protocol support, only v1 is supported at this time
48
51
  # http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt
@@ -74,22 +77,67 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
74
77
  #
75
78
  config :locale, :validate => :string
76
79
 
77
- public
78
- def register
79
- @metric_errors = metric.namespace(:errors)
80
+ # ECS only option to configure [service][type] value in produced events.
81
+ #
82
+ # NOTE: for now, purposefully un-documented as there are other [service] fields we could support,
83
+ # assuming users would want that (they have specific use-case for LS as syslog server).
84
+ config :service_type, :validate => :string, :default => 'system'
85
+
86
+ def initialize(*params)
87
+ super
88
+
89
+ @priority_key = ecs_select[disabled:'priority', v1:'[log][syslog][priority]']
90
+ @facility_key = ecs_select[disabled:'facility', v1:'[log][syslog][facility][code]']
91
+ @severity_key = ecs_select[disabled:'severity', v1:'[log][syslog][severity][code]']
92
+
93
+ @facility_label_key = ecs_select[disabled:'facility_label', v1:'[log][syslog][facility][name]']
94
+ @severity_label_key = ecs_select[disabled:'severity_label', v1:'[log][syslog][severity][name]']
95
+
96
+ @host_key = ecs_select[disabled:'host', v1:'[host][ip]']
97
+
98
+ @grok_pattern ||= ecs_select[
99
+ disabled:"<%{POSINT:#{@priority_key}}>%{SYSLOGLINE}",
100
+ v1:"<%{POSINT:#{@priority_key}:int}>%{SYSLOGLINE}"
101
+ ]
80
102
 
81
103
  @grok_filter = LogStash::Filters::Grok.new(
82
- "overwrite" => @syslog_field,
83
- "match" => { @syslog_field => @grok_pattern },
84
- "tag_on_failure" => ["_grokparsefailure_sysloginput"],
104
+ "overwrite" => @syslog_field,
105
+ "match" => { @syslog_field => @grok_pattern },
106
+ "tag_on_failure" => ["_grokparsefailure_sysloginput"],
107
+ "ecs_compatibility" => ecs_compatibility # use ecs-compliant patterns
85
108
  )
86
109
 
110
+ @grok_filter_exec = ecs_select[
111
+ disabled: -> (event) { @grok_filter.filter(event) },
112
+ v1: -> (event) {
113
+ event.set('[event][original]', event.get(@syslog_field))
114
+ @grok_filter.filter(event)
115
+ set_service_fields(event)
116
+ }
117
+ ]
118
+
87
119
  @date_filter = LogStash::Filters::Date.new(
88
- "match" => [ "timestamp", "MMM dd HH:mm:ss", "MMM d HH:mm:ss", "ISO8601"],
89
- "locale" => @locale,
90
- "timezone" => @timezone,
120
+ "match" => [ "timestamp", "MMM dd HH:mm:ss", "MMM d HH:mm:ss", "MMM d HH:mm:ss", "ISO8601"],
121
+ "locale" => @locale,
122
+ "timezone" => @timezone,
91
123
  )
92
124
 
125
+ @date_filter_exec = ecs_select[
126
+ disabled: -> (event) {
127
+ # in legacy (non-ecs) mode we used to match (SYSLOGBASE2) timestamp into two fields
128
+ event.set("timestamp", event.get("timestamp8601")) if event.include?("timestamp8601")
129
+ @date_filter.filter(event)
130
+ },
131
+ v1: -> (event) {
132
+ @date_filter.filter(event)
133
+ event.remove('timestamp')
134
+ }
135
+ ]
136
+ end
137
+
138
+ def register
139
+ @metric_errors = metric.namespace(:errors)
140
+
93
141
  @grok_filter.register
94
142
  @date_filter.register
95
143
 
@@ -97,7 +145,8 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
97
145
  @tcp = @udp = nil
98
146
  end # def register
99
147
 
100
- public
148
+ private
149
+
101
150
  def run(output_queue)
102
151
  udp_thr = Thread.new(output_queue) do |output_queue|
103
152
  server(:udp, output_queue)
@@ -112,8 +161,8 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
112
161
  udp_thr.join
113
162
  tcp_thr.join
114
163
  end # def run
164
+ public :run
115
165
 
116
- private
117
166
  # server call the specified protocol listener and basically restarts on
118
167
  # any listener uncatched exception
119
168
  #
@@ -130,7 +179,6 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
130
179
  end
131
180
  end
132
181
 
133
- private
134
182
  # udp_listener creates the udp socket and continously read from it.
135
183
  # upon exception the socket will be closed and the exception bubbled
136
184
  # in the server which will restart the listener
@@ -151,7 +199,6 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
151
199
  close_udp
152
200
  end # def udp_listener
153
201
 
154
- private
155
202
  # tcp_listener accepts tcp connections and creates a new tcp_receiver thread
156
203
  # for each accepted socket.
157
204
  # upon exception all tcp sockets will be closed and the exception bubbled
@@ -177,11 +224,14 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
177
224
  # tcp_receiver is executed in a thread, any uncatched exception will be bubbled up to the
178
225
  # tcp server thread and all tcp connections will be closed and the listener restarted.
179
226
  def tcp_receiver(output_queue, socket)
180
- ip, port = socket.peeraddr[3], socket.peeraddr[1]
181
- first_read = true
227
+ peer_addr = socket.peeraddr
228
+ ip, port = peer_addr[3], peer_addr[1]
229
+
182
230
  @logger.info("new connection", :client => "#{ip}:#{port}")
183
231
  LogStash::Util::set_thread_name("input|syslog|tcp|#{ip}:#{port}}")
184
232
 
233
+ first_read = true
234
+
185
235
  socket.each do |line|
186
236
  metric.increment(:messages_received)
187
237
  if @proxy_protocol && first_read
@@ -189,10 +239,10 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
189
239
  pp_info = line.split(/\s/)
190
240
  # PROXY proto clientip proxyip clientport proxyport
191
241
  if pp_info[0] != "PROXY"
192
- @logger.error("invalid proxy protocol header label", :hdr => line)
242
+ @logger.error("invalid proxy protocol header label", header: line)
193
243
  raise IOError
194
244
  else
195
- # would be nice to log the proxy host and port data as well, but minimizing changes
245
+ @logger.debug("proxy protocol detected", header: line)
196
246
  ip = pp_info[2]
197
247
  port = pp_info[3]
198
248
  next
@@ -206,20 +256,19 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
206
256
  rescue Errno::EBADF
207
257
  # swallow connection closed exceptions to avoid bubling up the tcp_listener & server
208
258
  logger.info("connection closed", :client => "#{ip}:#{port}")
209
- rescue IOError => ioerror
259
+ rescue IOError => e
210
260
  # swallow connection closed exceptions to avoid bubling up the tcp_listener & server
211
- raise unless socket.closed? && ioerror.message.include?("closed")
212
- logger.info("connection error: #{ioerror.message}")
261
+ raise(e) unless socket.closed? && e.message.to_s.include?("closed")
262
+ logger.info("connection error:", :exception => e.class, :message => e.message)
213
263
  ensure
214
264
  @tcp_sockets.delete(socket)
215
265
  socket.close rescue log_and_squash(:close_tcp_receiver_socket)
216
266
  end
217
267
 
218
- private
219
- def decode(host, output_queue, data)
268
+ def decode(ip, output_queue, data)
220
269
  @codec.decode(data) do |event|
221
270
  decorate(event)
222
- event.set("host", host)
271
+ event.set(@host_key, ip)
223
272
  syslog_relay(event)
224
273
  output_queue << event
225
274
  metric.increment(:events)
@@ -230,13 +279,13 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
230
279
  @metric_errors.increment(:decoding)
231
280
  end
232
281
 
233
- public
282
+ # @see LogStash::Plugin#close
234
283
  def stop
235
284
  close_udp
236
285
  close_tcp
237
286
  end
287
+ public :stop
238
288
 
239
- private
240
289
  def close_udp
241
290
  if @udp
242
291
  @udp.close_read rescue log_and_squash(:close_udp_read)
@@ -245,8 +294,6 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
245
294
  @udp = nil
246
295
  end
247
296
 
248
- private
249
-
250
297
  # Helper for inline rescues, which logs the exception at "DEBUG" level and returns nil.
251
298
  #
252
299
  # Instead of:
@@ -276,46 +323,54 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
276
323
  # If the message cannot be recognized (see @grok_filter), we'll
277
324
  # treat it like the whole event["message"] is correct and try to fill
278
325
  # the missing pieces (host, priority, etc)
279
- public
280
326
  def syslog_relay(event)
281
- @grok_filter.filter(event)
327
+ @grok_filter_exec.(event)
282
328
 
283
329
  if event.get("tags").nil? || !event.get("tags").include?(@grok_filter.tag_on_failure)
284
330
  # Per RFC3164, priority = (facility * 8) + severity
285
331
  # = (facility << 3) & (severity)
286
- priority = event.get("priority").to_i rescue 13
287
- severity = priority & 7 # 7 is 111 (3 bits)
288
- facility = priority >> 3
289
- event.set("priority", priority)
290
- event.set("severity", severity)
291
- event.set("facility", facility)
292
-
293
- event.set("timestamp", event.get("timestamp8601")) if event.include?("timestamp8601")
294
- @date_filter.filter(event)
332
+ priority = event.get(@priority_key).to_i rescue 13
333
+ set_priority event, priority
334
+
335
+ @date_filter_exec.(event)
336
+
295
337
  else
296
- @logger.debug? && @logger.debug("NOT SYSLOG", :message => event.get("message"))
338
+ @logger.debug? && @logger.debug("un-matched syslog message", :message => event.get("message"))
297
339
 
298
340
  # RFC3164 says unknown messages get pri=13
299
- priority = 13
300
- event.set("priority", 13)
301
- event.set("severity", 5) # 13 & 7 == 5
302
- event.set("facility", 1) # 13 >> 3 == 1
341
+ set_priority event, 13
303
342
  metric.increment(:unknown_messages)
304
343
  end
305
344
 
306
- # Apply severity and facility metadata if
307
- # use_labels => true
308
- if @use_labels
309
- facility_number = event.get("facility")
310
- severity_number = event.get("severity")
345
+ # Apply severity and facility metadata if use_labels => true
346
+ set_labels(event) if @use_labels
347
+ end # def syslog_relay
348
+ public :syslog_relay
349
+
350
+ def set_priority(event, priority)
351
+ severity = priority & 7 # 7 is 111 (3 bits)
352
+ facility = priority >> 3
353
+ event.set(@priority_key, priority)
354
+ event.set(@severity_key, severity)
355
+ event.set(@facility_key, facility)
356
+ end
311
357
 
312
- if @facility_labels[facility_number]
313
- event.set("facility_label", @facility_labels[facility_number])
314
- end
358
+ def set_labels(event)
359
+ facility_number = event.get(@facility_key)
360
+ severity_number = event.get(@severity_key)
315
361
 
316
- if @severity_labels[severity_number]
317
- event.set("severity_label", @severity_labels[severity_number])
318
- end
362
+ facility_label = @facility_labels[facility_number]
363
+ event.set(@facility_label_key, facility_label) if facility_label
364
+
365
+ severity_label = @severity_labels[severity_number]
366
+ event.set(@severity_label_key, severity_label) if severity_label
367
+ end
368
+
369
+ def set_service_fields(event)
370
+ service_type = @service_type
371
+ if service_type && !service_type.empty?
372
+ event.set('[service][type]', service_type) unless event.include?('[service][type]')
319
373
  end
320
- end # def syslog_relay
374
+ end
375
+
321
376
  end # class LogStash::Inputs::Syslog
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-input-syslog'
4
- s.version = '3.4.5'
4
+ s.version = '3.5.0'
5
5
  s.licenses = ['Apache License (2.0)']
6
6
  s.summary = "Reads syslog messages as events"
7
7
  s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
@@ -21,12 +21,13 @@ Gem::Specification.new do |s|
21
21
 
22
22
  # Gem dependencies
23
23
  s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
24
+ s.add_runtime_dependency 'logstash-mixin-ecs_compatibility_support', '~> 1.1'
24
25
 
25
26
  s.add_runtime_dependency 'concurrent-ruby'
26
27
  s.add_runtime_dependency 'stud', '>= 0.0.22', '< 0.1.0'
27
28
 
28
29
  s.add_runtime_dependency 'logstash-codec-plain'
29
- s.add_runtime_dependency 'logstash-filter-grok'
30
+ s.add_runtime_dependency 'logstash-filter-grok', '>= 4.4.0'
30
31
  s.add_runtime_dependency 'logstash-filter-date'
31
32
 
32
33
  s.add_development_dependency 'logstash-devutils'
@@ -2,6 +2,8 @@
2
2
  require "logstash/devutils/rspec/spec_helper"
3
3
  require "logstash/devutils/rspec/shared_examples"
4
4
 
5
+ require 'logstash/plugin_mixins/ecs_compatibility_support/spec_helper'
6
+
5
7
  # running the grok code outside a logstash package means
6
8
  # LOGSTASH_HOME will not be defined, so let's set it here
7
9
  # before requiring the grok filter
@@ -32,7 +34,7 @@ describe LogStash::Inputs::Syslog do
32
34
  SYSLOG_LINE = "<164>Oct 26 15:19:25 1.2.3.4 %ASA-4-106023: Deny udp src DRAC:10.1.2.3/43434 dst outside:192.168.0.1/53 by access-group \"acl_drac\" [0x0, 0x0]"
33
35
 
34
36
  it "should properly handle priority, severity and facilities" do
35
- skip 'elastic/logstash#11196 known LS 7.5 issue' if ENV['ELASTIC_STACK_VERSION'] && JRUBY_VERSION.eql?('9.2.8.0')
37
+ skip_if_stack_known_issue
36
38
  port = 5511
37
39
  event_count = 10
38
40
  conf = <<-CONFIG
@@ -63,7 +65,7 @@ describe LogStash::Inputs::Syslog do
63
65
  end
64
66
 
65
67
  it "should properly PROXY protocol v1" do
66
- skip 'elastic/logstash#11196 known LS 7.5 issue' if ENV['ELASTIC_STACK_VERSION'] && JRUBY_VERSION.eql?('9.2.8.0')
68
+ skip_if_stack_known_issue
67
69
  port = 5511
68
70
  event_count = 10
69
71
  conf = <<-CONFIG
@@ -97,101 +99,190 @@ describe LogStash::Inputs::Syslog do
97
99
  end
98
100
  end
99
101
 
100
- it "should add unique tag when grok parsing fails with live syslog input" do
101
- skip 'elastic/logstash#11196 known LS 7.5 issue' if ENV['ELASTIC_STACK_VERSION'] && JRUBY_VERSION.eql?('9.2.8.0')
102
- port = 5511
103
- event_count = 10
104
- conf = <<-CONFIG
105
- input {
106
- syslog {
107
- type => "blah"
108
- port => #{port}
109
- }
110
- }
111
- CONFIG
102
+ context 'tag', :ecs_compatibility_support do
103
+ ecs_compatibility_matrix(:disabled, :v1) do
112
104
 
113
- events = input(conf) do |pipeline, queue|
114
- socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
115
- event_count.times do |i|
116
- socket.puts("message which causes the a grok parse failure")
105
+ before(:each) do
106
+ allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
117
107
  end
118
- socket.close
119
108
 
120
- event_count.times.collect { queue.pop }
121
- end
109
+ it "should add unique tag when grok parsing fails with live syslog input" do
110
+ skip_if_stack_known_issue
111
+ port = 5511
112
+ event_count = 10
113
+ conf = <<-CONFIG
114
+ input {
115
+ syslog {
116
+ type => "blah"
117
+ port => #{port}
118
+ }
119
+ }
120
+ CONFIG
121
+
122
+ events = input(conf) do |pipeline, queue|
123
+ socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
124
+ event_count.times do |i|
125
+ socket.puts("message which causes the a grok parse failure")
126
+ end
127
+ socket.close
128
+
129
+ event_count.times.collect { queue.pop }
130
+ end
131
+
132
+ expect( events.length ).to eql event_count
133
+ event_count.times do |i|
134
+ expect( events[i].get("tags") ).to eql ["_grokparsefailure_sysloginput"]
135
+ end
136
+ end
122
137
 
123
- expect( events.length ).to eql event_count
124
- event_count.times do |i|
125
- expect( events[i].get("tags") ).to eql ["_grokparsefailure_sysloginput"]
126
138
  end
127
139
  end
128
140
 
129
- it "should properly handle locale and timezone" do
130
- port = 5511
131
- event_count = 10
141
+ context 'timestamp', :ecs_compatibility_support do
142
+ ecs_compatibility_matrix(:disabled, :v1) do
132
143
 
133
- conf = <<-CONFIG
134
- input {
135
- syslog {
136
- type => "blah"
137
- port => #{port}
138
- locale => "en"
139
- timezone => "UTC"
140
- }
141
- }
142
- CONFIG
144
+ before(:each) do
145
+ allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
146
+ end
143
147
 
144
- events = input(conf) do |pipeline, queue|
145
- socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
146
- event_count.times do |i|
147
- socket.puts(SYSLOG_LINE)
148
+ it "should properly handle locale and timezone" do
149
+ port = 5511
150
+ event_count = 10
151
+
152
+ conf = <<-CONFIG
153
+ input {
154
+ syslog {
155
+ type => "blah"
156
+ port => #{port}
157
+ locale => "en"
158
+ timezone => "UTC"
159
+ }
160
+ }
161
+ CONFIG
162
+
163
+ events = input(conf) do |pipeline, queue|
164
+ socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
165
+ event_count.times do |i|
166
+ socket.puts(SYSLOG_LINE)
167
+ end
168
+ socket.close
169
+
170
+ event_count.times.collect { queue.pop }
171
+ end
172
+
173
+ expect( events.length ).to eql event_count
174
+ events.each do |event|
175
+ expect( event.get("@timestamp").to_iso8601 ).to eql "#{Time.now.year}-10-26T15:19:25.000Z"
176
+ end
148
177
  end
149
- socket.close
150
178
 
151
- event_count.times.collect { queue.pop }
152
- end
179
+ it "should properly handle no locale and no timezone" do
180
+ port = 5511
181
+
182
+ conf = <<-CONFIG
183
+ input {
184
+ syslog {
185
+ type => "blah"
186
+ port => #{port}
187
+ }
188
+ }
189
+ CONFIG
190
+
191
+ event = input(conf) do |pipeline, queue|
192
+ socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
193
+ socket.puts(SYSLOG_LINE)
194
+ socket.close
195
+
196
+ queue.pop
197
+ end
198
+
199
+ # chances platform timezone is not UTC so ignore the hours
200
+ expect( event.get("@timestamp").to_iso8601 ).to match /#{Time.now.year}-10-26T\d\d:19:25.000Z/
201
+ end
202
+
203
+ it "should support non UTC timezone" do
204
+ input = LogStash::Inputs::Syslog.new({"timezone" => "-05:00"})
205
+ input.register
206
+
207
+ # event which is not syslog should have a new tag
208
+
209
+ syslog_event = LogStash::Event.new({ "message" => "<164>Oct 26 15:19:25 1.2.3.4 %ASA-4-106023: Deny udp src DRAC:10.1.2.3/43434" })
210
+ input.syslog_relay(syslog_event)
211
+
212
+ expect( syslog_event.get("@timestamp").to_iso8601 ).to eql "#{Time.now.year}-10-26T20:19:25.000Z"
213
+
214
+ input.close
215
+ end
153
216
 
154
- expect( events.length ).to eql event_count
155
- events.each do |event|
156
- expect( event.get("@timestamp").to_iso8601 ).to eql "#{Time.now.year}-10-26T15:19:25.000Z"
157
217
  end
158
218
  end
159
219
 
160
- it "should properly handle no locale and no timezone" do
161
- port = 5511
220
+ context 'ECS behavior', :ecs_compatibility_support do
162
221
 
163
- conf = <<-CONFIG
164
- input {
165
- syslog {
166
- type => "blah"
167
- port => #{port}
168
- }
169
- }
170
- CONFIG
222
+ ecs_compatibility_matrix(:v1) do
171
223
 
172
- event = input(conf) do |pipeline, queue|
173
- socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
174
- socket.puts(SYSLOG_LINE)
175
- socket.close
224
+ before(:each) do
225
+ allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
226
+ end
176
227
 
177
- queue.pop
178
- end
228
+ let(:event) do
229
+ LogStash::Event.new("message" => "<164>Oct 26 15:19:25 1.2.3.4 a sample message")
230
+ end
179
231
 
180
- # chances platform timezone is not UTC so ignore the hours
181
- expect( event.get("@timestamp").to_iso8601 ).to match /#{Time.now.year}-10-26T\d\d:19:25.000Z/
182
- end
232
+ subject { LogStash::Inputs::Syslog.new }
183
233
 
184
- it "should support non UTC timezone" do
185
- input = LogStash::Inputs::Syslog.new({"timezone" => "-05:00"})
186
- input.register
234
+ before { subject.register }
235
+ after { subject.close }
187
236
 
188
- # event which is not syslog should have a new tag
237
+ it "should not have a timestamp field" do
238
+ subject.syslog_relay(event)
189
239
 
190
- syslog_event = LogStash::Event.new({ "message" => "<164>Oct 26 15:19:25 1.2.3.4 %ASA-4-106023: Deny udp src DRAC:10.1.2.3/43434" })
191
- input.syslog_relay(syslog_event)
192
- expect( syslog_event.get("@timestamp").to_iso8601 ).to eql "#{Time.now.year}-10-26T20:19:25.000Z"
240
+ expect( event.to_hash.keys ).to_not include 'timestamp'
241
+ end
193
242
 
194
- input.close
243
+ it "overwrites message" do
244
+ subject.syslog_relay(event)
245
+
246
+ expect( event.get('message') ).to eql 'a sample message'
247
+ end
248
+
249
+ it "keep original log message" do
250
+ subject.syslog_relay(event)
251
+
252
+ expect( event.get('[event][original]') ).to eql '<164>Oct 26 15:19:25 1.2.3.4 a sample message'
253
+ end
254
+
255
+ it "sets syslog priority and severity" do
256
+ subject.syslog_relay(event)
257
+
258
+ expect( event.get('log') ).to include 'syslog' => hash_including('priority' => 164)
259
+ expect( event.get('log') ).to include 'syslog' => hash_including('severity' => { 'code' => 4, 'name' => 'Warning' })
260
+ end
261
+
262
+ it "sets service type" do
263
+ subject.syslog_relay(event)
264
+
265
+ expect( event.get('service') ).to include 'type' => 'system'
266
+ end
267
+
268
+ let(:queue) { Queue.new }
269
+
270
+ let(:socket) do
271
+ server = double('tcp-server')
272
+ allow( server ).to receive(:each).and_yield "<133>Mar 11 08:44:43 precision kernel: [765135.424096] mce: CPU6: Package temperature/speed normal\n"
273
+ allow( server ).to receive(:close)
274
+ server
275
+ end
276
+
277
+ it "sets host IP" do
278
+ expect( socket ).to receive(:peeraddr).and_return(["AF_INET", 514, "192.168.0.10", "192.168.0.10"])
279
+ subject.send :tcp_receiver, queue, socket
280
+
281
+ expect( queue.size ).to eql 1
282
+ event = queue.pop
283
+ expect( event.get('host') ).to eql 'hostname' => 'precision', 'ip' => '192.168.0.10'
284
+ end
285
+ end
195
286
  end
196
287
 
197
288
  it "should add unique tag when grok parsing fails" do
@@ -292,4 +383,10 @@ describe LogStash::Inputs::Syslog do
292
383
  expect( event.get("timestamp") ).to eql timestamp
293
384
  end
294
385
  end
386
+
387
+ private
388
+
389
+ def skip_if_stack_known_issue
390
+ skip 'elastic/logstash#11196 known LS 7.5 issue' if ENV['ELASTIC_STACK_VERSION'] && JRUBY_VERSION.eql?('9.2.8.0')
391
+ end
295
392
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-input-syslog
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.5
4
+ version: 3.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-11 00:00:00.000000000 Z
11
+ date: 2021-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -30,6 +30,20 @@ dependencies:
30
30
  - - "<="
31
31
  - !ruby/object:Gem::Version
32
32
  version: '2.99'
33
+ - !ruby/object:Gem::Dependency
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - "~>"
37
+ - !ruby/object:Gem::Version
38
+ version: '1.1'
39
+ name: logstash-mixin-ecs_compatibility_support
40
+ prerelease: false
41
+ type: :runtime
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.1'
33
47
  - !ruby/object:Gem::Dependency
34
48
  requirement: !ruby/object:Gem::Requirement
35
49
  requirements:
@@ -83,7 +97,7 @@ dependencies:
83
97
  requirements:
84
98
  - - ">="
85
99
  - !ruby/object:Gem::Version
86
- version: '0'
100
+ version: 4.4.0
87
101
  name: logstash-filter-grok
88
102
  prerelease: false
89
103
  type: :runtime
@@ -91,7 +105,7 @@ dependencies:
91
105
  requirements:
92
106
  - - ">="
93
107
  - !ruby/object:Gem::Version
94
- version: '0'
108
+ version: 4.4.0
95
109
  - !ruby/object:Gem::Dependency
96
110
  requirement: !ruby/object:Gem::Requirement
97
111
  requirements: