fluent-plugin-windows-eventlog 0.8.1 → 0.8.2
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 +4 -4
- data/.github/workflows/unit-test.yml +36 -34
- data/.gitignore +14 -14
- data/CHANGELOG.md +77 -74
- data/Gemfile +4 -4
- data/LICENSE.txt +203 -203
- data/README.md +387 -387
- data/Rakefile +10 -10
- data/appveyor.yml +24 -24
- data/fluent-plugin-winevtlog.gemspec +28 -28
- data/lib/fluent/plugin/bookmark_sax_parser.rb +30 -30
- data/lib/fluent/plugin/in_windows_eventlog.rb +241 -241
- data/lib/fluent/plugin/in_windows_eventlog2.rb +410 -406
- data/test/generate-windows-event.rb +47 -47
- data/test/helper.rb +34 -34
- data/test/plugin/test_bookmark_sax_parser.rb +41 -41
- data/test/plugin/test_in_windows_eventlog2.rb +619 -600
- data/test/plugin/test_in_winevtlog.rb +48 -48
- metadata +8 -8
@@ -1,600 +1,619 @@
|
|
1
|
-
require 'helper'
|
2
|
-
require 'fileutils'
|
3
|
-
require 'generate-windows-event'
|
4
|
-
|
5
|
-
# Monkey patch for testing
|
6
|
-
class Winevt::EventLog::Session
|
7
|
-
def ==(obj)
|
8
|
-
self.server == obj.server &&
|
9
|
-
self.domain == obj.domain &&
|
10
|
-
self.username == obj.username &&
|
11
|
-
self.password == obj.password &&
|
12
|
-
self.flags == obj.flags
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
class WindowsEventLog2InputTest < Test::Unit::TestCase
|
17
|
-
|
18
|
-
def setup
|
19
|
-
Fluent::Test.setup
|
20
|
-
end
|
21
|
-
|
22
|
-
CONFIG = config_element("ROOT", "", {"tag" => "fluent.eventlog"}, [
|
23
|
-
config_element("storage", "", {
|
24
|
-
'@type' => 'local',
|
25
|
-
'persistent' => false
|
26
|
-
})
|
27
|
-
])
|
28
|
-
|
29
|
-
XML_RENDERING_CONFIG = config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
30
|
-
"render_as_xml" => true}, [
|
31
|
-
config_element("storage", "", {
|
32
|
-
'@type' => 'local',
|
33
|
-
'persistent' => false
|
34
|
-
})
|
35
|
-
])
|
36
|
-
|
37
|
-
def create_driver(conf = CONFIG)
|
38
|
-
Fluent::Test::Driver::Input.new(Fluent::Plugin::WindowsEventLog2Input).configure(conf)
|
39
|
-
end
|
40
|
-
|
41
|
-
def test_configure
|
42
|
-
d = create_driver CONFIG
|
43
|
-
assert_equal 'fluent.eventlog', d.instance.tag
|
44
|
-
assert_equal 2, d.instance.read_interval
|
45
|
-
assert_equal [], d.instance.channels
|
46
|
-
assert_false d.instance.read_existing_events
|
47
|
-
assert_false d.instance.render_as_xml
|
48
|
-
assert_nil d.instance.refresh_subscription_interval
|
49
|
-
end
|
50
|
-
|
51
|
-
sub_test_case "configure" do
|
52
|
-
test "refresh subscription interval" do
|
53
|
-
d = create_driver config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
54
|
-
"refresh_subscription_interval" => "2m"}, [
|
55
|
-
config_element("storage", "", {
|
56
|
-
'@type' => 'local',
|
57
|
-
'persistent' => false
|
58
|
-
})
|
59
|
-
])
|
60
|
-
assert_equal 120, d.instance.refresh_subscription_interval
|
61
|
-
end
|
62
|
-
|
63
|
-
test "subscribe directive" do
|
64
|
-
d = create_driver config_element("ROOT", "", {"tag" => "fluent.eventlog"}, [
|
65
|
-
config_element("storage", "", {
|
66
|
-
'@type' => 'local',
|
67
|
-
'persistent' => false
|
68
|
-
}),
|
69
|
-
config_element("subscribe", "", {
|
70
|
-
'channels' => ['System', 'Windows PowerShell'],
|
71
|
-
}),
|
72
|
-
config_element("subscribe", "", {
|
73
|
-
'channels' => ['Security'],
|
74
|
-
'read_existing_events' => true
|
75
|
-
}),
|
76
|
-
])
|
77
|
-
expected = [["system", false, nil], ["windows powershell", false, nil], ["security", true, nil]]
|
78
|
-
assert_equal expected, d.instance.instance_variable_get(:@chs)
|
79
|
-
end
|
80
|
-
|
81
|
-
test "subscribe directive with remote server session" do
|
82
|
-
d = create_driver config_element("ROOT", "", {"tag" => "fluent.eventlog"}, [
|
83
|
-
config_element("storage", "", {
|
84
|
-
'@type' => 'local',
|
85
|
-
'persistent' => false
|
86
|
-
}),
|
87
|
-
config_element("subscribe", "", {
|
88
|
-
'channels' => ['System', 'Windows PowerShell'],
|
89
|
-
'remote_server' => '127.0.0.1',
|
90
|
-
}),
|
91
|
-
config_element("subscribe", "", {
|
92
|
-
'channels' => ['Security'],
|
93
|
-
'read_existing_events' => true,
|
94
|
-
'remote_server' => '192.168.0.1',
|
95
|
-
'remote_username' => 'fluentd',
|
96
|
-
'remote_password' => 'changeme!'
|
97
|
-
}),
|
98
|
-
])
|
99
|
-
localhost_session = Winevt::EventLog::Session.new("127.0.0.1")
|
100
|
-
remote_session = Winevt::EventLog::Session.new("192.168.0.1",
|
101
|
-
nil,
|
102
|
-
"fluentd",
|
103
|
-
"changeme!")
|
104
|
-
expected = [["system", false, localhost_session],
|
105
|
-
["windows powershell", false, localhost_session],
|
106
|
-
["security", true, remote_session]]
|
107
|
-
assert_equal expected, d.instance.instance_variable_get(:@chs)
|
108
|
-
end
|
109
|
-
|
110
|
-
test "duplicated subscribe" do
|
111
|
-
d = create_driver config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
112
|
-
"channels" => ["System", "Windows PowerShell"]
|
113
|
-
}, [
|
114
|
-
config_element("storage", "", {
|
115
|
-
'@type' => 'local',
|
116
|
-
'persistent' => false
|
117
|
-
}),
|
118
|
-
config_element("subscribe", "", {
|
119
|
-
'channels' => ['System', 'Windows PowerShell'],
|
120
|
-
}),
|
121
|
-
config_element("subscribe", "", {
|
122
|
-
'channels' => ['Security'],
|
123
|
-
'read_existing_events' => true
|
124
|
-
}),
|
125
|
-
])
|
126
|
-
expected = [["system", false, nil], ["windows powershell", false, nil], ["security", true, nil]]
|
127
|
-
assert_equal 1, d.instance.instance_variable_get(:@chs).select {|ch, flag| ch == "system"}.size
|
128
|
-
assert_equal expected, d.instance.instance_variable_get(:@chs)
|
129
|
-
end
|
130
|
-
|
131
|
-
test "non duplicated subscribe" do
|
132
|
-
d = create_driver config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
133
|
-
"channels" => ["System", "Windows PowerShell"]
|
134
|
-
}, [
|
135
|
-
config_element("storage", "", {
|
136
|
-
'@type' => 'local',
|
137
|
-
'persistent' => false
|
138
|
-
}),
|
139
|
-
config_element("subscribe", "", {
|
140
|
-
'channels' => ['System', 'Windows PowerShell'],
|
141
|
-
'read_existing_events' => true
|
142
|
-
}),
|
143
|
-
config_element("subscribe", "", {
|
144
|
-
'channels' => ['Security'],
|
145
|
-
'read_existing_events' => true
|
146
|
-
}),
|
147
|
-
])
|
148
|
-
expected = [["system", false, nil], ["windows powershell", false, nil], ["system", true, nil], ["windows powershell", true, nil], ["security", true, nil]]
|
149
|
-
assert_equal 2, d.instance.instance_variable_get(:@chs).select {|ch, flag| ch == "system"}.size
|
150
|
-
assert_equal expected, d.instance.instance_variable_get(:@chs)
|
151
|
-
end
|
152
|
-
|
153
|
-
test "invalid combination for preserving qualifiers" do
|
154
|
-
assert_raise(Fluent::ConfigError) do
|
155
|
-
create_driver config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
156
|
-
"render_as_xml" => true,
|
157
|
-
"preserve_qualifiers_on_hash" => true,
|
158
|
-
}, [
|
159
|
-
config_element("storage", "", {
|
160
|
-
'@type' => 'local',
|
161
|
-
'persistent' => false
|
162
|
-
}),
|
163
|
-
])
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
test "invalid description locale" do
|
168
|
-
assert_raise(Fluent::ConfigError) do
|
169
|
-
create_driver config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
170
|
-
"description_locale" => "ex_EX"
|
171
|
-
}, [
|
172
|
-
config_element("storage", "", {
|
173
|
-
'@type' => 'local',
|
174
|
-
'persistent' => false
|
175
|
-
})
|
176
|
-
])
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
data("Japanese" => ["ja_JP", false],
|
182
|
-
"English (United States)" => ["en_US", false],
|
183
|
-
"English (UK)" => ["en_GB", false],
|
184
|
-
"Dutch" => ["nl_NL", false],
|
185
|
-
"French" => ["fr_FR", false],
|
186
|
-
"German" => ["de_DE", false],
|
187
|
-
"Russian" => ["ru_RU", false],
|
188
|
-
"Spanish" => ["es_ES", false],
|
189
|
-
"Invalid" => ["ex_EX", true],
|
190
|
-
)
|
191
|
-
def test_unsupported_locale_p(data)
|
192
|
-
description_locale, expected = data
|
193
|
-
d = create_driver CONFIG
|
194
|
-
locale = Winevt::EventLog::Locale.new
|
195
|
-
result = d.instance.unsupported_locale?(locale, description_locale)
|
196
|
-
assert_equal expected, result
|
197
|
-
end
|
198
|
-
|
199
|
-
data("application" => ["Application", "Application"],
|
200
|
-
"windows powershell" => ["Windows PowerShell", "Windows PowerShell"],
|
201
|
-
"escaped" => ["Should_Be_Escaped_", "Should+Be;Escaped/"]
|
202
|
-
)
|
203
|
-
def test_escape_channel(data)
|
204
|
-
expected, actual = data
|
205
|
-
d = create_driver CONFIG
|
206
|
-
assert_equal expected, d.instance.escape_channel(actual)
|
207
|
-
end
|
208
|
-
|
209
|
-
def test_parse_desc
|
210
|
-
d = create_driver
|
211
|
-
desc =<<-DESC
|
212
|
-
A user's local group membership was enumerated.\r\n\r\nSubject:\r\n\tSecurity ID:\t\tS-X-Y-XX-WWWWWW-VVVV\r\n\tAccount Name:\t\tAdministrator\r\n\tAccount Domain:\t\tDESKTOP-FLUENTTEST\r\n\tLogon ID:\t\t0x3185B1\r\n\r\nUser:\r\n\tSecurity ID:\t\tS-X-Y-XX-WWWWWW-VVVV\r\n\tAccount Name:\t\tAdministrator\r\n\tAccount Domain:\t\tDESKTOP-FLUENTTEST\r\n\r\nProcess Information:\r\n\tProcess ID:\t\t0x50b8\r\n\tProcess Name:\t\tC:\\msys64\\usr\\bin\\make.exe
|
213
|
-
DESC
|
214
|
-
h = {"Description" => desc}
|
215
|
-
expected = {"DescriptionTitle" => "A user's local group membership was enumerated.",
|
216
|
-
"subject.security_id" => "S-X-Y-XX-WWWWWW-VVVV",
|
217
|
-
"subject.account_name" => "Administrator",
|
218
|
-
"subject.account_domain" => "DESKTOP-FLUENTTEST",
|
219
|
-
"subject.logon_id" => "0x3185B1",
|
220
|
-
"user.security_id" => "S-X-Y-XX-WWWWWW-VVVV",
|
221
|
-
"user.account_name" => "Administrator",
|
222
|
-
"user.account_domain" => "DESKTOP-FLUENTTEST",
|
223
|
-
"process_information.process_id" => "0x50b8",
|
224
|
-
"process_information.process_name" => "C:\\msys64\\usr\\bin\\make.exe"}
|
225
|
-
d.instance.parse_desc(h)
|
226
|
-
assert_equal(expected, h)
|
227
|
-
end
|
228
|
-
|
229
|
-
def test_parse_privileges_description
|
230
|
-
d = create_driver
|
231
|
-
desc = ["Special privileges assigned to new logon.\r\n\r\nSubject:\r\n\tSecurity ID:\t\tS-X-Y-ZZ\r\n\t",
|
232
|
-
"AccountName:\t\tSYSTEM\r\n\tAccount Domain:\t\tNT AUTHORITY\r\n\tLogon ID:\t\t0x3E7\r\n\r\n",
|
233
|
-
"Privileges:\t\tSeAssignPrimaryTokenPrivilege\r\n\t\t\tSeTcbPrivilege\r\n\t\t\t",
|
234
|
-
"SeSecurityPrivilege\r\n\t\t\tSeTakeOwnershipPrivilege\r\n\t\t\tSeLoadDriverPrivilege\r\n\t\t\t",
|
235
|
-
"SeBackupPrivilege\r\n\t\t\tSeRestorePrivilege\r\n\t\t\tSeDebugPrivilege\r\n\t\t\t",
|
236
|
-
"SeAuditPrivilege\r\n\t\t\tSeSystemEnvironmentPrivilege\r\n\t\t\tSeImpersonatePrivilege\r\n\t\t\t",
|
237
|
-
"SeDelegateSessionUserImpersonatePrivilege"].join("")
|
238
|
-
|
239
|
-
h = {"Description" => desc}
|
240
|
-
expected = {"DescriptionTitle" => "Special privileges assigned to new logon.",
|
241
|
-
"subject.security_id" => "S-X-Y-ZZ",
|
242
|
-
"subject.accountname" => "SYSTEM",
|
243
|
-
"subject.account_domain" => "NT AUTHORITY",
|
244
|
-
"subject.logon_id" => "0x3E7",
|
245
|
-
"privileges" => ["SeAssignPrimaryTokenPrivilege",
|
246
|
-
"SeTcbPrivilege",
|
247
|
-
"SeSecurityPrivilege",
|
248
|
-
"SeTakeOwnershipPrivilege",
|
249
|
-
"SeLoadDriverPrivilege",
|
250
|
-
"SeBackupPrivilege",
|
251
|
-
"SeRestorePrivilege",
|
252
|
-
"SeDebugPrivilege",
|
253
|
-
"SeAuditPrivilege",
|
254
|
-
"SeSystemEnvironmentPrivilege",
|
255
|
-
"SeImpersonatePrivilege",
|
256
|
-
"SeDelegateSessionUserImpersonatePrivilege"]}
|
257
|
-
d.instance.parse_desc(h)
|
258
|
-
assert_equal(expected, h)
|
259
|
-
end
|
260
|
-
|
261
|
-
test "A new external device was recognized by the system." do
|
262
|
-
# using the event log example: eventopedia.cloudapp.net/EventDetails.aspx?id=17ef124e-eb89-4c01-9ba2-d761e06b2b68
|
263
|
-
d = create_driver
|
264
|
-
desc = nil
|
265
|
-
File.open('./test/data/eventid_6416', 'r') do |f|
|
266
|
-
desc = f.read.gsub(/\R/, "\r\n")
|
267
|
-
end
|
268
|
-
h = {"Description" => desc}
|
269
|
-
expected = {"DescriptionTitle" => "A new external device was recognized by the system.",
|
270
|
-
"class_id" => "{1ed2bbf9-11f0-4084-b21f-ad83a8e6dcdc}",
|
271
|
-
"class_name" => "PrintQueue",
|
272
|
-
"compatible_ids" => ["GenPrintQueue", "SWD\\GenericRaw", "SWD\\Generic"],
|
273
|
-
"device_id" => "SWD\\PRINTENUM\\{60FA1C6A-1AB2-440A-AEE1-62ABFB9A4650}",
|
274
|
-
"device_name" => "Microsoft Print to PDF",
|
275
|
-
"subject.account_domain" => "ITSS",
|
276
|
-
"subject.account_name" => "IIZHU2016$",
|
277
|
-
"subject.logon_id" => "0x3E7",
|
278
|
-
"subject.security_id" => "SYSTEM",
|
279
|
-
"vendor_ids" => ["PRINTENUM\\{084f01fa-e634-4d77-83ee-074817c03581}",
|
280
|
-
"PRINTENUM\\LocalPrintQueue",
|
281
|
-
"{084f01fa-e634-4d77-83ee-074817c03581}"]}
|
282
|
-
d.instance.parse_desc(h)
|
283
|
-
assert_equal(expected, h)
|
284
|
-
end
|
285
|
-
|
286
|
-
def test_write
|
287
|
-
d = create_driver
|
288
|
-
|
289
|
-
service = Fluent::Plugin::EventService.new
|
290
|
-
|
291
|
-
d.run(expect_emits: 1) do
|
292
|
-
service.run
|
293
|
-
end
|
294
|
-
|
295
|
-
assert(d.events.length >= 1)
|
296
|
-
event = d.events.select {|e| e.last["EventID"] == "65500" }.last
|
297
|
-
record = event.last
|
298
|
-
|
299
|
-
assert_equal("Application", record["Channel"])
|
300
|
-
assert_equal("65500", record["EventID"])
|
301
|
-
assert_equal("4", record["Level"])
|
302
|
-
assert_equal("fluent-plugins", record["ProviderName"])
|
303
|
-
end
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
end
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
1
|
+
require 'helper'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'generate-windows-event'
|
4
|
+
|
5
|
+
# Monkey patch for testing
|
6
|
+
class Winevt::EventLog::Session
|
7
|
+
def ==(obj)
|
8
|
+
self.server == obj.server &&
|
9
|
+
self.domain == obj.domain &&
|
10
|
+
self.username == obj.username &&
|
11
|
+
self.password == obj.password &&
|
12
|
+
self.flags == obj.flags
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class WindowsEventLog2InputTest < Test::Unit::TestCase
|
17
|
+
|
18
|
+
def setup
|
19
|
+
Fluent::Test.setup
|
20
|
+
end
|
21
|
+
|
22
|
+
CONFIG = config_element("ROOT", "", {"tag" => "fluent.eventlog"}, [
|
23
|
+
config_element("storage", "", {
|
24
|
+
'@type' => 'local',
|
25
|
+
'persistent' => false
|
26
|
+
})
|
27
|
+
])
|
28
|
+
|
29
|
+
XML_RENDERING_CONFIG = config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
30
|
+
"render_as_xml" => true}, [
|
31
|
+
config_element("storage", "", {
|
32
|
+
'@type' => 'local',
|
33
|
+
'persistent' => false
|
34
|
+
})
|
35
|
+
])
|
36
|
+
|
37
|
+
def create_driver(conf = CONFIG)
|
38
|
+
Fluent::Test::Driver::Input.new(Fluent::Plugin::WindowsEventLog2Input).configure(conf)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_configure
|
42
|
+
d = create_driver CONFIG
|
43
|
+
assert_equal 'fluent.eventlog', d.instance.tag
|
44
|
+
assert_equal 2, d.instance.read_interval
|
45
|
+
assert_equal [], d.instance.channels
|
46
|
+
assert_false d.instance.read_existing_events
|
47
|
+
assert_false d.instance.render_as_xml
|
48
|
+
assert_nil d.instance.refresh_subscription_interval
|
49
|
+
end
|
50
|
+
|
51
|
+
sub_test_case "configure" do
|
52
|
+
test "refresh subscription interval" do
|
53
|
+
d = create_driver config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
54
|
+
"refresh_subscription_interval" => "2m"}, [
|
55
|
+
config_element("storage", "", {
|
56
|
+
'@type' => 'local',
|
57
|
+
'persistent' => false
|
58
|
+
})
|
59
|
+
])
|
60
|
+
assert_equal 120, d.instance.refresh_subscription_interval
|
61
|
+
end
|
62
|
+
|
63
|
+
test "subscribe directive" do
|
64
|
+
d = create_driver config_element("ROOT", "", {"tag" => "fluent.eventlog"}, [
|
65
|
+
config_element("storage", "", {
|
66
|
+
'@type' => 'local',
|
67
|
+
'persistent' => false
|
68
|
+
}),
|
69
|
+
config_element("subscribe", "", {
|
70
|
+
'channels' => ['System', 'Windows PowerShell'],
|
71
|
+
}),
|
72
|
+
config_element("subscribe", "", {
|
73
|
+
'channels' => ['Security'],
|
74
|
+
'read_existing_events' => true
|
75
|
+
}),
|
76
|
+
])
|
77
|
+
expected = [["system", false, nil], ["windows powershell", false, nil], ["security", true, nil]]
|
78
|
+
assert_equal expected, d.instance.instance_variable_get(:@chs)
|
79
|
+
end
|
80
|
+
|
81
|
+
test "subscribe directive with remote server session" do
|
82
|
+
d = create_driver config_element("ROOT", "", {"tag" => "fluent.eventlog"}, [
|
83
|
+
config_element("storage", "", {
|
84
|
+
'@type' => 'local',
|
85
|
+
'persistent' => false
|
86
|
+
}),
|
87
|
+
config_element("subscribe", "", {
|
88
|
+
'channels' => ['System', 'Windows PowerShell'],
|
89
|
+
'remote_server' => '127.0.0.1',
|
90
|
+
}),
|
91
|
+
config_element("subscribe", "", {
|
92
|
+
'channels' => ['Security'],
|
93
|
+
'read_existing_events' => true,
|
94
|
+
'remote_server' => '192.168.0.1',
|
95
|
+
'remote_username' => 'fluentd',
|
96
|
+
'remote_password' => 'changeme!'
|
97
|
+
}),
|
98
|
+
])
|
99
|
+
localhost_session = Winevt::EventLog::Session.new("127.0.0.1")
|
100
|
+
remote_session = Winevt::EventLog::Session.new("192.168.0.1",
|
101
|
+
nil,
|
102
|
+
"fluentd",
|
103
|
+
"changeme!")
|
104
|
+
expected = [["system", false, localhost_session],
|
105
|
+
["windows powershell", false, localhost_session],
|
106
|
+
["security", true, remote_session]]
|
107
|
+
assert_equal expected, d.instance.instance_variable_get(:@chs)
|
108
|
+
end
|
109
|
+
|
110
|
+
test "duplicated subscribe" do
|
111
|
+
d = create_driver config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
112
|
+
"channels" => ["System", "Windows PowerShell"]
|
113
|
+
}, [
|
114
|
+
config_element("storage", "", {
|
115
|
+
'@type' => 'local',
|
116
|
+
'persistent' => false
|
117
|
+
}),
|
118
|
+
config_element("subscribe", "", {
|
119
|
+
'channels' => ['System', 'Windows PowerShell'],
|
120
|
+
}),
|
121
|
+
config_element("subscribe", "", {
|
122
|
+
'channels' => ['Security'],
|
123
|
+
'read_existing_events' => true
|
124
|
+
}),
|
125
|
+
])
|
126
|
+
expected = [["system", false, nil], ["windows powershell", false, nil], ["security", true, nil]]
|
127
|
+
assert_equal 1, d.instance.instance_variable_get(:@chs).select {|ch, flag| ch == "system"}.size
|
128
|
+
assert_equal expected, d.instance.instance_variable_get(:@chs)
|
129
|
+
end
|
130
|
+
|
131
|
+
test "non duplicated subscribe" do
|
132
|
+
d = create_driver config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
133
|
+
"channels" => ["System", "Windows PowerShell"]
|
134
|
+
}, [
|
135
|
+
config_element("storage", "", {
|
136
|
+
'@type' => 'local',
|
137
|
+
'persistent' => false
|
138
|
+
}),
|
139
|
+
config_element("subscribe", "", {
|
140
|
+
'channels' => ['System', 'Windows PowerShell'],
|
141
|
+
'read_existing_events' => true
|
142
|
+
}),
|
143
|
+
config_element("subscribe", "", {
|
144
|
+
'channels' => ['Security'],
|
145
|
+
'read_existing_events' => true
|
146
|
+
}),
|
147
|
+
])
|
148
|
+
expected = [["system", false, nil], ["windows powershell", false, nil], ["system", true, nil], ["windows powershell", true, nil], ["security", true, nil]]
|
149
|
+
assert_equal 2, d.instance.instance_variable_get(:@chs).select {|ch, flag| ch == "system"}.size
|
150
|
+
assert_equal expected, d.instance.instance_variable_get(:@chs)
|
151
|
+
end
|
152
|
+
|
153
|
+
test "invalid combination for preserving qualifiers" do
|
154
|
+
assert_raise(Fluent::ConfigError) do
|
155
|
+
create_driver config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
156
|
+
"render_as_xml" => true,
|
157
|
+
"preserve_qualifiers_on_hash" => true,
|
158
|
+
}, [
|
159
|
+
config_element("storage", "", {
|
160
|
+
'@type' => 'local',
|
161
|
+
'persistent' => false
|
162
|
+
}),
|
163
|
+
])
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
test "invalid description locale" do
|
168
|
+
assert_raise(Fluent::ConfigError) do
|
169
|
+
create_driver config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
170
|
+
"description_locale" => "ex_EX"
|
171
|
+
}, [
|
172
|
+
config_element("storage", "", {
|
173
|
+
'@type' => 'local',
|
174
|
+
'persistent' => false
|
175
|
+
})
|
176
|
+
])
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
data("Japanese" => ["ja_JP", false],
|
182
|
+
"English (United States)" => ["en_US", false],
|
183
|
+
"English (UK)" => ["en_GB", false],
|
184
|
+
"Dutch" => ["nl_NL", false],
|
185
|
+
"French" => ["fr_FR", false],
|
186
|
+
"German" => ["de_DE", false],
|
187
|
+
"Russian" => ["ru_RU", false],
|
188
|
+
"Spanish" => ["es_ES", false],
|
189
|
+
"Invalid" => ["ex_EX", true],
|
190
|
+
)
|
191
|
+
def test_unsupported_locale_p(data)
|
192
|
+
description_locale, expected = data
|
193
|
+
d = create_driver CONFIG
|
194
|
+
locale = Winevt::EventLog::Locale.new
|
195
|
+
result = d.instance.unsupported_locale?(locale, description_locale)
|
196
|
+
assert_equal expected, result
|
197
|
+
end
|
198
|
+
|
199
|
+
data("application" => ["Application", "Application"],
|
200
|
+
"windows powershell" => ["Windows PowerShell", "Windows PowerShell"],
|
201
|
+
"escaped" => ["Should_Be_Escaped_", "Should+Be;Escaped/"]
|
202
|
+
)
|
203
|
+
def test_escape_channel(data)
|
204
|
+
expected, actual = data
|
205
|
+
d = create_driver CONFIG
|
206
|
+
assert_equal expected, d.instance.escape_channel(actual)
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_parse_desc
|
210
|
+
d = create_driver
|
211
|
+
desc =<<-DESC
|
212
|
+
A user's local group membership was enumerated.\r\n\r\nSubject:\r\n\tSecurity ID:\t\tS-X-Y-XX-WWWWWW-VVVV\r\n\tAccount Name:\t\tAdministrator\r\n\tAccount Domain:\t\tDESKTOP-FLUENTTEST\r\n\tLogon ID:\t\t0x3185B1\r\n\r\nUser:\r\n\tSecurity ID:\t\tS-X-Y-XX-WWWWWW-VVVV\r\n\tAccount Name:\t\tAdministrator\r\n\tAccount Domain:\t\tDESKTOP-FLUENTTEST\r\n\r\nProcess Information:\r\n\tProcess ID:\t\t0x50b8\r\n\tProcess Name:\t\tC:\\msys64\\usr\\bin\\make.exe
|
213
|
+
DESC
|
214
|
+
h = {"Description" => desc}
|
215
|
+
expected = {"DescriptionTitle" => "A user's local group membership was enumerated.",
|
216
|
+
"subject.security_id" => "S-X-Y-XX-WWWWWW-VVVV",
|
217
|
+
"subject.account_name" => "Administrator",
|
218
|
+
"subject.account_domain" => "DESKTOP-FLUENTTEST",
|
219
|
+
"subject.logon_id" => "0x3185B1",
|
220
|
+
"user.security_id" => "S-X-Y-XX-WWWWWW-VVVV",
|
221
|
+
"user.account_name" => "Administrator",
|
222
|
+
"user.account_domain" => "DESKTOP-FLUENTTEST",
|
223
|
+
"process_information.process_id" => "0x50b8",
|
224
|
+
"process_information.process_name" => "C:\\msys64\\usr\\bin\\make.exe"}
|
225
|
+
d.instance.parse_desc(h)
|
226
|
+
assert_equal(expected, h)
|
227
|
+
end
|
228
|
+
|
229
|
+
def test_parse_privileges_description
|
230
|
+
d = create_driver
|
231
|
+
desc = ["Special privileges assigned to new logon.\r\n\r\nSubject:\r\n\tSecurity ID:\t\tS-X-Y-ZZ\r\n\t",
|
232
|
+
"AccountName:\t\tSYSTEM\r\n\tAccount Domain:\t\tNT AUTHORITY\r\n\tLogon ID:\t\t0x3E7\r\n\r\n",
|
233
|
+
"Privileges:\t\tSeAssignPrimaryTokenPrivilege\r\n\t\t\tSeTcbPrivilege\r\n\t\t\t",
|
234
|
+
"SeSecurityPrivilege\r\n\t\t\tSeTakeOwnershipPrivilege\r\n\t\t\tSeLoadDriverPrivilege\r\n\t\t\t",
|
235
|
+
"SeBackupPrivilege\r\n\t\t\tSeRestorePrivilege\r\n\t\t\tSeDebugPrivilege\r\n\t\t\t",
|
236
|
+
"SeAuditPrivilege\r\n\t\t\tSeSystemEnvironmentPrivilege\r\n\t\t\tSeImpersonatePrivilege\r\n\t\t\t",
|
237
|
+
"SeDelegateSessionUserImpersonatePrivilege"].join("")
|
238
|
+
|
239
|
+
h = {"Description" => desc}
|
240
|
+
expected = {"DescriptionTitle" => "Special privileges assigned to new logon.",
|
241
|
+
"subject.security_id" => "S-X-Y-ZZ",
|
242
|
+
"subject.accountname" => "SYSTEM",
|
243
|
+
"subject.account_domain" => "NT AUTHORITY",
|
244
|
+
"subject.logon_id" => "0x3E7",
|
245
|
+
"privileges" => ["SeAssignPrimaryTokenPrivilege",
|
246
|
+
"SeTcbPrivilege",
|
247
|
+
"SeSecurityPrivilege",
|
248
|
+
"SeTakeOwnershipPrivilege",
|
249
|
+
"SeLoadDriverPrivilege",
|
250
|
+
"SeBackupPrivilege",
|
251
|
+
"SeRestorePrivilege",
|
252
|
+
"SeDebugPrivilege",
|
253
|
+
"SeAuditPrivilege",
|
254
|
+
"SeSystemEnvironmentPrivilege",
|
255
|
+
"SeImpersonatePrivilege",
|
256
|
+
"SeDelegateSessionUserImpersonatePrivilege"]}
|
257
|
+
d.instance.parse_desc(h)
|
258
|
+
assert_equal(expected, h)
|
259
|
+
end
|
260
|
+
|
261
|
+
test "A new external device was recognized by the system." do
|
262
|
+
# using the event log example: eventopedia.cloudapp.net/EventDetails.aspx?id=17ef124e-eb89-4c01-9ba2-d761e06b2b68
|
263
|
+
d = create_driver
|
264
|
+
desc = nil
|
265
|
+
File.open('./test/data/eventid_6416', 'r') do |f|
|
266
|
+
desc = f.read.gsub(/\R/, "\r\n")
|
267
|
+
end
|
268
|
+
h = {"Description" => desc}
|
269
|
+
expected = {"DescriptionTitle" => "A new external device was recognized by the system.",
|
270
|
+
"class_id" => "{1ed2bbf9-11f0-4084-b21f-ad83a8e6dcdc}",
|
271
|
+
"class_name" => "PrintQueue",
|
272
|
+
"compatible_ids" => ["GenPrintQueue", "SWD\\GenericRaw", "SWD\\Generic"],
|
273
|
+
"device_id" => "SWD\\PRINTENUM\\{60FA1C6A-1AB2-440A-AEE1-62ABFB9A4650}",
|
274
|
+
"device_name" => "Microsoft Print to PDF",
|
275
|
+
"subject.account_domain" => "ITSS",
|
276
|
+
"subject.account_name" => "IIZHU2016$",
|
277
|
+
"subject.logon_id" => "0x3E7",
|
278
|
+
"subject.security_id" => "SYSTEM",
|
279
|
+
"vendor_ids" => ["PRINTENUM\\{084f01fa-e634-4d77-83ee-074817c03581}",
|
280
|
+
"PRINTENUM\\LocalPrintQueue",
|
281
|
+
"{084f01fa-e634-4d77-83ee-074817c03581}"]}
|
282
|
+
d.instance.parse_desc(h)
|
283
|
+
assert_equal(expected, h)
|
284
|
+
end
|
285
|
+
|
286
|
+
def test_write
|
287
|
+
d = create_driver
|
288
|
+
|
289
|
+
service = Fluent::Plugin::EventService.new
|
290
|
+
|
291
|
+
d.run(expect_emits: 1) do
|
292
|
+
service.run
|
293
|
+
end
|
294
|
+
|
295
|
+
assert(d.events.length >= 1)
|
296
|
+
event = d.events.select {|e| e.last["EventID"] == "65500" }.last
|
297
|
+
record = event.last
|
298
|
+
|
299
|
+
assert_equal("Application", record["Channel"])
|
300
|
+
assert_equal("65500", record["EventID"])
|
301
|
+
assert_equal("4", record["Level"])
|
302
|
+
assert_equal("fluent-plugins", record["ProviderName"])
|
303
|
+
end
|
304
|
+
|
305
|
+
CONFIG_WITH_NON_EXISTENT_CHANNEL = config_element("ROOT", "", {
|
306
|
+
"channels" => ["application", "NonExistentChannel"]
|
307
|
+
})
|
308
|
+
def test_skip_non_existent_channel
|
309
|
+
d = create_driver(CONFIG + CONFIG_WITH_NON_EXISTENT_CHANNEL)
|
310
|
+
|
311
|
+
service = Fluent::Plugin::EventService.new
|
312
|
+
|
313
|
+
assert_nothing_raised do
|
314
|
+
d.run(expect_emits: 1) do
|
315
|
+
service.run
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
assert(d.events.length >= 1)
|
320
|
+
assert(d.logs.any?{|log| log.include?("[warn]: Channel Not Found: nonexistentchannel") },
|
321
|
+
d.logs.join("\n"))
|
322
|
+
end
|
323
|
+
|
324
|
+
CONFIG_WITH_QUERY = config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
325
|
+
"event_query" => "Event/System[EventID=65500]"}, [
|
326
|
+
config_element("storage", "", {
|
327
|
+
'@type' => 'local',
|
328
|
+
'persistent' => false
|
329
|
+
})
|
330
|
+
])
|
331
|
+
def test_write_with_event_query
|
332
|
+
d = create_driver(CONFIG_WITH_QUERY)
|
333
|
+
|
334
|
+
service = Fluent::Plugin::EventService.new
|
335
|
+
|
336
|
+
d.run(expect_emits: 1) do
|
337
|
+
service.run
|
338
|
+
end
|
339
|
+
|
340
|
+
assert(d.events.length >= 1)
|
341
|
+
event = d.events.last
|
342
|
+
record = event.last
|
343
|
+
|
344
|
+
assert_equal("Application", record["Channel"])
|
345
|
+
assert_equal("65500", record["EventID"])
|
346
|
+
assert_equal("4", record["Level"])
|
347
|
+
assert_equal("fluent-plugins", record["ProviderName"])
|
348
|
+
end
|
349
|
+
|
350
|
+
|
351
|
+
CONFIG_KEYS = config_element("ROOT", "", {
|
352
|
+
"tag" => "fluent.eventlog",
|
353
|
+
"keys" => ["EventID", "Level", "Channel", "ProviderName"]
|
354
|
+
}, [
|
355
|
+
config_element("storage", "", {
|
356
|
+
'@type' => 'local',
|
357
|
+
'persistent' => false
|
358
|
+
})
|
359
|
+
])
|
360
|
+
def test_write_with_keys
|
361
|
+
d = create_driver(CONFIG_KEYS)
|
362
|
+
|
363
|
+
service = Fluent::Plugin::EventService.new
|
364
|
+
|
365
|
+
d.run(expect_emits: 1) do
|
366
|
+
service.run
|
367
|
+
end
|
368
|
+
|
369
|
+
assert(d.events.length >= 1)
|
370
|
+
event = d.events.select {|e| e.last["EventID"] == "65500" }.last
|
371
|
+
record = event.last
|
372
|
+
|
373
|
+
expected = {"EventID" => "65500",
|
374
|
+
"Level" => "4",
|
375
|
+
"Channel" => "Application",
|
376
|
+
"ProviderName" => "fluent-plugins"}
|
377
|
+
|
378
|
+
assert_equal(expected, record)
|
379
|
+
end
|
380
|
+
|
381
|
+
REMOTING_ACCESS_CONFIG = config_element("ROOT", "", {"tag" => "fluent.eventlog"}, [
|
382
|
+
config_element("storage", "", {
|
383
|
+
'@type' => 'local',
|
384
|
+
'persistent' => false
|
385
|
+
}),
|
386
|
+
config_element("subscribe", "", {
|
387
|
+
'channels' => ['Application'],
|
388
|
+
'remote_server' => '127.0.0.1',
|
389
|
+
}),
|
390
|
+
])
|
391
|
+
|
392
|
+
def test_write_with_remoting_access
|
393
|
+
d = create_driver(REMOTING_ACCESS_CONFIG)
|
394
|
+
|
395
|
+
service = Fluent::Plugin::EventService.new
|
396
|
+
|
397
|
+
d.run(expect_emits: 1) do
|
398
|
+
service.run
|
399
|
+
end
|
400
|
+
|
401
|
+
assert(d.events.length >= 1)
|
402
|
+
event = d.events.select {|e| e.last["EventID"] == "65500" }.last
|
403
|
+
record = event.last
|
404
|
+
|
405
|
+
assert_equal("Application", record["Channel"])
|
406
|
+
assert_equal("65500", record["EventID"])
|
407
|
+
assert_equal("4", record["Level"])
|
408
|
+
assert_equal("fluent-plugins", record["ProviderName"])
|
409
|
+
end
|
410
|
+
|
411
|
+
class HashRendered < self
|
412
|
+
def test_write
|
413
|
+
d = create_driver(config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
414
|
+
"render_as_xml" => false}, [
|
415
|
+
config_element("storage", "", {
|
416
|
+
'@type' => 'local',
|
417
|
+
'persistent' => false
|
418
|
+
})
|
419
|
+
]))
|
420
|
+
|
421
|
+
service = Fluent::Plugin::EventService.new
|
422
|
+
|
423
|
+
d.run(expect_emits: 1) do
|
424
|
+
service.run
|
425
|
+
end
|
426
|
+
|
427
|
+
assert(d.events.length >= 1)
|
428
|
+
event = d.events.select {|e| e.last["EventID"] == "65500" }.last
|
429
|
+
record = event.last
|
430
|
+
|
431
|
+
assert_false(d.instance.render_as_xml)
|
432
|
+
assert_equal("Application", record["Channel"])
|
433
|
+
assert_equal("65500", record["EventID"])
|
434
|
+
assert_equal("4", record["Level"])
|
435
|
+
assert_equal("fluent-plugins", record["ProviderName"])
|
436
|
+
end
|
437
|
+
|
438
|
+
def test_write_with_preserving_qualifiers
|
439
|
+
require 'winevt'
|
440
|
+
|
441
|
+
d = create_driver(config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
442
|
+
"render_as_xml" => false,
|
443
|
+
'preserve_qualifiers_on_hash' => true
|
444
|
+
}, [
|
445
|
+
config_element("storage", "", {
|
446
|
+
'@type' => 'local',
|
447
|
+
'persistent' => false
|
448
|
+
}),
|
449
|
+
]))
|
450
|
+
|
451
|
+
service = Fluent::Plugin::EventService.new
|
452
|
+
subscribe = Winevt::EventLog::Subscribe.new
|
453
|
+
|
454
|
+
omit "@parser.preserve_qualifiers does not respond" unless subscribe.respond_to?(:preserve_qualifiers?)
|
455
|
+
|
456
|
+
d.run(expect_emits: 1) do
|
457
|
+
service.run
|
458
|
+
end
|
459
|
+
|
460
|
+
assert(d.events.length >= 1)
|
461
|
+
event = d.events.last
|
462
|
+
record = event.last
|
463
|
+
|
464
|
+
assert_true(record.has_key?("Description"))
|
465
|
+
assert_true(record.has_key?("EventData"))
|
466
|
+
assert_true(record.has_key?("Qualifiers"))
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
class PersistBookMark < self
|
471
|
+
TEST_PLUGIN_STORAGE_PATH = File.join( File.dirname(File.dirname(__FILE__)), 'tmp', 'in_windows_eventlog2', 'store' )
|
472
|
+
CONFIG2 = config_element("ROOT", "", {"tag" => "fluent.eventlog"}, [
|
473
|
+
config_element("storage", "", {
|
474
|
+
'@type' => 'local',
|
475
|
+
'@id' => 'test-02',
|
476
|
+
'@log_level' => "info",
|
477
|
+
'path' => File.join(TEST_PLUGIN_STORAGE_PATH,
|
478
|
+
'json', 'test-02.json'),
|
479
|
+
'persistent' => true,
|
480
|
+
})
|
481
|
+
])
|
482
|
+
|
483
|
+
def setup
|
484
|
+
FileUtils.rm_rf(TEST_PLUGIN_STORAGE_PATH)
|
485
|
+
FileUtils.mkdir_p(File.join(TEST_PLUGIN_STORAGE_PATH, 'json'))
|
486
|
+
FileUtils.chmod_R(0755, File.join(TEST_PLUGIN_STORAGE_PATH, 'json'))
|
487
|
+
end
|
488
|
+
|
489
|
+
def test_write
|
490
|
+
d = create_driver(CONFIG2)
|
491
|
+
|
492
|
+
assert !File.exist?(File.join(TEST_PLUGIN_STORAGE_PATH, 'json', 'test-02.json'))
|
493
|
+
|
494
|
+
service = Fluent::Plugin::EventService.new
|
495
|
+
|
496
|
+
d.run(expect_emits: 1) do
|
497
|
+
service.run
|
498
|
+
end
|
499
|
+
|
500
|
+
assert(d.events.length >= 1)
|
501
|
+
event = d.events.select {|e| e.last["EventID"] == "65500" }.last
|
502
|
+
record = event.last
|
503
|
+
|
504
|
+
prev_id = record["EventRecordID"].to_i
|
505
|
+
assert_equal("Application", record["Channel"])
|
506
|
+
assert_equal("65500", record["EventID"])
|
507
|
+
assert_equal("4", record["Level"])
|
508
|
+
assert_equal("fluent-plugins", record["ProviderName"])
|
509
|
+
|
510
|
+
assert File.exist?(File.join(TEST_PLUGIN_STORAGE_PATH, 'json', 'test-02.json'))
|
511
|
+
|
512
|
+
d2 = create_driver(CONFIG2)
|
513
|
+
d2.run(expect_emits: 1) do
|
514
|
+
service.run
|
515
|
+
end
|
516
|
+
|
517
|
+
events = d2.events.select {|e| e.last["EventID"] == "65500" }
|
518
|
+
assert(events.length == 1) # should be tailing after previous context.
|
519
|
+
event2 = events.last
|
520
|
+
record2 = event2.last
|
521
|
+
|
522
|
+
curr_id = record2["EventRecordID"].to_i
|
523
|
+
assert(curr_id > prev_id)
|
524
|
+
|
525
|
+
assert File.exist?(File.join(TEST_PLUGIN_STORAGE_PATH, 'json', 'test-02.json'))
|
526
|
+
end
|
527
|
+
|
528
|
+
def test_start_with_invalid_bookmark
|
529
|
+
invalid_storage_contents = <<-EOS
|
530
|
+
<BookmarkList>\r\n <Bookmark Channel='Application' RecordId='20063' IsCurrent='true'/>\r\n
|
531
|
+
EOS
|
532
|
+
d = create_driver(CONFIG2)
|
533
|
+
storage = d.instance.instance_variable_get(:@bookmarks_storage)
|
534
|
+
storage.put('application', invalid_storage_contents)
|
535
|
+
assert File.exist?(File.join(TEST_PLUGIN_STORAGE_PATH, 'json', 'test-02.json'))
|
536
|
+
|
537
|
+
d2 = create_driver(CONFIG2)
|
538
|
+
assert_raise(Fluent::ConfigError) do
|
539
|
+
d2.instance.start
|
540
|
+
end
|
541
|
+
assert_equal 0, d2.logs.grep(/This stored bookmark is incomplete for using. Referring `read_existing_events` parameter to subscribe:/).length
|
542
|
+
end
|
543
|
+
|
544
|
+
def test_start_with_empty_bookmark
|
545
|
+
invalid_storage_contents = <<-EOS
|
546
|
+
<BookmarkList>\r\n</BookmarkList>
|
547
|
+
EOS
|
548
|
+
d = create_driver(CONFIG2)
|
549
|
+
storage = d.instance.instance_variable_get(:@bookmarks_storage)
|
550
|
+
storage.put('application', invalid_storage_contents)
|
551
|
+
assert File.exist?(File.join(TEST_PLUGIN_STORAGE_PATH, 'json', 'test-02.json'))
|
552
|
+
|
553
|
+
d2 = create_driver(CONFIG2)
|
554
|
+
d2.instance.start
|
555
|
+
assert_equal 1, d2.logs.grep(/This stored bookmark is incomplete for using. Referring `read_existing_events` parameter to subscribe:/).length
|
556
|
+
end
|
557
|
+
end
|
558
|
+
|
559
|
+
def test_write_with_none_parser
|
560
|
+
d = create_driver(config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
561
|
+
"render_as_xml" => true}, [
|
562
|
+
config_element("storage", "", {
|
563
|
+
'@type' => 'local',
|
564
|
+
'persistent' => false
|
565
|
+
}),
|
566
|
+
config_element("parse", "", {
|
567
|
+
'@type' => 'none',
|
568
|
+
}),
|
569
|
+
]))
|
570
|
+
|
571
|
+
service = Fluent::Plugin::EventService.new
|
572
|
+
|
573
|
+
d.run(expect_emits: 1) do
|
574
|
+
service.run
|
575
|
+
end
|
576
|
+
|
577
|
+
assert(d.events.length >= 1)
|
578
|
+
event = d.events.last
|
579
|
+
record = event.last
|
580
|
+
|
581
|
+
assert do
|
582
|
+
# record should be {message: <RAW XML EventLog>}.
|
583
|
+
record["message"]
|
584
|
+
end
|
585
|
+
|
586
|
+
assert_true(record.has_key?("Description"))
|
587
|
+
assert_true(record.has_key?("EventData"))
|
588
|
+
end
|
589
|
+
|
590
|
+
def test_write_with_winevt_xml_parser_without_qualifiers
|
591
|
+
d = create_driver(config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
592
|
+
"render_as_xml" => true}, [
|
593
|
+
config_element("storage", "", {
|
594
|
+
'@type' => 'local',
|
595
|
+
'persistent' => false
|
596
|
+
}),
|
597
|
+
config_element("parse", "", {
|
598
|
+
'@type' => 'winevt_xml',
|
599
|
+
'preserve_qualifiers' => false
|
600
|
+
}),
|
601
|
+
]))
|
602
|
+
|
603
|
+
service = Fluent::Plugin::EventService.new
|
604
|
+
|
605
|
+
omit "@parser.preserve_qualifiers does not respond" unless d.instance.instance_variable_get(:@parser).respond_to?(:preserve_qualifiers?)
|
606
|
+
|
607
|
+
d.run(expect_emits: 1) do
|
608
|
+
service.run
|
609
|
+
end
|
610
|
+
|
611
|
+
assert(d.events.length >= 1)
|
612
|
+
event = d.events.last
|
613
|
+
record = event.last
|
614
|
+
|
615
|
+
assert_true(record.has_key?("Description"))
|
616
|
+
assert_true(record.has_key?("EventData"))
|
617
|
+
assert_false(record.has_key?("Qualifiers"))
|
618
|
+
end
|
619
|
+
end
|