logstash-filter-useragent 3.2.2-java → 3.3.2-java

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.
@@ -1,105 +1,448 @@
1
1
  # encoding: utf-8
2
-
3
2
  require "logstash/devutils/rspec/spec_helper"
3
+ require 'logstash/plugin_mixins/ecs_compatibility_support/spec_helper'
4
4
  require "logstash/filters/useragent"
5
5
 
6
6
  describe LogStash::Filters::UserAgent do
7
7
 
8
- describe "defaults" do
9
- config <<-CONFIG
10
- filter {
11
- useragent {
12
- source => "message"
13
- target => "ua"
8
+ subject { LogStash::Filters::UserAgent.new(options) }
9
+
10
+ let(:options) { { 'source' => 'message' } }
11
+ let(:message) { "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36" }
12
+
13
+ let(:event) { LogStash::Event.new('message' => message) }
14
+
15
+ context 'with target', :ecs_compatibility_support do
16
+ ecs_compatibility_matrix(:disabled, :v1, :v8 => :v1) do |ecs_select|
17
+
18
+ let(:ecs_compatibility?) { ecs_select.active_mode != :disabled }
19
+
20
+ before(:each) do
21
+ allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
22
+ end
23
+
24
+ config <<-CONFIG
25
+ filter {
26
+ useragent {
27
+ source => "message"
28
+ target => "ua"
29
+ }
14
30
  }
15
- }
16
- CONFIG
31
+ CONFIG
32
+
33
+ sample "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31" do
34
+ expect( subject.to_hash ).to include("ua")
35
+ expect( subject.get("[ua][name]") ).to eql "Chrome"
36
+ if ecs_compatibility?
37
+ expect( subject.get("[ua][os][name]") ).to eql "Linux"
38
+ expect( subject.get("[ua][os][full]") ).to eql "Linux"
39
+ expect( subject.get("[ua][device][name]") ).to eql "Other"
40
+ ua_metadata = subject.get("[@metadata][filter][user_agent]")
41
+ expect( ua_metadata ).to include 'version' => { 'major' => '26', 'minor' => '0', 'patch' => '1410' }
42
+ expect( subject.get("[ua][version]") ).to eql "26.0.1410.63"
43
+ expect( subject.get("[ua]").keys ).to_not include 'major'
44
+ expect( subject.get("[ua]").keys ).to_not include 'minor'
45
+ else
46
+ expect( subject.get("[ua][os_name]") ).to eql "Linux"
47
+ expect( subject.get("[ua][os_full]") ).to eql "Linux"
48
+ expect( subject.get("[ua][os]") ).to eql "Linux"
49
+ expect( subject.get("[ua][device]") ).to eql "Other"
50
+ expect( subject.get("[ua][major]") ).to eql "26"
51
+ expect( subject.get("[ua][minor]") ).to eql "0"
52
+ end
53
+
54
+ expect( subject.get("[ua][name]").encoding ).to eql Encoding::UTF_8
55
+ end
56
+
57
+ sample "MacOutlook/16.24.0.190414 (Intelx64 Mac OS X Version 10.14.4 (Build 18E226))" do
58
+ expect( subject.to_hash ).to include("ua")
59
+ expect( subject.get("[ua][name]") ).to eql "MacOutlook"
60
+ if ecs_compatibility?
61
+ expect( subject.get("[ua][version]") ).to eql "16.24.0.190414"
62
+ expect( subject.get("[ua][os][full]") ).to eql "Mac OS X 10.14.4"
63
+ expect( subject.get("[ua][os][name]") ).to eql "Mac OS X"
64
+ expect( subject.get("[ua][os][version]") ).to eql '10.14.4'
65
+ expect( subject.get("[ua][device][name]") ).to eql 'Mac'
66
+
67
+ expect( subject.get("[ua][os][name]").encoding ).to eql Encoding::UTF_8
68
+ else
69
+ expect( subject.get("[ua][major]") ).to eql "16"
70
+ expect( subject.get("[ua][minor]") ).to eql "24"
71
+ expect( subject.get("[ua][patch]") ).to eql "0"
72
+ expect( subject.get("[ua][os_full]") ).to eql "Mac OS X 10.14.4"
73
+ expect( subject.get("[ua][os_name]") ).to eql "Mac OS X"
74
+ expect( subject.get("[ua][os_major]") ).to eql '10'
75
+ expect( subject.get("[ua][os_minor]") ).to eql '14'
76
+ expect( subject.get("[ua][device]") ).to eql 'Mac'
77
+
78
+ expect( subject.get("[ua][os]") ).to eql "Mac OS X"
79
+ expect( subject.get("[ua][os]").encoding ).to eql Encoding::UTF_8
80
+ end
81
+ end
82
+
83
+ # Safari 12 on Mojave
84
+ sample "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Safari/605.1.15" do
85
+ expect( subject.to_hash ).to include("ua")
86
+ expect( subject.get("[ua][name]") ).to eql "Safari"
87
+ if ecs_compatibility?
88
+ expect( subject.get("[ua][version]") ).to eql "12.0"
89
+ expect( subject.get("[ua][os][full]") ).to eql "Mac OS X 10.14"
90
+ expect( subject.get("[ua][os][name]") ).to eql "Mac OS X"
91
+ expect( subject.get("[ua][os][version]") ).to eql '10.14'
92
+ ua_metadata = subject.get("[@metadata][filter][user_agent][os]")
93
+ expect( ua_metadata ).to include 'version' => { 'major' => '10', 'minor' => '14' }
94
+
95
+ expect( subject.get("[@metadata][filter][user_agent][os][version][major]").encoding ).to eql Encoding::UTF_8
96
+ else
97
+ expect( subject.get("[ua][major]") ).to eql "12"
98
+ expect( subject.get("[ua][minor]") ).to eql "0"
99
+ expect( subject.get("[ua][patch]") ).to be nil
100
+ expect( subject.get("[ua][os_full]") ).to eql "Mac OS X 10.14"
101
+ expect( subject.get("[ua][os_name]") ).to eql "Mac OS X"
102
+ expect( subject.get("[ua][os_major]") ).to eql '10'
103
+ expect( subject.get("[ua][os_minor]") ).to eql '14'
104
+
105
+ expect( subject.get("[ua][os_major]").encoding ).to eql Encoding::UTF_8
106
+ end
107
+ end
108
+
109
+ # Safari 7 on Mac OS X (Mavericks)
110
+ sample "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A" do
111
+ expect( subject.to_hash ).to include("ua")
112
+ expect( subject.get("[ua][name]") ).to eql "Safari"
113
+ if ecs_compatibility?
114
+ expect( subject.get("[ua][version]") ).to eql "7.0.3"
115
+ expect( subject.get("[ua][os][full]") ).to eql "Mac OS X 10.9.3"
116
+ expect( subject.get("[ua][os][name]") ).to eql "Mac OS X"
117
+ expect( subject.get("[ua][device][name]") ).to eql 'Mac'
118
+ else
119
+ expect( subject.get("[ua][major]") ).to eql "7"
120
+ expect( subject.get("[ua][minor]") ).to eql "0"
121
+ expect( subject.get("[ua][patch]") ).to eql "3"
122
+ expect( subject.get("[ua][os_full]") ).to eql "Mac OS X 10.9.3"
123
+ expect( subject.get("[ua][os_name]") ).to eql "Mac OS X"
124
+ expect( subject.get("[ua][os_major]") ).to eql '10'
125
+ expect( subject.get("[ua][os_minor]") ).to eql '9'
126
+ expect( subject.get("[ua][device]") ).to eql 'Mac'
127
+ end
128
+ end
129
+
130
+ sample "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Firefox/45.0" do
131
+ expect( subject.to_hash ).to include("ua")
132
+ expect( subject.get("[ua][name]") ).to eql "Firefox"
133
+ if ecs_compatibility?
134
+ expect( subject.get("[ua][version]") ).to eql "45.0"
135
+ expect( subject.get("[ua][os][full]") ).to eql "Mac OS X 10.11"
136
+ expect( subject.get("[ua][os][name]") ).to eql "Mac OS X"
137
+ expect( subject.get("[ua][os][version]") ).to eql '10.11'
138
+ expect( subject.get("[ua][device][name]") ).to eql 'Mac'
139
+ else
140
+ expect( subject.get("[ua][major]") ).to eql "45"
141
+ expect( subject.get("[ua][minor]") ).to eql "0"
142
+ expect( subject.get("[ua][patch]") ).to be nil
143
+ expect( subject.get("[ua][os_full]") ).to eql "Mac OS X 10.11"
144
+ expect( subject.get("[ua][os_name]") ).to eql "Mac OS X"
145
+ expect( subject.get("[ua][os_major]") ).to eql '10'
146
+ expect( subject.get("[ua][os_minor]") ).to eql '11'
147
+ expect( subject.get("[ua][device]") ).to eql 'Mac'
148
+ end
149
+ end
150
+
151
+ # IE7 Vista
152
+ sample "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)" do
153
+ expect( subject.to_hash ).to include("ua")
154
+ if ecs_compatibility?
155
+ expect( subject.get("[ua][os][name]") ).to eql "Windows"
156
+ expect( subject.get("[ua][os][version]") ).to eql 'Vista'
157
+ expect( subject.get("[ua][device][name]") ).to eql 'Other'
158
+
159
+ expect( subject.get("[ua][device][name]").encoding ).to eql Encoding::UTF_8
160
+ else
161
+ expect( subject.get("[ua][os_name]") ).to eql "Windows"
162
+ expect( subject.get("[ua][os_major]") ).to eql 'Vista'
163
+ expect( subject.get("[ua][os_minor]") ).to be nil
164
+ expect( subject.get("[ua][device]") ).to eql 'Other'
165
+
166
+ expect( subject.get("[ua][device]").encoding ).to eql Encoding::UTF_8
167
+ end
168
+ end
169
+
170
+ # IE8 XP
171
+ sample "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.5.30729)" do
172
+ expect( subject.to_hash ).to include("ua")
173
+ expect( subject.get("[ua][name]") ).to eql 'IE'
174
+ if ecs_compatibility?
175
+ expect( subject.get("[ua][os][name]") ).to eql 'Windows'
176
+ expect( subject.get("[ua][os][version]") ).to eql 'XP'
177
+ expect( subject.get("[ua][device][name]") ).to eql 'Other'
178
+ else
179
+ expect( subject.get("[ua][os_name]") ).to eql 'Windows'
180
+ expect( subject.get("[ua][os_major]") ).to eql 'XP'
181
+ expect( subject.get("[ua][os_minor]") ).to be nil
182
+ expect( subject.get("[ua][device]") ).to eql 'Other'
183
+ end
184
+ end
185
+
186
+ # # Windows 8.1
187
+ sample "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246" do
188
+ expect( subject.to_hash ).to include("ua")
189
+ expect( subject.get("[ua][name]") ).to eql 'Edge'
190
+ if ecs_compatibility?
191
+ expect( subject.get("[ua][os][name]") ).to eql 'Windows'
192
+ expect( subject.get("[ua][os][version]") ).to eql '8.1'
193
+ else
194
+ expect( subject.get("[ua][os_name]") ).to eql 'Windows'
195
+ expect( subject.get("[ua][os_major]") ).to eql '8'
196
+ expect( subject.get("[ua][os_minor]") ).to eql '1'
197
+ end
198
+ end
199
+
200
+ # Windows 10
201
+ sample "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36 Edg/89.0.774.50" do
202
+ expect( subject.to_hash ).to include("ua")
203
+ expect( subject.get("[ua][name]") ).to eql "Edge"
204
+ if ecs_compatibility?
205
+ expect( subject.get("[ua][version]") ).to eql "89.0.774.50"
206
+ expect( subject.get("[ua][os][full]") ).to eql "Windows 10"
207
+ expect( subject.get("[ua][os][name]") ).to eql "Windows"
208
+ expect( subject.get("[ua][os][version]") ).to eql '10'
209
+ ua_metadata = subject.get("[@metadata][filter][user_agent][os]")
210
+ expect( ua_metadata ).to include 'version' => { 'major' => '10' }
211
+ expect( subject.get("[ua][device][name]") ).to eql 'Other'
212
+ else
213
+ expect( subject.get("[ua][os_name]") ).to eql "Windows"
214
+ expect( subject.get("[ua][os_major]") ).to eql '10'
215
+ expect( subject.get("[ua][os_minor]") ).to be nil
216
+ expect( subject.get("[ua][device]") ).to eql 'Other'
217
+ end
218
+ end
219
+
220
+ # Chrome on Linux
221
+ sample "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36" do
222
+ expect( subject.to_hash ).to include("ua")
223
+ expect( subject.get("[ua][name]") ).to eql 'Chrome'
224
+ if ecs_compatibility?
225
+ expect( subject.get("[ua][os][name]") ).to eql "Linux"
226
+ expect( subject.get("[ua][os][version]") ).to be nil
227
+ expect( subject.get("[ua][device][name]") ).to eql 'Other'
228
+ else
229
+ expect( subject.get("[ua][os_name]") ).to eql "Linux"
230
+ expect( subject.get("[ua][os_major]") ).to be nil
231
+ expect( subject.get("[ua][os_minor]") ).to be nil
232
+ expect( subject.get("[ua][device]") ).to eql 'Other'
233
+ end
234
+ end
17
235
 
18
- sample "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31" do
19
- insist { subject }.include?("ua")
20
- insist { subject.get("[ua][name]") } == "Chrome"
21
- insist { subject.get("[ua][os]") } == "Linux"
22
- insist { subject.get("[ua][major]") } == "26"
23
- insist { subject.get("[ua][minor]") } == "0"
24
236
  end
25
237
  end
26
238
 
27
- describe "manually specified regexes file" do
28
- config <<-CONFIG
29
- filter {
30
- useragent {
31
- source => "message"
32
- target => "ua"
33
- regexes => "build/resources/main/regexes.yaml"
239
+ context "manually specified regexes file", :ecs_compatibility_support do
240
+ ecs_compatibility_matrix(:disabled, :v1, :v8 => :v1) do |ecs_select|
241
+
242
+ let(:ecs_compatibility?) { ecs_select.active_mode != :disabled }
243
+
244
+ before(:each) do
245
+ allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
246
+ end
247
+
248
+ config <<-CONFIG
249
+ filter {
250
+ useragent {
251
+ source => "message"
252
+ target => "[ua]"
253
+ regexes => "build/resources/main/regexes.yaml"
254
+ }
34
255
  }
35
- }
36
- CONFIG
256
+ CONFIG
257
+
258
+ sample "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31" do
259
+ expect( subject.to_hash ).to include("ua")
260
+ if ecs_compatibility?
261
+ expect( subject.get("[ua][name]") ).to eql "Chrome"
262
+ expect( subject.get("[ua][os][name]") ).to eql "Linux"
263
+ expect( subject.get("[ua][version]") ).to eql "26.0.1410.63"
264
+ expect( subject.get("[@metadata][filter][user_agent][version][major]") ).to eql "26"
265
+ expect( subject.get("[@metadata][filter][user_agent][version][minor]") ).to eql "0"
266
+ else
267
+ expect( subject.get("[ua][name]") ).to eql "Chrome"
268
+ expect( subject.get("[ua][os]") ).to eql "Linux"
269
+ expect( subject.get("[ua][major]") ).to eql "26"
270
+ expect( subject.get("[ua][minor]") ).to eql "0"
271
+ end
272
+ end
37
273
 
38
- sample "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31" do
39
- insist { subject }.include?("ua")
40
- insist { subject.get("[ua][name]") } == "Chrome"
41
- insist { subject.get("[ua][os]") } == "Linux"
42
- insist { subject.get("[ua][major]") } == "26"
43
- insist { subject.get("[ua][minor]") } == "0"
44
274
  end
45
275
  end
46
-
47
- describe "Without target field" do
48
- config <<-CONFIG
49
- filter {
50
- useragent {
51
- source => "message"
276
+
277
+ context "without target field", :ecs_compatibility_support do
278
+ ecs_compatibility_matrix(:disabled, :v1, :v8 => :v1) do |ecs_select|
279
+
280
+ let(:ecs_compatibility?) { ecs_select.active_mode != :disabled }
281
+
282
+ before(:each) do
283
+ allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
284
+ end
285
+
286
+ config <<-CONFIG
287
+ filter {
288
+ useragent {
289
+ source => "message"
290
+ }
52
291
  }
53
- }
54
- CONFIG
292
+ CONFIG
293
+
294
+ sample "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31" do
295
+ if ecs_compatibility? # [user_agent] default target in ECS
296
+ expect( subject.get("user_agent") ).to include 'name' => 'Chrome'
297
+ expect( subject.get("user_agent") ).to include 'os' => hash_including('name' => 'Linux')
298
+ expect( subject.get("user_agent") ).to include 'version' => '26.0.1410.63'
299
+ else
300
+ expect( subject.get("name") ).to eql "Chrome"
301
+ expect( subject.get("os_name") ).to eql "Linux"
302
+ expect( subject.get("os") ).to eql "Linux"
303
+ expect( subject.get("major") ).to eql "26"
304
+ expect( subject.get("minor") ).to eql "0"
305
+ expect( subject.get("patch") ).to eql "1410"
306
+ expect( subject.get("version") ).to eql "26.0.1410.63"
307
+ end
308
+ end
309
+ end
310
+ end
311
+
312
+ context "nested target field", :ecs_compatibility_support do
313
+ ecs_compatibility_matrix(:disabled, :v1, :v8 => :v1) do
314
+
315
+ before(:each) do
316
+ allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
317
+ end
318
+
319
+ config <<-CONFIG
320
+ filter {
321
+ useragent {
322
+ source => "message"
323
+ target => "[foo][bar]"
324
+ }
325
+ }
326
+ CONFIG
327
+
328
+ # Facebook App User Agent
329
+ sample "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) " +
330
+ "Mobile/15E148 [FBAN/FBIOS;FBDV/iPhone11,8;FBMD/iPhone;FBSN/iOS;FBSV/13.3.1;FBSS/2;FBID/phone;FBLC/en_US;FBOP/5;FBCR/]" do
331
+ expect( subject ).to include 'foo'
332
+ expect( subject.get('foo') ).to include 'bar'
333
+ expect( subject.get('foo')['bar'] ).to include "name" => "Facebook"
334
+ end
335
+
336
+ end
337
+ end
338
+
339
+ context "without user agent", :ecs_compatibility_support do
340
+ ecs_compatibility_matrix(:disabled, :v1, :v8 => :v1) do |ecs_select|
341
+
342
+ let(:ecs_compatibility?) { ecs_select.active_mode != :disabled }
343
+
344
+ before(:each) do
345
+ allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
346
+ end
347
+
348
+ config <<-CONFIG
349
+ filter {
350
+ useragent {
351
+ source => "message"
352
+ target => "ua"
353
+ }
354
+ }
355
+ CONFIG
356
+
357
+ sample "foo" => "bar" do
358
+ expect( subject.to_hash ).to_not include("ua")
359
+ end
360
+
361
+ sample "" do
362
+ expect( subject.to_hash ).to_not include("ua")
363
+ end
55
364
 
56
- sample "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31" do
57
- insist { subject.get("name") } == "Chrome"
58
- insist { subject.get("os") } == "Linux"
59
- insist { subject.get("major") } == "26"
60
- insist { subject.get("minor") } == "0"
61
365
  end
62
366
  end
63
367
 
64
- describe "Without user agent" do
368
+ describe "non-exact UA data" do
65
369
  config <<-CONFIG
66
370
  filter {
67
371
  useragent {
68
372
  source => "message"
69
- target => "ua"
373
+ target => "user_agent"
70
374
  }
71
375
  }
72
376
  CONFIG
73
377
 
74
- sample "foo" => "bar" do
75
- reject { subject }.include?("ua")
378
+ sample 'Prefix DATA! Mozilla/5.0 (Android 11; Mobile; rv:68.0) Gecko/68.0 Firefox/86.0' do
379
+ expect( subject.to_hash ).to include("user_agent")
380
+ expect( subject.get('user_agent') ).to include "name" => "Firefox Mobile", "version" => '86.0', "os_name" => "Android"
76
381
  end
77
382
 
78
- sample "" do
79
- reject { subject }.include?("ua")
383
+ end
384
+
385
+ context "with prefix", :ecs_compatibility_support do
386
+ ecs_compatibility_matrix(:disabled, :v1, :v8 => :v1) do |ecs_select|
387
+
388
+ let(:message) { 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0' }
389
+ let(:options) { super().merge('prefix' => 'pre_') }
390
+
391
+ before(:each) do
392
+ allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
393
+ end
394
+
395
+ it 'works in legacy mode with prefix (without a warning)' do
396
+ expect( subject.logger ).to_not receive(:warn)
397
+ subject.register
398
+
399
+ subject.filter(event)
400
+
401
+ expect( event.to_hash ).to include('pre_name' => 'Firefox', 'pre_version' => '78.0')
402
+ end if ecs_select.active_mode == :disabled
403
+
404
+ it 'warns in ECS mode (and ignores prefix)' do
405
+ expect( subject.logger ).to receive(:warn).with %r{Field prefix isn't supported in ECS compatibility mode}
406
+ subject.register
407
+
408
+ subject.filter(event)
409
+
410
+ expect( event.to_hash.keys.find { |key| key.index('pre_') } ).to be nil
411
+ expect( event.get('user_agent').keys.find { |key| key.index('pre_') } ).to be nil
412
+ expect( event.get('user_agent') ).to include('name' => 'Firefox', 'version' => '78.0')
413
+ end if ecs_select.active_mode != :disabled
414
+
80
415
  end
81
416
  end
82
417
 
83
- describe "LRU object identity" do
84
- let(:ua_string) { "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36" }
85
- let(:uafilter) { LogStash::Filters::UserAgent.new("source" => "foo") }
86
- let(:ua_data) { uafilter.lookup_useragent(ua_string) }
418
+ context "no prefix", :ecs_compatibility_support do
419
+ ecs_compatibility_matrix(:disabled, :v1, :v8 => :v1) do
87
420
 
88
- subject(:target) { LogStash::Event.new("foo" => ua_string) }
421
+ let(:message) { 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0' }
89
422
 
90
- before do
91
- uafilter.register
423
+ before(:each) do
424
+ allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
425
+ end
426
+
427
+ it 'does not warn' do
428
+ expect( subject.logger ).to_not receive(:warn)
429
+ subject.register
430
+ end
92
431
 
93
- # Stub this out because this UA doesn't have this field
94
- allow(ua_data.userAgent).to receive(:patchMinor).and_return("foo")
432
+ end
433
+ end
434
+
435
+ describe "LRU object identity" do
95
436
 
96
- # expect(event).receive(:lookup_useragent)
97
- uafilter.filter(target)
437
+ let(:ua_data) { subject.send :lookup_useragent, message }
438
+
439
+ before do
440
+ subject.register
441
+ subject.filter(event)
98
442
  end
99
443
 
100
444
  {
101
445
  "name" => lambda {|uad| uad.userAgent.family},
102
- "os" => lambda {|uad| uad.os.family},
103
446
  "os_name" => lambda {|uad| uad.os.family},
104
447
  "os_major" => lambda {|uad| uad.os.major},
105
448
  "os_minor" => lambda {|uad| uad.os.minor},
@@ -107,11 +450,10 @@ describe LogStash::Filters::UserAgent do
107
450
  "major" => lambda {|uad| uad.userAgent.major},
108
451
  "minor" => lambda {|uad| uad.userAgent.minor},
109
452
  "patch" => lambda {|uad| uad.userAgent.patch},
110
- "build" => lambda {|uad| uad.userAgent.patchMinor}
111
453
  }.each do |field, uad_getter|
112
454
  context "for the #{field} field" do
113
- let(:value) {uad_getter.call(ua_data)}
114
- let(:target_field) { target.get(field)}
455
+ let(:value) { uad_getter.call(ua_data) }
456
+ let(:target_field) { event.get(field) }
115
457
 
116
458
  it "should not have a nil value" do
117
459
  expect(target_field).to be_truthy
@@ -124,6 +466,10 @@ describe LogStash::Filters::UserAgent do
124
466
  it "should dup/clone the field to prevent cache corruption" do
125
467
  expect(target_field.object_id).not_to eql(value.object_id)
126
468
  end
469
+
470
+ it "should be an utf-8 string" do
471
+ expect(target_field.encoding.name).to eql 'UTF-8'
472
+ end
127
473
  end
128
474
  end
129
475
  end
@@ -139,11 +485,25 @@ describe LogStash::Filters::UserAgent do
139
485
  CONFIG
140
486
 
141
487
  sample "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31" do
142
- insist { subject.to_hash }.include?("message")
143
- insist { subject.get("[message][name]") } == "Chrome"
144
- insist { subject.get("[message][os]") } == "Linux"
145
- insist { subject.get("[message][major]") } == "26"
146
- insist { subject.get("[message][minor]") } == "0"
488
+ expect( subject.to_hash ).to include("message")
489
+ expect( subject.get("[message][name]") ).to eql "Chrome"
490
+ expect( subject.get("[message][os]") ).to eql "Linux"
491
+ expect( subject.get("[message][major]") ).to eql "26"
492
+ expect( subject.get("[message][minor]") ).to eql "0"
147
493
  end
148
494
  end
495
+
496
+ context 'exception handling' do
497
+
498
+ before do
499
+ subject.register
500
+ expect(subject).to receive(:lookup_useragent).and_raise RuntimeError.new('this is a test')
501
+ end
502
+
503
+ it 'errors do not propagate' do
504
+ expect(subject.logger).to receive(:error).with(/Unknown error while parsing user agent data/, hash_including(exception: RuntimeError, message: 'this is a test'))
505
+ expect { subject.filter(event) }.not_to raise_error
506
+ end
507
+
508
+ end
149
509
  end
data/version CHANGED
@@ -1 +1 @@
1
- 3.2.2
1
+ 3.3.2
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-filter-useragent
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.2
4
+ version: 3.3.2
5
5
  platform: java
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-07 00:00:00.000000000 Z
11
+ date: 2021-11-10 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.3'
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.3'
33
47
  - !ruby/object:Gem::Dependency
34
48
  requirement: !ruby/object:Gem::Requirement
35
49
  requirements:
@@ -63,7 +77,7 @@ files:
63
77
  - lib/logstash/filters/useragent.rb
64
78
  - logstash-filter-useragent.gemspec
65
79
  - spec/filters/useragent_spec.rb
66
- - vendor/jar-dependencies/org/logstash/filters/logstash-filter-useragent/3.2.2/logstash-filter-useragent-3.2.2.jar
80
+ - vendor/jar-dependencies/org/logstash/filters/logstash-filter-useragent/3.3.2/logstash-filter-useragent-3.3.2.jar
67
81
  - version
68
82
  homepage: http://www.elastic.co/guide/en/logstash/current/index.html
69
83
  licenses:
@@ -87,8 +101,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
87
101
  - !ruby/object:Gem::Version
88
102
  version: '0'
89
103
  requirements: []
90
- rubyforge_project:
91
- rubygems_version: 2.6.11
104
+ rubygems_version: 3.1.6
92
105
  signing_key:
93
106
  specification_version: 4
94
107
  summary: Parses user agent strings into fields