logstash-patterns-core 4.0.2 → 4.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +149 -8
- data/CONTRIBUTORS +1 -0
- data/Gemfile +11 -1
- data/LICENSE +199 -10
- data/README.md +12 -19
- data/lib/logstash/patterns/core.rb +11 -3
- data/logstash-patterns-core.gemspec +1 -1
- data/patterns/ecs-v1/aws +28 -0
- data/patterns/ecs-v1/bacula +53 -0
- data/patterns/ecs-v1/bind +13 -0
- data/patterns/ecs-v1/bro +30 -0
- data/patterns/ecs-v1/exim +26 -0
- data/patterns/ecs-v1/firewalls +111 -0
- data/patterns/ecs-v1/grok-patterns +95 -0
- data/patterns/ecs-v1/haproxy +40 -0
- data/patterns/ecs-v1/httpd +17 -0
- data/patterns/ecs-v1/java +34 -0
- data/patterns/ecs-v1/junos +13 -0
- data/patterns/ecs-v1/linux-syslog +16 -0
- data/patterns/ecs-v1/maven +1 -0
- data/patterns/ecs-v1/mcollective +4 -0
- data/patterns/ecs-v1/mongodb +7 -0
- data/patterns/ecs-v1/nagios +124 -0
- data/patterns/ecs-v1/postgresql +2 -0
- data/patterns/ecs-v1/rails +13 -0
- data/patterns/ecs-v1/redis +3 -0
- data/patterns/ecs-v1/ruby +2 -0
- data/patterns/ecs-v1/squid +6 -0
- data/patterns/ecs-v1/zeek +33 -0
- data/patterns/legacy/aws +14 -0
- data/patterns/{bacula → legacy/bacula} +5 -5
- data/patterns/legacy/bind +3 -0
- data/patterns/{bro → legacy/bro} +0 -0
- data/patterns/{exim → legacy/exim} +8 -2
- data/patterns/{firewalls → legacy/firewalls} +7 -2
- data/patterns/{grok-patterns → legacy/grok-patterns} +5 -13
- data/patterns/{haproxy → legacy/haproxy} +1 -1
- data/patterns/legacy/httpd +15 -0
- data/patterns/{java → legacy/java} +1 -4
- data/patterns/{junos → legacy/junos} +0 -0
- data/patterns/{linux-syslog → legacy/linux-syslog} +1 -1
- data/patterns/legacy/maven +1 -0
- data/patterns/{mcollective → legacy/mcollective} +0 -0
- data/patterns/{mcollective-patterns → legacy/mcollective-patterns} +0 -0
- data/patterns/{mongodb → legacy/mongodb} +0 -0
- data/patterns/{nagios → legacy/nagios} +1 -1
- data/patterns/{postgresql → legacy/postgresql} +0 -0
- data/patterns/{rails → legacy/rails} +0 -0
- data/patterns/legacy/redis +3 -0
- data/patterns/{ruby → legacy/ruby} +0 -0
- data/patterns/legacy/squid +4 -0
- data/spec/patterns/aws_spec.rb +395 -0
- data/spec/patterns/bacula_spec.rb +367 -0
- data/spec/patterns/bind_spec.rb +78 -0
- data/spec/patterns/bro_spec.rb +613 -0
- data/spec/patterns/core_spec.rb +271 -16
- data/spec/patterns/exim_spec.rb +201 -0
- data/spec/patterns/firewalls_spec.rb +683 -49
- data/spec/patterns/haproxy_spec.rb +253 -28
- data/spec/patterns/httpd_spec.rb +291 -10
- data/spec/patterns/java_spec.rb +375 -0
- data/spec/patterns/junos_spec.rb +101 -0
- data/spec/patterns/maven_spec.rb +61 -0
- data/spec/patterns/mcollective_spec.rb +35 -0
- data/spec/patterns/mongodb_spec.rb +170 -33
- data/spec/patterns/nagios_spec.rb +299 -78
- data/spec/patterns/netscreen_spec.rb +123 -0
- data/spec/patterns/rails3_spec.rb +87 -29
- data/spec/patterns/redis_spec.rb +207 -0
- data/spec/patterns/shorewall_spec.rb +85 -74
- data/spec/patterns/squid_spec.rb +139 -0
- data/spec/patterns/syslog_spec.rb +266 -8
- data/spec/spec_helper.rb +83 -5
- metadata +74 -26
- data/patterns/aws +0 -11
- data/patterns/redis +0 -3
- data/spec/patterns/bro.rb +0 -126
- data/spec/patterns/s3_spec.rb +0 -132
data/spec/patterns/core_spec.rb
CHANGED
@@ -20,16 +20,6 @@ describe "SYSLOGLINE" do
|
|
20
20
|
|
21
21
|
end
|
22
22
|
|
23
|
-
describe "COMMONAPACHELOG" do
|
24
|
-
|
25
|
-
let(:value) { '83.149.9.216 - - [24/Feb/2015:23:13:42 +0000] "GET /presentations/logstash-monitorama-2013/images/kibana-search.png HTTP/1.1" 200 203023 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36'}
|
26
|
-
|
27
|
-
it "generates the clientip field" do
|
28
|
-
expect(grok_match(subject, value)).to include("clientip" => "83.149.9.216")
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
23
|
describe "HTTP DATE parsing" do
|
34
24
|
|
35
25
|
context "HTTPDATE", "when having a German month" do
|
@@ -64,12 +54,16 @@ describe "HTTP DATE parsing" do
|
|
64
54
|
|
65
55
|
end
|
66
56
|
|
67
|
-
describe
|
68
|
-
|
69
|
-
|
57
|
+
describe 'LOGLEVEL' do
|
58
|
+
it 'matches info label' do
|
59
|
+
expect(grok_match(subject, 'INFO')).to pass
|
60
|
+
expect(grok_match(subject, 'info')).to pass
|
61
|
+
end
|
70
62
|
|
71
|
-
it
|
72
|
-
expect(grok_match(subject,
|
63
|
+
it 'matches information label' do
|
64
|
+
expect(grok_match(subject, 'information')).to pass
|
65
|
+
expect(grok_match(subject, 'Information')).to pass
|
66
|
+
expect(grok_match(subject, 'INFORMATION')).to pass
|
73
67
|
end
|
74
68
|
end
|
75
69
|
|
@@ -100,14 +94,224 @@ describe "UNIXPATH" do
|
|
100
94
|
let(:value) { '/foo/bar' }
|
101
95
|
|
102
96
|
it "should match the path" do
|
103
|
-
expect(grok_match(pattern,value)).to pass
|
97
|
+
expect(grok_match(pattern, value, true)).to pass
|
104
98
|
end
|
105
99
|
|
106
100
|
context "when using comma separators and other regexp" do
|
107
101
|
|
102
|
+
let(:pattern) { '((a=(?<a>%{UNIXPATH})?|b=(?<b>%{UNIXPATH})?)(,\s)?)+' }
|
103
|
+
|
104
|
+
let(:grok) do
|
105
|
+
grok = LogStash::Filters::Grok.new("match" => ["message", pattern])
|
106
|
+
grok.register
|
107
|
+
grok
|
108
|
+
end
|
109
|
+
|
108
110
|
let(:value) { 'a=/some/path, b=/some/other/path' }
|
109
111
|
|
112
|
+
it "was expected to extract both but never really did" do # or maybe on JRuby 1.7
|
113
|
+
event = build_event(value)
|
114
|
+
grok.filter(event)
|
115
|
+
expect( event.to_hash['a'] ).to eql '/some/path,'
|
116
|
+
expect( event.to_hash['b'] ).to be nil
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'relative path' do
|
122
|
+
|
123
|
+
let(:path_matcher) do # non-exact matcher
|
124
|
+
grok = LogStash::Filters::Grok.new("match" => ["message", '%{UNIXPATH:path}'])
|
125
|
+
grok.register
|
126
|
+
lambda { |msg| event = build_event(msg); grok.filter(event); event }
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should not match (only partially)" do
|
130
|
+
expect(grok_match(pattern, 'a/./b/c', true)).to_not pass
|
131
|
+
event = path_matcher.('a/./b/c')
|
132
|
+
expect( event.to_hash['path'] ).to eql '/./b/c'
|
133
|
+
|
134
|
+
expect(grok_match(pattern, ',/.', true)).to_not pass
|
135
|
+
event = path_matcher.(',/.')
|
136
|
+
expect( event.to_hash['path'] ).to eql '/.'
|
137
|
+
|
138
|
+
expect(grok_match(pattern, '+/.../', true)).to_not pass
|
139
|
+
event = path_matcher.('+/.../')
|
140
|
+
expect( event.to_hash['path'] ).to eql '/.../'
|
141
|
+
|
142
|
+
expect(grok_match(pattern, '~/b/', true)).to_not pass
|
143
|
+
event = path_matcher.('~/b/')
|
144
|
+
expect( event.to_hash['path'] ).to eql '/b/'
|
145
|
+
|
146
|
+
expect(grok_match(pattern, './b//', true)).to_not pass
|
147
|
+
expect(grok_match(pattern, 'a//b', true)).to_not pass
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should not match paths starting with ." do
|
151
|
+
expect(grok_match(pattern, '../0', true)).to_not pass
|
152
|
+
expect(grok_match(pattern, './~', true)).to_not pass
|
153
|
+
expect(grok_match(pattern, '.../-', true)).to_not pass
|
154
|
+
expect(grok_match(pattern, './', true)).to_not pass
|
155
|
+
expect(grok_match(pattern, './,', true)).to_not pass
|
156
|
+
expect(grok_match(pattern, '../', true)).to_not pass
|
157
|
+
expect(grok_match(pattern, '.a/', true)).to_not pass
|
158
|
+
expect(grok_match(pattern, '.~/', true)).to_not pass
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should not match expression wout separator" do
|
162
|
+
expect(grok_match(pattern, '.')).to_not pass
|
163
|
+
expect(grok_match(pattern, '..')).to_not pass
|
164
|
+
expect(grok_match(pattern, '...')).to_not pass
|
165
|
+
expect(grok_match(pattern, '.,')).to_not pass
|
166
|
+
expect(grok_match(pattern, '.-')).to_not pass
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
context "dotted path" do
|
172
|
+
|
173
|
+
it "should match path containing ." do
|
174
|
+
expect(grok_match(pattern, '/some/./path/', true)).to pass
|
175
|
+
expect(grok_match(pattern, '/some/../path', true)).to pass
|
176
|
+
expect(grok_match(pattern, '/../.', true)).to pass
|
177
|
+
expect(grok_match(pattern, '/.', true)).to pass
|
178
|
+
expect(grok_match(pattern, '/..', true)).to pass
|
179
|
+
expect(grok_match(pattern, '/...', true)).to pass
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
|
184
|
+
context "separators" do
|
185
|
+
|
186
|
+
it "should match root" do
|
187
|
+
expect(grok_match(pattern, '/', true)).to pass
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should match" do
|
191
|
+
expect(grok_match(pattern, '//', true)).to pass
|
192
|
+
expect(grok_match(pattern, '//00', true)).to pass
|
193
|
+
expect(grok_match(pattern, '///a', true)).to pass
|
194
|
+
expect(grok_match(pattern, '/a//', true)).to pass
|
195
|
+
expect(grok_match(pattern, '///a//b/c///', true)).to pass
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should not match windows separator" do
|
199
|
+
expect(grok_match(pattern, "\\a", true)).to_not pass
|
200
|
+
expect(grok_match(pattern, '/0\\', true)).to_not pass
|
201
|
+
expect(grok_match(pattern, "/a\\b", true)).to_not pass
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
context "long path" do
|
207
|
+
|
208
|
+
let(:grok) do
|
209
|
+
grok = LogStash::Filters::Grok.new("match" => ["message", '%{UNIXPATH:path} '], 'timeout_millis' => 1500)
|
210
|
+
grok.register
|
211
|
+
grok
|
212
|
+
end
|
213
|
+
|
214
|
+
let(:value) { '/opt/abcdef/1/.22/3:3+3/foo@BAR/X-Y+Z/~Sample_l_SUBc b' }
|
215
|
+
|
110
216
|
it "should match the path" do
|
217
|
+
event = build_event(value)
|
218
|
+
grok.filter(event)
|
219
|
+
expect( event.to_hash['path'] ).to eql '/opt/abcdef/1/.22/3:3+3/foo@BAR/X-Y+Z/~Sample_l_SUBc'
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should not match with invalid chars (or cause DoS)" do
|
223
|
+
event = build_event(value.sub('SUB', '&^_'))
|
224
|
+
grok.filter(event) # used to call a looong looop (DoS) despite the timeout guard
|
225
|
+
expect( event.to_hash['tags'] ).to include '_grokparsefailure'
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
it "matches paths with non-ascii characters" do
|
230
|
+
event = build_event path = '/opt/Čierný_Peter/.中'
|
231
|
+
build_grok('UNIXPATH:path').filter event
|
232
|
+
expect( event.get('path') ).to eql path
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
describe "WINPATH" do
|
238
|
+
|
239
|
+
let(:pattern) { 'WINPATH' }
|
240
|
+
let(:value) { 'C:\\foo\\bar' }
|
241
|
+
|
242
|
+
it "should match the path" do
|
243
|
+
expect(grok_match(pattern, value, true)).to pass
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should match root path" do
|
247
|
+
expect(grok_match(pattern, 'C:\\', true)).to pass
|
248
|
+
expect(grok_match(pattern, 'C:\\\\', true)).to pass
|
249
|
+
expect(grok_match(pattern, 'a:\\', true)).to pass
|
250
|
+
expect(grok_match(pattern, 'x:\\\\', true)).to pass
|
251
|
+
end
|
252
|
+
|
253
|
+
it "should match paths with spaces" do
|
254
|
+
expect(grok_match(pattern, 'C:\\Documents and Settings\\Public', true)).to pass
|
255
|
+
expect(grok_match(pattern, 'C:\\\\Users\\\\Public\\\\.Mozilla Firefox', true)).to pass
|
256
|
+
end
|
257
|
+
|
258
|
+
it "should not match unix-style paths" do
|
259
|
+
expect(grok_match(pattern, '/foo', true)).to_not pass
|
260
|
+
expect(grok_match(pattern, '//C/path', true)).to_not pass
|
261
|
+
expect(grok_match(pattern, '/', true)).to_not pass
|
262
|
+
expect(grok_match(pattern, '/foo/bar', true)).to_not pass
|
263
|
+
expect(grok_match(pattern, '/..', true)).to_not pass
|
264
|
+
expect(grok_match(pattern, 'C://', true)).to_not pass
|
265
|
+
end
|
266
|
+
|
267
|
+
it "matches paths with non-ascii characters" do
|
268
|
+
expect(grok_match(pattern, 'C:\\Čierný Peter\\.中.exe', true)).to pass
|
269
|
+
end
|
270
|
+
|
271
|
+
context 'relative paths' do
|
272
|
+
|
273
|
+
it "should not match" do
|
274
|
+
expect(grok_match(pattern, 'a\\bar', true)).to_not pass
|
275
|
+
expect(grok_match(pattern, 'foo\\bar', true)).to_not pass
|
276
|
+
expect(grok_match(pattern, 'C\\A\\B', true)).to_not pass
|
277
|
+
expect(grok_match(pattern, 'C\\\\0', true)).to_not pass
|
278
|
+
expect(grok_match(pattern, '.\\0', true)).to_not pass
|
279
|
+
expect(grok_match(pattern, '..\\', true)).to_not pass
|
280
|
+
expect(grok_match(pattern, '...\\-', true)).to_not pass
|
281
|
+
expect(grok_match(pattern, '.\\', true)).to_not pass
|
282
|
+
expect(grok_match(pattern, '.\\,', true)).to_not pass
|
283
|
+
expect(grok_match(pattern, '..\\', true)).to_not pass
|
284
|
+
expect(grok_match(pattern, '.a\\', true)).to_not pass
|
285
|
+
end
|
286
|
+
|
287
|
+
it "should not match expression wout separator" do
|
288
|
+
expect(grok_match(pattern, '.')).to_not pass
|
289
|
+
expect(grok_match(pattern, '..')).to_not pass
|
290
|
+
expect(grok_match(pattern, '...')).to_not pass
|
291
|
+
expect(grok_match(pattern, 'C:')).to_not pass
|
292
|
+
expect(grok_match(pattern, 'C')).to_not pass
|
293
|
+
end
|
294
|
+
|
295
|
+
end
|
296
|
+
|
297
|
+
end
|
298
|
+
|
299
|
+
|
300
|
+
describe "URIPROTO" do
|
301
|
+
let(:pattern) { 'URIPROTO' }
|
302
|
+
|
303
|
+
context "http is a valid URIPROTO" do
|
304
|
+
let(:value) { 'http' }
|
305
|
+
|
306
|
+
it "should match" do
|
307
|
+
expect(grok_match(pattern,value)).to pass
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
context "android-app is a valid URIPROTO" do
|
312
|
+
let(:value) { 'android-app' }
|
313
|
+
|
314
|
+
it "should match" do
|
111
315
|
expect(grok_match(pattern,value)).to pass
|
112
316
|
end
|
113
317
|
end
|
@@ -282,3 +486,54 @@ describe "URN" do
|
|
282
486
|
end
|
283
487
|
end
|
284
488
|
end
|
489
|
+
|
490
|
+
describe_pattern "EMAILADDRESS", ['legacy', 'ecs-v1'] do
|
491
|
+
|
492
|
+
# NOTE: EMAILLOCALPART was only updated in ECS mode, as following the RFC is
|
493
|
+
# actually a breaking change -> legacy does match incorrect e-mail addresses.
|
494
|
+
|
495
|
+
it "matches 'hello.world@123.net' address" do
|
496
|
+
expect(grok_exact_match(pattern, 'hello.world@123.net')).to pass
|
497
|
+
end
|
498
|
+
|
499
|
+
[
|
500
|
+
'a@example.com',
|
501
|
+
'a{b}@example.com',
|
502
|
+
'Foo+Bar@x.exposed',
|
503
|
+
].each do |valid_email|
|
504
|
+
it "matches #{valid_email.inspect} address" do
|
505
|
+
expect(grok_exact_match(pattern, valid_email)).to pass if ecs_compatibility?
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
509
|
+
it "does not match 'x y@example.com' address" do
|
510
|
+
expect(grok_exact_match(pattern, 'hello.world@123.net')).to pass
|
511
|
+
end
|
512
|
+
|
513
|
+
[
|
514
|
+
'a:b@example.com',
|
515
|
+
'a..b@example.com',
|
516
|
+
].each do |invalid_email|
|
517
|
+
it "does not match #{invalid_email.inspect} address" do
|
518
|
+
expect(grok_exact_match(pattern, invalid_email)).to_not pass if ecs_compatibility?
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
522
|
+
it "matches e-mail with digits only local-part" do
|
523
|
+
expect(grok_exact_match(pattern, '00@q.ro')).to pass if ecs_compatibility?
|
524
|
+
end
|
525
|
+
|
526
|
+
it "matches e-mail with 64 chars in local-part" do
|
527
|
+
expect(grok_exact_match(pattern, ('ab' * 32) + '@root.cz')).to pass
|
528
|
+
expect(grok_exact_match(pattern, ('a.bc' * 16) + '@00.cz')).to pass
|
529
|
+
end
|
530
|
+
|
531
|
+
it "does not match e-mail with more than 64 char length local-part" do
|
532
|
+
if ecs_compatibility?
|
533
|
+
expect(grok_exact_match(pattern, ('ab' * 32) + 'a' + '@root.cz')).to_not pass
|
534
|
+
# NOTE: we allow longer with '.' but at least we limit "too long" :
|
535
|
+
expect(grok_exact_match(pattern, ('a.bc' * 64) + '@00.cz')).to_not pass
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
539
|
+
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
require "logstash/patterns/core"
|
4
|
+
|
5
|
+
describe_pattern 'EXIM', ['legacy', 'ecs-v1'] do
|
6
|
+
|
7
|
+
context 'message arrival (old)' do
|
8
|
+
|
9
|
+
let(:message) do
|
10
|
+
"1995-10-31 08:57:53 0tACW1-0005MB-00 <= kryten@dwarf.fict.example H=mailer.fict.example [192.168.123.123] " +
|
11
|
+
"U=exim P=smtp S=5678 id=f828ca60127d8646a0fa75cbf8db9ba3@dwarf.fict.example"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "matches" do
|
15
|
+
expect(grok).to include("timestamp" => "1995-10-31 08:57:53")
|
16
|
+
|
17
|
+
if ecs_compatibility?
|
18
|
+
expect(grok).to include("exim"=>{"log"=>{
|
19
|
+
"flags"=>"<=",
|
20
|
+
"sender"=>{"email"=>"kryten@dwarf.fict.example"},
|
21
|
+
"message"=>{"id"=>"0tACW1-0005MB-00", "size"=>5678},
|
22
|
+
"header_id"=>"f828ca60127d8646a0fa75cbf8db9ba3@dwarf.fict.example"
|
23
|
+
}})
|
24
|
+
expect(grok).to include("source"=>{"address"=>"mailer.fict.example", "ip"=>"192.168.123.123"})
|
25
|
+
expect(grok).to include("network"=>{"protocol"=>"smtp"})
|
26
|
+
else
|
27
|
+
expect(grok).to include("exim_year" => "1995", "exim_month" => "10", "exim_day" => "31", "@version" => "1", "exim_time" => "08:57:53")
|
28
|
+
expect(grok.keys).to_not include("pid")
|
29
|
+
expect(grok).to include("exim_sender_email" => "kryten@dwarf.fict.example")
|
30
|
+
expect(grok).to include("exim_flags" => "<=")
|
31
|
+
expect(grok).to include("exim_msg_size" => "5678")
|
32
|
+
expect(grok).to include("exim_msgid" => "0tACW1-0005MB-00")
|
33
|
+
expect(grok).to include("remote_hostname" => "mailer.fict.example", "remote_host" => "192.168.123.123")
|
34
|
+
expect(grok).to include("protocol" => "smtp")
|
35
|
+
expect(grok).to include("exim_header_id" => "f828ca60127d8646a0fa75cbf8db9ba3@dwarf.fict.example")
|
36
|
+
end
|
37
|
+
|
38
|
+
expect(grok).to include("message" => message)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'message arrival (new)' do
|
44
|
+
let(:message) do
|
45
|
+
'2010-09-13 05:00:13 [1487] 1Ov4tU-0000Nz-Rm <= mailling.list@domain.com ' +
|
46
|
+
'H=mailhost.domain.com [208.42.54.2]:51792 I=[67.215.162.175]:25 P=esmtps X=TLSv1:AES256-SHA:256 CV=no S=21778 ' +
|
47
|
+
'id=384a86a39e83be0d9b3a94d1feb3119f@domain.com T="Daily List: Chameleon" for user@example.com'
|
48
|
+
end
|
49
|
+
|
50
|
+
it "matches" do
|
51
|
+
expect(grok).to include("timestamp" => "2010-09-13 05:00:13") # new in legacy mode
|
52
|
+
|
53
|
+
if ecs_compatibility?
|
54
|
+
expect(grok).to include("process"=>{"pid"=>1487})
|
55
|
+
expect(grok).to include("exim"=>{"log"=>hash_including(
|
56
|
+
"message"=>{"id"=>"1Ov4tU-0000Nz-Rm", "size"=>21778, "subject"=>"Daily List: Chameleon"},
|
57
|
+
"flags"=>"<=",
|
58
|
+
"header_id"=>"384a86a39e83be0d9b3a94d1feb3119f@domain.com",
|
59
|
+
"sender"=>{"email"=>"mailling.list@domain.com"},
|
60
|
+
"recipient"=>{"email"=>"user@example.com"},
|
61
|
+
)})
|
62
|
+
expect(grok).to include("source"=>{"address"=>"mailhost.domain.com", "ip"=>"208.42.54.2", "port"=>51792})
|
63
|
+
expect(grok).to include("destination"=>{"ip"=>"67.215.162.175", "port"=>25})
|
64
|
+
else
|
65
|
+
|
66
|
+
expect(grok).to include("exim_year" => "2010", "exim_month" => "09", "exim_day" => "13", "exim_time" => "05:00:13")
|
67
|
+
expect(grok).to include("pid" => "1487") # new
|
68
|
+
expect(grok).to include("exim_sender_email" => "mailling.list@domain.com") # new
|
69
|
+
expect(grok).to include("remote_hostname" => "mailhost.domain.com", "remote_host" => "208.42.54.2", "remote_port" => "51792") # (remote_port) new
|
70
|
+
expect(grok).to include("exim_interface" => "67.215.162.175", "exim_interface_port" => "25")
|
71
|
+
expect(grok).to include("protocol" => "esmtps")
|
72
|
+
expect(grok).to include("exim_msg_size" => "21778")
|
73
|
+
expect(grok).to include("exim_header_id" => "384a86a39e83be0d9b3a94d1feb3119f@domain.com")
|
74
|
+
expect(grok).to include("exim_subject" => '"Daily List: Chameleon"')
|
75
|
+
expect(grok).to include("exim_recipient_email" => "user@example.com") # new
|
76
|
+
end
|
77
|
+
|
78
|
+
expect(grok).to include("message" => message)
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'message arrival (simple)' do
|
84
|
+
|
85
|
+
let(:message) do
|
86
|
+
'2020-02-11 17:09:46 1j1Z2g-00Faoy-Uh <= example@strawberry.active-ns.com U=example P=local ' +
|
87
|
+
'T="[Examples Galore] Please moderate: \"Hello world!\"" for admin@example.net'
|
88
|
+
end
|
89
|
+
|
90
|
+
it "matches" do
|
91
|
+
expect(grok).to include("timestamp"=>"2020-02-11 17:09:46")
|
92
|
+
if ecs_compatibility?
|
93
|
+
expect(grok).to include("exim"=>{"log"=>{
|
94
|
+
"flags"=>"<=",
|
95
|
+
"message"=>{"id"=>"1j1Z2g-00Faoy-Uh", "subject"=>'[Examples Galore] Please moderate: \\"Hello world!\\"'},
|
96
|
+
"sender"=>{"email"=>"example@strawberry.active-ns.com"},
|
97
|
+
"recipient"=>{"email"=>"admin@example.net"}
|
98
|
+
}})
|
99
|
+
expect(grok).to include("network"=>{"protocol"=>"local"})
|
100
|
+
else
|
101
|
+
expect(grok).to include(
|
102
|
+
"exim_msgid"=>"1j1Z2g-00Faoy-Uh",
|
103
|
+
"exim_sender_email"=>"example@strawberry.active-ns.com",
|
104
|
+
"exim_flags"=>"<=",
|
105
|
+
"protocol"=>"local",
|
106
|
+
"exim_subject"=>"\"[Examples Galore] Please moderate: \\\"Hello world!\\\"\""
|
107
|
+
)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'message arrival with quoted hostname' do
|
114
|
+
|
115
|
+
let(:message) do
|
116
|
+
'2013-03-20 12:44:02 1UIIN7-0004t9-8R <= root@example.com ' +
|
117
|
+
'H=localhost (hostname.example.com) [127.0.0.1] ' +
|
118
|
+
'P=esmtps X=TLSv1:DHE-RSA-AES256-SHA:256 S=811 id=201303201244.r2KCi11V018784@hostname.example.com'
|
119
|
+
end
|
120
|
+
|
121
|
+
it "matches" do
|
122
|
+
expect(grok).to include("timestamp"=>"2013-03-20 12:44:02")
|
123
|
+
|
124
|
+
if ecs_compatibility?
|
125
|
+
expect(grok).to include("exim"=>{"log"=>hash_including(
|
126
|
+
"sender"=>{ "email"=>"root@example.com" },
|
127
|
+
"message"=>{ "id"=>"1UIIN7-0004t9-8R", "size"=>811 },
|
128
|
+
"header_id"=>"201303201244.r2KCi11V018784@hostname.example.com",
|
129
|
+
"remote_address"=>"hostname.example.com")})
|
130
|
+
expect(grok).to include("source"=>{"address"=>"localhost", "ip"=>"127.0.0.1"})
|
131
|
+
expect(grok).to include("network"=>{"protocol"=>"esmtps"})
|
132
|
+
else
|
133
|
+
expect(grok).to include(
|
134
|
+
"exim_msgid"=>"1UIIN7-0004t9-8R",
|
135
|
+
"exim_sender_email"=>"root@example.com",
|
136
|
+
"exim_flags"=>"<=",
|
137
|
+
"protocol"=>"esmtps",
|
138
|
+
"exim_header_id"=>"201303201244.r2KCi11V018784@hostname.example.com"
|
139
|
+
)
|
140
|
+
expect(grok).to include(
|
141
|
+
"remote_host"=>"127.0.0.1",
|
142
|
+
"remote_heloname"=>"hostname.example.com",
|
143
|
+
"remote_hostname"=>"localhost"
|
144
|
+
)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
context 'message arrival with quoted hostname and port' do
|
152
|
+
|
153
|
+
let(:message) do
|
154
|
+
'2014-08-10 11:18:35 [28107] 1gsu1C-003dCu-Hb <= aaron@domain.com ' +
|
155
|
+
'H=localhost (10.5.40.204) [127.0.0.1]:39753 I=[127.0.0.1]:25 ' +
|
156
|
+
'P=esmtpa A=dovecot_plain:aaron@domain.com S=4315 M8S=0 id=d2b648f00f1a1b0813c483d552778dc6@domain.com ' +
|
157
|
+
"T=\"what's up?!? ;-)\" from <aaron@domain.com> for aaron+forward@domain.com"
|
158
|
+
end
|
159
|
+
|
160
|
+
it "matches" do
|
161
|
+
if ecs_compatibility?
|
162
|
+
expect(grok).to include("exim"=>{"log"=>hash_including(
|
163
|
+
"message"=>hash_including("id"=>"1gsu1C-003dCu-Hb", "subject"=>"what's up?!? ;-)"),
|
164
|
+
)})
|
165
|
+
expect(grok).to include("destination"=>{"ip"=>"127.0.0.1", "port"=>25})
|
166
|
+
expect(grok).to include("exim"=>{"log"=>hash_including(
|
167
|
+
"sender"=>{"email"=>"aaron@domain.com", 'original'=>'aaron@domain.com'}
|
168
|
+
)})
|
169
|
+
expect(grok).to include("exim"=>{"log"=>hash_including("recipient"=>{"email"=>"aaron+forward@domain.com"})})
|
170
|
+
expect(grok).to include("source"=>{"address"=>"localhost", "ip"=>"127.0.0.1", "port"=>39753})
|
171
|
+
expect(grok).to include("exim"=>{"log" => hash_including("remote_address"=>'10.5.40.204')})
|
172
|
+
else
|
173
|
+
expect(grok).to include(
|
174
|
+
"exim_msgid"=>"1gsu1C-003dCu-Hb",
|
175
|
+
"exim_sender_email"=>"aaron@domain.com",
|
176
|
+
"exim_flags"=>"<=",
|
177
|
+
"protocol"=>"esmtpa"
|
178
|
+
)
|
179
|
+
expect(grok).to include(
|
180
|
+
"remote_host"=>"127.0.0.1", "remote_port"=>"39753",
|
181
|
+
"remote_heloname"=>"10.5.40.204",
|
182
|
+
"remote_hostname"=>"localhost"
|
183
|
+
)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
|
189
|
+
context 'delivery failed' do
|
190
|
+
|
191
|
+
let(:message) do
|
192
|
+
'2020-02-11 17:09:47 1j1Z2g-00Faoy-Uh ** admin@example.net R=virtual_aliases: No such person at this address.'
|
193
|
+
end
|
194
|
+
|
195
|
+
it "does not parse" do # matching not implemented
|
196
|
+
expect(grok['tags']).to include("_grokparsefailure")
|
197
|
+
end
|
198
|
+
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|