logstash-patterns-core 4.1.0 → 4.3.1

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.
Files changed (78) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +118 -0
  3. data/CONTRIBUTORS +1 -0
  4. data/Gemfile +8 -1
  5. data/LICENSE +199 -10
  6. data/README.md +12 -19
  7. data/lib/logstash/patterns/core.rb +11 -3
  8. data/logstash-patterns-core.gemspec +1 -1
  9. data/patterns/ecs-v1/aws +28 -0
  10. data/patterns/ecs-v1/bacula +53 -0
  11. data/patterns/ecs-v1/bind +13 -0
  12. data/patterns/ecs-v1/bro +30 -0
  13. data/patterns/ecs-v1/exim +26 -0
  14. data/patterns/ecs-v1/firewalls +111 -0
  15. data/patterns/ecs-v1/grok-patterns +95 -0
  16. data/patterns/ecs-v1/haproxy +40 -0
  17. data/patterns/ecs-v1/httpd +17 -0
  18. data/patterns/ecs-v1/java +34 -0
  19. data/patterns/ecs-v1/junos +13 -0
  20. data/patterns/ecs-v1/linux-syslog +16 -0
  21. data/patterns/{maven → ecs-v1/maven} +0 -0
  22. data/patterns/ecs-v1/mcollective +4 -0
  23. data/patterns/ecs-v1/mongodb +7 -0
  24. data/patterns/ecs-v1/nagios +124 -0
  25. data/patterns/ecs-v1/postgresql +2 -0
  26. data/patterns/ecs-v1/rails +13 -0
  27. data/patterns/ecs-v1/redis +3 -0
  28. data/patterns/ecs-v1/ruby +2 -0
  29. data/patterns/ecs-v1/squid +6 -0
  30. data/patterns/ecs-v1/zeek +33 -0
  31. data/patterns/{aws → legacy/aws} +1 -1
  32. data/patterns/{bacula → legacy/bacula} +5 -5
  33. data/patterns/legacy/bind +3 -0
  34. data/patterns/{bro → legacy/bro} +0 -0
  35. data/patterns/{exim → legacy/exim} +8 -2
  36. data/patterns/{firewalls → legacy/firewalls} +2 -2
  37. data/patterns/{grok-patterns → legacy/grok-patterns} +5 -5
  38. data/patterns/{haproxy → legacy/haproxy} +1 -1
  39. data/patterns/{httpd → legacy/httpd} +3 -3
  40. data/patterns/{java → legacy/java} +1 -3
  41. data/patterns/{junos → legacy/junos} +0 -0
  42. data/patterns/{linux-syslog → legacy/linux-syslog} +0 -0
  43. data/patterns/legacy/maven +1 -0
  44. data/patterns/{mcollective → legacy/mcollective} +0 -0
  45. data/patterns/{mcollective-patterns → legacy/mcollective-patterns} +0 -0
  46. data/patterns/{mongodb → legacy/mongodb} +0 -0
  47. data/patterns/{nagios → legacy/nagios} +1 -1
  48. data/patterns/{postgresql → legacy/postgresql} +0 -0
  49. data/patterns/{rails → legacy/rails} +0 -0
  50. data/patterns/{redis → legacy/redis} +0 -0
  51. data/patterns/{ruby → legacy/ruby} +0 -0
  52. data/patterns/legacy/squid +4 -0
  53. data/spec/patterns/aws_spec.rb +395 -0
  54. data/spec/patterns/bacula_spec.rb +367 -0
  55. data/spec/patterns/bind_spec.rb +78 -0
  56. data/spec/patterns/bro_spec.rb +613 -0
  57. data/spec/patterns/core_spec.rb +271 -6
  58. data/spec/patterns/exim_spec.rb +201 -0
  59. data/spec/patterns/firewalls_spec.rb +707 -66
  60. data/spec/patterns/haproxy_spec.rb +253 -28
  61. data/spec/patterns/httpd_spec.rb +255 -77
  62. data/spec/patterns/java_spec.rb +375 -0
  63. data/spec/patterns/junos_spec.rb +101 -0
  64. data/spec/patterns/mcollective_spec.rb +35 -0
  65. data/spec/patterns/mongodb_spec.rb +170 -33
  66. data/spec/patterns/nagios_spec.rb +299 -78
  67. data/spec/patterns/netscreen_spec.rb +123 -0
  68. data/spec/patterns/rails3_spec.rb +87 -29
  69. data/spec/patterns/redis_spec.rb +157 -121
  70. data/spec/patterns/shorewall_spec.rb +85 -74
  71. data/spec/patterns/squid_spec.rb +139 -0
  72. data/spec/patterns/syslog_spec.rb +266 -22
  73. data/spec/spec_helper.rb +83 -5
  74. metadata +70 -30
  75. data/patterns/bind +0 -3
  76. data/patterns/squid +0 -4
  77. data/spec/patterns/bro.rb +0 -126
  78. data/spec/patterns/s3_spec.rb +0 -173
File without changes
File without changes
@@ -89,7 +89,7 @@ NAGIOS_PASSIVE_HOST_CHECK %{NAGIOS_TYPE_PASSIVE_HOST_CHECK:nagios_type}: %{DATA:
89
89
  NAGIOS_SERVICE_EVENT_HANDLER %{NAGIOS_TYPE_SERVICE_EVENT_HANDLER:nagios_type}: %{DATA:nagios_hostname};%{DATA:nagios_service};%{DATA:nagios_state};%{DATA:nagios_statelevel};%{DATA:nagios_event_handler_name}
90
90
  NAGIOS_HOST_EVENT_HANDLER %{NAGIOS_TYPE_HOST_EVENT_HANDLER:nagios_type}: %{DATA:nagios_hostname};%{DATA:nagios_state};%{DATA:nagios_statelevel};%{DATA:nagios_event_handler_name}
91
91
 
92
- NAGIOS_TIMEPERIOD_TRANSITION %{NAGIOS_TYPE_TIMEPERIOD_TRANSITION:nagios_type}: %{DATA:nagios_service};%{DATA:nagios_unknown1};%{DATA:nagios_unknown2}
92
+ NAGIOS_TIMEPERIOD_TRANSITION %{NAGIOS_TYPE_TIMEPERIOD_TRANSITION:nagios_type}: %{DATA:nagios_service};%{NUMBER:nagios_unknown1};%{NUMBER:nagios_unknown2}
93
93
 
94
94
  ####################
95
95
  #### External checks
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,4 @@
1
+ # Pattern squid3
2
+ # Documentation of squid3 logs formats can be found at the following link:
3
+ # http://wiki.squid-cache.org/Features/LogFormat
4
+ SQUID3 %{NUMBER:timestamp}\s+%{NUMBER:duration}\s%{IP:client_address}\s%{WORD:cache_result}/%{NONNEGINT:status_code}\s%{NUMBER:bytes}\s%{WORD:request_method}\s%{NOTSPACE:url}\s(%{NOTSPACE:user}|-)\s%{WORD:hierarchy_code}/(%{IPORHOST:server}|-)\s%{NOTSPACE:content_type}
@@ -0,0 +1,395 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+ require "logstash/patterns/core"
4
+
5
+ describe_pattern "ELB_ACCESS_LOG", ['legacy', 'ecs-v1'] do
6
+
7
+ context "parsing an access log" do
8
+
9
+ let(:message) do
10
+ "2014-02-15T23:39:43.945958Z my-test-loadbalancer 192.168.131.39:2817 10.0.0.1:80 0.000073 0.001048 0.000057 200 200 0 29 \"GET http://www.example.com:80/ HTTP/1.1\""
11
+ end
12
+
13
+ it 'matches' do
14
+ should include("timestamp" => "2014-02-15T23:39:43.945958Z" )
15
+ if ecs_compatibility?
16
+ expect(grok).to include("aws" => { "elb" => {
17
+ "name"=>"my-test-loadbalancer",
18
+ "request_processing_time"=>{"sec"=>0.000073},
19
+ "response_processing_time"=>{"sec"=>0.000057},
20
+ "backend_processing_time"=>{"sec"=>0.001048},
21
+ "backend"=>{
22
+ "ip"=>"10.0.0.1", "port"=>80,
23
+ "http"=>{"response"=>{"status_code"=>200}}
24
+ }
25
+ }})
26
+ expect(grok).to include("http"=>{
27
+ "request"=>{"body"=>{"bytes"=>0}, "method"=>"GET"},
28
+ "response"=>{"body"=>{"bytes"=>29}, "status_code"=>200},
29
+ "version"=>"1.1"
30
+ })
31
+ expect(grok).to include("source"=>{"ip"=>"192.168.131.39", "port"=>2817})
32
+ expect(grok).to include("url"=>{
33
+ "original"=>"http://www.example.com:80/",
34
+ "port"=>80, "path"=>"/", "domain"=>"www.example.com", "scheme"=>"http"
35
+ })
36
+ else
37
+ should include("elb" => "my-test-loadbalancer" )
38
+ should include("clientip" => "192.168.131.39" )
39
+ should include("clientport" => 2817 )
40
+ should include("backendip" => "10.0.0.1" )
41
+ should include("backendport" => 80 )
42
+ should include("request_processing_time" => 0.000073 )
43
+ should include("backend_processing_time" => 0.001048 )
44
+ should include("response_processing_time" => 0.000057 )
45
+ should include("response" => 200 )
46
+ should include("backend_response" => 200 )
47
+ should include("received_bytes" => 0 )
48
+ should include("bytes" => 29 )
49
+ should include("verb" => "GET" )
50
+ should include("request" => "http://www.example.com:80/" )
51
+ should include("proto" => "http" )
52
+ should include("httpversion" => "1.1" )
53
+ should include("urihost" => "www.example.com:80" )
54
+ should include("path" => "/" )
55
+ end
56
+ end
57
+
58
+ ["tags", "params"].each do |attribute|
59
+ it "have #{attribute} as nil" do
60
+ expect(subject[attribute]).to be_nil
61
+ end
62
+ end
63
+ end
64
+
65
+ context "parsing a PUT request access log with missing backend info" do
66
+
67
+ let(:message) do
68
+ '2015-04-10T08:11:09.865823Z us-west-1-production-media 49.150.87.133:55128 - -1 -1 -1 408 - 1294336 0 "PUT https://media.xxxyyyzzz.com:443/videos/F4_M-T4X0MM6Hvy1PFHesw HTTP/1.1"'
69
+ end
70
+
71
+ it "matches" do
72
+ expect(grok).to include("timestamp"=>"2015-04-10T08:11:09.865823Z")
73
+ if ecs_compatibility?
74
+ expect(grok).to include("url"=>{
75
+ "original"=>"https://media.xxxyyyzzz.com:443/videos/F4_M-T4X0MM6Hvy1PFHesw",
76
+ "scheme"=>"https", "port"=>443, "path"=>"/videos/F4_M-T4X0MM6Hvy1PFHesw", "domain"=>"media.xxxyyyzzz.com"
77
+ })
78
+ expect(grok).to include("source"=>{"port"=>55128, "ip"=>"49.150.87.133"})
79
+ expect(grok).to include("http"=>{
80
+ "request"=>{"method"=>"PUT", "body"=>{"bytes"=>1294336}}, "version"=>"1.1",
81
+ "response"=>{"body"=>{"bytes"=>0}, "status_code"=>408}
82
+ })
83
+ # no backend.ip and backend.port
84
+ # no backend.http.status.code
85
+ # no request_processing_time.sec and friends
86
+ expect(grok).to include("aws"=>{"elb"=>{"name"=>"us-west-1-production-media"}})
87
+ else
88
+ expect(grok).to include(
89
+ "elb"=>"us-west-1-production-media",
90
+ "clientip"=>"49.150.87.133", "clientport"=>55128,
91
+ "response_processing_time"=>-1.0,
92
+ "request_processing_time"=>-1.0,
93
+ "backend_processing_time"=>-1.0,
94
+ "response"=>408,
95
+ "received_bytes"=>1294336,
96
+ "bytes"=>0,
97
+ "verb"=>"PUT",
98
+ "request"=>"https://media.xxxyyyzzz.com:443/videos/F4_M-T4X0MM6Hvy1PFHesw",
99
+ "port"=>"443", "proto"=>"https", "path"=>"/videos/F4_M-T4X0MM6Hvy1PFHesw", "urihost"=>"media.xxxyyyzzz.com:443",
100
+ "httpversion"=>"1.1")
101
+
102
+ expect(grok.keys).to_not include("backendip", "backendport", "backendresponse")
103
+ end
104
+ end
105
+
106
+ end
107
+
108
+ context '(new) https format' do # slightly longer - 3 fields added at the end
109
+
110
+ let(:message) do
111
+ '2015-05-13T23:39:43.945958Z my-loadbalancer 192.168.131.39:2817 10.0.0.1:80 0.000086 0.001048 0.001337 200 200 0 57 "GET https://www.example.com:443/ HTTP/1.1" "curl/7.38.0 (#56-0ef1d4a5)" DHE-RSA-AES128-SHA TLSv1.2'
112
+ end
113
+
114
+ it 'matches (new) suffix fields' do
115
+ if ecs_compatibility?
116
+ expect(grok).to include "tls" => { "cipher" => "DHE-RSA-AES128-SHA" }
117
+ expect(grok).to include "aws" => { "elb" => hash_including("ssl_protocol" => 'TLSv1.2')}
118
+ expect(grok).to include "user_agent"=>{"original"=>"curl/7.38.0 (#56-0ef1d4a5)"}
119
+ end
120
+ end
121
+
122
+ context 'with optional fields' do
123
+
124
+ let(:message) do
125
+ '2015-05-13T23:39:43.945958Z my-loadbalancer 192.168.131.39:2817 10.0.0.1:80 0.000086 0.001048 0.001337 200 200 0 57 "GET https://www.example.com:443/ HTTP/1.1" "-" - -'
126
+ end
127
+
128
+ it 'matches (new) suffix fields' do
129
+ if ecs_compatibility?
130
+ expect(grok.keys).to_not include "tls"
131
+ expect(grok['aws']['elb'].keys).to_not include "ssl_protocol"
132
+ expect(grok.keys).to_not include "user_agent"
133
+ end
134
+ end
135
+
136
+ end
137
+
138
+ end
139
+ end
140
+
141
+ describe_pattern "S3_ACCESS_LOG", ['legacy', 'ecs-v1'] do
142
+
143
+ context "parsing GET.VERSIONING message" do
144
+
145
+ let(:message) do
146
+ "79a5 mybucket [06/Feb/2014:00:00:38 +0000] 192.0.2.3 79a5 3E57427F3EXAMPLE REST.GET.VERSIONING - \"GET /mybucket?versioning HTTP/1.1\" 200 - 113 - 7 - \"-\" \"S3Console/0.4\" -"
147
+ end
148
+
149
+ it { should include("owner" => "79a5" ) unless ecs_compatibility? }
150
+ it { should include("bucket" => "mybucket" ) unless ecs_compatibility? }
151
+ it { should include("timestamp" => "06/Feb/2014:00:00:38 +0000" ) unless ecs_compatibility? }
152
+ it { should include("clientip" => "192.0.2.3" ) unless ecs_compatibility? }
153
+ it { should include("requester" => "79a5" ) unless ecs_compatibility? }
154
+ it { should include("request_id" => "3E57427F3EXAMPLE" ) unless ecs_compatibility? }
155
+ it { should include("operation" => "REST.GET.VERSIONING" ) unless ecs_compatibility? }
156
+ it { should include("key" => "-" ) unless ecs_compatibility? }
157
+
158
+ it { should include("verb" => "GET" ) unless ecs_compatibility? }
159
+ it { should include("request" => "/mybucket?versioning" ) unless ecs_compatibility? }
160
+ it { should include("httpversion" => "1.1" ) unless ecs_compatibility? }
161
+ it { should include("response" => 200 ) unless ecs_compatibility? }
162
+ it { should include("bytes" => 113 ) unless ecs_compatibility? }
163
+
164
+ it { should include("request_time_ms" => 7 ) unless ecs_compatibility? }
165
+ it { should include("referrer" => "\"-\"" ) unless ecs_compatibility? }
166
+ it { should include("agent" => "\"S3Console/0.4\"" ) unless ecs_compatibility? }
167
+
168
+ ["tags", "error_code", "object_size", "turnaround_time_ms", "version_id"].each do |attribute|
169
+ it "have #{attribute} as nil" do
170
+ expect(subject[attribute]).to be_nil unless ecs_compatibility?
171
+ end
172
+ end
173
+
174
+ end
175
+
176
+ context "parsing a GET.OBJECT message" do
177
+
178
+ let(:message) do
179
+ "79a5 mybucket [12/May/2014:07:54:01 +0000] 10.0.1.2 - 7ACC4BE89EXAMPLE REST.GET.OBJECT foo/bar.html \"GET /foo/bar.html HTTP/1.1\" 304 - - 1718 10 - \"-\" \"Mozilla/5.0\" -"
180
+ end
181
+
182
+ it do
183
+ if ecs_compatibility?
184
+ should include("aws"=>{"s3access"=>hash_including("bucket_owner" => "79a5")})
185
+ else
186
+ should include("owner" => "79a5")
187
+ end
188
+ end
189
+
190
+ it { should include("bucket" => "mybucket" ) unless ecs_compatibility? }
191
+ it { should include("timestamp" => "12/May/2014:07:54:01 +0000" ) }
192
+
193
+ it { should include("clientip" => "10.0.1.2" ) unless ecs_compatibility? }
194
+ it { should include("requester" => "-" ) unless ecs_compatibility? }
195
+ it { should include("client" => { 'ip' => '10.0.1.2' } ) if ecs_compatibility? }
196
+
197
+ it { should include("request_id" => "7ACC4BE89EXAMPLE" ) unless ecs_compatibility? }
198
+ it { should include("operation" => "REST.GET.OBJECT" ) unless ecs_compatibility? }
199
+
200
+ it do
201
+ if ecs_compatibility?
202
+ should include("aws"=>{"s3access"=>hash_including("key" => "foo/bar.html")})
203
+ else
204
+ should include("key" => "foo/bar.html")
205
+ end
206
+ end
207
+
208
+ it { should include("verb" => "GET" ) unless ecs_compatibility? }
209
+ it { should include("request" => "/foo/bar.html" ) unless ecs_compatibility? }
210
+ it { should include("httpversion" => "1.1" ) unless ecs_compatibility? }
211
+ it { should include("response" => 304 ) unless ecs_compatibility? }
212
+ it { should include("object_size" => 1718 ) unless ecs_compatibility? }
213
+
214
+ it { should include("request_time_ms" => 10 ) unless ecs_compatibility? }
215
+ it { should include("referrer" => "\"-\"" ) unless ecs_compatibility? }
216
+
217
+ it { should include("agent" => "\"Mozilla/5.0\"" ) unless ecs_compatibility? }
218
+ it { should include("user_agent"=>{"original"=>"Mozilla/5.0"}) if ecs_compatibility? }
219
+
220
+ ["tags", "error_code", "turnaround_time_ms", "version_id", "bytes"].each do |attribute|
221
+ it "have #{attribute} as nil" do
222
+ expect(subject[attribute]).to be_nil unless ecs_compatibility?
223
+ end
224
+ end
225
+
226
+ end
227
+
228
+ context 'a long line' do
229
+
230
+ let(:message) do
231
+ '79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be awsexamplebucket1 [06/Feb/2019:00:00:38 +0000] ' +
232
+ '192.0.2.3 arn:aws:iam::123456:user/test@elastic.co A1206F460EXAMPLE REST.GET.BUCKETPOLICY - ' +
233
+ '"GET /awsexamplebucket1?policy HTTP/1.1" 404 NoSuchBucketPolicy 297 - 38 12 "-" ' +
234
+ '"AWS-Support-TrustedAdvisor, aws-internal/3 aws-sdk-java/1.11.590 Linux/4.9.137-0.1.ac.218.74.329.metal1.x86_64" - ' +
235
+ 'BNaBsXZQQDbssi6xMBdBU2sLt+Yf5kZDmeBUP35sFoKa3sLLeMC78iwEIWxs99CRUrbS4n11234= SigV2 ECDHE-RSA-AES128-GCM-SHA256 ' +
236
+ 'AuthHeader awsexamplebucket1.s3.us-west-1.amazonaws.com TLSV1.1'
237
+ end
238
+
239
+ it 'matches' do
240
+ if ecs_compatibility?
241
+ expect(grok).to include("client"=>{"ip"=>"192.0.2.3", "user"=>{"id"=>"arn:aws:iam::123456:user/test@elastic.co"}})
242
+ expect(grok).to include("http"=>{"request"=>{"method"=>"GET"}, "version"=>"1.1", "response"=>{"status_code"=>404}})
243
+ expect(grok).to include("url"=>{"original"=>"/awsexamplebucket1?policy"})
244
+ expect(grok).to include("aws"=>{"s3access"=>{
245
+ "bucket_owner"=>"79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be",
246
+ "bucket"=>"awsexamplebucket1",
247
+ "request_id"=>"A1206F460EXAMPLE",
248
+ "operation"=>"REST.GET.BUCKETPOLICY",
249
+ "turn_around_time"=>12,
250
+ "bytes_sent"=>297,
251
+ "request_uri"=>"GET /awsexamplebucket1?policy HTTP/1.1", # NOTE: redundant (beats compatibility)
252
+ "error_code"=>"NoSuchBucketPolicy",
253
+ "total_time" => 38,
254
+ # these fields weren't matched in legacy mode:
255
+ # Host Id -> Signature Version -> Cipher Suite -> Authentication Type -> Host Header -> TLS version
256
+ "host_id" => "BNaBsXZQQDbssi6xMBdBU2sLt+Yf5kZDmeBUP35sFoKa3sLLeMC78iwEIWxs99CRUrbS4n11234=",
257
+ "signature_version" => "SigV2",
258
+ #"cipher_suite" => "ECDHE-RSA-AES128-GCM-SHA256", # tls.cipher
259
+ "authentication_type" => "AuthHeader",
260
+ "host_header" => "awsexamplebucket1.s3.us-west-1.amazonaws.com",
261
+ "tls_version" => "TLSV1.1"
262
+ }})
263
+ expect(grok).to include("tls"=>{"cipher"=>"ECDHE-RSA-AES128-GCM-SHA256"})
264
+ expect(grok).to include("user_agent"=>{
265
+ "original"=>"AWS-Support-TrustedAdvisor, aws-internal/3 aws-sdk-java/1.11.590 Linux/4.9.137-0.1.ac.218.74.329.metal1.x86_64"
266
+ })
267
+ else
268
+ expect(grok).to include("owner"=>"79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be",
269
+ "bucket"=>"awsexamplebucket1",
270
+ "timestamp"=>"06/Feb/2019:00:00:38 +0000",
271
+ "clientip"=>"192.0.2.3",
272
+ "requester"=>"arn:aws:iam::123456:user/test@elastic.co",
273
+ "request_id"=>"A1206F460EXAMPLE",
274
+ "operation"=>"REST.GET.BUCKETPOLICY",
275
+ "key"=>"-",
276
+ "verb"=>"GET",
277
+ "request"=>"/awsexamplebucket1?policy",
278
+ "httpversion"=>"1.1",
279
+ "response"=>404,
280
+ "error_code"=>"NoSuchBucketPolicy",
281
+ "bytes"=>297,
282
+ # object_size nil
283
+ "request_time_ms"=>38,
284
+ "turnaround_time_ms"=>12,
285
+ "referrer"=>"\"-\"",
286
+ "agent"=>"\"AWS-Support-TrustedAdvisor, aws-internal/3 aws-sdk-java/1.11.590 Linux/4.9.137-0.1.ac.218.74.329.metal1.x86_64\"")
287
+ end
288
+ end
289
+
290
+ end
291
+ end
292
+
293
+ describe_pattern "CLOUDFRONT_ACCESS_LOG", ['legacy', 'ecs-v1'] do
294
+
295
+ let(:message) do
296
+ "2016-06-10 18:41:39 IAD53 224281 192.168.1.1 GET d27enomp470abc.cloudfront.net /content/sample/thing.pdf 200 https://example.com/ Mozilla/5.0%2520(Windows%2520NT%25206.1;%2520WOW64)%2520AppleWebKit/537.36%2520(KHTML,%2520like%2520Gecko)%2520Chrome/51.0.2704.79%2520Safari/537.36 - - Miss UGskZ6dUKY7b4C6Pt7wAWVsU2KO-vTRe-mR4r9H-WQMjhNvY6w1Xcg== host.example.com https 883 0.036 - TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RefreshHit"
297
+ end
298
+
299
+ it 'matches' do
300
+ should include("timestamp" => "2016-06-10 18:41:39" )
301
+
302
+ if ecs_compatibility?
303
+ should include("aws"=>{"cloudfront"=>hash_including("x_edge_location"=>"IAD53")})
304
+ should include("destination"=>{"bytes"=>224281})
305
+ should include("source"=>{"ip"=>"192.168.1.1", "bytes"=>883})
306
+ should include("http"=>{
307
+ "request"=>{"method"=>"GET", "referrer"=>"https://example.com/"},
308
+ "response"=>{"status_code"=>200}
309
+ })
310
+ should include("user_agent"=>{"original"=>"Mozilla/5.0%2520(Windows%2520NT%25206.1;%2520WOW64)%2520AppleWebKit/537.36%2520(KHTML,%2520like%2520Gecko)%2520Chrome/51.0.2704.79%2520Safari/537.36"})
311
+ should include("url"=>{"domain"=>"d27enomp470abc.cloudfront.net", "path"=>"/content/sample/thing.pdf"})
312
+ should include("aws"=>{"cloudfront"=>hash_including("x_edge_result_type"=>"Miss")})
313
+ should include("aws"=>{"cloudfront"=>hash_including("x_edge_request_id"=>'UGskZ6dUKY7b4C6Pt7wAWVsU2KO-vTRe-mR4r9H-WQMjhNvY6w1Xcg==')})
314
+ should include("network"=>{"protocol"=>"https"})
315
+ should include("aws"=>{"cloudfront"=>hash_including("http"=>{"request"=>{"host"=>"host.example.com"}})})
316
+ should include("aws"=>{"cloudfront"=>hash_including("time_taken"=>0.036)})
317
+ should include("aws"=>{"cloudfront"=>hash_including("ssl_protocol"=>"TLSv1.2")})
318
+ should include("tls"=>{"cipher"=>"ECDHE-RSA-AES128-GCM-SHA256"})
319
+ should include("aws"=>{"cloudfront"=>hash_including("x_edge_response_result_type"=>"RefreshHit")})
320
+ else
321
+ should include("x_edge_location" => "IAD53" )
322
+ should include("sc_bytes" => 224281 )
323
+ should include("clientip" => "192.168.1.1" )
324
+ should include("cs_method" => "GET" )
325
+ should include("cs_host" => "d27enomp470abc.cloudfront.net" )
326
+ should include("cs_uri_stem" => "/content/sample/thing.pdf" )
327
+ should include("sc_status" => 200 )
328
+ should include("referrer" => "https://example.com/" )
329
+ should include("agent" => "Mozilla/5.0%2520(Windows%2520NT%25206.1;%2520WOW64)%2520AppleWebKit/537.36%2520(KHTML,%2520like%2520Gecko)%2520Chrome/51.0.2704.79%2520Safari/537.36" )
330
+ should include("cs_uri_query" => "-" )
331
+ should include("cookies" => "-" )
332
+ should include("x_edge_result_type" => "Miss" )
333
+ should include("x_edge_request_id" => "UGskZ6dUKY7b4C6Pt7wAWVsU2KO-vTRe-mR4r9H-WQMjhNvY6w1Xcg==" )
334
+ should include("x_host_header" => "host.example.com" )
335
+ should include("cs_protocol" => "https" )
336
+ should include("cs_bytes" => 883 )
337
+ should include("time_taken" => 0.036 )
338
+ should include("x_forwarded_for" => "-" )
339
+ should include("ssl_protocol" => "TLSv1.2" )
340
+ should include("ssl_cipher" => "ECDHE-RSA-AES128-GCM-SHA256" )
341
+ should include("x_edge_response_result_type" => "RefreshHit" )
342
+ end
343
+ end
344
+
345
+ ["tags", "params"].each do |attribute|
346
+ it "have #{attribute} as nil" do
347
+ expect(subject[attribute]).to be_nil
348
+ end
349
+ end
350
+
351
+ context 'version 1.0' do # more fields at the end
352
+
353
+ let(:message) do
354
+ # Version: 1.0 - https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html
355
+ # Fields: date time x-edge-location sc-bytes c-ip cs-method cs(Host) cs-uri-stem sc-status cs(Referer) cs(User-Agent) cs-uri-query cs(Cookie) x-edge-result-type x-edge-request-id x-host-header cs-protocol cs-bytes time-taken x-forwarded-for ssl-protocol ssl-cipher x-edge-response-result-type cs-protocol-version fle-status fle-encrypted-fields c-port time-to-first-byte x-edge-detailed-result-type sc-content-type sc-content-len sc-range-start sc-range-end
356
+ "2019-12-04 21:02:31 LAX1 392 192.0.2.100 GET d111111abcdef8.cloudfront.net /index.html 200 - Mozilla/5.0%20(Windows%20NT%2010.0;%20Win64;%20x64)%20AppleWebKit/537.36%20(KHTML,%20like%20Gecko)%20Chrome/78.0.3904.108%20Safari/537.36 - - Hit SOX4xwn4XV6Q4rgb7XiVGOHms_BGlTAC4KyHmureZmBNrjGdRLiNIQ== d111111abcdef8.cloudfront.net https 23 0.001 - TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 Hit HTTP/2.0 - - 11040 0.001 Hit text/html 78 - -"
357
+ end
358
+
359
+ it 'matches' do
360
+ should include("timestamp" => "2019-12-04\t21:02:31")
361
+
362
+ if ecs_compatibility?
363
+ should include("destination"=>{"bytes"=>392}, "source"=>{"ip"=>"192.0.2.100", "bytes"=>23, "port"=>11040}) # source.port not matched in legacy mode
364
+ should include("url"=>{"domain"=>"d111111abcdef8.cloudfront.net", "path"=>"/index.html"})
365
+ should include("http"=>hash_including("request"=>{"mime_type"=>"text/html", "method"=>"GET"}, "response"=>{"status_code"=>200})) # mime_type not matched in legacy mode
366
+ should include("user_agent"=>{"original"=>"Mozilla/5.0%20(Windows%20NT%2010.0;%20Win64;%20x64)%20AppleWebKit/537.36%20(KHTML,%20like%20Gecko)%20Chrome/78.0.3904.108%20Safari/537.36"})
367
+ should include("tls"=>{"cipher"=>"ECDHE-RSA-AES128-GCM-SHA256"})
368
+ should include("network"=>{"protocol"=>"https"})
369
+
370
+ should include("http"=>hash_including("version"=>"2.0"))
371
+ should include("aws"=>{"cloudfront"=>{
372
+ "x_edge_location"=>"LAX1",
373
+ "x_edge_request_id"=>"SOX4xwn4XV6Q4rgb7XiVGOHms_BGlTAC4KyHmureZmBNrjGdRLiNIQ==", # event.id
374
+ "x_edge_result_type"=>"Hit",
375
+ "x_edge_response_result_type"=>"Hit",
376
+ "x_edge_detailed_result_type"=>"Hit", # not captured in legacy mode
377
+ "time_taken"=>0.001,
378
+ "time_to_first_byte"=>0.001, # not captured in legacy mode
379
+ "http"=>{"request"=>{"host"=>"d111111abcdef8.cloudfront.net", "size"=>78}}, # http.request.size not captured in legacy mode
380
+ "ssl_protocol"=>"TLSv1.2",
381
+ }})
382
+ else
383
+ should include("cs_method"=>"GET", "cs_host"=>"d111111abcdef8.cloudfront.net", "cs_uri_stem"=>"/index.html", "cs_protocol"=>"https", "cs_bytes"=>23)
384
+ should include("x_host_header"=>"d111111abcdef8.cloudfront.net")
385
+ should include("time_taken"=>0.001)
386
+ should include("x_edge_request_id"=>"SOX4xwn4XV6Q4rgb7XiVGOHms_BGlTAC4KyHmureZmBNrjGdRLiNIQ==")
387
+ should include("agent"=>"Mozilla/5.0%20(Windows%20NT%2010.0;%20Win64;%20x64)%20AppleWebKit/537.36%20(KHTML,%20like%20Gecko)%20Chrome/78.0.3904.108%20Safari/537.36")
388
+
389
+ should include("x_forwarded_for"=>"text/html") # TODO the legacy pattern does not handle the long(er) format correctly
390
+ end
391
+ end
392
+
393
+ end
394
+
395
+ end
@@ -0,0 +1,367 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+ require "logstash/patterns/core"
4
+
5
+ describe_pattern "BACULA_LOG_MAX_CAPACITY", ['legacy', 'ecs-v1'] do
6
+
7
+ let(:message) do
8
+ 'User defined maximum volume capacity 108,372,182,400 exceeded on device "FStorage" (/var/lib/bac/storage).'
9
+ end
10
+
11
+ it 'matches' do
12
+ if ecs_compatibility?
13
+ should include "bacula"=>{"volume"=>{"max_capacity"=>"108,372,182,400", "device"=>"FStorage", "path"=>"/var/lib/bac/storage"}}
14
+ else
15
+ should include("device"=>"FStorage")
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+ describe_pattern "BACULA_LOG_END_VOLUME", ['legacy', 'ecs-v1'] do
22
+
23
+ let(:message) do
24
+ 'End of medium on Volume "TestShortZN0014" Bytes=5,228,777 Blocks=82 at 21-Dec-2016 12:30.'
25
+ end
26
+
27
+ it 'matches' do
28
+ if ecs_compatibility?
29
+ should include "bacula"=>hash_including("volume"=>{"name"=>"TestShortZN0014", "bytes"=>"5,228,777", "blocks"=>"82"})
30
+ # bacula.timestamp is 'duplicate' information when the full BACULA_LOGLINE is matched
31
+ # we're keeping it as it includes year and might be slightly off the matched timestamp
32
+ should include "bacula"=>hash_including("timestamp"=>"21-Dec-2016 12:30")
33
+ else
34
+ should include("volume"=>"TestShortZN0014")
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ describe_pattern "BACULA_LOGLINE", ['legacy', 'ecs-v1'] do # BACULA_LOG_NEW_VOLUME
41
+
42
+ let(:message) do
43
+ '09-Jan 19:54 bacula-host JobId 265896: Created new Volume "FullAuto-8812" in catalog.'
44
+ # NOTE: we do not match full message log format that look like:
45
+ # 'Created new Volume="FullAuto-8812", Pool="FullFile", MediaType="FullFile" in catalog.'
46
+ end
47
+
48
+ it 'matches' do
49
+ should include (ecs_compatibility? ? "timestamp" : "bts") => '09-Jan 19:54'
50
+ if ecs_compatibility?
51
+ should include "bacula"=>{"volume"=>{"name"=>"FullAuto-8812"}, "job"=>{"id"=>"265896"}}
52
+ should include "host" => {"hostname"=>"bacula-host"}
53
+ else
54
+ should include("volume"=>"FullAuto-8812")
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+ describe_pattern "BACULA_LOGLINE", ['legacy', 'ecs-v1'] do # BACULA_LOG_NEW_LABEL
61
+
62
+ let(:message) do
63
+ '25-Aug 10:50 bacula-sd JobId 24: Labeled new Volume "Vol-0018" on device "FileChgr1-Dev1" (/opt/bacula/disk).'
64
+ end
65
+
66
+ it 'matches' do
67
+ should include (ecs_compatibility? ? "timestamp" : "bts") => '25-Aug 10:50'
68
+ if ecs_compatibility?
69
+ should include "bacula"=>hash_including("volume"=>{"name"=>"Vol-0018", "device"=>"FileChgr1-Dev1", "path"=>"/opt/bacula/disk"})
70
+ should include "bacula"=>hash_including("job"=>{"id"=>"24"})
71
+ should include "host" => {"hostname"=>"bacula-sd"}
72
+ else
73
+ should include("volume"=>"Vol-0018", "device" => "FileChgr1-Dev1")
74
+ end
75
+ end
76
+
77
+ end
78
+
79
+ describe_pattern "BACULA_LOGLINE", ['legacy', 'ecs-v1'] do # BACULA_LOG_WROTE_LABEL
80
+
81
+ let(:message) do
82
+ '25-Aug 10:50 bacula-sd JobId 24: Wrote label to prelabeled Volume "Volume01" on device "Device01" (/dev/nst0)'
83
+ end
84
+
85
+ it 'matches' do
86
+ should include (ecs_compatibility? ? "timestamp" : "bts") => '25-Aug 10:50'
87
+ if ecs_compatibility?
88
+ should include "bacula"=>hash_including("volume"=>{"name"=>"Volume01", "device"=>"Device01", "path"=>"/dev/nst0"})
89
+ else
90
+ should include("jobid"=>"24")
91
+ end
92
+ end
93
+
94
+ end
95
+
96
+ describe_pattern "BACULA_LOGLINE", ['legacy', 'ecs-v1'] do # BACULA_LOG_NEW_MOUNT
97
+
98
+ let(:message) do
99
+ '24-Aug 01:54 crey-sd JobId 215534: New volume "DiffAuto-4861" mounted on device "vDrive-1" (/usr/local/bac/volumes) at 24-Aug-2015 01:54.'
100
+ end
101
+
102
+ it 'matches' do
103
+ should include (ecs_compatibility? ? "timestamp" : "bts") => '24-Aug 01:54'
104
+ if ecs_compatibility?
105
+ should include "bacula"=>hash_including("volume"=>{"name"=>"DiffAuto-4861", "device"=>"vDrive-1", "path"=>"/usr/local/bac/volumes"})
106
+ else
107
+ should include("device"=>"vDrive-1", "volume"=>"DiffAuto-4861", "hostname"=>"crey-sd", "jobid"=>"215534")
108
+ end
109
+ end
110
+
111
+ end
112
+
113
+ describe_pattern "BACULA_LOGLINE", ['legacy', 'ecs-v1'] do # BACULA_LOG_NOOPENDIR
114
+
115
+ let(:message) do
116
+ '24-Feb 16:36 starfury-fd JobId 3: Could not open directory "/root": ERR=Permission denied'
117
+ end
118
+
119
+ it 'matches' do
120
+ should include (ecs_compatibility? ? "timestamp" : "bts") => '24-Feb 16:36'
121
+ if ecs_compatibility?
122
+ should include "file"=>{"path"=>"/root"}
123
+ should include "error"=>{"message"=>"Permission denied"}
124
+ else
125
+ should include("berror"=>"Permission denied")
126
+ end
127
+ end
128
+
129
+ end
130
+
131
+ describe_pattern "BACULA_LOGLINE", ['legacy', 'ecs-v1'] do # BACULA_LOG_NOSTAT
132
+
133
+ let(:message) do
134
+ '15-Dec 17:50 u22.com JobId 13: Could not stat /var/lib/bacula/bacula.sql: ERR=No such file or directory'
135
+ end
136
+
137
+ it 'matches' do
138
+ if ecs_compatibility?
139
+ should include "timestamp" => '15-Dec 17:50'
140
+ should include "file"=>{"path"=>"/var/lib/bacula/bacula.sql"}
141
+ should include "error"=>{"message"=>"No such file or directory"}
142
+ else
143
+ # NOTE: not matching due BACULA_HOST
144
+ # should include "bts" => '15-Dec 17:50'
145
+ # should include "berror"=>"No such file or directory"
146
+ end
147
+ end
148
+
149
+ end
150
+
151
+ describe_pattern "BACULA_LOGLINE", ['legacy', 'ecs-v1'] do # BACULA_LOG_ALL_RECORDS_PRUNED
152
+
153
+ let(:message) do
154
+ '12-Apr 14:23 VU0EM005: All records pruned from Volume "06D125L3"; marking it "Purged"'
155
+ end
156
+
157
+ it 'matches' do
158
+ should include (ecs_compatibility? ? "timestamp" : "bts") => '12-Apr 14:23'
159
+ if ecs_compatibility?
160
+ should include "bacula"=>{"volume"=>{"name"=>"06D125L3"}},
161
+ "host"=>{"hostname"=>"VU0EM005"}
162
+ else
163
+ should include "hostname"=>"VU0EM005", "volume"=>"06D125L3"
164
+ end
165
+ end
166
+
167
+ end
168
+
169
+ describe_pattern "BACULA_LOGLINE", ['legacy', 'ecs-v1'] do # BACULA_LOG_PRUNED_JOBS
170
+
171
+ let(:message) do
172
+ '29-Jan 04:16 lbu02-dir: Pruned 24 Jobs for client uni-horn from catalog.'
173
+ end
174
+
175
+ it 'matches' do
176
+ should include (ecs_compatibility? ? "timestamp" : "bts") => '29-Jan 04:16'
177
+ if ecs_compatibility?
178
+ should include "bacula"=>{"client"=>{"name"=>"uni-horn"}}, "host"=>{"hostname"=>"lbu02-dir"}
179
+ else
180
+ should include "hostname"=>"lbu02-dir", "client"=>"uni-horn"
181
+ end
182
+ end
183
+
184
+ end
185
+
186
+ describe_pattern "BACULA_LOGLINE", ['legacy', 'ecs-v1'] do # BACULA_LOG_STARTJOB
187
+
188
+ let(:message) do
189
+ '06-Mar 20:00 srvbkp-dir JobId 1075: Start Backup JobId 1075, Job=srv1-bind.2018-03-06_20.00.01_05'
190
+ end
191
+
192
+ it 'matches' do
193
+ should include (ecs_compatibility? ? "timestamp" : "bts") => '06-Mar 20:00'
194
+ if ecs_compatibility?
195
+ should include "bacula"=>{"job"=>{"name"=>"srv1-bind.2018-03-06_20.00.01_05", "id"=>"1075"}}
196
+ else
197
+ should include "job"=>"srv1-bind.2018-03-06_20.00.01_05", "jobid"=>"1075"
198
+ end
199
+ end
200
+
201
+ end
202
+
203
+ describe_pattern "BACULA_LOGLINE", ['legacy', 'ecs-v1'] do # BACULA_LOG_DIFF_FS
204
+
205
+ let(:message) do
206
+ '01-Feb 00:34 ohms-fd JobId 1662: /var/spool/bareos is a different filesystem. Will not descend from /var into it.'
207
+ end
208
+
209
+ it 'matches' do
210
+ should include (ecs_compatibility? ? "timestamp" : "bts") => '01-Feb 00:34'
211
+ end
212
+
213
+ end
214
+
215
+ describe_pattern "BACULA_LOGLINE", ['legacy', 'ecs-v1'] do # BACULA_LOG_JOBEND
216
+
217
+ let(:message) do
218
+ '28-Aug 21:55 bacula-sd JobId 16: Job write elapsed time = 00:00:01, Transfer rate = 0 Bytes/second'
219
+ end
220
+
221
+ it 'matches' do
222
+ should include (ecs_compatibility? ? "timestamp" : "bts") => '28-Aug 21:55'
223
+ if ecs_compatibility?
224
+ should include "bacula"=>{"job"=>{"elapsed_time"=>"00:00:01", "id"=>"16"}}
225
+ else
226
+ should include "jobid"=>"16", "elapsed" => "00:00:01"
227
+ end
228
+ end
229
+
230
+ end
231
+
232
+ describe_pattern "BACULA_LOGLINE", ['legacy', 'ecs-v1'] do # BACULA_LOG_VOLUME_PREVWRITTEN
233
+
234
+ let(:message) do
235
+ '17-Jan-2003 16:45 home-sd: Volume test01 previously written, moving to end of data.'
236
+ end
237
+
238
+ it 'matches' do
239
+ if ecs_compatibility?
240
+ should include "timestamp" => '17-Jan-2003 16:45'
241
+ should include "bacula"=>{"volume"=>{"name"=>"test01"}}
242
+ else
243
+ # fails to match (due timestamp format)
244
+ end
245
+ end
246
+
247
+ end
248
+
249
+ describe_pattern "BACULA_LOG_READYAPPEND", ['legacy', 'ecs-v1'] do
250
+
251
+ let(:message) do
252
+ 'Ready to append to end of Volume "F-0032" size=97835302'
253
+ end
254
+
255
+ it 'matches' do
256
+ if ecs_compatibility?
257
+ should include "bacula"=>{"volume"=>{"name"=>"F-0032", "size"=>97835302}}
258
+ else
259
+ should include "volume"=>"F-0032"
260
+ end
261
+ end
262
+
263
+ end
264
+
265
+ describe_pattern "BACULA_LOGLINE", ['legacy', 'ecs-v1'] do # BACULA_LOG_CLIENT_RBJ
266
+
267
+ let(:message) do
268
+ '01-Aug 13:30 toe-fd JobId 686: shell command: run ClientRunBeforeJob "/etc/bacula/cbe_hanfs.sh /mnt/baxter/fs1"'
269
+ end
270
+
271
+ it 'matches' do
272
+ if ecs_compatibility?
273
+ should include "bacula"=>{"job"=>{"id"=>"686", "client_run_before_command"=>'/etc/bacula/cbe_hanfs.sh /mnt/baxter/fs1'}}
274
+ else
275
+ should include "jobid"=>"686", "runjob"=>"/etc/bacula/cbe_hanfs.sh /mnt/baxter/fs1"
276
+ end
277
+ end
278
+
279
+ end
280
+
281
+ describe_pattern "BACULA_LOGLINE", ['legacy', 'ecs-v1'] do # BACULA_LOG_FATAL_CONN
282
+
283
+ let(:message) do
284
+ '11-Nov 13:28 bacula-dir JobId 11: Fatal error: bsock.c:133 Unable to connect to Client: dc0-fd on dc0.teamworld.com:9102. ERR=Connection refused'
285
+ end
286
+
287
+ it 'matches' do
288
+ if ecs_compatibility?
289
+ should include "client"=>{"address"=>"dc0.teamworld.com", "port"=>9102},
290
+ "bacula"=>hash_including("client"=>{"name"=>"dc0-fd"}),
291
+ "error"=>{"message"=>"Connection refused"}
292
+ else
293
+ should include "client"=>"dc0-fd", "berror"=>"Connection refused"
294
+ end
295
+ end
296
+
297
+ end
298
+
299
+ describe_pattern "BACULA_LOGLINE", ['legacy', 'ecs-v1'] do # BACULA_LOG_NO_AUTH
300
+
301
+ let(:message) do
302
+ '16-May 11:59 samy-dir JobId 0: Fatal error: Unable to authenticate with File daemon at "cardam.home.domain:9102". Possible causes:'
303
+ end
304
+
305
+ it 'matches' do
306
+ if ecs_compatibility?
307
+ # NOTE: due a grok bug port:int type-casting does not work :
308
+ #should include "client"=>{"address"=>"cardam.home.domain", "port"=>9102}
309
+ expect( subject['client'] ).to be_a Hash
310
+ expect( subject['client']['address'] ).to eql 'cardam.home.domain'
311
+ expect( subject['client']['port'].to_i ).to eql 9102
312
+ else
313
+ # does not match due client address:port
314
+ end
315
+ end
316
+
317
+ end
318
+
319
+ describe_pattern "BACULA_LOGLINE", ['legacy', 'ecs-v1'] do # BACULA_LOG_CANCELLING
320
+
321
+ let(:message) do
322
+ '03-Aug 06:20 DIRECTOR JobId 316677: Cancelling duplicate JobId=316646.'
323
+ end
324
+
325
+ it 'matches' do
326
+ if ecs_compatibility?
327
+ expect( subject ).to include "bacula" => hash_including("job" => {'id' => '316677', 'other_id' => '316646'})
328
+ else
329
+ expect( subject ).to include "jobid" => "316677"
330
+ end
331
+ end
332
+
333
+ end
334
+
335
+ describe_pattern "BACULA_LOGLINE", ['legacy', 'ecs-v1'] do # BACULA_LOG_MARKCANCEL
336
+
337
+ let(:message) do
338
+ '09-Aug 15:14 InternetServer-sd JobId 122971, Job nyi_maildir.2013-03-03_22.00.00_51 marked to be canceled.'
339
+ end
340
+
341
+ it 'matches' do
342
+ if ecs_compatibility?
343
+ expect( subject ).to include "bacula" => hash_including(
344
+ "job" => {'id' => '122971', 'name' => 'nyi_maildir.2013-03-03_22.00.00_51'})
345
+ else
346
+ expect( subject ).to include "job" => "nyi_maildir.2013-03-03_22.00.00_51"
347
+ end
348
+ end
349
+
350
+ end
351
+
352
+
353
+ describe_pattern "BACULA_LOGLINE", ['legacy', 'ecs-v1'] do # BACULA_LOG_FATAL_CONN
354
+
355
+ let(:message) do
356
+ '25-Aug 09:02 marlin2-dir JobId 10783: Fatal Error: JobId 10782 already running. Duplicate job not allowed.'
357
+ end
358
+
359
+ it 'matches' do
360
+ if ecs_compatibility?
361
+ expect( subject ).to include "bacula" => hash_including("job" => {'id' => '10783', 'other_id' => '10782'})
362
+ else
363
+ # NOTE: not matching due expecting 'error' instead of 'Error' in "Fatal Error: JobId ..."
364
+ end
365
+ end
366
+
367
+ end