fluent-plugin-windows-eventlog 0.3.0 → 0.4.4
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/CHANGELOG.md +19 -0
- data/README.md +10 -4
- data/fluent-plugin-winevtlog.gemspec +3 -2
- data/lib/fluent/plugin/in_windows_eventlog.rb +8 -2
- data/lib/fluent/plugin/in_windows_eventlog2.rb +101 -28
- data/test/helper.rb +0 -2
- data/test/plugin/test_in_windows_eventlog2.rb +81 -2
- data/test/plugin/test_in_winevtlog.rb +1 -1
- metadata +18 -9
- data/lib/fluent/plugin/parser_winevt_xml.rb +0 -34
- data/test/data/eventlog.xml +0 -1
- data/test/plugin/test_parser_winevt_xml.rb +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6634a0ee22c7988e40ebe92ebd457996eb25cfdd926a09c557e497065f6dbeac
|
4
|
+
data.tar.gz: 8f3a1543db5dd4a2299c5675ccd81ee19e10b476b06e3f6b7685213e14247814
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c9450771f970e88ec85ec5a44f3156a93475aeef12a729ffafe87c863516939fa66c739791b20c6e5bff30ba72e5958f14701b0713d5dca747c1b7919dee72c
|
7
|
+
data.tar.gz: 4d44d036e961e7cd502932863eedeb3781f25507384737850f9a81eb70f4099b0d24d27f8cc0f7753d310f9c3702273fd914271efa398e102610a2084b90c06a
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
# Release v0.4.4 - 2019/11/07
|
2
|
+
* in_windows_eventlog: Improve error handling and logging when failed to open Windows Event Log.
|
3
|
+
|
4
|
+
# Release v0.4.3 - 2019/10/31
|
5
|
+
* in_windows_eventlog2: Handle privileges record on #parse_desc
|
6
|
+
* in_windows_eventlog2: Raise error when handling invalid bookmark xml
|
7
|
+
|
8
|
+
# Release v0.4.2 - 2019/10/16
|
9
|
+
* in_windows_eventlog2: Handle invalid data error from `Winevt::EventLog::Query::Error`
|
10
|
+
|
11
|
+
# Release v0.4.1 - 2019/10/11
|
12
|
+
* in_windows_eventlog2: Add a missing ProcessID record
|
13
|
+
|
14
|
+
# Release v0.4.0 - 2019/10/10
|
15
|
+
|
16
|
+
* in_windows_eventlog2: Add new `render_as_xml` parameter to switch rendering as XML or Ruby Hash object
|
17
|
+
* in_windows_eventlog2: Support rate limit with `rate_limit` option
|
18
|
+
* parser_winevt_xml: Separate `parser_winevt_xml` plugin to other repository and published as Fluentd parser plugin
|
19
|
+
|
1
20
|
# Release v0.3.0 - 2019/07/08
|
2
21
|
|
3
22
|
* Add new `in_windows_eventlog2` plugin. This plugin uses newer windows event logging API.
|
data/README.md
CHANGED
@@ -4,10 +4,10 @@
|
|
4
4
|
|
5
5
|
### fluentd Input plugin for the Windows Event Log
|
6
6
|
|
7
|
-
[Fluentd](
|
7
|
+
[Fluentd](https://www.fluentd.org/) plugin to read the Windows Event Log.
|
8
8
|
|
9
9
|
## Installation
|
10
|
-
gem install fluent-plugin-windows-eventlog
|
10
|
+
ridk exec gem install fluent-plugin-windows-eventlog
|
11
11
|
|
12
12
|
## Configuration
|
13
13
|
|
@@ -15,7 +15,7 @@
|
|
15
15
|
|
16
16
|
Check [in_windows_eventlog2](https://github.com/fluent/fluent-plugin-windows-eventlog#in_windows_eventlog2) first. `in_windows_eventlog` will be replaced with `in_windows_eventlog2`.
|
17
17
|
|
18
|
-
|
18
|
+
fluentd Input plugin for the Windows Event Log using old Windows Event Logging API
|
19
19
|
|
20
20
|
<source>
|
21
21
|
@type windows_eventlog
|
@@ -130,7 +130,7 @@ If your `description` doesn't follow this format, the parsed result is only `des
|
|
130
130
|
|
131
131
|
### in_windows_eventlog2
|
132
132
|
|
133
|
-
|
133
|
+
fluentd Input plugin for the Windows Event Log using newer Windows Event Logging API. This is successor to `in_windows_eventlog`. See also [this slide](https://www.slideshare.net/cosmo0920/fluentd-meetup-2019) for the details of `in_windows_eventlog2` plugin.
|
134
134
|
|
135
135
|
<source>
|
136
136
|
@type windows_eventlog2
|
@@ -138,6 +138,8 @@ If your `description` doesn't follow this format, the parsed result is only `des
|
|
138
138
|
channels application,system
|
139
139
|
read_interval 2
|
140
140
|
tag winevt.raw
|
141
|
+
render_as_xml false # default is true.
|
142
|
+
rate_limit 200 # default is -1(Winevt::EventLog::Subscribe::RATE_INFINITE).
|
141
143
|
<storage>
|
142
144
|
@type local # @type local is the default.
|
143
145
|
persistent true # default is true. Set to false to use in-memory storage.
|
@@ -153,6 +155,10 @@ If your `description` doesn't follow this format, the parsed result is only `des
|
|
153
155
|
|
154
156
|
**NOTE:** When `Description` contains error message such as `The message resource is present but the message was not found in the message table.`, eventlog's resource file (.mui) related to error generating event is something wrong. This issue is also occurred in built-in Windows Event Viewer which is the part of Windows management tool.
|
155
157
|
|
158
|
+
**NOTE:** When `render_as_xml` as `false`, the dependent winevt_c gem renders Windows EventLog as Ruby Hash object directly. This reduces bottleneck to consume EventLog. Specifying `render_as_xml` as `false` should be faster consuming than `render_as_xml` as `true` case.
|
159
|
+
|
160
|
+
**NOTE:** If you encountered CPU spike due to massively huge EventLog channel, `rate_limit` parameter may help you. Currently, this paramter can handle the multiples of 10 or -1(`Winevt::EventLog::Subscribe::RATE_INFINITE`).
|
161
|
+
|
156
162
|
#### parameters
|
157
163
|
|
158
164
|
|name | description |
|
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "fluent-plugin-windows-eventlog"
|
7
|
-
spec.version = "0.
|
7
|
+
spec.version = "0.4.4"
|
8
8
|
spec.authors = ["okahashi117", "Hiroshi Hatake", "Masahiro Nakagawa"]
|
9
9
|
spec.email = ["naruki_okahashi@jbat.co.jp", "cosmo0920.oucc@gmail.com", "repeatedly@gmail.com"]
|
10
10
|
spec.summary = %q{Fluentd Input plugin to read windows event log.}
|
@@ -22,6 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_development_dependency "test-unit", "~> 3.2.0"
|
23
23
|
spec.add_runtime_dependency "fluentd", [">= 0.14.12", "< 2"]
|
24
24
|
spec.add_runtime_dependency "win32-eventlog"
|
25
|
-
spec.add_runtime_dependency "winevt_c"
|
25
|
+
spec.add_runtime_dependency "winevt_c", ">= 0.6.1"
|
26
26
|
spec.add_runtime_dependency "nokogiri", "~> 1.10"
|
27
|
+
spec.add_runtime_dependency "fluent-plugin-parser-winevt_xml", ">= 0.1.2"
|
27
28
|
end
|
@@ -151,7 +151,11 @@ module Fluent::Plugin
|
|
151
151
|
end
|
152
152
|
|
153
153
|
def on_notify(ch)
|
154
|
-
|
154
|
+
begin
|
155
|
+
el = Win32::EventLog.open(ch)
|
156
|
+
rescue => e
|
157
|
+
log.error "Failed to open Windows Event log.", error: e
|
158
|
+
end
|
155
159
|
|
156
160
|
current_oldest_record_number = el.oldest_record_number
|
157
161
|
current_total_records = el.total_records
|
@@ -186,7 +190,9 @@ module Fluent::Plugin
|
|
186
190
|
receive_lines(ch, winlogs)
|
187
191
|
@pos_storage.put(ch, [read_start, read_num + winlogs.size])
|
188
192
|
ensure
|
189
|
-
el
|
193
|
+
if el
|
194
|
+
el.close
|
195
|
+
end
|
190
196
|
end
|
191
197
|
|
192
198
|
GROUP_DELIMITER = "\r\n\r\n".freeze
|
@@ -21,6 +21,7 @@ module Fluent::Plugin
|
|
21
21
|
"EventRecordID" => ["EventRecordID", :string],
|
22
22
|
"ActivityID" => ["ActivityID", :string],
|
23
23
|
"RelatedActivityID" => ["RelatedActivityID", :string],
|
24
|
+
"ProcessID" => ["ProcessID", :string],
|
24
25
|
"ThreadID" => ["ThreadID", :string],
|
25
26
|
"Channel" => ["Channel", :string],
|
26
27
|
"Computer" => ["Computer", :string],
|
@@ -35,6 +36,8 @@ module Fluent::Plugin
|
|
35
36
|
config_param :keys, :array, default: []
|
36
37
|
config_param :read_from_head, :bool, default: false
|
37
38
|
config_param :parse_description, :bool, default: false
|
39
|
+
config_param :render_as_xml, :bool, default: true
|
40
|
+
config_param :rate_limit, :integer, default: Winevt::EventLog::Subscribe::RATE_INFINITE
|
38
41
|
|
39
42
|
config_section :storage do
|
40
43
|
config_set_default :usage, "bookmarks"
|
@@ -60,12 +63,24 @@ module Fluent::Plugin
|
|
60
63
|
if @keynames.empty?
|
61
64
|
@keynames = KEY_MAP.keys
|
62
65
|
end
|
66
|
+
@keynames.delete('Qualifiers') unless @render_as_xml
|
63
67
|
@keynames.delete('EventData') if @parse_description
|
64
68
|
|
65
69
|
@tag = tag
|
66
70
|
@tailing = @read_from_head ? false : true
|
67
71
|
@bookmarks_storage = storage_create(usage: "bookmarks")
|
68
|
-
@
|
72
|
+
@winevt_xml = false
|
73
|
+
if @render_as_xml
|
74
|
+
@parser = parser_create
|
75
|
+
@winevt_xml = @parser.respond_to?(:winevt_xml?) && @parser.winevt_xml?
|
76
|
+
class << self
|
77
|
+
alias_method :on_notify, :on_notify_xml
|
78
|
+
end
|
79
|
+
else
|
80
|
+
class << self
|
81
|
+
alias_method :on_notify, :on_notify_hash
|
82
|
+
end
|
83
|
+
end
|
69
84
|
end
|
70
85
|
|
71
86
|
def start
|
@@ -74,9 +89,19 @@ module Fluent::Plugin
|
|
74
89
|
@chs.each do |ch|
|
75
90
|
bookmarkXml = @bookmarks_storage.get(ch) || ""
|
76
91
|
subscribe = Winevt::EventLog::Subscribe.new
|
77
|
-
bookmark =
|
92
|
+
bookmark = unless bookmarkXml.empty?
|
93
|
+
Winevt::EventLog::Bookmark.new(bookmarkXml)
|
94
|
+
else
|
95
|
+
nil
|
96
|
+
end
|
78
97
|
subscribe.tail = @tailing
|
79
|
-
|
98
|
+
begin
|
99
|
+
subscribe.subscribe(ch, "*", bookmark)
|
100
|
+
rescue Winevt::EventLog::Query::Error => e
|
101
|
+
raise Fluent::ConfigError, "Invalid Bookmark XML is loaded. #{e}"
|
102
|
+
end
|
103
|
+
subscribe.render_as_xml = @render_as_xml
|
104
|
+
subscribe.rate_limit = @rate_limit
|
80
105
|
timer_execute("in_windows_eventlog_#{escape_channel(ch)}".to_sym, @read_interval) do
|
81
106
|
on_notify(ch, subscribe)
|
82
107
|
end
|
@@ -88,34 +113,75 @@ module Fluent::Plugin
|
|
88
113
|
end
|
89
114
|
|
90
115
|
def on_notify(ch, subscribe)
|
116
|
+
# for safety.
|
117
|
+
end
|
118
|
+
|
119
|
+
def on_notify_xml(ch, subscribe)
|
91
120
|
es = Fluent::MultiEventStream.new
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
121
|
+
begin
|
122
|
+
subscribe.each do |xml, message, string_inserts|
|
123
|
+
@parser.parse(xml) do |time, record|
|
124
|
+
# record.has_key?("EventData") for none parser checking.
|
125
|
+
if @winevt_xml
|
126
|
+
record["Description"] = message
|
127
|
+
record["EventData"] = string_inserts
|
128
|
+
|
129
|
+
h = {}
|
130
|
+
@keynames.each do |k|
|
131
|
+
type = KEY_MAP[k][1]
|
132
|
+
value = record[KEY_MAP[k][0]]
|
133
|
+
h[k]=case type
|
134
|
+
when :string
|
135
|
+
value.to_s
|
136
|
+
when :array
|
137
|
+
value.map {|v| v.to_s}
|
138
|
+
else
|
139
|
+
raise "Unknown value type: #{type}"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
parse_desc(h) if @parse_description
|
143
|
+
es.add(Fluent::Engine.now, h)
|
144
|
+
else
|
145
|
+
record["Description"] = message
|
146
|
+
record["EventData"] = string_inserts
|
147
|
+
# for none parser
|
148
|
+
es.add(Fluent::Engine.now, record)
|
111
149
|
end
|
112
|
-
parse_desc(h) if @parse_description
|
113
|
-
es.add(Fluent::Engine.now, h)
|
114
|
-
else
|
115
|
-
# for none parser
|
116
|
-
es.add(Fluent::Engine.now, record)
|
117
150
|
end
|
118
151
|
end
|
152
|
+
rescue Winevt::EventLog::Query::Error => e
|
153
|
+
log.warn "Invalid XML data", error: e
|
154
|
+
log.warn_backtrace
|
155
|
+
end
|
156
|
+
router.emit_stream(@tag, es)
|
157
|
+
@bookmarks_storage.put(ch, subscribe.bookmark)
|
158
|
+
end
|
159
|
+
|
160
|
+
def on_notify_hash(ch, subscribe)
|
161
|
+
es = Fluent::MultiEventStream.new
|
162
|
+
begin
|
163
|
+
subscribe.each do |record, message, string_inserts|
|
164
|
+
record["Description"] = message
|
165
|
+
record["EventData"] = string_inserts
|
166
|
+
h = {}
|
167
|
+
@keynames.each do |k|
|
168
|
+
type = KEY_MAP[k][1]
|
169
|
+
value = record[KEY_MAP[k][0]]
|
170
|
+
h[k]=case type
|
171
|
+
when :string
|
172
|
+
value.to_s
|
173
|
+
when :array
|
174
|
+
value.map {|v| v.to_s}
|
175
|
+
else
|
176
|
+
raise "Unknown value type: #{type}"
|
177
|
+
end
|
178
|
+
end
|
179
|
+
parse_desc(h) if @parse_description
|
180
|
+
es.add(Fluent::Engine.now, h)
|
181
|
+
end
|
182
|
+
rescue Winevt::EventLog::Query::Error => e
|
183
|
+
log.warn "Invalid Hash data", error: e
|
184
|
+
log.warn_backtrace
|
119
185
|
end
|
120
186
|
router.emit_stream(@tag, es)
|
121
187
|
@bookmarks_storage.put(ch, subscribe.bookmark)
|
@@ -134,6 +200,7 @@ module Fluent::Plugin
|
|
134
200
|
|
135
201
|
elems = desc.split(GROUP_DELIMITER)
|
136
202
|
record['DescriptionTitle'] = elems.shift
|
203
|
+
previous_key = nil
|
137
204
|
elems.each { |elem|
|
138
205
|
parent_key = nil
|
139
206
|
elem.split(RECORD_DELIMITER).each { |r|
|
@@ -148,13 +215,19 @@ module Fluent::Plugin
|
|
148
215
|
else
|
149
216
|
# parsed value sometimes contain unexpected "\t". So remove it.
|
150
217
|
value.strip!
|
151
|
-
|
218
|
+
# merge empty key values into the previous non-empty key record.
|
219
|
+
if key.empty?
|
220
|
+
record[previous_key] = [record[previous_key], value].flatten
|
221
|
+
elsif parent_key.nil?
|
152
222
|
record[to_key(key)] = value
|
153
223
|
else
|
154
224
|
k = "#{parent_key}.#{to_key(key)}"
|
155
225
|
record[k] = value
|
156
226
|
end
|
157
227
|
end
|
228
|
+
# XXX: This is for empty privileges record key.
|
229
|
+
# We should investigate whether an another case exists or not.
|
230
|
+
previous_key = to_key(key) unless key.empty?
|
158
231
|
}
|
159
232
|
}
|
160
233
|
end
|
data/test/helper.rb
CHANGED
@@ -23,10 +23,8 @@ unless ENV.has_key?('VERBOSE')
|
|
23
23
|
end
|
24
24
|
|
25
25
|
require 'fluent/test/driver/input'
|
26
|
-
require 'fluent/test/driver/parser'
|
27
26
|
require 'fluent/plugin/in_windows_eventlog'
|
28
27
|
require 'fluent/plugin/in_windows_eventlog2'
|
29
|
-
require 'fluent/plugin/parser_winevt_xml'
|
30
28
|
|
31
29
|
class Test::Unit::TestCase
|
32
30
|
end
|
@@ -25,6 +25,7 @@ class WindowsEventLog2InputTest < Test::Unit::TestCase
|
|
25
25
|
assert_equal 2, d.instance.read_interval
|
26
26
|
assert_equal ['application'], d.instance.channels
|
27
27
|
assert_false d.instance.read_from_head
|
28
|
+
assert_true d.instance.render_as_xml
|
28
29
|
end
|
29
30
|
|
30
31
|
def test_parse_desc
|
@@ -47,6 +48,38 @@ DESC
|
|
47
48
|
assert_equal(expected, h)
|
48
49
|
end
|
49
50
|
|
51
|
+
def test_parse_privileges_description
|
52
|
+
d = create_driver
|
53
|
+
desc = ["Special privileges assigned to new logon.\r\n\r\nSubject:\r\n\tSecurity ID:\t\tS-X-Y-ZZ\r\n\t",
|
54
|
+
"AccountName:\t\tSYSTEM\r\n\tAccount Domain:\t\tNT AUTHORITY\r\n\tLogon ID:\t\t0x3E7\r\n\r\n",
|
55
|
+
"Privileges:\t\tSeAssignPrimaryTokenPrivilege\r\n\t\t\tSeTcbPrivilege\r\n\t\t\t",
|
56
|
+
"SeSecurityPrivilege\r\n\t\t\tSeTakeOwnershipPrivilege\r\n\t\t\tSeLoadDriverPrivilege\r\n\t\t\t",
|
57
|
+
"SeBackupPrivilege\r\n\t\t\tSeRestorePrivilege\r\n\t\t\tSeDebugPrivilege\r\n\t\t\t",
|
58
|
+
"SeAuditPrivilege\r\n\t\t\tSeSystemEnvironmentPrivilege\r\n\t\t\tSeImpersonatePrivilege\r\n\t\t\t",
|
59
|
+
"SeDelegateSessionUserImpersonatePrivilege"].join("")
|
60
|
+
|
61
|
+
h = {"Description" => desc}
|
62
|
+
expected = {"DescriptionTitle" => "Special privileges assigned to new logon.",
|
63
|
+
"subject.security_id" => "S-X-Y-ZZ",
|
64
|
+
"subject.accountname" => "SYSTEM",
|
65
|
+
"subject.account_domain" => "NT AUTHORITY",
|
66
|
+
"subject.logon_id" => "0x3E7",
|
67
|
+
"privileges" => ["SeAssignPrimaryTokenPrivilege",
|
68
|
+
"SeTcbPrivilege",
|
69
|
+
"SeSecurityPrivilege",
|
70
|
+
"SeTakeOwnershipPrivilege",
|
71
|
+
"SeLoadDriverPrivilege",
|
72
|
+
"SeBackupPrivilege",
|
73
|
+
"SeRestorePrivilege",
|
74
|
+
"SeDebugPrivilege",
|
75
|
+
"SeAuditPrivilege",
|
76
|
+
"SeSystemEnvironmentPrivilege",
|
77
|
+
"SeImpersonatePrivilege",
|
78
|
+
"SeDelegateSessionUserImpersonatePrivilege"]}
|
79
|
+
d.instance.parse_desc(h)
|
80
|
+
assert_equal(expected, h)
|
81
|
+
end
|
82
|
+
|
50
83
|
def test_write
|
51
84
|
d = create_driver
|
52
85
|
|
@@ -57,7 +90,7 @@ DESC
|
|
57
90
|
end
|
58
91
|
|
59
92
|
assert(d.events.length >= 1)
|
60
|
-
event = d.events.last
|
93
|
+
event = d.events.select {|e| e.last["EventID"] == "65500" }.last
|
61
94
|
record = event.last
|
62
95
|
|
63
96
|
assert_equal("Application", record["Channel"])
|
@@ -96,6 +129,34 @@ DESC
|
|
96
129
|
assert_equal(expected, record)
|
97
130
|
end
|
98
131
|
|
132
|
+
class HashRendered < self
|
133
|
+
def test_write
|
134
|
+
d = create_driver(config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
135
|
+
"render_as_xml" => false}, [
|
136
|
+
config_element("storage", "", {
|
137
|
+
'@type' => 'local',
|
138
|
+
'persistent' => false
|
139
|
+
})
|
140
|
+
]))
|
141
|
+
|
142
|
+
service = Fluent::Plugin::EventService.new
|
143
|
+
|
144
|
+
d.run(expect_emits: 1) do
|
145
|
+
service.run
|
146
|
+
end
|
147
|
+
|
148
|
+
assert(d.events.length >= 1)
|
149
|
+
event = d.events.select {|e| e.last["EventID"] == "65500" }.last
|
150
|
+
record = event.last
|
151
|
+
|
152
|
+
assert_false(d.instance.render_as_xml)
|
153
|
+
assert_equal("Application", record["Channel"])
|
154
|
+
assert_equal("65500", record["EventID"])
|
155
|
+
assert_equal("4", record["Level"])
|
156
|
+
assert_equal("fluent-plugins", record["ProviderName"])
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
99
160
|
class PersistBookMark < self
|
100
161
|
TEST_PLUGIN_STORAGE_PATH = File.join( File.dirname(File.dirname(__FILE__)), 'tmp', 'in_windows_eventlog2', 'store' )
|
101
162
|
CONFIG2 = config_element("ROOT", "", {"tag" => "fluent.eventlog"}, [
|
@@ -126,7 +187,7 @@ DESC
|
|
126
187
|
end
|
127
188
|
|
128
189
|
assert(d.events.length >= 1)
|
129
|
-
event = d.events.last
|
190
|
+
event = d.events.select {|e| e.last["EventID"] == "65500" }.last
|
130
191
|
record = event.last
|
131
192
|
|
132
193
|
prev_id = record["EventRecordID"].to_i
|
@@ -151,6 +212,21 @@ DESC
|
|
151
212
|
|
152
213
|
assert File.exist?(File.join(TEST_PLUGIN_STORAGE_PATH, 'json', 'test-02.json'))
|
153
214
|
end
|
215
|
+
|
216
|
+
def test_start_with_invalid_bookmark
|
217
|
+
invalid_storage_contents = <<-EOS
|
218
|
+
<BookmarkList>\r\n <Bookmark Channel='Application' RecordId='20063' IsCurrent='true'/>\r\n
|
219
|
+
EOS
|
220
|
+
d = create_driver(CONFIG2)
|
221
|
+
storage = d.instance.instance_variable_get(:@bookmarks_storage)
|
222
|
+
storage.put('application', invalid_storage_contents)
|
223
|
+
assert File.exist?(File.join(TEST_PLUGIN_STORAGE_PATH, 'json', 'test-02.json'))
|
224
|
+
|
225
|
+
d2 = create_driver(CONFIG2)
|
226
|
+
assert_raise(Fluent::ConfigError) do
|
227
|
+
d2.instance.start
|
228
|
+
end
|
229
|
+
end
|
154
230
|
end
|
155
231
|
|
156
232
|
def test_write_with_none_parser
|
@@ -178,5 +254,8 @@ DESC
|
|
178
254
|
# record should be {message: <RAW XML EventLog>}.
|
179
255
|
record["message"]
|
180
256
|
end
|
257
|
+
|
258
|
+
assert_true(record.has_key?("Description"))
|
259
|
+
assert_true(record.has_key?("EventData"))
|
181
260
|
end
|
182
261
|
end
|
@@ -38,7 +38,7 @@ class WindowsEventLogInputTest < Test::Unit::TestCase
|
|
38
38
|
end
|
39
39
|
|
40
40
|
assert(d.events.length >= 1)
|
41
|
-
event = d.events.last
|
41
|
+
event = d.events.select {|e| e.last["event_id"] == "65500" }.last
|
42
42
|
record = event.last
|
43
43
|
assert_equal("application", record["channel"])
|
44
44
|
assert_equal("65500", record["event_id"])
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-windows-eventlog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- okahashi117
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2019-07
|
13
|
+
date: 2019-11-07 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -94,14 +94,14 @@ dependencies:
|
|
94
94
|
requirements:
|
95
95
|
- - ">="
|
96
96
|
- !ruby/object:Gem::Version
|
97
|
-
version:
|
97
|
+
version: 0.6.1
|
98
98
|
type: :runtime
|
99
99
|
prerelease: false
|
100
100
|
version_requirements: !ruby/object:Gem::Requirement
|
101
101
|
requirements:
|
102
102
|
- - ">="
|
103
103
|
- !ruby/object:Gem::Version
|
104
|
-
version:
|
104
|
+
version: 0.6.1
|
105
105
|
- !ruby/object:Gem::Dependency
|
106
106
|
name: nokogiri
|
107
107
|
requirement: !ruby/object:Gem::Requirement
|
@@ -116,6 +116,20 @@ dependencies:
|
|
116
116
|
- - "~>"
|
117
117
|
- !ruby/object:Gem::Version
|
118
118
|
version: '1.10'
|
119
|
+
- !ruby/object:Gem::Dependency
|
120
|
+
name: fluent-plugin-parser-winevt_xml
|
121
|
+
requirement: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 0.1.2
|
126
|
+
type: :runtime
|
127
|
+
prerelease: false
|
128
|
+
version_requirements: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: 0.1.2
|
119
133
|
description: Fluentd Input plugin to read windows event log.
|
120
134
|
email:
|
121
135
|
- naruki_okahashi@jbat.co.jp
|
@@ -135,13 +149,10 @@ files:
|
|
135
149
|
- fluent-plugin-winevtlog.gemspec
|
136
150
|
- lib/fluent/plugin/in_windows_eventlog.rb
|
137
151
|
- lib/fluent/plugin/in_windows_eventlog2.rb
|
138
|
-
- lib/fluent/plugin/parser_winevt_xml.rb
|
139
|
-
- test/data/eventlog.xml
|
140
152
|
- test/generate-windows-event.rb
|
141
153
|
- test/helper.rb
|
142
154
|
- test/plugin/test_in_windows_eventlog2.rb
|
143
155
|
- test/plugin/test_in_winevtlog.rb
|
144
|
-
- test/plugin/test_parser_winevt_xml.rb
|
145
156
|
homepage: https://github.com/fluent/fluent-plugin-windows-eventlog
|
146
157
|
licenses:
|
147
158
|
- Apache-2.0
|
@@ -167,9 +178,7 @@ signing_key:
|
|
167
178
|
specification_version: 4
|
168
179
|
summary: Fluentd Input plugin to read windows event log.
|
169
180
|
test_files:
|
170
|
-
- test/data/eventlog.xml
|
171
181
|
- test/generate-windows-event.rb
|
172
182
|
- test/helper.rb
|
173
183
|
- test/plugin/test_in_windows_eventlog2.rb
|
174
184
|
- test/plugin/test_in_winevtlog.rb
|
175
|
-
- test/plugin/test_parser_winevt_xml.rb
|
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'fluent/plugin/parser'
|
2
|
-
require 'nokogiri'
|
3
|
-
|
4
|
-
module Fluent::Plugin
|
5
|
-
class WinevtXMLparser < Parser
|
6
|
-
Fluent::Plugin.register_parser('winevt_xml', self)
|
7
|
-
|
8
|
-
def parse(text)
|
9
|
-
record = {}
|
10
|
-
doc = Nokogiri::XML(text)
|
11
|
-
system_elem = doc/'Event'/'System'
|
12
|
-
record["ProviderName"] = (system_elem/"Provider").attribute("Name").text rescue nil
|
13
|
-
record["ProviderGUID"] = (system_elem/"Provider").attribute("Guid").text rescue nil
|
14
|
-
record["EventID"] = (system_elem/'EventID').text rescue nil
|
15
|
-
record["Qualifiers"] = (system_elem/'EventID').attribute("Qualifiers").text rescue nil
|
16
|
-
record["Level"] = (system_elem/'Level').text rescue nil
|
17
|
-
record["Task"] = (system_elem/'Task').text rescue nil
|
18
|
-
record["Opcode"] = (system_elem/'Opcode').text rescue nil
|
19
|
-
record["Keywords"] = (system_elem/'Keywords').text rescue nil
|
20
|
-
record["TimeCreated"] = (system_elem/'TimeCreated').attribute("SystemTime").text rescue nil
|
21
|
-
record["EventRecordID"] = (system_elem/'EventRecordID').text rescue nil
|
22
|
-
record["ActivityID"] = (system_elem/'ActivityID').text rescue nil
|
23
|
-
record["RelatedActivityID"] = (system_elem/'Correlation').attribute("ActivityID").text rescue nil
|
24
|
-
record["ThreadID"] = (system_elem/'Execution').attribute("ThreadID").text rescue nil
|
25
|
-
record["Channel"] = (system_elem/'Channel').text rescue nil
|
26
|
-
record["Computer"] = (system_elem/"Computer").text rescue nil
|
27
|
-
record["UserID"] = (system_elem/'Security').attribute("UserID").text rescue nil
|
28
|
-
record["Version"] = (system_elem/'Version').text rescue nil
|
29
|
-
record["EventData"] = [] # These parameters are processed in winevt_c.
|
30
|
-
time = @estimate_current_event ? Fluent::EventTime.now : nil
|
31
|
-
yield time, record
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
data/test/data/eventlog.xml
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System><Provider Name='Microsoft-Windows-Security-Auditing' Guid='{54849625-5478-4994-A5BA-3E3B0328C30D}'/><EventID>4624</EventID><Version>2</Version><Level>0</Level><Task>12544</Task><Opcode>0</Opcode><Keywords>0x8020000000000000</Keywords><TimeCreated SystemTime='2019-06-13T09:21:23.345889600Z'/><EventRecordID>80688</EventRecordID><Correlation ActivityID='{587F0743-1F71-0006-5007-7F58711FD501}'/><Execution ProcessID='912' ThreadID='24708'/><Channel>Security</Channel><Computer>Fluentd-Developing-Windows</Computer><Security/></System><EventData><Data Name='SubjectUserSid'>S-1-5-18</Data><Data Name='SubjectUserName'>Fluentd-Developing-Windows$</Data><Data Name='SubjectDomainName'>WORKGROUP</Data><Data Name='SubjectLogonId'>0x3e7</Data><Data Name='TargetUserSid'>S-1-5-18</Data><Data Name='TargetUserName'>SYSTEM</Data><Data Name='TargetDomainName'>NT AUTHORITY</Data><Data Name='TargetLogonId'>0x3e7</Data><Data Name='LogonType'>5</Data><Data Name='LogonProcessName'>Advapi </Data><Data Name='AuthenticationPackageName'>Negotiate</Data><Data Name='WorkstationName'>-</Data><Data Name='LogonGuid'>{00000000-0000-0000-0000-000000000000}</Data><Data Name='TransmittedServices'>-</Data><Data Name='LmPackageName'>-</Data><Data Name='KeyLength'>0</Data><Data Name='ProcessId'>0x344</Data><Data Name='ProcessName'>C:\Windows\System32\services.exe</Data><Data Name='IpAddress'>-</Data><Data Name='IpPort'>-</Data><Data Name='ImpersonationLevel'>%%1833</Data><Data Name='RestrictedAdminMode'>-</Data><Data Name='TargetOutboundUserName'>-</Data><Data Name='TargetOutboundDomainName'>-</Data><Data Name='VirtualAccount'>%%1843</Data><Data Name='TargetLinkedLogonId'>0x0</Data><Data Name='ElevatedToken'>%%1842</Data></EventData></Event>
|
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
require 'generate-windows-event'
|
3
|
-
|
4
|
-
class WinevtXMLparserTest < Test::Unit::TestCase
|
5
|
-
|
6
|
-
def setup
|
7
|
-
Fluent::Test.setup
|
8
|
-
end
|
9
|
-
|
10
|
-
CONFIG = %[]
|
11
|
-
XMLLOG = File.open(File.join(__dir__, "..", "data", "eventlog.xml") )
|
12
|
-
|
13
|
-
def create_driver(conf = CONFIG)
|
14
|
-
Fluent::Test::Driver::Parser.new(Fluent::Plugin::WinevtXMLparser).configure(conf)
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_parse
|
18
|
-
d = create_driver
|
19
|
-
xml = XMLLOG
|
20
|
-
expected = {"ProviderName" => "Microsoft-Windows-Security-Auditing",
|
21
|
-
"ProviderGUID" => "{54849625-5478-4994-A5BA-3E3B0328C30D}",
|
22
|
-
"EventID" => "4624",
|
23
|
-
"Qualifiers" => nil,
|
24
|
-
"Level" => "0",
|
25
|
-
"Task" => "12544",
|
26
|
-
"Opcode" => "0",
|
27
|
-
"Keywords" => "0x8020000000000000",
|
28
|
-
"TimeCreated" => "2019-06-13T09:21:23.345889600Z",
|
29
|
-
"EventRecordID" => "80688",
|
30
|
-
"ActivityID" => "",
|
31
|
-
"RelatedActivityID" => "{587F0743-1F71-0006-5007-7F58711FD501}",
|
32
|
-
"ThreadID" => "24708",
|
33
|
-
"Channel" => "Security",
|
34
|
-
"Computer" => "Fluentd-Developing-Windows",
|
35
|
-
"UserID" => nil,
|
36
|
-
"Version" => "2",
|
37
|
-
"EventData" => []}
|
38
|
-
d.instance.parse(xml) do |time, record|
|
39
|
-
assert_equal(expected, record)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|