fluent-plugin-windows-eventlog 0.7.1.rc1 → 0.8.0

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: c5bfbe6035f27762fffa9e75863aee873ac0873ebd24694ae19733c230cb9170
4
- data.tar.gz: 663554158b2d149821ca54701b655392afff19132c453c0be3f534aa1a684898
3
+ metadata.gz: 29f3b9ced1cd226756c2c6859e50cc974ec95e42a0efdc4b0e5544d69eac9c63
4
+ data.tar.gz: 61875762c40f75317704cc62a476dc16d947363c7dca6bf167b8c7a23c86a095
5
5
  SHA512:
6
- metadata.gz: 067ec531a1b265133b924709203d54a45c9641ac982ce0a1b876dc16d4968362c691ac4950bbdb5c38516a3a9bebd0389d46a66c1d1cc1e95715d3c76a783ee6
7
- data.tar.gz: '097951b41de440a39b7ca983b93320778e38d15c28bbaa1495aff593637d4b805f4413dedd7e2855ec8b3d89b72c90fd23c354d4e7e34d075af5d0a5ebaeb326'
6
+ metadata.gz: 1c126f6937f433079ddf703d141ecf73d1c3e1bd82e9fb605726109c20c97ab89f3307438da9fd62c80ef80770a39a884c3800c66874ca9519e680d17c9c9ba9
7
+ data.tar.gz: f5e9178ed7c1b477977d61d4fe306745f2efb3203bf430a612c96e9a27f1186d9980ef7ea236b679ab05c805bca3426b70d77a41288458747e684eb20009609f
@@ -1,3 +1,6 @@
1
+ # Release v0.8.0 - 2020/09/16
2
+ * in_windows_eventlog2: Support remoting access
3
+
1
4
  # Release v.0.7.1.rc1 - 2020/06/23
2
5
  * in_windows_eventlog2: Depends on nokogiri 1.11 series
3
6
 
data/README.md CHANGED
@@ -144,6 +144,7 @@ fluentd Input plugin for the Windows Event Log using newer Windows Event Logging
144
144
  # preserve_qualifiers_on_hash true # default is false.
145
145
  # read_all_channels false # default is false.
146
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.
147
148
  <storage>
148
149
  @type local # @type local is the default.
149
150
  persistent true # default is true. Set to false to use in-memory storage.
@@ -161,6 +162,10 @@ fluentd Input plugin for the Windows Event Log using newer Windows Event Logging
161
162
  # <subscribe>
162
163
  # channles application, system
163
164
  # read_existing_events false # read_existing_events should be applied each of subscribe directive(s)
165
+ # remote_server 127.0.0.1 # Remote server ip/fqdn
166
+ # remote_domain WORKGROUP # Domain name
167
+ # remote_username fluentd # Remoting access account name
168
+ # remote_password changeme! # Remoting access account password
164
169
  # </subscribe>
165
170
  </source>
166
171
 
@@ -190,6 +195,7 @@ fluentd Input plugin for the Windows Event Log using newer Windows Event Logging
190
195
  |`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`.|
191
196
  |`read_all_channels`| (option) Read from all channels. Default is `false`|
192
197
  |`description_locale`| (option) Specify description locale. Default is `nil`. See also: [Supported locales](https://github.com/fluent-plugins-nursery/winevt_c#multilingual-description) |
198
+ |`refresh_subscription_interval`|(option) It specifies refresh interval for channel subscriptions. Default is `nil`.|
193
199
  |`<subscribe>` | Setting for subscribe channels. |
194
200
 
195
201
  ##### subscribe section
@@ -198,6 +204,10 @@ fluentd Input plugin for the Windows Event Log using newer Windows Event Logging
198
204
  |:----- |:----- |
199
205
  |`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. |
200
206
  |`read_existing_events` | (option) Read the entries which already exist before fluentd is started. Defaults to `false`. |
207
+ |`remote_server` | (option) Remoting access server ip address/fqdn. Defaults to `nil`. |
208
+ |`remote_domain` | (option) Remoting access server joining domain name. Defaults to `nil`. |
209
+ |`remote_username` | (option) Remoting access access account's username. Defaults to `nil`. |
210
+ |`remote_password` | (option) Remoting access access account's password. Defaults to `nil`. |
201
211
 
202
212
 
203
213
  **Motivation:** subscribe directive is designed for applying `read_existing_events` each of channels which is specified in subscribe section(s).
@@ -234,6 +244,33 @@ This configuration can be handled as:
234
244
  * "Application" and "Security" channels just tailing
235
245
  * "HardwareEvent" channel read existing events before launching Fluentd
236
246
 
247
+ ###### Remoting access
248
+
249
+ `<subscribe>` section supports remoting access parameters:
250
+
251
+ * `remote_server`
252
+ * `remote_domain`
253
+ * `remote_username`
254
+ * `remote_password`
255
+
256
+ These parameters are only in `<subscribe>` directive.
257
+
258
+ Note that before using this feature, remoting access users should belong to "Event Log Readers" group:
259
+
260
+ ```console
261
+ > net localgroup "Event Log Readers" <domain\username> /add
262
+ ```
263
+
264
+ And then, users also should set up their remote box's Firewall configuration:
265
+
266
+ ```console
267
+ > netsh advfirewall firewall set rule group="Remote Event Log Management" new enable=yes
268
+ ```
269
+
270
+ As a security best practices, remoting access account _should not be administrator account_.
271
+
272
+ 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.
273
+
237
274
  ##### Available keys
238
275
 
239
276
  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.1.rc1"
7
+ spec.version = "0.8.0"
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.}
@@ -20,9 +20,9 @@ Gem::Specification.new do |spec|
20
20
  spec.add_development_dependency "bundler"
21
21
  spec.add_development_dependency "rake"
22
22
  spec.add_development_dependency "test-unit", "~> 3.2.0"
23
- spec.add_development_dependency "nokogiri", [">= 1.11.pre", "< 1.12"]
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.8.1"
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'
@@ -43,10 +45,15 @@ module Fluent::Plugin
43
45
  config_param :preserve_qualifiers_on_hash, :bool, default: false
44
46
  config_param :read_all_channels, :bool, default: false
45
47
  config_param :description_locale, :string, default: nil
48
+ config_param :refresh_subscription_interval, :time, default: nil
46
49
 
47
50
  config_section :subscribe, param_name: :subscribe_configs, required: false, multi: true do
48
51
  config_param :channels, :array
49
52
  config_param :read_existing_events, :bool, default: false
53
+ config_param :remote_server, :string, default: nil
54
+ config_param :remote_domain, :string, default: nil
55
+ config_param :remote_username, :string, default: nil
56
+ config_param :remote_password, :string, default: nil, secret: true
50
57
  end
51
58
 
52
59
  config_section :storage do
@@ -68,9 +75,12 @@ module Fluent::Plugin
68
75
 
69
76
  def configure(conf)
70
77
  super
78
+ @session = nil
71
79
  @chs = []
80
+ @subscriptions = {}
72
81
  @all_chs = Winevt::EventLog::Channel.new
73
82
  @all_chs.force_enumerate = false
83
+ @timers = {}
74
84
 
75
85
  if @read_all_channels
76
86
  @all_chs.each do |ch|
@@ -81,14 +91,22 @@ module Fluent::Plugin
81
91
 
82
92
  @read_existing_events = @read_from_head || @read_existing_events
83
93
  if @channels.empty? && @subscribe_configs.empty? && !@read_all_channels
84
- @chs.push(['application', @read_existing_events])
94
+ @chs.push(['application', @read_existing_events, nil])
85
95
  else
86
96
  @channels.map {|ch| ch.strip.downcase }.uniq.each do |uch|
87
- @chs.push([uch, @read_existing_events])
97
+ @chs.push([uch, @read_existing_events, nil])
88
98
  end
89
99
  @subscribe_configs.each do |subscribe|
100
+ if subscribe.remote_server
101
+ @session = Winevt::EventLog::Session.new(subscribe.remote_server,
102
+ subscribe.remote_domain,
103
+ subscribe.remote_username,
104
+ subscribe.remote_password)
105
+
106
+ log.debug("connect to remote box (server: #{subscribe.remote_server}) domain: #{subscribe.remote_domain} username: #{subscribe.remote_username})")
107
+ end
90
108
  subscribe.channels.map {|ch| ch.strip.downcase }.uniq.each do |uch|
91
- @chs.push([uch, subscribe.read_existing_events])
109
+ @chs.push([uch, subscribe.read_existing_events, @session])
92
110
  end
93
111
  end
94
112
  end
@@ -137,12 +155,73 @@ module Fluent::Plugin
137
155
  def start
138
156
  super
139
157
 
140
- @chs.each do |ch, read_existing_events|
141
- subscribe_channel(ch, read_existing_events)
158
+ refresh_subscriptions
159
+ if @refresh_subscription_interval
160
+ timer_execute(:in_windows_eventlog_refresh_subscription_timer, @refresh_subscription_interval, &method(:refresh_subscriptions))
142
161
  end
143
162
  end
144
163
 
145
- def subscribe_channel(ch, read_existing_events)
164
+ def shutdown
165
+ super
166
+
167
+ @subscriptions.keys.each do |ch|
168
+ subscription = @subscriptions.delete(ch)
169
+ if subscription
170
+ subscription.cancel
171
+ log.debug "channel (#{ch}) subscription is canceled."
172
+ end
173
+ end
174
+ end
175
+
176
+ def retry_on_error(channel, times: 15)
177
+ try = 0
178
+ begin
179
+ log.debug "Retry to subscribe for #{channel}...." if try > 1
180
+ try += 1
181
+ yield
182
+ log.info "Retry to subscribe for #{channel} succeeded." if try > 1
183
+ try = 0
184
+ rescue Winevt::EventLog::Subscribe::RemoteHandlerError => e
185
+ raise ReconnectError, "Retrying limit is exceeded." if try > times
186
+ log.warn "#{e.message}. Remaining retry count(s): #{times - try}"
187
+ sleep 2**try
188
+ retry
189
+ end
190
+ end
191
+
192
+ def refresh_subscriptions
193
+ clear_subscritpions
194
+
195
+ @chs.each do |ch, read_existing_events, session|
196
+ retry_on_error(ch) do
197
+ ch, subscribe = subscription(ch, read_existing_events, session)
198
+ @subscriptions[ch] = subscribe
199
+ end
200
+ end
201
+ subscribe_channels(@subscriptions)
202
+ end
203
+
204
+ def clear_subscritpions
205
+ @subscriptions.keys.each do |ch|
206
+ subscription = @subscriptions.delete(ch)
207
+ if subscription
208
+ if subscription.cancel
209
+ log.debug "channel (#{ch}) subscription is cancelled."
210
+ subscription.close
211
+ log.debug "channel (#{ch}) subscription handles are closed forcibly."
212
+ end
213
+ end
214
+ end
215
+ @timers.keys.each do |ch|
216
+ timer = @timers.delete(ch)
217
+ if timer
218
+ event_loop_detach(timer)
219
+ log.debug "channel (#{ch}) subscription watcher is detached."
220
+ end
221
+ end
222
+ end
223
+
224
+ def subscription(ch, read_existing_events, remote_session)
146
225
  bookmarkXml = @bookmarks_storage.get(ch) || ""
147
226
  bookmark = nil
148
227
  if bookmark_validator(bookmarkXml, ch)
@@ -151,7 +230,7 @@ module Fluent::Plugin
151
230
  subscribe = Winevt::EventLog::Subscribe.new
152
231
  subscribe.read_existing_events = read_existing_events
153
232
  begin
154
- subscribe.subscribe(ch, "*", bookmark)
233
+ subscribe.subscribe(ch, "*", bookmark, remote_session)
155
234
  if !@render_as_xml && @preserve_qualifiers_on_hash
156
235
  subscribe.preserve_qualifiers = @preserve_qualifiers_on_hash
157
236
  end
@@ -161,8 +240,15 @@ module Fluent::Plugin
161
240
  subscribe.render_as_xml = @render_as_xml
162
241
  subscribe.rate_limit = @rate_limit
163
242
  subscribe.locale = @description_locale if @description_locale
164
- timer_execute("in_windows_eventlog_#{escape_channel(ch)}".to_sym, @read_interval) do
165
- on_notify(ch, subscribe)
243
+ [ch, subscribe]
244
+ end
245
+
246
+ def subscribe_channels(subscriptions)
247
+ subscriptions.each do |ch, subscribe|
248
+ @timers[ch] = timer_execute("in_windows_eventlog_#{escape_channel(ch)}".to_sym, @read_interval) do
249
+ on_notify(ch, subscribe)
250
+ end
251
+ log.debug "channel (#{ch}) subscription is subscribed."
166
252
  end
167
253
  end
168
254
 
@@ -222,12 +308,12 @@ module Fluent::Plugin
222
308
  end
223
309
  end
224
310
  end
311
+ router.emit_stream(@tag, es)
312
+ @bookmarks_storage.put(ch, subscribe.bookmark)
225
313
  rescue Winevt::EventLog::Query::Error => e
226
- log.warn "Invalid XML data", error: e
314
+ log.warn "Invalid XML data on #{ch}.", error: e
227
315
  log.warn_backtrace
228
316
  end
229
- router.emit_stream(@tag, es)
230
- @bookmarks_storage.put(ch, subscribe.bookmark)
231
317
  end
232
318
 
233
319
  def on_notify_hash(ch, subscribe)
@@ -252,12 +338,12 @@ module Fluent::Plugin
252
338
  parse_desc(h) if @parse_description
253
339
  es.add(Fluent::Engine.now, h)
254
340
  end
341
+ router.emit_stream(@tag, es)
342
+ @bookmarks_storage.put(ch, subscribe.bookmark)
255
343
  rescue Winevt::EventLog::Query::Error => e
256
- log.warn "Invalid Hash data", error: e
344
+ log.warn "Invalid Hash data on #{ch}.", error: e
257
345
  log.warn_backtrace
258
346
  end
259
- router.emit_stream(@tag, es)
260
- @bookmarks_storage.put(ch, subscribe.bookmark)
261
347
  end
262
348
 
263
349
  #### 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
@@ -269,7 +321,7 @@ DESC
269
321
  end
270
322
 
271
323
  assert(d.events.length >= 1)
272
- event = d.events.last
324
+ event = d.events.select {|e| e.last["EventID"] == "65500" }.last
273
325
  record = event.last
274
326
 
275
327
  expected = {"EventID" => "65500",
@@ -280,6 +332,36 @@ DESC
280
332
  assert_equal(expected, record)
281
333
  end
282
334
 
335
+ REMOTING_ACCESS_CONFIG = config_element("ROOT", "", {"tag" => "fluent.eventlog"}, [
336
+ config_element("storage", "", {
337
+ '@type' => 'local',
338
+ 'persistent' => false
339
+ }),
340
+ config_element("subscribe", "", {
341
+ 'channels' => ['Application'],
342
+ 'remote_server' => '127.0.0.1',
343
+ }),
344
+ ])
345
+
346
+ def test_write_with_remoting_access
347
+ d = create_driver(REMOTING_ACCESS_CONFIG)
348
+
349
+ service = Fluent::Plugin::EventService.new
350
+
351
+ d.run(expect_emits: 1) do
352
+ service.run
353
+ end
354
+
355
+ assert(d.events.length >= 1)
356
+ event = d.events.select {|e| e.last["EventID"] == "65500" }.last
357
+ record = event.last
358
+
359
+ assert_equal("Application", record["Channel"])
360
+ assert_equal("65500", record["EventID"])
361
+ assert_equal("4", record["Level"])
362
+ assert_equal("fluent-plugins", record["ProviderName"])
363
+ end
364
+
283
365
  class HashRendered < self
284
366
  def test_write
285
367
  d = create_driver(config_element("ROOT", "", {"tag" => "fluent.eventlog",
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.7.1.rc1
4
+ version: 0.8.0
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: 2020-06-23 00:00:00.000000000 Z
13
+ date: 2020-09-16 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -60,7 +60,7 @@ dependencies:
60
60
  requirements:
61
61
  - - ">="
62
62
  - !ruby/object:Gem::Version
63
- version: 1.11.pre
63
+ version: '1.10'
64
64
  - - "<"
65
65
  - !ruby/object:Gem::Version
66
66
  version: '1.12'
@@ -70,7 +70,7 @@ dependencies:
70
70
  requirements:
71
71
  - - ">="
72
72
  - !ruby/object:Gem::Version
73
- version: 1.11.pre
73
+ version: '1.10'
74
74
  - - "<"
75
75
  - !ruby/object:Gem::Version
76
76
  version: '1.12'
@@ -128,14 +128,14 @@ dependencies:
128
128
  requirements:
129
129
  - - ">="
130
130
  - !ruby/object:Gem::Version
131
- version: 0.8.1
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.8.1
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
@@ -177,9 +177,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
177
177
  version: '0'
178
178
  required_rubygems_version: !ruby/object:Gem::Requirement
179
179
  requirements:
180
- - - ">"
180
+ - - ">="
181
181
  - !ruby/object:Gem::Version
182
- version: 1.3.1
182
+ version: '0'
183
183
  requirements: []
184
184
  rubyforge_project:
185
185
  rubygems_version: 2.7.6.2