fluent-plugin-windows-eventlog 0.4.0 → 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5ea9a134414a5572bf7d3c9dca355ea53d47d6a8701b6a631f0426bafa0de5c9
4
- data.tar.gz: 26d9fa562585f26fdbef294aa6f64a13e7749ed11915390d1822c5367656ccb7
3
+ metadata.gz: b22aa563236f503aa9b606c6848b223995eab6174cf5ab244ef9cf535afcb8c9
4
+ data.tar.gz: 90dfddd1015ff28d730d11168fe60466e6a9c69b9c436601fb25eff867c935b0
5
5
  SHA512:
6
- metadata.gz: e292b037dc58e418aa8b74b1fa8b19db22124c927876e4fbf2e59b457042e08944e912e37104891fdd93f841b306ea8d09d2b1bbf939dad2015f18e26c021a11
7
- data.tar.gz: 6d82ed5588b14f92bca8bdf42a8c9a085306ed23717e9b0f0fc6cdc994b376a00195469c51dcb9ddeb5a6a786fc7c5b96e24279037bc20bfa96f42477407851d
6
+ metadata.gz: 57f27df3303f3424057f4fce75d7a12c804cc7bd5ecc2c8cf9579512dd9dc29c944ebea038541bbdac508028c9da669a246ac754c572fac19e3028ecabefab8c
7
+ data.tar.gz: 78d02ada2bbc70fc91df533fdcd7f47a4d680707c06f1a26eaa014a2c57435c90d2e47c3d82b3c43d81229ffabc3e2f7791d397bf168d11911b20a8d4a451250
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ # Release v0.4.5 - 2020/01/28
2
+ * in_windows_eventlog2: Handle empty key case in parsing description method.
3
+
4
+ # Release v0.4.4 - 2019/11/07
5
+ * in_windows_eventlog: Improve error handling and logging when failed to open Windows Event Log.
6
+
7
+ # Release v0.4.3 - 2019/10/31
8
+ * in_windows_eventlog2: Handle privileges record on #parse_desc
9
+ * in_windows_eventlog2: Raise error when handling invalid bookmark xml
10
+
11
+ # Release v0.4.2 - 2019/10/16
12
+ * in_windows_eventlog2: Handle invalid data error from `Winevt::EventLog::Query::Error`
13
+
14
+ # Release v0.4.1 - 2019/10/11
15
+ * in_windows_eventlog2: Add a missing ProcessID record
16
+
1
17
  # Release v0.4.0 - 2019/10/10
2
18
 
3
19
  * in_windows_eventlog2: Add new `render_as_xml` parameter to switch rendering as XML or Ruby Hash object
@@ -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.4.0"
7
+ spec.version = "0.4.5"
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,7 +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", ">= 0.6.0"
25
+ spec.add_runtime_dependency "winevt_c", ">= 0.6.1"
26
26
  spec.add_runtime_dependency "nokogiri", "~> 1.10"
27
27
  spec.add_runtime_dependency "fluent-plugin-parser-winevt_xml", ">= 0.1.2"
28
28
  end
@@ -151,7 +151,11 @@ module Fluent::Plugin
151
151
  end
152
152
 
153
153
  def on_notify(ch)
154
- el = Win32::EventLog.open(ch)
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.close
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],
@@ -88,9 +89,17 @@ module Fluent::Plugin
88
89
  @chs.each do |ch|
89
90
  bookmarkXml = @bookmarks_storage.get(ch) || ""
90
91
  subscribe = Winevt::EventLog::Subscribe.new
91
- bookmark = Winevt::EventLog::Bookmark.new(bookmarkXml)
92
+ bookmark = unless bookmarkXml.empty?
93
+ Winevt::EventLog::Bookmark.new(bookmarkXml)
94
+ else
95
+ nil
96
+ end
92
97
  subscribe.tail = @tailing
93
- subscribe.subscribe(ch, "*", bookmark)
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
94
103
  subscribe.render_as_xml = @render_as_xml
95
104
  subscribe.rate_limit = @rate_limit
96
105
  timer_execute("in_windows_eventlog_#{escape_channel(ch)}".to_sym, @read_interval) do
@@ -109,35 +118,40 @@ module Fluent::Plugin
109
118
 
110
119
  def on_notify_xml(ch, subscribe)
111
120
  es = Fluent::MultiEventStream.new
112
- subscribe.each do |xml, message, string_inserts|
113
- @parser.parse(xml) do |time, record|
114
- # record.has_key?("EventData") for none parser checking.
115
- if @winevt_xml
116
- record["Description"] = message
117
- record["EventData"] = string_inserts
118
-
119
- h = {}
120
- @keynames.each do |k|
121
- type = KEY_MAP[k][1]
122
- value = record[KEY_MAP[k][0]]
123
- h[k]=case type
124
- when :string
125
- value.to_s
126
- when :array
127
- value.map {|v| v.to_s}
128
- else
129
- raise "Unknown value type: #{type}"
130
- end
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)
131
149
  end
132
- parse_desc(h) if @parse_description
133
- es.add(Fluent::Engine.now, h)
134
- else
135
- record["Description"] = message
136
- record["EventData"] = string_inserts
137
- # for none parser
138
- es.add(Fluent::Engine.now, record)
139
150
  end
140
151
  end
152
+ rescue Winevt::EventLog::Query::Error => e
153
+ log.warn "Invalid XML data", error: e
154
+ log.warn_backtrace
141
155
  end
142
156
  router.emit_stream(@tag, es)
143
157
  @bookmarks_storage.put(ch, subscribe.bookmark)
@@ -145,24 +159,29 @@ module Fluent::Plugin
145
159
 
146
160
  def on_notify_hash(ch, subscribe)
147
161
  es = Fluent::MultiEventStream.new
148
- subscribe.each do |record, message, string_inserts|
149
- record["Description"] = message
150
- record["EventData"] = string_inserts
151
- h = {}
152
- @keynames.each do |k|
153
- type = KEY_MAP[k][1]
154
- value = record[KEY_MAP[k][0]]
155
- h[k]=case type
156
- when :string
157
- value.to_s
158
- when :array
159
- value.map {|v| v.to_s}
160
- else
161
- raise "Unknown value type: #{type}"
162
- end
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)
163
181
  end
164
- parse_desc(h) if @parse_description
165
- es.add(Fluent::Engine.now, h)
182
+ rescue Winevt::EventLog::Query::Error => e
183
+ log.warn "Invalid Hash data", error: e
184
+ log.warn_backtrace
166
185
  end
167
186
  router.emit_stream(@tag, es)
168
187
  @bookmarks_storage.put(ch, subscribe.bookmark)
@@ -181,6 +200,7 @@ module Fluent::Plugin
181
200
 
182
201
  elems = desc.split(GROUP_DELIMITER)
183
202
  record['DescriptionTitle'] = elems.shift
203
+ previous_key = nil
184
204
  elems.each { |elem|
185
205
  parent_key = nil
186
206
  elem.split(RECORD_DELIMITER).each { |r|
@@ -189,19 +209,26 @@ module Fluent::Plugin
189
209
  else
190
210
  r.split(NONE_FIELD_DELIMITER)
191
211
  end
212
+ key = "" if key.nil?
192
213
  key.chop! # remove ':' from key
193
214
  if value.nil?
194
215
  parent_key = to_key(key)
195
216
  else
196
217
  # parsed value sometimes contain unexpected "\t". So remove it.
197
218
  value.strip!
198
- if parent_key.nil?
219
+ # merge empty key values into the previous non-empty key record.
220
+ if key.empty?
221
+ record[previous_key] = [record[previous_key], value].flatten.reject {|e| e.nil?}
222
+ elsif parent_key.nil?
199
223
  record[to_key(key)] = value
200
224
  else
201
225
  k = "#{parent_key}.#{to_key(key)}"
202
226
  record[k] = value
203
227
  end
204
228
  end
229
+ # XXX: This is for empty privileges record key.
230
+ # We should investigate whether an another case exists or not.
231
+ previous_key = to_key(key) unless key.empty?
205
232
  }
206
233
  }
207
234
  end
@@ -0,0 +1,27 @@
1
+ A new external device was recognized by the system.
2
+
3
+ Subject:
4
+ Security ID: SYSTEM
5
+ Account Name: IIZHU2016$
6
+ Account Domain: ITSS
7
+ Logon ID: 0x3E7
8
+
9
+ Device ID: SWD\PRINTENUM\{60FA1C6A-1AB2-440A-AEE1-62ABFB9A4650}
10
+
11
+ Device Name: Microsoft Print to PDF
12
+
13
+ Class ID: {1ed2bbf9-11f0-4084-b21f-ad83a8e6dcdc}
14
+
15
+ Class Name: PrintQueue
16
+
17
+ Vendor IDs:
18
+ PRINTENUM\{084f01fa-e634-4d77-83ee-074817c03581}
19
+ PRINTENUM\LocalPrintQueue
20
+ {084f01fa-e634-4d77-83ee-074817c03581}
21
+
22
+
23
+
24
+ Compatible IDs:
25
+ GenPrintQueue
26
+ SWD\GenericRaw
27
+ SWD\Generic
@@ -48,6 +48,63 @@ DESC
48
48
  assert_equal(expected, h)
49
49
  end
50
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
+
83
+ test "A new external device was recognized by the system." do
84
+ # using the event log example: eventopedia.cloudapp.net/EventDetails.aspx?id=17ef124e-eb89-4c01-9ba2-d761e06b2b68
85
+ d = create_driver
86
+ desc = nil
87
+ File.open('./test/data/eventid_6416', 'r') do |f|
88
+ desc = f.read.gsub(/\R/, "\r\n")
89
+ end
90
+ h = {"Description" => desc}
91
+ expected = {"DescriptionTitle" => "A new external device was recognized by the system.",
92
+ "class_id" => "{1ed2bbf9-11f0-4084-b21f-ad83a8e6dcdc}",
93
+ "class_name" => "PrintQueue",
94
+ "compatible_ids" => ["GenPrintQueue", "SWD\\GenericRaw", "SWD\\Generic"],
95
+ "device_id" => "SWD\\PRINTENUM\\{60FA1C6A-1AB2-440A-AEE1-62ABFB9A4650}",
96
+ "device_name" => "Microsoft Print to PDF",
97
+ "subject.account_domain" => "ITSS",
98
+ "subject.account_name" => "IIZHU2016$",
99
+ "subject.logon_id" => "0x3E7",
100
+ "subject.security_id" => "SYSTEM",
101
+ "vendor_ids" => ["PRINTENUM\\{084f01fa-e634-4d77-83ee-074817c03581}",
102
+ "PRINTENUM\\LocalPrintQueue",
103
+ "{084f01fa-e634-4d77-83ee-074817c03581}"]}
104
+ d.instance.parse_desc(h)
105
+ assert_equal(expected, h)
106
+ end
107
+
51
108
  def test_write
52
109
  d = create_driver
53
110
 
@@ -58,7 +115,7 @@ DESC
58
115
  end
59
116
 
60
117
  assert(d.events.length >= 1)
61
- event = d.events.last
118
+ event = d.events.select {|e| e.last["EventID"] == "65500" }.last
62
119
  record = event.last
63
120
 
64
121
  assert_equal("Application", record["Channel"])
@@ -114,7 +171,7 @@ DESC
114
171
  end
115
172
 
116
173
  assert(d.events.length >= 1)
117
- event = d.events.last
174
+ event = d.events.select {|e| e.last["EventID"] == "65500" }.last
118
175
  record = event.last
119
176
 
120
177
  assert_false(d.instance.render_as_xml)
@@ -155,7 +212,7 @@ DESC
155
212
  end
156
213
 
157
214
  assert(d.events.length >= 1)
158
- event = d.events.last
215
+ event = d.events.select {|e| e.last["EventID"] == "65500" }.last
159
216
  record = event.last
160
217
 
161
218
  prev_id = record["EventRecordID"].to_i
@@ -180,6 +237,21 @@ DESC
180
237
 
181
238
  assert File.exist?(File.join(TEST_PLUGIN_STORAGE_PATH, 'json', 'test-02.json'))
182
239
  end
240
+
241
+ def test_start_with_invalid_bookmark
242
+ invalid_storage_contents = <<-EOS
243
+ <BookmarkList>\r\n <Bookmark Channel='Application' RecordId='20063' IsCurrent='true'/>\r\n
244
+ EOS
245
+ d = create_driver(CONFIG2)
246
+ storage = d.instance.instance_variable_get(:@bookmarks_storage)
247
+ storage.put('application', invalid_storage_contents)
248
+ assert File.exist?(File.join(TEST_PLUGIN_STORAGE_PATH, 'json', 'test-02.json'))
249
+
250
+ d2 = create_driver(CONFIG2)
251
+ assert_raise(Fluent::ConfigError) do
252
+ d2.instance.start
253
+ end
254
+ end
183
255
  end
184
256
 
185
257
  def test_write_with_none_parser
@@ -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.0
4
+ version: 0.4.5
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-10-10 00:00:00.000000000 Z
13
+ date: 2020-01-28 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: 0.6.0
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: 0.6.0
104
+ version: 0.6.1
105
105
  - !ruby/object:Gem::Dependency
106
106
  name: nokogiri
107
107
  requirement: !ruby/object:Gem::Requirement
@@ -149,6 +149,7 @@ files:
149
149
  - fluent-plugin-winevtlog.gemspec
150
150
  - lib/fluent/plugin/in_windows_eventlog.rb
151
151
  - lib/fluent/plugin/in_windows_eventlog2.rb
152
+ - test/data/eventid_6416
152
153
  - test/generate-windows-event.rb
153
154
  - test/helper.rb
154
155
  - test/plugin/test_in_windows_eventlog2.rb
@@ -173,11 +174,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
173
174
  version: '0'
174
175
  requirements: []
175
176
  rubyforge_project:
176
- rubygems_version: 2.7.3
177
+ rubygems_version: 2.7.6.2
177
178
  signing_key:
178
179
  specification_version: 4
179
180
  summary: Fluentd Input plugin to read windows event log.
180
181
  test_files:
182
+ - test/data/eventid_6416
181
183
  - test/generate-windows-event.rb
182
184
  - test/helper.rb
183
185
  - test/plugin/test_in_windows_eventlog2.rb