logstash-input-syslog 3.5.0 → 3.7.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: 6f54c37d7c50508f001a49df641a45df74cf61cf4c4a4fcebafef442e380df68
4
- data.tar.gz: 8c269bbad63b3ee0b022e7e206fc0884ed213b38380b15bdda9ee421e7f8ebeb
3
+ metadata.gz: 0c25de14662bbd82e873e09199f770ae115e73ab837d78300ad23d2f1a5f8617
4
+ data.tar.gz: ce332bc77901424f297d992d43c08999fbc30cc69547af624ead0d3aef2486f7
5
5
  SHA512:
6
- metadata.gz: 8c886952d2095e9cefddeaaebbefa8495b78732b74350a6579849dd22da8f85f3065a35b411ce8952cd2cb12a80d49468cb44eeabfac4d93d8610663f7536366
7
- data.tar.gz: a254785ecca431fc409bd2ebd031a14b2901295f2293913c6d7f92629327e8694e1ee2e13e7e04898cdc7c1939f29b1a6bb674e5dbc183b7c5c1487146d47284
6
+ metadata.gz: 5a1cf93965af7f77e9f543d339567c0cba16e481d325c345fea9fcd945a85f032ab87ff4f135c4ebff82c44f14365e650e9e6fe08ef546efab42c8ba56cd273e
7
+ data.tar.gz: b6c4d596cac63c5432717086040ba6fb03cb2f7ae17b813f7414facef60c33cd3f3ea3239e5933768e2ca03721e596744d3301126087bc224db1c8abb09e4d72
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 3.7.0
2
+ - Changed the TCP reading mode to use the non-blocking method [#75](https://github.com/logstash-plugins/logstash-input-syslog/pull/75)
3
+ It fixes the high CPU usage when TCP clients do not properly disconnect/send EOF.
4
+ - Fixed broken tests
5
+
6
+ ## 3.6.0
7
+ - Add support for ECS v8 as alias to v1 implementation [#68](https://github.com/logstash-plugins/logstash-input-syslog/pull/68)
8
+
1
9
  ## 3.5.0
2
10
  - Feat: ECS compatibility support [#63](https://github.com/logstash-plugins/logstash-input-syslog/pull/63)
3
11
 
data/docs/index.asciidoc CHANGED
@@ -71,7 +71,7 @@ input plugins.
71
71
  * Value type is <<string,string>>
72
72
  * Supported values are:
73
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]`)
74
+ ** `v1`,`v8`: uses fields that are compatible with Elastic Common Schema (for example, `[log][syslog][priority]`)
75
75
  * Default value depends on which version of Logstash is running:
76
76
  ** When Logstash provides a `pipeline.ecs_compatibility` setting, its value is used as the default
77
77
  ** Otherwise, the default value is `disabled`.
@@ -26,7 +26,7 @@ require "stud/interval"
26
26
  # Note: This input will start listeners on both TCP and UDP.
27
27
  #
28
28
  class LogStash::Inputs::Syslog < LogStash::Inputs::Base
29
- include LogStash::PluginMixins::ECSCompatibilitySupport(:disabled, :v1)
29
+ include LogStash::PluginMixins::ECSCompatibilitySupport(:disabled, :v1, :v8 => :v1)
30
30
 
31
31
  config_name "syslog"
32
32
 
@@ -221,6 +221,21 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
221
221
  close_tcp
222
222
  end # def tcp_listener
223
223
 
224
+ def tcp_read_lines(socket)
225
+ buffer = String.new
226
+ loop do
227
+ begin
228
+ buffer << socket.read_nonblock(1024)
229
+ while (newline = buffer.index("\n"))
230
+ yield buffer.slice!(0..newline)
231
+ end
232
+ rescue IO::WaitReadable
233
+ IO.select([socket], nil)
234
+ retry
235
+ end
236
+ end
237
+ end
238
+
224
239
  # tcp_receiver is executed in a thread, any uncatched exception will be bubbled up to the
225
240
  # tcp server thread and all tcp connections will be closed and the listener restarted.
226
241
  def tcp_receiver(output_queue, socket)
@@ -232,7 +247,7 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
232
247
 
233
248
  first_read = true
234
249
 
235
- socket.each do |line|
250
+ tcp_read_lines(socket) do |line|
236
251
  metric.increment(:messages_received)
237
252
  if @proxy_protocol && first_read
238
253
  first_read = false
@@ -253,7 +268,7 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
253
268
  rescue Errno::ECONNRESET
254
269
  # swallow connection reset exceptions to avoid bubling up the tcp_listener & server
255
270
  logger.info("connection reset", :client => "#{ip}:#{port}")
256
- rescue Errno::EBADF
271
+ rescue Errno::EBADF, EOFError
257
272
  # swallow connection closed exceptions to avoid bubling up the tcp_listener & server
258
273
  logger.info("connection closed", :client => "#{ip}:#{port}")
259
274
  rescue IOError => e
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-input-syslog'
4
- s.version = '3.5.0'
4
+ s.version = '3.7.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,16 +21,16 @@ 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
+ s.add_runtime_dependency 'logstash-mixin-ecs_compatibility_support', '~> 1.2'
25
25
 
26
26
  s.add_runtime_dependency 'concurrent-ruby'
27
27
  s.add_runtime_dependency 'stud', '>= 0.0.22', '< 0.1.0'
28
28
 
29
29
  s.add_runtime_dependency 'logstash-codec-plain'
30
- s.add_runtime_dependency 'logstash-filter-grok', '>= 4.4.0'
30
+ s.add_runtime_dependency 'logstash-filter-grok', '>= 4.4.1'
31
31
  s.add_runtime_dependency 'logstash-filter-date'
32
32
 
33
- s.add_development_dependency 'logstash-devutils'
33
+ s.add_development_dependency 'logstash-devutils', '~> 2.3'
34
34
  s.add_development_dependency 'logstash-codec-cef'
35
35
  end
36
36
 
@@ -33,80 +33,18 @@ require "socket"
33
33
  describe LogStash::Inputs::Syslog do
34
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]"
35
35
 
36
- it "should properly handle priority, severity and facilities" do
37
- skip_if_stack_known_issue
38
- port = 5511
39
- event_count = 10
40
- conf = <<-CONFIG
41
- input {
42
- syslog {
43
- type => "blah"
44
- port => #{port}
45
- }
46
- }
47
- CONFIG
48
-
49
- events = input(conf) do |pipeline, queue|
50
- socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
51
- event_count.times do |i|
52
- socket.puts(SYSLOG_LINE)
53
- end
54
- socket.close
55
-
56
- event_count.times.collect { queue.pop }
57
- end
58
-
59
- expect( events.length ).to eql event_count
60
- events.each do |event|
61
- expect( event.get("priority") ).to eql 164
62
- expect( event.get("severity") ).to eql 4
63
- expect( event.get("facility") ).to eql 20
64
- end
65
- end
66
-
67
- it "should properly PROXY protocol v1" do
68
- skip_if_stack_known_issue
69
- port = 5511
70
- event_count = 10
71
- conf = <<-CONFIG
72
- input {
73
- syslog {
74
- type => "blah"
75
- port => #{port}
76
- proxy_protocol => true
77
- }
78
- }
79
- CONFIG
80
-
81
- events = input(conf) do |pipeline, queue|
82
- socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
83
- socket.puts("PROXY TCP4 1.2.3.4 5.6.7.8 1234 5678\r");
84
- socket.flush
85
- event_count.times do |i|
86
- socket.puts(SYSLOG_LINE)
87
- end
88
- socket.close
89
-
90
- event_count.times.collect { queue.pop }
91
- end
92
-
93
- expect( events.length ).to eql event_count
94
- events.each do |event|
95
- expect( event.get("priority") ).to eql 164
96
- expect( event.get("severity") ).to eql 4
97
- expect( event.get("facility") ).to eql 20
98
- expect( event.get("host") ).to eql "1.2.3.4"
99
- end
100
- end
101
-
102
- context 'tag', :ecs_compatibility_support do
103
- ecs_compatibility_matrix(:disabled, :v1) do
36
+ context 'ECS common behavior', :ecs_compatibility_support do
37
+ ecs_compatibility_matrix(:disabled, :v1, :v8 => :v1) do |ecs_select|
38
+ let(:priority_key) { ecs_select[disabled:'priority', v1:'[log][syslog][priority]'] }
39
+ let(:facility_key) { ecs_select[disabled:'facility', v1:'[log][syslog][facility][code]'] }
40
+ let(:severity_key) { ecs_select[disabled:'severity', v1:'[log][syslog][severity][code]'] }
41
+ let(:host_key) { ecs_select[disabled:'host', v1:'[host][ip]'] }
104
42
 
105
43
  before(:each) do
106
44
  allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
107
45
  end
108
46
 
109
- it "should add unique tag when grok parsing fails with live syslog input" do
47
+ it "should properly handle priority, severity and facilities" do
110
48
  skip_if_stack_known_issue
111
49
  port = 5511
112
50
  event_count = 10
@@ -122,7 +60,7 @@ describe LogStash::Inputs::Syslog do
122
60
  events = input(conf) do |pipeline, queue|
123
61
  socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
124
62
  event_count.times do |i|
125
- socket.puts("message which causes the a grok parse failure")
63
+ socket.puts(SYSLOG_LINE)
126
64
  end
127
65
  socket.close
128
66
 
@@ -130,38 +68,31 @@ describe LogStash::Inputs::Syslog do
130
68
  end
131
69
 
132
70
  expect( events.length ).to eql event_count
133
- event_count.times do |i|
134
- expect( events[i].get("tags") ).to eql ["_grokparsefailure_sysloginput"]
71
+ events.each do |event|
72
+ expect( event.get(priority_key) ).to eql 164
73
+ expect( event.get(severity_key) ).to eql 4
74
+ expect( event.get(facility_key) ).to eql 20
135
75
  end
136
76
  end
137
77
 
138
- end
139
- end
140
-
141
- context 'timestamp', :ecs_compatibility_support do
142
- ecs_compatibility_matrix(:disabled, :v1) do
143
-
144
- before(:each) do
145
- allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
146
- end
147
-
148
- it "should properly handle locale and timezone" do
78
+ it "should properly PROXY protocol v1" do
79
+ skip_if_stack_known_issue
149
80
  port = 5511
150
81
  event_count = 10
151
-
152
82
  conf = <<-CONFIG
153
83
  input {
154
84
  syslog {
155
85
  type => "blah"
156
86
  port => #{port}
157
- locale => "en"
158
- timezone => "UTC"
87
+ proxy_protocol => true
159
88
  }
160
89
  }
161
90
  CONFIG
162
91
 
163
92
  events = input(conf) do |pipeline, queue|
164
93
  socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
94
+ socket.puts("PROXY TCP4 1.2.3.4 5.6.7.8 1234 5678\r\n")
95
+ socket.flush
165
96
  event_count.times do |i|
166
97
  socket.puts(SYSLOG_LINE)
167
98
  end
@@ -172,52 +103,217 @@ describe LogStash::Inputs::Syslog do
172
103
 
173
104
  expect( events.length ).to eql event_count
174
105
  events.each do |event|
175
- expect( event.get("@timestamp").to_iso8601 ).to eql "#{Time.now.year}-10-26T15:19:25.000Z"
106
+ expect( event.get(priority_key) ).to eql 164
107
+ expect( event.get(severity_key) ).to eql 4
108
+ expect( event.get(facility_key) ).to eql 20
109
+ expect( event.get(host_key) ).to eql "1.2.3.4"
176
110
  end
177
111
  end
178
112
 
179
- it "should properly handle no locale and no timezone" do
180
- port = 5511
113
+ context 'grok' do
114
+ it "should add unique tag when grok parsing fails with live syslog input" do
115
+ skip_if_stack_known_issue
116
+ port = 5511
117
+ event_count = 10
118
+ conf = <<-CONFIG
119
+ input {
120
+ syslog {
121
+ type => "blah"
122
+ port => #{port}
123
+ }
124
+ }
125
+ CONFIG
126
+ events = input(conf) do |pipeline, queue|
127
+ socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
128
+ event_count.times do |i|
129
+ socket.puts("message which causes the a grok parse failure")
130
+ end
131
+ socket.close
132
+ event_count.times.collect { queue.pop }
133
+ end
134
+ expect( events.length ).to eql event_count
135
+ event_count.times do |i|
136
+ expect( events[i].get("tags") ).to eql ["_grokparsefailure_sysloginput"]
137
+ end
138
+ end
181
139
 
182
- conf = <<-CONFIG
183
- input {
184
- syslog {
185
- type => "blah"
186
- port => #{port}
140
+ it "should add unique tag when grok parsing fails" do
141
+ input = LogStash::Inputs::Syslog.new({})
142
+ input.register
143
+
144
+ # event which is not syslog should have a new tag
145
+ event = LogStash::Event.new({ "message" => "hello world, this is not syslog RFC3164" })
146
+ input.syslog_relay(event)
147
+ expect( event.get("tags") ).to eql ["_grokparsefailure_sysloginput"]
148
+
149
+ 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" })
150
+ input.syslog_relay(syslog_event)
151
+ expect( syslog_event.get(priority_key) ).to eql 164
152
+ expect( syslog_event.get(severity_key) ).to eql 4
153
+ expect( syslog_event.get("tags") ).to be nil
154
+
155
+ input.close
156
+ end
157
+
158
+ it "should properly handle a custom grok_pattern" do
159
+ port = 5511
160
+ event_count = 1
161
+ custom_grok = "<%{POSINT:#{priority_key}}>%{SYSLOGTIMESTAMP:timestamp} atypical %{GREEDYDATA:message}"
162
+ message_field = "This part constitutes the message field"
163
+ timestamp = "Oct 26 15:19:25"
164
+ custom_line = "<164>#{timestamp} atypical #{message_field}"
165
+
166
+ conf = <<-CONFIG
167
+ input {
168
+ syslog {
169
+ type => "blah"
170
+ port => #{port}
171
+ grok_pattern => "#{custom_grok}"
172
+ }
187
173
  }
188
- }
189
- CONFIG
174
+ CONFIG
190
175
 
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
176
+ events = input(conf) do |pipeline, queue|
177
+ socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
178
+ event_count.times do |i|
179
+ socket.puts(custom_line)
180
+ end
181
+ socket.close
182
+
183
+ event_count.times.collect { queue.pop }
184
+ end
195
185
 
196
- queue.pop
186
+ expect( events.length ).to eql event_count
187
+ events.each do |event|
188
+ expect( event.get(priority_key) ).to eql 164
189
+ expect( event.get(severity_key) ).to eql 4
190
+ expect( event.get(facility_key) ).to eql 20
191
+ expect( event.get("message") ).to eql "#{message_field}\n"
192
+ expect( event.get('timestamp') ).to eql timestamp if ecs_compatibility == :disabled
193
+ expect( event.include?('timestamp') ).to be false if ecs_compatibility != :disabled
194
+ end
197
195
  end
198
196
 
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/
197
+ it "should properly handle the cef codec with a custom grok_pattern" do
198
+ port = 5511
199
+ event_count = 1
200
+
201
+ custom_grok = "<%{POSINT:#{priority_key}}>%{TIMESTAMP_ISO8601:timestamp} atypical %{GREEDYDATA:syslog_message}"
202
+ timestamp = "2018-02-07T12:40:00.000Z"
203
+ cef_message = "Description Omitted"
204
+ syslog_message = "foo bar"
205
+ syslog_message_envelope = "<134>#{timestamp} atypical #{syslog_message}"
206
+ custom_line = "CEF:0|Company Name|Application Name|Application Version Number|632|Syslog Configuration Updated|3|src=192.168.0.1 suser=user@example.com target=TARGET msg=#{cef_message} syslog=#{syslog_message_envelope} KeyValueOne=kv1 KeyValueTwo=12345 "
207
+
208
+ conf = <<-CONFIG
209
+ input {
210
+ syslog {
211
+ port => #{port}
212
+ syslog_field => "syslog"
213
+ grok_pattern => "#{custom_grok}"
214
+ codec => cef { ecs_compatibility => #{ ecs_compatibility } }
215
+ }
216
+ }
217
+ CONFIG
218
+
219
+ events = input(conf) do |pipeline, queue|
220
+ socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
221
+ event_count.times do |i|
222
+ socket.puts(custom_line)
223
+ end
224
+ socket.close
225
+
226
+ event_count.times.collect { queue.pop }
227
+ end
228
+
229
+ expect( events.length ).to eql event_count
230
+ events.each do |event|
231
+ expect( event.get(priority_key) ).to eql 134
232
+ expect( event.get(severity_key) ).to eql 6
233
+ expect( event.get(facility_key) ).to eql 16
234
+ expect( event.get("message") ).to eql cef_message
235
+ expect( event.get("syslog_message") ).to eql syslog_message
236
+ expect( event.get('timestamp') ).to eql timestamp if ecs_compatibility == :disabled
237
+ expect( event.include?('timestamp') ).to be false if ecs_compatibility != :disabled
238
+ end
239
+ end
201
240
  end
202
241
 
203
- it "should support non UTC timezone" do
204
- input = LogStash::Inputs::Syslog.new({"timezone" => "-05:00"})
205
- input.register
242
+ context 'timestamp' do
243
+ it "should properly handle locale and timezone" do
244
+ port = 5511
245
+ event_count = 10
246
+
247
+ conf = <<-CONFIG
248
+ input {
249
+ syslog {
250
+ type => "blah"
251
+ port => #{port}
252
+ locale => "en"
253
+ timezone => "UTC"
254
+ }
255
+ }
256
+ CONFIG
257
+
258
+ events = input(conf) do |pipeline, queue|
259
+ socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
260
+ event_count.times do |i|
261
+ socket.puts(SYSLOG_LINE)
262
+ end
263
+ socket.close
206
264
 
207
- # event which is not syslog should have a new tag
265
+ event_count.times.collect { queue.pop }
266
+ end
208
267
 
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)
268
+ expect( events.length ).to eql event_count
269
+ events.each do |event|
270
+ expect( event.get("@timestamp") ).to be_a_logstash_timestamp_equivalent_to("#{Time.now.year}-10-26T15:19:25Z")
271
+ end
272
+ end
211
273
 
212
- expect( syslog_event.get("@timestamp").to_iso8601 ).to eql "#{Time.now.year}-10-26T20:19:25.000Z"
274
+ it "should properly handle no locale and no timezone" do
275
+ port = 5511
213
276
 
214
- input.close
215
- end
277
+ conf = <<-CONFIG
278
+ input {
279
+ syslog {
280
+ type => "blah"
281
+ port => #{port}
282
+ }
283
+ }
284
+ CONFIG
285
+
286
+ event = input(conf) do |pipeline, queue|
287
+ socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
288
+ socket.puts(SYSLOG_LINE)
289
+ socket.close
290
+
291
+ queue.pop
292
+ end
216
293
 
294
+ # chances platform timezone is not UTC, so parse without offset to create expectation
295
+ equivalent_time = Time.parse("#{Time.now.year}-10-26T15:19:25")
296
+ expect( event.get("@timestamp") ).to be_a_logstash_timestamp_equivalent_to(equivalent_time)
297
+ end
298
+
299
+ it "should support non UTC timezone" do
300
+ input = LogStash::Inputs::Syslog.new({"timezone" => "-05:00"})
301
+ input.register
302
+
303
+ # event which is not syslog should have a new tag
304
+
305
+ 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" })
306
+ input.syslog_relay(syslog_event)
307
+
308
+ expect( syslog_event.get("@timestamp") ).to be_a_logstash_timestamp_equivalent_to("#{Time.now.year}-10-26T20:19:25Z")
309
+
310
+ input.close
311
+ end
312
+ end
217
313
  end
218
314
  end
219
315
 
220
- context 'ECS behavior', :ecs_compatibility_support do
316
+ context 'ECS :v1 behavior', :ecs_compatibility_support do
221
317
 
222
318
  ecs_compatibility_matrix(:v1) do
223
319
 
@@ -269,7 +365,7 @@ describe LogStash::Inputs::Syslog do
269
365
 
270
366
  let(:socket) do
271
367
  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"
368
+ allow( subject ).to receive(:tcp_read_lines).and_yield("<133>Mar 11 08:44:43 precision kernel: [765135.424096] mce: CPU6: Package temperature/speed normal\n")
273
369
  allow( server ).to receive(:close)
274
370
  server
275
371
  end
@@ -285,103 +381,51 @@ describe LogStash::Inputs::Syslog do
285
381
  end
286
382
  end
287
383
 
288
- it "should add unique tag when grok parsing fails" do
289
- input = LogStash::Inputs::Syslog.new({})
290
- input.register
384
+ context 'tcp receiver' do
385
+ subject(:plugin) { LogStash::Inputs::Syslog.new }
386
+ before { plugin.register }
387
+ after { plugin.close }
291
388
 
292
- # event which is not syslog should have a new tag
293
- event = LogStash::Event.new({ "message" => "hello world, this is not syslog RFC3164" })
294
- input.syslog_relay(event)
295
- expect( event.get("tags") ).to eql ["_grokparsefailure_sysloginput"]
389
+ let(:queue) { Queue.new }
390
+ let(:socket) do
391
+ socket = double('tcp-socket')
392
+ expect( socket ).to receive(:peeraddr).and_return(["AF_INET", 514, "192.168.0.10", "192.168.0.10"])
393
+ socket
394
+ end
296
395
 
297
- 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" })
298
- input.syslog_relay(syslog_event)
299
- expect( syslog_event.get("priority") ).to eql 164
300
- expect( syslog_event.get("severity") ).to eql 4
301
- expect( syslog_event.get("tags") ).to be nil
396
+ it 'should close connection when client sends EOF' do
397
+ expect( socket ).to receive(:read_nonblock).and_raise(EOFError)
398
+ expect( socket ).to receive(:close)
399
+ allow( plugin.logger ).to receive(:info)
302
400
 
303
- input.close
304
- end
401
+ plugin.send :tcp_receiver, queue, socket
305
402
 
306
- it_behaves_like 'an interruptible input plugin' do
307
- let(:config) { { "port" => 5511 } }
308
- end
403
+ expect( plugin.logger ).to have_received(:info).with(/connection closed/, anything)
404
+ expect( queue.size ).to eql 0
405
+ end
309
406
 
310
- it "should properly handle a custom grok_pattern" do
311
- port = 5511
312
- event_count = 1
313
- custom_grok = "<%{POSINT:priority}>%{SYSLOGTIMESTAMP:timestamp} atypical %{GREEDYDATA:message}"
314
- message_field = "This part constitutes the message field"
315
- timestamp = "Oct 26 15:19:25"
316
- custom_line = "<164>#{timestamp} atypical #{message_field}"
317
-
318
- conf = <<-CONFIG
319
- input {
320
- syslog {
321
- type => "blah"
322
- port => #{port}
323
- grok_pattern => "#{custom_grok}"
324
- }
325
- }
326
- CONFIG
327
-
328
- events = input(conf) do |pipeline, queue|
329
- socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
330
- event_count.times do |i|
331
- socket.puts(custom_line)
407
+ it 'should properly read partially received messages' do
408
+ expect( socket ).to receive(:close)
409
+ allow( plugin.codec ).to receive(:decode).and_call_original
410
+
411
+ messages = ["<133>Mar 11 08:44:43 localhost message 2\n", "message 1\n", "<133>Mar 11 08:44:43 localhost ", ]
412
+ allow( socket ).to receive(:read_nonblock).at_least(messages.size).times do
413
+ msg = messages.pop
414
+ raise EOFError unless msg
415
+ msg
332
416
  end
333
- socket.close
334
417
 
335
- event_count.times.collect { queue.pop }
336
- end
418
+ plugin.send :tcp_receiver, queue, socket
337
419
 
338
- expect( events.length ).to eql event_count
339
- events.each do |event|
340
- expect( event.get("priority") ).to eql 164
341
- expect( event.get("severity") ).to eql 4
342
- expect( event.get("facility") ).to eql 20
343
- expect( event.get("message") ).to eql "#{message_field}\n"
344
- expect( event.get("timestamp") ).to eql timestamp
420
+ expect( queue.size ).to eql 2
421
+ expect( plugin.codec ).to have_received(:decode).with("<133>Mar 11 08:44:43 localhost message 1\n")
422
+ expect( plugin.codec ).to have_received(:decode).with("<133>Mar 11 08:44:43 localhost message 2\n")
345
423
  end
346
424
  end
347
425
 
348
- it "should properly handle the cef codec with a custom grok_pattern" do
349
- port = 5511
350
- event_count = 1
351
- custom_grok = "<%{POSINT:priority}>%{TIMESTAMP_ISO8601:timestamp} atypical"
352
- message_field = "Description Omitted"
353
- timestamp = "2018-02-07T12:40:00.000Z"
354
- custom_line = "<134>#{timestamp} atypical CEF:0|Company Name|Application Name|Application Version Number|632|Syslog Configuration Updated|3|src=192.168.0.1 suser=user@example.com target=TARGET msg=#{message_field} KeyValueOne=kv1 KeyValueTwo=12345 "
355
-
356
- conf = <<-CONFIG
357
- input {
358
- syslog {
359
- port => #{port}
360
- syslog_field => "syslog"
361
- grok_pattern => "#{custom_grok}"
362
- codec => cef
363
- }
364
- }
365
- CONFIG
366
-
367
- events = input(conf) do |pipeline, queue|
368
- socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
369
- event_count.times do |i|
370
- socket.puts(custom_line)
371
- end
372
- socket.close
373
426
 
374
- event_count.times.collect { queue.pop }
375
- end
376
-
377
- expect( events.length ).to eql event_count
378
- events.each do |event|
379
- expect( event.get("priority") ).to eql 134
380
- expect( event.get("severity") ).to eql 6
381
- expect( event.get("facility") ).to eql 16
382
- expect( event.get("message") ).to eql message_field
383
- expect( event.get("timestamp") ).to eql timestamp
384
- end
427
+ it_behaves_like 'an interruptible input plugin' do
428
+ let(:config) { { "port" => 5511 } }
385
429
  end
386
430
 
387
431
  private
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.5.0
4
+ version: 3.7.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-03-22 00:00:00.000000000 Z
11
+ date: 2023-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -35,7 +35,7 @@ dependencies:
35
35
  requirements:
36
36
  - - "~>"
37
37
  - !ruby/object:Gem::Version
38
- version: '1.1'
38
+ version: '1.2'
39
39
  name: logstash-mixin-ecs_compatibility_support
40
40
  prerelease: false
41
41
  type: :runtime
@@ -43,7 +43,7 @@ dependencies:
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '1.1'
46
+ version: '1.2'
47
47
  - !ruby/object:Gem::Dependency
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  requirements:
@@ -97,7 +97,7 @@ dependencies:
97
97
  requirements:
98
98
  - - ">="
99
99
  - !ruby/object:Gem::Version
100
- version: 4.4.0
100
+ version: 4.4.1
101
101
  name: logstash-filter-grok
102
102
  prerelease: false
103
103
  type: :runtime
@@ -105,7 +105,7 @@ dependencies:
105
105
  requirements:
106
106
  - - ">="
107
107
  - !ruby/object:Gem::Version
108
- version: 4.4.0
108
+ version: 4.4.1
109
109
  - !ruby/object:Gem::Dependency
110
110
  requirement: !ruby/object:Gem::Requirement
111
111
  requirements:
@@ -123,17 +123,17 @@ dependencies:
123
123
  - !ruby/object:Gem::Dependency
124
124
  requirement: !ruby/object:Gem::Requirement
125
125
  requirements:
126
- - - ">="
126
+ - - "~>"
127
127
  - !ruby/object:Gem::Version
128
- version: '0'
128
+ version: '2.3'
129
129
  name: logstash-devutils
130
130
  prerelease: false
131
131
  type: :development
132
132
  version_requirements: !ruby/object:Gem::Requirement
133
133
  requirements:
134
- - - ">="
134
+ - - "~>"
135
135
  - !ruby/object:Gem::Version
136
- version: '0'
136
+ version: '2.3'
137
137
  - !ruby/object:Gem::Dependency
138
138
  requirement: !ruby/object:Gem::Requirement
139
139
  requirements:
@@ -187,8 +187,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
187
187
  - !ruby/object:Gem::Version
188
188
  version: '0'
189
189
  requirements: []
190
- rubyforge_project:
191
- rubygems_version: 2.6.13
190
+ rubygems_version: 3.2.33
192
191
  signing_key:
193
192
  specification_version: 4
194
193
  summary: Reads syslog messages as events