fluent-plugin-windows-eventlog 0.6.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/unit-test.yml +34 -0
- data/CHANGELOG.md +13 -0
- data/README.md +48 -6
- data/fluent-plugin-winevtlog.gemspec +3 -3
- data/lib/fluent/plugin/in_windows_eventlog2.rb +117 -16
- data/test/plugin/test_in_windows_eventlog2.rb +147 -6
- metadata +11 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bdf1842ac573845b2a01c853ab4dd7afb349c0e014d5538c24aff33f0c674499
|
4
|
+
data.tar.gz: 92003b55f2e2380b3d9d8ebbc3ea794c018cd75b51100562f932ef7fcd751728
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4f8f6b2198d8a8861b1c25a85a7a553b4757db942c03a8246e36f7d1e9a5d085328668a6b55ac32de6cad0491285d2e3009e49606eee0da03c1d7c2fab0dab8
|
7
|
+
data.tar.gz: 474b65132114f707e358d62984becd02f750f7913b2f248ff21db8ac27c668835a6541fa7f8fd3df5a944e241c255e8bdbd607cc0d143d687222bd0e6412e2f7
|
@@ -0,0 +1,34 @@
|
|
1
|
+
name: Unit Test
|
2
|
+
on:
|
3
|
+
- push
|
4
|
+
- pull_request
|
5
|
+
jobs:
|
6
|
+
test:
|
7
|
+
runs-on: ${{ matrix.os }}
|
8
|
+
continue-on-error: ${{ matrix.experimental }}
|
9
|
+
strategy:
|
10
|
+
fail-fast: false
|
11
|
+
matrix:
|
12
|
+
ruby: [ '2.5', '2.6', '2.7', '3.0' ]
|
13
|
+
os:
|
14
|
+
- windows-latest
|
15
|
+
experimental: [false]
|
16
|
+
include:
|
17
|
+
- ruby: 'head'
|
18
|
+
os: windows-latest
|
19
|
+
experimental: true
|
20
|
+
name: Unit testing with Ruby ${{ matrix.ruby }} on ${{ matrix.os }}
|
21
|
+
steps:
|
22
|
+
- uses: actions/checkout@v2
|
23
|
+
- uses: ruby/setup-ruby@v1
|
24
|
+
with:
|
25
|
+
ruby-version: ${{ matrix.ruby }}
|
26
|
+
- name: Install
|
27
|
+
run: |
|
28
|
+
ruby --version
|
29
|
+
gem --version
|
30
|
+
gem install bundler rake
|
31
|
+
ridk exec bundle install --jobs 4 --retry 3
|
32
|
+
- name: Unit Test
|
33
|
+
run: |
|
34
|
+
bundle exec rake test
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
# Release v0.8.1 - 2021/09/16
|
2
|
+
* in_windows_eventlog2: Add trace logs for debugging
|
3
|
+
* in_windows_eventlog2: Support event query parameter on Windows EventLog channel subscriptions
|
4
|
+
|
5
|
+
# Release v0.8.0 - 2020/09/16
|
6
|
+
* in_windows_eventlog2: Support remoting access
|
7
|
+
|
8
|
+
# Release v.0.7.1.rc1 - 2020/06/23
|
9
|
+
* in_windows_eventlog2: Depends on nokogiri 1.11 series
|
10
|
+
|
11
|
+
# Release v0.7.0 - 2020/05/22
|
12
|
+
* in_windows_eventlog2: Support multilingual description
|
13
|
+
|
1
14
|
# Release v0.6.0 - 2020/04/15
|
2
15
|
* Make fluent-plugin-parser-winevt_xml plugin as optional dependency
|
3
16
|
* in_windows_eventlog2: Render Ruby hash object directly by default
|
data/README.md
CHANGED
@@ -142,23 +142,31 @@ fluentd Input plugin for the Windows Event Log using newer Windows Event Logging
|
|
142
142
|
render_as_xml false # default is false.
|
143
143
|
rate_limit 200 # default is -1(Winevt::EventLog::Subscribe::RATE_INFINITE).
|
144
144
|
# preserve_qualifiers_on_hash true # default is false.
|
145
|
+
# read_all_channels false # default is false.
|
146
|
+
# description_locale en_US # default is nil. It means that system locale is used for obtaining description.
|
147
|
+
# refresh_subscription_interval 10m # default is nil. It specifies refresh interval for channel subscriptions.
|
148
|
+
# event_query "Event/System[EventID!=1001]" # default is "*".
|
145
149
|
<storage>
|
146
150
|
@type local # @type local is the default.
|
147
151
|
persistent true # default is true. Set to false to use in-memory storage.
|
148
|
-
path ./tmp/storage.json # This is required when persistent is true.
|
152
|
+
path ./tmp/storage.json # This is required when persistent is true. If migrating from eventlog v1 please ensure that you remove the old .pos folder
|
149
153
|
# Or, please consider using <system> section's `root_dir` parameter.
|
150
154
|
</storage>
|
151
|
-
<parse>
|
152
|
-
|
155
|
+
# <parse> # Note: parsing is only available when render_as_xml true
|
156
|
+
# @type winevt_xml # @type winevt_xml is the default. winevt_xml and none parsers are supported for now.
|
153
157
|
# When set up it as true, this plugin preserves "Qualifiers" and "EventID" keys.
|
154
158
|
# When set up it as false, this plugin calculates actual "EventID" from "Qualifiers" and removing "Qualifiers".
|
155
159
|
# With the following equation:
|
156
160
|
# (EventID & 0xffff) | (Qualifiers & 0xffff) << 16
|
157
|
-
preserve_qualifiers true
|
158
|
-
</parse>
|
161
|
+
# preserve_qualifiers true # preserve_qualifiers_on_hash can be used as a setting outside <parse> if render_as_xml is false
|
162
|
+
# </parse>
|
159
163
|
# <subscribe>
|
160
164
|
# channles application, system
|
161
165
|
# read_existing_events false # read_existing_events should be applied each of subscribe directive(s)
|
166
|
+
# remote_server 127.0.0.1 # Remote server ip/fqdn
|
167
|
+
# remote_domain WORKGROUP # Domain name
|
168
|
+
# remote_username fluentd # Remoting access account name
|
169
|
+
# remote_password changeme! # Remoting access account password
|
162
170
|
# </subscribe>
|
163
171
|
</source>
|
164
172
|
|
@@ -174,7 +182,7 @@ fluentd Input plugin for the Windows Event Log using newer Windows Event Logging
|
|
174
182
|
|
175
183
|
|name | description |
|
176
184
|
|:----- |:----- |
|
177
|
-
|`channels` | (option) No default value just empty array, but 'application' is used as default due to backward compatibility. One or more of {'application', 'system', 'setup', 'security'}. If you want to read 'setup' or 'security' logs, you must launch fluentd with administrator privileges.|
|
185
|
+
|`channels` | (option) No default value just empty array, but 'application' is used as default due to backward compatibility. One or more of {'application', 'system', 'setup', 'security'} and other evtx, which is the brand new Windows XML Event Log (EVTX) format since Windows Vista, formatted channels. Theoritically, `in_windows_ventlog2` may read all of channels except for debug and analytical typed channels. If you want to read 'setup' or 'security' logs or some privileged channels, you must launch fluentd with administrator privileges.|
|
178
186
|
|`keys` | (option) A subset of [keys](#read-keys) to read. Defaults to all keys.|
|
179
187
|
|`read_interval` | (option) Read interval in seconds. 2 seconds as default.|
|
180
188
|
|`from_encoding` | (option) Input character encoding. `nil` as default.|
|
@@ -187,6 +195,9 @@ fluentd Input plugin for the Windows Event Log using newer Windows Event Logging
|
|
187
195
|
|`rate_limit` | (option) Specify rate limit to consume EventLog. Default is `Winevt::EventLog::Subscribe::RATE_INFINITE`.|
|
188
196
|
|`preserve_qualifiers_on_hash` | (option) When set up it as true, this plugin preserves "Qualifiers" and "EventID" keys. When set up it as false, this plugin calculates actual "EventID" from "Qualifiers" and removing "Qualifiers". Default is `false`.|
|
189
197
|
|`read_all_channels`| (option) Read from all channels. Default is `false`|
|
198
|
+
|`description_locale`| (option) Specify description locale. Default is `nil`. See also: [Supported locales](https://github.com/fluent-plugins-nursery/winevt_c#multilingual-description) |
|
199
|
+
|`refresh_subscription_interval`|(option) It specifies refresh interval for channel subscriptions. Default is `nil`.|
|
200
|
+
|`event_query`|(option) It specifies query for deny/allow/filter events with XPath 1.0 or structured XML query. Default is `"*"` (retrieving all events).|
|
190
201
|
|`<subscribe>` | Setting for subscribe channels. |
|
191
202
|
|
192
203
|
##### subscribe section
|
@@ -195,6 +206,10 @@ fluentd Input plugin for the Windows Event Log using newer Windows Event Logging
|
|
195
206
|
|:----- |:----- |
|
196
207
|
|`channels` | One or more of {'application', 'system', 'setup', 'security'}. If you want to read 'setup' or 'security' logs, you must launch fluentd with administrator privileges. |
|
197
208
|
|`read_existing_events` | (option) Read the entries which already exist before fluentd is started. Defaults to `false`. |
|
209
|
+
|`remote_server` | (option) Remoting access server ip address/fqdn. Defaults to `nil`. |
|
210
|
+
|`remote_domain` | (option) Remoting access server joining domain name. Defaults to `nil`. |
|
211
|
+
|`remote_username` | (option) Remoting access access account's username. Defaults to `nil`. |
|
212
|
+
|`remote_password` | (option) Remoting access access account's password. Defaults to `nil`. |
|
198
213
|
|
199
214
|
|
200
215
|
**Motivation:** subscribe directive is designed for applying `read_existing_events` each of channels which is specified in subscribe section(s).
|
@@ -231,6 +246,33 @@ This configuration can be handled as:
|
|
231
246
|
* "Application" and "Security" channels just tailing
|
232
247
|
* "HardwareEvent" channel read existing events before launching Fluentd
|
233
248
|
|
249
|
+
###### Remoting access
|
250
|
+
|
251
|
+
`<subscribe>` section supports remoting access parameters:
|
252
|
+
|
253
|
+
* `remote_server`
|
254
|
+
* `remote_domain`
|
255
|
+
* `remote_username`
|
256
|
+
* `remote_password`
|
257
|
+
|
258
|
+
These parameters are only in `<subscribe>` directive.
|
259
|
+
|
260
|
+
Note that before using this feature, remoting access users should belong to "Event Log Readers" group:
|
261
|
+
|
262
|
+
```console
|
263
|
+
> net localgroup "Event Log Readers" <domain\username> /add
|
264
|
+
```
|
265
|
+
|
266
|
+
And then, users also should set up their remote box's Firewall configuration:
|
267
|
+
|
268
|
+
```console
|
269
|
+
> netsh advfirewall firewall set rule group="Remote Event Log Management" new enable=yes
|
270
|
+
```
|
271
|
+
|
272
|
+
As a security best practices, remoting access account _should not be administrator account_.
|
273
|
+
|
274
|
+
For graphical instructions, please refer to [Preconfigure a Machine to Collect Remote Windows Events | Sumo Logic](https://help.sumologic.com/03Send-Data/Sources/01Sources-for-Installed-Collectors/Remote-Windows-Event-Log-Source/Preconfigure-a-Machine-to-Collect-Remote-Windows-Events) document for example.
|
275
|
+
|
234
276
|
##### Available keys
|
235
277
|
|
236
278
|
This plugin reads the following fields from Windows Event Log entries. Use the `keys` configuration option to select a subset. No other customization is allowed for now.
|
@@ -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.8.1"
|
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.}
|
@@ -19,10 +19,10 @@ Gem::Specification.new do |spec|
|
|
19
19
|
|
20
20
|
spec.add_development_dependency "bundler"
|
21
21
|
spec.add_development_dependency "rake"
|
22
|
-
spec.add_development_dependency "test-unit", "~> 3.
|
22
|
+
spec.add_development_dependency "test-unit", "~> 3.4.0"
|
23
23
|
spec.add_development_dependency "nokogiri", [">= 1.10", "< 1.12"]
|
24
24
|
spec.add_development_dependency "fluent-plugin-parser-winevt_xml", ">= 0.1.2"
|
25
25
|
spec.add_runtime_dependency "fluentd", [">= 0.14.12", "< 2"]
|
26
26
|
spec.add_runtime_dependency "win32-eventlog"
|
27
|
-
spec.add_runtime_dependency "winevt_c", ">= 0.
|
27
|
+
spec.add_runtime_dependency "winevt_c", ">= 0.9.1"
|
28
28
|
end
|
@@ -7,6 +7,8 @@ module Fluent::Plugin
|
|
7
7
|
class WindowsEventLog2Input < Input
|
8
8
|
Fluent::Plugin.register_input('windows_eventlog2', self)
|
9
9
|
|
10
|
+
class ReconnectError < Fluent::UnrecoverableError; end
|
11
|
+
|
10
12
|
helpers :timer, :storage, :parser
|
11
13
|
|
12
14
|
DEFAULT_STORAGE_TYPE = 'local'
|
@@ -42,10 +44,17 @@ module Fluent::Plugin
|
|
42
44
|
config_param :rate_limit, :integer, default: Winevt::EventLog::Subscribe::RATE_INFINITE
|
43
45
|
config_param :preserve_qualifiers_on_hash, :bool, default: false
|
44
46
|
config_param :read_all_channels, :bool, default: false
|
47
|
+
config_param :description_locale, :string, default: nil
|
48
|
+
config_param :refresh_subscription_interval, :time, default: nil
|
49
|
+
config_param :event_query, :string, default: "*"
|
45
50
|
|
46
51
|
config_section :subscribe, param_name: :subscribe_configs, required: false, multi: true do
|
47
52
|
config_param :channels, :array
|
48
53
|
config_param :read_existing_events, :bool, default: false
|
54
|
+
config_param :remote_server, :string, default: nil
|
55
|
+
config_param :remote_domain, :string, default: nil
|
56
|
+
config_param :remote_username, :string, default: nil
|
57
|
+
config_param :remote_password, :string, default: nil, secret: true
|
49
58
|
end
|
50
59
|
|
51
60
|
config_section :storage do
|
@@ -67,9 +76,12 @@ module Fluent::Plugin
|
|
67
76
|
|
68
77
|
def configure(conf)
|
69
78
|
super
|
79
|
+
@session = nil
|
70
80
|
@chs = []
|
81
|
+
@subscriptions = {}
|
71
82
|
@all_chs = Winevt::EventLog::Channel.new
|
72
83
|
@all_chs.force_enumerate = false
|
84
|
+
@timers = {}
|
73
85
|
|
74
86
|
if @read_all_channels
|
75
87
|
@all_chs.each do |ch|
|
@@ -80,14 +92,22 @@ module Fluent::Plugin
|
|
80
92
|
|
81
93
|
@read_existing_events = @read_from_head || @read_existing_events
|
82
94
|
if @channels.empty? && @subscribe_configs.empty? && !@read_all_channels
|
83
|
-
@chs.push(['application', @read_existing_events])
|
95
|
+
@chs.push(['application', @read_existing_events, nil])
|
84
96
|
else
|
85
97
|
@channels.map {|ch| ch.strip.downcase }.uniq.each do |uch|
|
86
|
-
@chs.push([uch, @read_existing_events])
|
98
|
+
@chs.push([uch, @read_existing_events, nil])
|
87
99
|
end
|
88
100
|
@subscribe_configs.each do |subscribe|
|
101
|
+
if subscribe.remote_server
|
102
|
+
@session = Winevt::EventLog::Session.new(subscribe.remote_server,
|
103
|
+
subscribe.remote_domain,
|
104
|
+
subscribe.remote_username,
|
105
|
+
subscribe.remote_password)
|
106
|
+
|
107
|
+
log.debug("connect to remote box (server: #{subscribe.remote_server}) domain: #{subscribe.remote_domain} username: #{subscribe.remote_username})")
|
108
|
+
end
|
89
109
|
subscribe.channels.map {|ch| ch.strip.downcase }.uniq.each do |uch|
|
90
|
-
@chs.push([uch, subscribe.read_existing_events])
|
110
|
+
@chs.push([uch, subscribe.read_existing_events, @session])
|
91
111
|
end
|
92
112
|
end
|
93
113
|
end
|
@@ -122,17 +142,87 @@ module Fluent::Plugin
|
|
122
142
|
@keynames.delete('Qualifiers')
|
123
143
|
end
|
124
144
|
@keynames.delete('EventData') if @parse_description
|
145
|
+
|
146
|
+
locale = Winevt::EventLog::Locale.new
|
147
|
+
if @description_locale && unsupported_locale?(locale, @description_locale)
|
148
|
+
raise Fluent::ConfigError, "'#{@description_locale}' is not supported. Supported locales are: #{locale.each.map{|code, _desc| code}.join(" ")}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def unsupported_locale?(locale, description_locale)
|
153
|
+
locale.each.select {|c, _d| c.downcase == description_locale.downcase}.empty?
|
125
154
|
end
|
126
155
|
|
127
156
|
def start
|
128
157
|
super
|
129
158
|
|
130
|
-
|
131
|
-
|
159
|
+
refresh_subscriptions
|
160
|
+
if @refresh_subscription_interval
|
161
|
+
timer_execute(:in_windows_eventlog_refresh_subscription_timer, @refresh_subscription_interval, &method(:refresh_subscriptions))
|
132
162
|
end
|
133
163
|
end
|
134
164
|
|
135
|
-
def
|
165
|
+
def shutdown
|
166
|
+
super
|
167
|
+
|
168
|
+
@subscriptions.keys.each do |ch|
|
169
|
+
subscription = @subscriptions.delete(ch)
|
170
|
+
if subscription
|
171
|
+
subscription.cancel
|
172
|
+
log.debug "channel (#{ch}) subscription is canceled."
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def retry_on_error(channel, times: 15)
|
178
|
+
try = 0
|
179
|
+
begin
|
180
|
+
log.debug "Retry to subscribe for #{channel}...." if try > 1
|
181
|
+
try += 1
|
182
|
+
yield
|
183
|
+
log.info "Retry to subscribe for #{channel} succeeded." if try > 1
|
184
|
+
try = 0
|
185
|
+
rescue Winevt::EventLog::Subscribe::RemoteHandlerError => e
|
186
|
+
raise ReconnectError, "Retrying limit is exceeded." if try > times
|
187
|
+
log.warn "#{e.message}. Remaining retry count(s): #{times - try}"
|
188
|
+
sleep 2**try
|
189
|
+
retry
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def refresh_subscriptions
|
194
|
+
clear_subscritpions
|
195
|
+
|
196
|
+
@chs.each do |ch, read_existing_events, session|
|
197
|
+
retry_on_error(ch) do
|
198
|
+
ch, subscribe = subscription(ch, read_existing_events, session)
|
199
|
+
@subscriptions[ch] = subscribe
|
200
|
+
end
|
201
|
+
end
|
202
|
+
subscribe_channels(@subscriptions)
|
203
|
+
end
|
204
|
+
|
205
|
+
def clear_subscritpions
|
206
|
+
@subscriptions.keys.each do |ch|
|
207
|
+
subscription = @subscriptions.delete(ch)
|
208
|
+
if subscription
|
209
|
+
if subscription.cancel
|
210
|
+
log.debug "channel (#{ch}) subscription is cancelled."
|
211
|
+
subscription.close
|
212
|
+
log.debug "channel (#{ch}) subscription handles are closed forcibly."
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
@timers.keys.each do |ch|
|
217
|
+
timer = @timers.delete(ch)
|
218
|
+
if timer
|
219
|
+
event_loop_detach(timer)
|
220
|
+
log.debug "channel (#{ch}) subscription watcher is detached."
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def subscription(ch, read_existing_events, remote_session)
|
136
226
|
bookmarkXml = @bookmarks_storage.get(ch) || ""
|
137
227
|
bookmark = nil
|
138
228
|
if bookmark_validator(bookmarkXml, ch)
|
@@ -141,8 +231,8 @@ module Fluent::Plugin
|
|
141
231
|
subscribe = Winevt::EventLog::Subscribe.new
|
142
232
|
subscribe.read_existing_events = read_existing_events
|
143
233
|
begin
|
144
|
-
subscribe.subscribe(ch,
|
145
|
-
if !@render_as_xml && @preserve_qualifiers_on_hash
|
234
|
+
subscribe.subscribe(ch, event_query, bookmark, remote_session)
|
235
|
+
if !@render_as_xml && @preserve_qualifiers_on_hash
|
146
236
|
subscribe.preserve_qualifiers = @preserve_qualifiers_on_hash
|
147
237
|
end
|
148
238
|
rescue Winevt::EventLog::Query::Error => e
|
@@ -150,8 +240,17 @@ module Fluent::Plugin
|
|
150
240
|
end
|
151
241
|
subscribe.render_as_xml = @render_as_xml
|
152
242
|
subscribe.rate_limit = @rate_limit
|
153
|
-
|
154
|
-
|
243
|
+
subscribe.locale = @description_locale if @description_locale
|
244
|
+
[ch, subscribe]
|
245
|
+
end
|
246
|
+
|
247
|
+
def subscribe_channels(subscriptions)
|
248
|
+
subscriptions.each do |ch, subscribe|
|
249
|
+
log.trace "Subscribing Windows EventLog at #{ch} channel"
|
250
|
+
@timers[ch] = timer_execute("in_windows_eventlog_#{escape_channel(ch)}".to_sym, @read_interval) do
|
251
|
+
on_notify(ch, subscribe)
|
252
|
+
end
|
253
|
+
log.debug "channel (#{ch}) subscription is subscribed."
|
155
254
|
end
|
156
255
|
end
|
157
256
|
|
@@ -211,12 +310,13 @@ module Fluent::Plugin
|
|
211
310
|
end
|
212
311
|
end
|
213
312
|
end
|
313
|
+
router.emit_stream(@tag, es)
|
314
|
+
@bookmarks_storage.put(ch, subscribe.bookmark)
|
315
|
+
log.trace "Collecting Windows EventLog from #{ch} channel. Collected size: #{es.size}"
|
214
316
|
rescue Winevt::EventLog::Query::Error => e
|
215
|
-
log.warn "Invalid XML data", error: e
|
317
|
+
log.warn "Invalid XML data on #{ch}.", error: e
|
216
318
|
log.warn_backtrace
|
217
319
|
end
|
218
|
-
router.emit_stream(@tag, es)
|
219
|
-
@bookmarks_storage.put(ch, subscribe.bookmark)
|
220
320
|
end
|
221
321
|
|
222
322
|
def on_notify_hash(ch, subscribe)
|
@@ -241,12 +341,13 @@ module Fluent::Plugin
|
|
241
341
|
parse_desc(h) if @parse_description
|
242
342
|
es.add(Fluent::Engine.now, h)
|
243
343
|
end
|
344
|
+
router.emit_stream(@tag, es)
|
345
|
+
@bookmarks_storage.put(ch, subscribe.bookmark)
|
346
|
+
log.trace "Collecting Windows EventLog from #{ch} channel. Collected size: #{es.size}"
|
244
347
|
rescue Winevt::EventLog::Query::Error => e
|
245
|
-
log.warn "Invalid Hash data", error: e
|
348
|
+
log.warn "Invalid Hash data on #{ch}.", error: e
|
246
349
|
log.warn_backtrace
|
247
350
|
end
|
248
|
-
router.emit_stream(@tag, es)
|
249
|
-
@bookmarks_storage.put(ch, subscribe.bookmark)
|
250
351
|
end
|
251
352
|
|
252
353
|
#### These lines copied from in_windows_eventlog plugin:
|
@@ -2,6 +2,17 @@ require 'helper'
|
|
2
2
|
require 'fileutils'
|
3
3
|
require 'generate-windows-event'
|
4
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
|
+
|
5
16
|
class WindowsEventLog2InputTest < Test::Unit::TestCase
|
6
17
|
|
7
18
|
def setup
|
@@ -34,9 +45,21 @@ class WindowsEventLog2InputTest < Test::Unit::TestCase
|
|
34
45
|
assert_equal [], d.instance.channels
|
35
46
|
assert_false d.instance.read_existing_events
|
36
47
|
assert_false d.instance.render_as_xml
|
48
|
+
assert_nil d.instance.refresh_subscription_interval
|
37
49
|
end
|
38
50
|
|
39
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
|
+
|
40
63
|
test "subscribe directive" do
|
41
64
|
d = create_driver config_element("ROOT", "", {"tag" => "fluent.eventlog"}, [
|
42
65
|
config_element("storage", "", {
|
@@ -51,7 +74,36 @@ class WindowsEventLog2InputTest < Test::Unit::TestCase
|
|
51
74
|
'read_existing_events' => true
|
52
75
|
}),
|
53
76
|
])
|
54
|
-
expected = [["system", false], ["windows powershell", false], ["security", true]]
|
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]]
|
55
107
|
assert_equal expected, d.instance.instance_variable_get(:@chs)
|
56
108
|
end
|
57
109
|
|
@@ -71,7 +123,7 @@ class WindowsEventLog2InputTest < Test::Unit::TestCase
|
|
71
123
|
'read_existing_events' => true
|
72
124
|
}),
|
73
125
|
])
|
74
|
-
expected = [["system", false], ["windows powershell", false], ["security", true]]
|
126
|
+
expected = [["system", false, nil], ["windows powershell", false, nil], ["security", true, nil]]
|
75
127
|
assert_equal 1, d.instance.instance_variable_get(:@chs).select {|ch, flag| ch == "system"}.size
|
76
128
|
assert_equal expected, d.instance.instance_variable_get(:@chs)
|
77
129
|
end
|
@@ -93,7 +145,7 @@ class WindowsEventLog2InputTest < Test::Unit::TestCase
|
|
93
145
|
'read_existing_events' => true
|
94
146
|
}),
|
95
147
|
])
|
96
|
-
expected = [["system", false], ["windows powershell", false], ["system", true], ["windows powershell", true], ["security", true]]
|
148
|
+
expected = [["system", false, nil], ["windows powershell", false, nil], ["system", true, nil], ["windows powershell", true, nil], ["security", true, nil]]
|
97
149
|
assert_equal 2, d.instance.instance_variable_get(:@chs).select {|ch, flag| ch == "system"}.size
|
98
150
|
assert_equal expected, d.instance.instance_variable_get(:@chs)
|
99
151
|
end
|
@@ -111,6 +163,37 @@ class WindowsEventLog2InputTest < Test::Unit::TestCase
|
|
111
163
|
])
|
112
164
|
end
|
113
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
|
114
197
|
end
|
115
198
|
|
116
199
|
data("application" => ["Application", "Application"],
|
@@ -219,6 +302,33 @@ DESC
|
|
219
302
|
assert_equal("fluent-plugins", record["ProviderName"])
|
220
303
|
end
|
221
304
|
|
305
|
+
CONFIG_WITH_QUERY = config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
306
|
+
"event_query" => "Event/System[EventID=65500]"}, [
|
307
|
+
config_element("storage", "", {
|
308
|
+
'@type' => 'local',
|
309
|
+
'persistent' => false
|
310
|
+
})
|
311
|
+
])
|
312
|
+
def test_write_with_event_query
|
313
|
+
d = create_driver(CONFIG_WITH_QUERY)
|
314
|
+
|
315
|
+
service = Fluent::Plugin::EventService.new
|
316
|
+
|
317
|
+
d.run(expect_emits: 1) do
|
318
|
+
service.run
|
319
|
+
end
|
320
|
+
|
321
|
+
assert(d.events.length >= 1)
|
322
|
+
event = d.events.last
|
323
|
+
record = event.last
|
324
|
+
|
325
|
+
assert_equal("Application", record["Channel"])
|
326
|
+
assert_equal("65500", record["EventID"])
|
327
|
+
assert_equal("4", record["Level"])
|
328
|
+
assert_equal("fluent-plugins", record["ProviderName"])
|
329
|
+
end
|
330
|
+
|
331
|
+
|
222
332
|
CONFIG_KEYS = config_element("ROOT", "", {
|
223
333
|
"tag" => "fluent.eventlog",
|
224
334
|
"keys" => ["EventID", "Level", "Channel", "ProviderName"]
|
@@ -238,7 +348,7 @@ DESC
|
|
238
348
|
end
|
239
349
|
|
240
350
|
assert(d.events.length >= 1)
|
241
|
-
event = d.events.last
|
351
|
+
event = d.events.select {|e| e.last["EventID"] == "65500" }.last
|
242
352
|
record = event.last
|
243
353
|
|
244
354
|
expected = {"EventID" => "65500",
|
@@ -249,6 +359,36 @@ DESC
|
|
249
359
|
assert_equal(expected, record)
|
250
360
|
end
|
251
361
|
|
362
|
+
REMOTING_ACCESS_CONFIG = config_element("ROOT", "", {"tag" => "fluent.eventlog"}, [
|
363
|
+
config_element("storage", "", {
|
364
|
+
'@type' => 'local',
|
365
|
+
'persistent' => false
|
366
|
+
}),
|
367
|
+
config_element("subscribe", "", {
|
368
|
+
'channels' => ['Application'],
|
369
|
+
'remote_server' => '127.0.0.1',
|
370
|
+
}),
|
371
|
+
])
|
372
|
+
|
373
|
+
def test_write_with_remoting_access
|
374
|
+
d = create_driver(REMOTING_ACCESS_CONFIG)
|
375
|
+
|
376
|
+
service = Fluent::Plugin::EventService.new
|
377
|
+
|
378
|
+
d.run(expect_emits: 1) do
|
379
|
+
service.run
|
380
|
+
end
|
381
|
+
|
382
|
+
assert(d.events.length >= 1)
|
383
|
+
event = d.events.select {|e| e.last["EventID"] == "65500" }.last
|
384
|
+
record = event.last
|
385
|
+
|
386
|
+
assert_equal("Application", record["Channel"])
|
387
|
+
assert_equal("65500", record["EventID"])
|
388
|
+
assert_equal("4", record["Level"])
|
389
|
+
assert_equal("fluent-plugins", record["ProviderName"])
|
390
|
+
end
|
391
|
+
|
252
392
|
class HashRendered < self
|
253
393
|
def test_write
|
254
394
|
d = create_driver(config_element("ROOT", "", {"tag" => "fluent.eventlog",
|
@@ -355,8 +495,9 @@ DESC
|
|
355
495
|
service.run
|
356
496
|
end
|
357
497
|
|
358
|
-
|
359
|
-
|
498
|
+
events = d2.events.select {|e| e.last["EventID"] == "65500" }
|
499
|
+
assert(events.length == 1) # should be tailing after previous context.
|
500
|
+
event2 = events.last
|
360
501
|
record2 = event2.last
|
361
502
|
|
362
503
|
curr_id = record2["EventRecordID"].to_i
|
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
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.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- okahashi117
|
8
8
|
- Hiroshi Hatake
|
9
9
|
- Masahiro Nakagawa
|
10
|
-
autorequire:
|
10
|
+
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2021-09-16 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -46,14 +46,14 @@ dependencies:
|
|
46
46
|
requirements:
|
47
47
|
- - "~>"
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version: 3.
|
49
|
+
version: 3.4.0
|
50
50
|
type: :development
|
51
51
|
prerelease: false
|
52
52
|
version_requirements: !ruby/object:Gem::Requirement
|
53
53
|
requirements:
|
54
54
|
- - "~>"
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version: 3.
|
56
|
+
version: 3.4.0
|
57
57
|
- !ruby/object:Gem::Dependency
|
58
58
|
name: nokogiri
|
59
59
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,14 +128,14 @@ dependencies:
|
|
128
128
|
requirements:
|
129
129
|
- - ">="
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: 0.
|
131
|
+
version: 0.9.1
|
132
132
|
type: :runtime
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
136
|
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: 0.
|
138
|
+
version: 0.9.1
|
139
139
|
description: Fluentd Input plugin to read windows event log.
|
140
140
|
email:
|
141
141
|
- naruki_okahashi@jbat.co.jp
|
@@ -145,6 +145,7 @@ executables: []
|
|
145
145
|
extensions: []
|
146
146
|
extra_rdoc_files: []
|
147
147
|
files:
|
148
|
+
- ".github/workflows/unit-test.yml"
|
148
149
|
- ".gitignore"
|
149
150
|
- CHANGELOG.md
|
150
151
|
- Gemfile
|
@@ -166,7 +167,7 @@ homepage: https://github.com/fluent/fluent-plugin-windows-eventlog
|
|
166
167
|
licenses:
|
167
168
|
- Apache-2.0
|
168
169
|
metadata: {}
|
169
|
-
post_install_message:
|
170
|
+
post_install_message:
|
170
171
|
rdoc_options: []
|
171
172
|
require_paths:
|
172
173
|
- lib
|
@@ -181,9 +182,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
181
182
|
- !ruby/object:Gem::Version
|
182
183
|
version: '0'
|
183
184
|
requirements: []
|
184
|
-
|
185
|
-
|
186
|
-
signing_key:
|
185
|
+
rubygems_version: 3.1.4
|
186
|
+
signing_key:
|
187
187
|
specification_version: 4
|
188
188
|
summary: Fluentd Input plugin to read windows event log.
|
189
189
|
test_files:
|