fluent-plugin-filter-geoip2 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8ac882bd000f48b5d8a4ec195553746e4c98017402222bdd685c64cbf8554ecc
4
+ data.tar.gz: c82f952ba08b6a1892c100bb5daf097354eb065b44c7a8bc693f3a7a420ab627
5
+ SHA512:
6
+ metadata.gz: b6723cf6facb64af533f39e878b9b91bcc4b6aeeea6d892b33fd0657ec5a7b344e79d20774f53e18790a1ce7bc57386078ea32e7287adeac5014e99f6b1379df
7
+ data.tar.gz: 36424fe02a0484646bfd42d07e8807c41d2f989f694f6eb4e4d9291837606a3b5e750407a912f990b2f05aa231ac23a4be54b868a1ddb2db7fd7c516764372b6
data/.gitignore ADDED
@@ -0,0 +1,43 @@
1
+ *.gem
2
+ *.rbc
3
+ *.mmdb
4
+ /test*.rb
5
+ /.config
6
+ /coverage/
7
+ /InstalledFiles
8
+ /pkg/
9
+ /spec/reports/
10
+ /test/tmp/
11
+ /test/version_tmp/
12
+ /tmp/
13
+
14
+ ## Specific to RubyMotion:
15
+ .dat*
16
+ .repl_history
17
+ build/
18
+
19
+ ## Documentation cache and generated files:
20
+ /.yardoc/
21
+ /_yardoc/
22
+ /doc/
23
+ /rdoc/
24
+
25
+ ## Environment normalisation:
26
+ /.bundle/
27
+ /vendor/bundle
28
+ /lib/bundler/man/
29
+
30
+ # for a library or gem, you might want to ignore these files since the code is
31
+ # intended to run in multiple environments; otherwise, check them in:
32
+ # Gemfile.lock
33
+ # .ruby-version
34
+ # .ruby-gemset
35
+
36
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
37
+ .rvmrc
38
+
39
+ Gemfile.lock
40
+ geoip
41
+
42
+ # RubyMine
43
+ .idea/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-out_solr.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "{}"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright 2017 Tokyo Home Security Operation Center
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,327 @@
1
+ # Fluent::Plugin::GeoIP2Filter
2
+
3
+ This is a [Fluentd](http://fluentd.org/) filter plugin for adding [GeoIP data](http://dev.maxmind.com/geoip/geoip2/geolite2/) to record. Supports the new Maxmind v2 database formats.
4
+
5
+ ## Installation
6
+
7
+ Install it yourself as:
8
+
9
+ ```
10
+ $ gem install fluent-plugin-filter-geoip2
11
+ ```
12
+
13
+ ## How to build
14
+
15
+ ```
16
+ $ gem install bundler
17
+ $ bundle install
18
+ $ rake test
19
+ $ rake build
20
+ $ rake install
21
+ ```
22
+
23
+ ## Config parameters
24
+
25
+ ### enable_auto_download
26
+
27
+ If true, enable to download GeoIP2 database autometically (default: true).
28
+
29
+ ```
30
+ enable_auto_download true
31
+ ```
32
+
33
+ ### md5_url
34
+
35
+ GeoIP2 MD5 checksum URL (default: http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz.md5)
36
+
37
+ ```
38
+ md5_url http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz.md5
39
+ ```
40
+
41
+ ### download_url
42
+
43
+ GeoIP2 database download URL (default: http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz).
44
+
45
+ ```
46
+ download_url http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz
47
+ ```
48
+
49
+ ### md5_path
50
+
51
+ GeoIP2 MD5 checksum path. (default: ./geoip/database/GeoLite2-City.md5)
52
+
53
+ ```
54
+ md5_path ./geoip/database/GeoLite2-City.md5
55
+ ```
56
+
57
+ ### database_path
58
+
59
+ GeoIP2 database path. (default: ./geoip/database/GeoLite2-City.md5)
60
+
61
+ ```
62
+ database_path ./geoip/database/GeoLite2-City.mmdb
63
+ ```
64
+
65
+ ### md5_asn_url
66
+
67
+ GeoIP2 MD5 checksum URL (default: http://geolite.maxmind.com/download/geoip/database/GeoLite2-ASN.tar.gz.md5)
68
+
69
+ ```
70
+ md5_asn_url http://geolite.maxmind.com/download/geoip/database/GeoLite2-ASN.tar.gz.md5
71
+ ```
72
+
73
+ ### download_asn_url
74
+
75
+ GeoIP2 database download URL (default: http://geolite.maxmind.com/download/geoip/database/GeoLite2-ASN.tar.gz).
76
+
77
+ ```
78
+ download_asn_url http://geolite.maxmind.com/download/geoip/database/GeoLite2-ASN.tar.gz
79
+ ```
80
+
81
+ ### md5_asn_path
82
+
83
+ GeoIP2 MD5 checksum path. (default: ./geoip/database/GeoLite2-ASN.md5)
84
+
85
+ ```
86
+ md5_asn_path ./geoip/database/GeoLite2-ASN.md5
87
+ ```
88
+
89
+ ### database_asn_path
90
+
91
+ GeoIP2 database path. (default: ./geoip/database/GeoLite2-ASN.mmdb)
92
+
93
+ ```
94
+ database_asn_path ./geoip/database/GeoLite2-ASN.mmdb
95
+ ```
96
+
97
+ ### lookup_field
98
+
99
+ Specify the field name that IP address is stored (default: ip).
100
+
101
+ ```
102
+ lookup_field host
103
+ ```
104
+
105
+ ### output_field
106
+
107
+ Specify the field name that store the result (default: geoip).
108
+
109
+ ```
110
+ output_field geoip
111
+ ```
112
+
113
+ ### field_delimiter
114
+
115
+ Specify the field delimiter (default .).
116
+
117
+ ```
118
+ field_delimiter .
119
+ ```
120
+
121
+ ### flatten
122
+
123
+ If true, to flatten the result using field_delimiter (default: false).
124
+
125
+ ```
126
+ flatten false
127
+ ```
128
+
129
+ ### locale
130
+
131
+ Get the data for the specified locale (default: en).
132
+
133
+ ```
134
+ locale en
135
+ ```
136
+
137
+ ### continent
138
+
139
+ If true, to get continent information (default: true).
140
+
141
+ ```
142
+ continent true
143
+ ```
144
+
145
+ ### country
146
+
147
+ If true, to get country information (default: true).
148
+
149
+ ```
150
+ country true
151
+ ```
152
+
153
+ ### city
154
+
155
+ If true, to get city information (default: true).
156
+
157
+ ```
158
+ city true
159
+ ```
160
+
161
+ ### location
162
+
163
+ If true, to get location information (default: true).
164
+
165
+ ```
166
+ location true
167
+ ```
168
+
169
+ ### postal
170
+
171
+ If true, to get postal information (default: fasle).
172
+
173
+ ```
174
+ postal false
175
+ ```
176
+
177
+ ### registered_country
178
+
179
+ If true, to get registered country information (default: false).
180
+
181
+ ```
182
+ registered_country false
183
+ ```
184
+
185
+ ### represented_country
186
+
187
+ If true, to get represented country information (default: false).
188
+
189
+ ```
190
+ represented_country false
191
+ ```
192
+
193
+ ### subdivisions
194
+
195
+ If true, to get subdivisions information (default: false).
196
+
197
+ ```
198
+ subdivisions false
199
+ ```
200
+
201
+ ### traits
202
+
203
+ If true, to get traits information (default: false).
204
+
205
+ ```
206
+ traits false
207
+ ```
208
+
209
+ ### connection_type
210
+
211
+ If true, to get connection type information (default: false).
212
+
213
+ ```
214
+ connection_type false
215
+ ```
216
+
217
+ ### Autonomous System
218
+
219
+ Autonomous System (default: true).
220
+
221
+ ```
222
+ autonomous_system true
223
+ ```
224
+
225
+
226
+ ## Plugin setup examples
227
+
228
+ ```
229
+ <filter tail.log>
230
+ @type geoip2
231
+
232
+ enable_auto_download true
233
+
234
+ lookup_field clientip
235
+ output_field geoip
236
+ field_delimiter .
237
+ flatten false
238
+
239
+ locale en
240
+ </filter>
241
+ ```
242
+
243
+ Assuming following inputs are coming:
244
+
245
+ ```javascript
246
+ {
247
+ "clientip": "200.114.49.218"
248
+ }
249
+ ```
250
+
251
+ then output bocomes as belows:
252
+
253
+ ```javascript
254
+ {
255
+ "ufw_ips": "106.154.25.44",
256
+ "geoip": {
257
+ "continent": {
258
+ "code": "AS",
259
+ "geoname_id": 6255147,
260
+ "name": "Asia"
261
+ },
262
+ "country": {
263
+ "geoname_id": 1861060,
264
+ "iso_code": "JP",
265
+ "name": "Japan"
266
+ },
267
+ "location": {
268
+ "latitude": 35.69,
269
+ "longitude": 139.69,
270
+ "time_zone": "Asia/Tokyo"
271
+ },
272
+ "autonomous_system": {
273
+ "number": 2516,
274
+ "organization": "KDDI CORPORATION"
275
+ }
276
+ }
277
+ }
278
+ ```
279
+
280
+
281
+ ## Example command
282
+
283
+ Start fluentd using example fluent.conf.
284
+
285
+ ```
286
+ $ fluentd -c ~/github/fluent-plugin-filter-geoip/fluent.conf
287
+ 2017-03-13 15:11:31 +0900 [info]: reading config file path="/Users/mosuka/github/fluent-plugin-filter-geoip/fluent.conf"
288
+ 2017-03-13 15:11:31 +0900 [info]: starting fluentd-0.12.33
289
+ 2017-03-13 15:11:31 +0900 [info]: gem 'fluent-plugin-filter-geoip' version '0.0.1'
290
+ 2017-03-13 15:11:31 +0900 [info]: gem 'fluent-plugin-grok-parser' version '1.0.0'
291
+ 2017-03-13 15:11:31 +0900 [info]: gem 'fluent-plugin-output-solr' version '0.4.0'
292
+ 2017-03-13 15:11:31 +0900 [info]: gem 'fluent-plugin-ua-parser' version '1.1.0'
293
+ 2017-03-13 15:11:31 +0900 [info]: gem 'fluentd' version '0.12.33'
294
+ 2017-03-13 15:11:31 +0900 [info]: gem 'fluentd' version '0.12.32'
295
+ 2017-03-13 15:11:31 +0900 [info]: adding filter pattern="messages" type="geoip"
296
+ 2017-03-13 15:11:31 +0900 [info]: Current MD5: cc1f9a6f7def282bc33cb477f3379d9f
297
+ 2017-03-13 15:11:31 +0900 [info]: Fetched MD5: cc1f9a6f7def282bc33cb477f3379d9f
298
+ 2017-03-13 15:11:32 +0900 [info]: adding match pattern="messages" type="stdout"
299
+ 2017-03-13 15:11:32 +0900 [info]: adding source type="forward"
300
+ 2017-03-13 15:11:32 +0900 [info]: using configuration file: <ROOT>
301
+ <source>
302
+ @type forward
303
+ port 24224
304
+ </source>
305
+ <filter messages>
306
+ @type geoip
307
+ enable_auto_download true
308
+ lookup_field clientip
309
+ output_field geoip
310
+ field_delimiter .
311
+ flatten false
312
+ locale en
313
+ </filter>
314
+ <match messages>
315
+ type stdout
316
+ </match>
317
+ </ROOT>
318
+ 2017-03-13 15:11:32 +0900 [info]: listening fluent socket on 0.0.0.0:24224
319
+ ```
320
+
321
+ ## Development
322
+
323
+ After checking out the repo, run `bundle install` to install dependencies. Then, run `rake test` to run the tests.
324
+
325
+ ## Contributing
326
+
327
+ Bug reports and pull requests are welcome on GitHub at https://github.com/tokyohomesoc/fluent-plugin-filter-geoip2.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |test|
5
+ test.libs << 'lib' << 'test'
6
+ test.pattern = 'test/**/test_*.rb'
7
+ test.verbose = true
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "fluent-plugin-filter-geoip2"
7
+ spec.version = "0.1.4"
8
+ spec.authors = ["imcotop SOC"]
9
+ spec.email = ["imcotop@icloud.com"]
10
+
11
+ spec.summary = "Fluent filter plugin for adding GeoIP data to record."
12
+ spec.description = "Fluent filter plugin for adding GeoIP data to record. Supports the new Maxmind v2 database formats."
13
+ spec.homepage = "https://github.com/OlehPalanskyi/fluent-plugin-filter-geoip2"
14
+
15
+ spec.license = "Apache-2.0"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_runtime_dependency 'fluentd', '~> 0.12.32'
23
+ spec.add_runtime_dependency 'maxminddb', '~> 0.1.11'
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.14.6'
26
+ spec.add_development_dependency 'rake', '~> 11.1.2'
27
+ spec.add_development_dependency 'test-unit', '~> 3.1.5'
28
+ spec.add_development_dependency 'minitest', '~> 5.8.3'
29
+ end
data/fluent.conf ADDED
@@ -0,0 +1,36 @@
1
+ <source>
2
+ @type forward
3
+ port 24224
4
+ </source>
5
+
6
+ <filter messages>
7
+ @type geoip2
8
+
9
+ enable_auto_download true
10
+ md5_url http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.md5
11
+ download_url http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz
12
+ md5_path ./geoip/database/GeoLite2-City.md5
13
+ database_path ./geoip/database/GeoLite2-City.mmdb
14
+
15
+ lookup_field clientip
16
+ output_field geoip
17
+ field_delimiter .
18
+ flatten false
19
+
20
+ locale en
21
+
22
+ continent true
23
+ country true
24
+ city true
25
+ location true
26
+ postal true
27
+ registered_country true
28
+ represented_country true
29
+ subdivisions true
30
+ traits true
31
+ connection_type true
32
+ </filter>
33
+
34
+ <match messages>
35
+ type stdout
36
+ </match>
@@ -0,0 +1,520 @@
1
+ require 'maxminddb'
2
+ require 'json'
3
+ require 'fileutils'
4
+ require 'open-uri'
5
+ require 'zlib'
6
+ require 'fileutils'
7
+
8
+ module Fluent
9
+ class GeoIP2Filter < Filter
10
+ Fluent::Plugin.register_filter('geoip2', self)
11
+
12
+ DEFAULT_ENABLE_DOWNLOAD = true
13
+
14
+ DEFAULT_MD5_CITY_URL = 'http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz.md5'
15
+ DEFAULT_DOWNLOAD_CITY_URL = 'http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz'
16
+ DEFAULT_MD5_CITY_PATH = './geoip/database/GeoLite2-City.md5'
17
+ DEFAULT_DATABASE_CITY_PATH = './geoip/database/GeoLite2-City.mmdb'
18
+
19
+ DEFAULT_MD5_ASN_URL = 'http://geolite.maxmind.com/download/geoip/database/GeoLite2-ASN.tar.gz.md5'
20
+ DEFAULT_DOWNLOAD_ASN_URL = 'http://geolite.maxmind.com/download/geoip/database/GeoLite2-ASN.tar.gz'
21
+ DEFAULT_MD5_ASN_PATH = './geoip/database/GeoLite2-ASN.md5'
22
+ DEFAULT_DATABASE_ASN_PATH = './geoip/database/GeoLite2-ASN.mmdb'
23
+
24
+ DEFAULT_LOOKUP_FIELD = 'ip'
25
+ DEFAULT_OUTPU_FIELD = 'geoip'
26
+ DEFAULT_FIELD_DELIMITER = '.'
27
+ DEFAULT_FLATTEN = false
28
+
29
+ DEFAULT_LOCALE = 'en'
30
+
31
+ DEFAULT_CITY = true
32
+ DEFAULT_CONTINENT = true
33
+ DEFAULT_COUNTRY = true
34
+ DEFAULT_LOCATION = true
35
+ DEFAULT_POSTAL = false
36
+ DEFAULT_REGISTERED_COUNTRY = false
37
+ DEFAULT_REPRESENTED_COUNTRY = false
38
+ DEFAULT_SUBDIVISIONS = false
39
+ DEFAULT_TRAITS = false
40
+ DEFAULT_CONNECTION_TYPE = false
41
+ DEFAULT_AUTONOMOUS_SYSTEM = true
42
+
43
+ config_param :enable_auto_download, :bool, :default => DEFAULT_ENABLE_DOWNLOAD,
44
+ :desc => 'If true, enable to download GeoIP2 database autometically (default: %s).' % DEFAULT_ENABLE_DOWNLOAD
45
+
46
+ config_param :md5_city_url, :string, :default => DEFAULT_MD5_CITY_URL,
47
+ :desc => 'GeoIP2 MD5 checksum URL (default: %s)' % DEFAULT_MD5_CITY_URL
48
+
49
+ config_param :download_city_url, :string, :default => DEFAULT_DOWNLOAD_CITY_URL,
50
+ :desc => 'GeoIP2 database download URL (default: %s).' % DEFAULT_DOWNLOAD_CITY_URL
51
+
52
+ config_param :md5_city_path, :string, :default => DEFAULT_MD5_CITY_PATH,
53
+ :desc => 'GeoIP2 MD5 checksum path. (default: %s)' % DEFAULT_MD5_CITY_PATH
54
+
55
+ config_param :database_city_path, :string, :default => DEFAULT_DATABASE_CITY_PATH,
56
+ :desc => 'GeoIP2 database path. (default: %s)' % DEFAULT_DATABASE_CITY_PATH
57
+
58
+ config_param :md5_asn_url, :string, :default => DEFAULT_MD5_ASN_URL,
59
+ :desc => 'GeoIP2 MD5 checksum URL (default: %s)' % DEFAULT_MD5_ASN_URL
60
+
61
+ config_param :download_asn_url, :string, :default => DEFAULT_DOWNLOAD_ASN_URL,
62
+ :desc => 'GeoIP2 database download URL (default: %s).' % DEFAULT_DOWNLOAD_ASN_URL
63
+
64
+ config_param :md5_asn_path, :string, :default => DEFAULT_MD5_ASN_PATH,
65
+ :desc => 'GeoIP2 MD5 checksum path. (default: %s)' % DEFAULT_MD5_ASN_PATH
66
+
67
+ config_param :database_asn_path, :string, :default => DEFAULT_DATABASE_ASN_PATH,
68
+ :desc => 'GeoIP2 database path. (default: %s)' % DEFAULT_DATABASE_ASN_PATH
69
+
70
+ config_param :lookup_field, :string, :default => DEFAULT_LOOKUP_FIELD,
71
+ :desc => 'Specify the field name that IP address is stored (default: %s).' % DEFAULT_LOOKUP_FIELD
72
+
73
+ config_param :output_field, :string, :default => DEFAULT_OUTPU_FIELD,
74
+ :desc => 'Specify the field name that store the result (default: %s).' % DEFAULT_OUTPU_FIELD
75
+
76
+ config_param :field_delimiter, :string, :default => DEFAULT_FIELD_DELIMITER,
77
+ :desc => 'Specify the field delimiter (default %s).' % DEFAULT_FIELD_DELIMITER
78
+
79
+ config_param :flatten, :bool, :default => DEFAULT_FLATTEN,
80
+ :desc => 'If true, to flatten the result using field_delimiter (default: %s).' % DEFAULT_FLATTEN
81
+
82
+ config_param :locale, :string, :default => DEFAULT_LOCALE,
83
+ :desc => 'Get the data for the specified locale (default: %s).' % DEFAULT_LOCALE
84
+
85
+ config_param :continent, :bool, :default => DEFAULT_CONTINENT,
86
+ :desc => 'If true, to get continent information (default: %s).' % DEFAULT_CONTINENT
87
+
88
+ config_param :country, :bool, :default => DEFAULT_COUNTRY,
89
+ :desc => 'If true, to get country information (default: %s).' % DEFAULT_COUNTRY
90
+
91
+ config_param :city, :bool, :default => DEFAULT_CITY,
92
+ :desc => 'If true, to get city information (default: %s).' % DEFAULT_CITY
93
+
94
+ config_param :location, :bool, :default => DEFAULT_LOCATION,
95
+ :desc => 'If true, to get location information (default: %s).' % DEFAULT_LOCATION
96
+
97
+ config_param :postal, :bool, :default => DEFAULT_POSTAL,
98
+ :desc => 'If true, to get postal information (default: %s).' % DEFAULT_POSTAL
99
+
100
+ config_param :registered_country, :bool, :default => DEFAULT_REGISTERED_COUNTRY,
101
+ :desc => 'If true, to get registered country information (default: %s).' % DEFAULT_REGISTERED_COUNTRY
102
+
103
+ config_param :represented_country, :bool, :default => DEFAULT_REPRESENTED_COUNTRY,
104
+ :desc => 'If true, to get represented country information (default: %s).' % DEFAULT_REPRESENTED_COUNTRY
105
+
106
+ config_param :subdivisions, :bool, :default => DEFAULT_SUBDIVISIONS,
107
+ :desc => 'If true, to get subdivisions information (default: %s).' % DEFAULT_SUBDIVISIONS
108
+
109
+ config_param :traits, :bool, :default => DEFAULT_TRAITS,
110
+ :desc => 'If true, to get traits information (default: %s).' % DEFAULT_TRAITS
111
+
112
+ config_param :connection_type, :bool, :default => DEFAULT_CONNECTION_TYPE,
113
+ :desc => 'If true, to get connection type information (default: %s).' % DEFAULT_CONNECTION_TYPE
114
+
115
+ config_param :autonomous_system, :bool, :default => DEFAULT_AUTONOMOUS_SYSTEM,
116
+ :desc => 'Autonomous System (default: %s).' % DEFAULT_AUTONOMOUS_SYSTEM
117
+
118
+
119
+
120
+
121
+
122
+ def initialize
123
+ super
124
+ end
125
+
126
+ def configure(conf)
127
+ super
128
+
129
+ if enable_auto_download then
130
+ download_database @download_city_url, @md5_city_url, @database_city_path, @md5_city_path
131
+ download_database @download_asn_url, @md5_asn_url, @database_asn_path, @md5_asn_path
132
+ end
133
+
134
+ @database_city = MaxMindDB.new(@database_city_path)
135
+ @database_asn = MaxMindDB.new(@database_asn_path)
136
+ end
137
+
138
+ def filter(tag, time, record)
139
+ ip = record[@lookup_field]
140
+
141
+ unless ip.nil? then
142
+
143
+ geoip_city = {}
144
+ geoip_asn = {}
145
+ begin
146
+ geoip_city = @database_city.lookup(ip)
147
+ geoip_asn = @database_asn.lookup(ip)
148
+ rescue IPAddr::InvalidAddressError => e
149
+ # Do nothing if if InvalidAddressError
150
+ return record
151
+ end
152
+
153
+ if geoip_city.found? then
154
+
155
+ unless @flatten then
156
+ record.merge!({@output_field => {}})
157
+ end
158
+
159
+ if @continent then
160
+ continent_hash = {}
161
+
162
+ unless geoip_city.continent.code.nil? then
163
+ continent_hash['continent_code'] = geoip_city.continent.code
164
+ end
165
+ unless geoip_city.continent.geoname_id.nil? then
166
+ continent_hash['continent_geoname_id'] = geoip_city.continent.geoname_id
167
+ end
168
+ unless geoip_city.continent.iso_code.nil? then
169
+ continent_hash['continent_iso_code'] = geoip_city.continent.iso_code
170
+ end
171
+ unless geoip_city.continent.name(@locale).nil? then
172
+ continent_hash['continent_name'] = geoip_city.continent.name(@locale)
173
+ end
174
+
175
+ unless continent_hash.empty? then
176
+ if @flatten then
177
+ record.merge!(to_flatten(continent_hash, [@output_field], @field_delimiter))
178
+ else
179
+ record[@output_field].merge!(continent_hash)
180
+ end
181
+ end
182
+ end
183
+
184
+ if @country then
185
+ country_hash = {}
186
+
187
+ unless geoip_city.country.code.nil? then
188
+ country_hash['country_code'] = geoip_city.country.code
189
+ end
190
+ unless geoip_city.country.geoname_id.nil? then
191
+ country_hash['country_geoname_id'] = geoip_city.country.geoname_id
192
+ end
193
+ unless geoip_city.country.iso_code.nil? then
194
+ country_hash['country'] = geoip_city.country.iso_code
195
+ end
196
+ unless geoip_city.country.name(@locale).nil? then
197
+ country_hash['country_name'] = geoip_city.country.name(@locale)
198
+ end
199
+
200
+ unless country_hash.empty? then
201
+ if @flatten then
202
+ record.merge!(to_flatten(country_hash, [@output_field], @field_delimiter))
203
+ else
204
+ record[@output_field].merge!(country_hash)
205
+ end
206
+ end
207
+ end
208
+
209
+ if @city then
210
+ city_hash = {}
211
+
212
+ unless geoip_city.city.code.nil? then
213
+ city_hash['city_code'] = geoip_city.city.code
214
+ end
215
+ unless geoip_city.city.geoname_id.nil? then
216
+ city_hash['city_geoname_id'] = geoip_city.city.geoname_id
217
+ end
218
+ unless geoip_city.city.iso_code.nil? then
219
+ city_hash['city_iso_code'] = geoip_city.city.iso_code
220
+ end
221
+ unless geoip_city.city.name(@locale).nil? then
222
+ city_hash['city'] = geoip_city.city.name(@locale)
223
+ end
224
+
225
+ unless city_hash.empty? then
226
+ if @flatten then
227
+ record.merge!(to_flatten(city_hash, [@output_field], @field_delimiter))
228
+ else
229
+ record[@output_field].merge!(city_hash)
230
+ end
231
+ end
232
+ end
233
+
234
+ if @location then
235
+ location_hash = {}
236
+
237
+ unless geoip_city.location.latitude.nil? or geoip_city.location.longitude.nil? then
238
+ location_hash['location'] = { "lat" => geoip_city.location.latitude, "lon" => geoip_city.location.longitude}
239
+ end
240
+ unless geoip_city.location.latitude.nil? then
241
+ location_hash['latitude'] = geoip_city.location.latitude
242
+ end
243
+ unless geoip_city.location.longitude.nil? then
244
+ location_hash['longitude'] = geoip_city.location.longitude
245
+ end
246
+ unless geoip_city.location.metro_code.nil? then
247
+ location_hash['metro_code'] = geoip_city.location.metro_code
248
+ end
249
+ unless geoip_city.location.time_zone.nil? then
250
+ location_hash['time_zone'] = geoip_city.location.time_zone
251
+ end
252
+
253
+ unless location_hash.empty? then
254
+ if @flatten then
255
+ record.merge!(to_flatten(location_hash, [@output_field], @field_delimiter))
256
+ else
257
+ record[@output_field].merge!(location_hash)
258
+ end
259
+ end
260
+ end
261
+
262
+ if @postal then
263
+ postal_hash = {}
264
+
265
+ unless geoip_city.postal.code.nil? then
266
+ postal_hash['postal_code'] = geoip_city.postal.code
267
+ end
268
+
269
+ unless postal_hash.empty? then
270
+ if @flatten then
271
+ record.merge!(to_flatten(postal_hash, [@output_field], @field_delimiter))
272
+ else
273
+ record[@output_field].merge!(postal_hash)
274
+ end
275
+ end
276
+ end
277
+
278
+ if @registered_country then
279
+ registered_country_hash = {}
280
+
281
+ unless geoip_city.registered_country.code.nil? then
282
+ registered_country_hash['code'] = geoip_city.registered_country.code
283
+ end
284
+ unless geoip_city.registered_country.geoname_id.nil? then
285
+ registered_country_hash['geoname_id'] = geoip_city.registered_country.geoname_id
286
+ end
287
+ unless geoip_city.registered_country.iso_code.nil? then
288
+ registered_country_hash['iso_code'] = geoip_city.registered_country.iso_code
289
+ end
290
+ unless geoip_city.registered_country.name(@locale).nil? then
291
+ registered_country_hash['name'] = geoip_city.registered_country.name(@locale)
292
+ end
293
+
294
+ unless registered_country_hash.empty? then
295
+ if @flatten then
296
+ record.merge!(to_flatten(registered_country_hash, [@output_field, 'registered_country'], @field_delimiter))
297
+ else
298
+ record[@output_field].merge!({'registered_country' => registered_country_hash})
299
+ end
300
+ end
301
+ end
302
+
303
+ if @represented_country then
304
+ represented_country_hash = {}
305
+
306
+ unless geoip_city.represented_country.code.nil? then
307
+ represented_country_hash['code'] = geoip_city.represented_country.code
308
+ end
309
+ unless geoip_city.represented_country.geoname_id.nil? then
310
+ represented_country_hash['geoname_id'] = geoip_city.represented_country.geoname_id
311
+ end
312
+ unless geoip_city.represented_country.iso_code.nil? then
313
+ represented_country_hash['iso_code'] = geoip_city.represented_country.iso_code
314
+ end
315
+ unless geoip_city.represented_country.name(@locale).nil? then
316
+ represented_country_hash['name'] = geoip_city.represented_country.name(@locale)
317
+ end
318
+
319
+ unless represented_country_hash.empty? then
320
+ if @flatten then
321
+ record.merge!(to_flatten(represented_country_hash, [@output_field, 'represented_country'], @field_delimiter))
322
+ else
323
+ record[@output_field].merge!({'represented_country' => represented_country_hash})
324
+ end
325
+ end
326
+ end
327
+
328
+ if @subdivisions then
329
+ subdivision_arry = []
330
+
331
+ i = 0
332
+ geoip_city.subdivisions.each do |subdivision|
333
+ subdivision_hash = {}
334
+
335
+ unless subdivision.code.nil? then
336
+ subdivision_hash['code_%d' % [i]] = subdivision.code
337
+ end
338
+ unless subdivision.geoname_id.nil? then
339
+ subdivision_hash['geoname_id_%d' % [i]] = subdivision.geoname_id
340
+ end
341
+ unless subdivision.iso_code.nil? then
342
+ subdivision_hash['iso_code_%d' % [i]] = subdivision.iso_code
343
+ end
344
+ unless subdivision.name(@locale).nil? then
345
+ subdivision_hash['name_%d' % [i]] = subdivision.name(@locale)
346
+ end
347
+
348
+ unless subdivision_hash.empty? then
349
+ subdivision_arry.push(subdivision_hash)
350
+ end
351
+
352
+ i = i + 1
353
+ end
354
+
355
+ unless subdivision_arry.empty? then
356
+ if @flatten then
357
+ subdivision_arry.each do |subdivision|
358
+ record.merge!(to_flatten(subdivision, [@output_field, 'subdivisions'], @field_delimiter))
359
+ end
360
+ else
361
+ record[@output_field].merge!({'subdivisions' => subdivision_arry})
362
+ end
363
+ end
364
+ end
365
+
366
+ if @traits then
367
+ traits_hash = {}
368
+
369
+ unless geoip_city.traits.is_anonymous_proxy.nil? then
370
+ traits_hash['is_anonymous_proxy'] = geoip_city.traits.is_anonymous_proxy
371
+ end
372
+ unless geoip_city.traits.is_satellite_provider.nil? then
373
+ traits_hash['is_satellite_provider'] = geoip_city.traits.is_satellite_provider
374
+ end
375
+
376
+ unless traits_hash.empty? then
377
+ if @flatten then
378
+ record.merge!(to_flatten(traits_hash, [@output_field, 'traits'], @field_delimiter))
379
+ else
380
+ record[@output_field].merge!({'traits' => traits_hash})
381
+ end
382
+ end
383
+ end
384
+
385
+ if @connection_type then
386
+ unless geoip_city.connection_type.nil? then
387
+ if @flatten then
388
+ record.merge!(to_flatten(geoip_city.connection_type, [@output_field, 'connection_type'], @field_delimiter))
389
+ else
390
+ record[@output_field].merge!({'connection_type' => geoip_city.connection_type})
391
+ end
392
+ end
393
+ end
394
+
395
+ if geoip_asn.found? then
396
+ if @autonomous_system then
397
+ autonomous_system_hash = {}
398
+
399
+ autonomous_system_hash['number'] = geoip_asn['autonomous_system_number']
400
+ autonomous_system_hash['organization'] = geoip_asn['autonomous_system_organization']
401
+
402
+ unless autonomous_system_hash.empty? then
403
+ if @flatten then
404
+ record.merge!(to_flatten(autonomous_system_hash, [@output_field, 'as'], @field_delimiter))
405
+ else
406
+ record[@output_field].merge!({'as' => autonomous_system_hash})
407
+ end
408
+ end
409
+ end
410
+ end
411
+
412
+ log.debug "Record: %s" % record.inspect
413
+ else
414
+ log.debug "It was not possible to look up the #{ip}."
415
+ end
416
+ end
417
+
418
+ return record
419
+ end
420
+
421
+ def to_flatten(hash, stack=[], delimiter='/')
422
+ output = {}
423
+
424
+ hash.keys.each do |key|
425
+ stack.push key
426
+
427
+ if hash[key].instance_of?(Hash) then
428
+ output.merge!(to_flatten(hash[key], stack, delimiter))
429
+ else
430
+ output[stack.join(delimiter)] = hash[key]
431
+ end
432
+
433
+ stack.pop
434
+ end
435
+
436
+ return output
437
+ end
438
+
439
+ def download_database(download_url, md5_url, database_path, md5_path)
440
+ # database directory
441
+ database_dir = File.dirname database_path
442
+ md5_dir = File.dirname md5_path
443
+
444
+ # create database directory if directory does not exist.
445
+ FileUtils.mkdir_p(database_dir) unless File.exist?(database_dir)
446
+ FileUtils.mkdir_p(md5_dir) unless File.exist?(md5_dir)
447
+
448
+ # create empty md5 file if file does not exist.
449
+ File.open(md5_path, 'wb').close() unless File.exist?(md5_path)
450
+
451
+ # read saved md5
452
+ current_md5 = nil
453
+ begin
454
+ open(md5_path, 'rb') do |data|
455
+ current_md5 = data.read
456
+ end
457
+ log.info "Current MD5: %s" % current_md5
458
+ rescue => e
459
+ log.warn e.message
460
+ end
461
+
462
+ # fetch md5
463
+ fetched_md5 = nil
464
+ begin
465
+ open(md5_url, 'rb') do |data|
466
+ fetched_md5 = data.read
467
+ end
468
+ log.info "Fetched MD5: %s" % fetched_md5
469
+ rescue => e
470
+ log.warn e.message
471
+ end
472
+
473
+ # check md5
474
+ unless current_md5 == fetched_md5 then
475
+ # download new database
476
+ download_path = database_dir + '/' + File.basename(download_url)
477
+ begin
478
+ log.info "Download: %s" % download_url
479
+ open(download_path, 'wb') do |output|
480
+ open(download_url, 'rb') do |data|
481
+ output.write(data.read)
482
+ end
483
+ end
484
+ log.info "Download done: %s" % download_path
485
+ rescue => e
486
+ log.warn e.message
487
+ end
488
+
489
+ # unzip new database temporaly
490
+ tmp_database_path = database_dir + '/tmp_' + File.basename(database_path)
491
+ log.info "temp_database_path: %s" % tmp_database_path
492
+ log.info "PWD %s" % File.expand_path(tmp_database_path)
493
+ begin
494
+ log.info "Unzip: %s" % download_path
495
+ Zlib::GzipReader.open(download_path) do |gz|
496
+ Archive::Tar::Minitar.unpack(gz, './tmp')
497
+ end
498
+ src_path = Dir.glob('./tmp/' + File.basename(download_path, ".tar.gz") + '_*/' + File.basename(download_path, ".tar.gz") + '.mmdb')
499
+ FileUtils.mv(src_path, database_dir)
500
+ FileUtils.rm_rf('./tmp')
501
+ log.info "Unzip done: %s" % tmp_database_path
502
+ rescue => e
503
+ puts e.message
504
+ end
505
+
506
+ # check mkd5
507
+ temp_md5 = Digest::MD5.hexdigest(File.open(download_path, 'rb').read)
508
+ log.info "New MD5: %s" % temp_md5
509
+ if fetched_md5 == temp_md5 then
510
+ # record new md5
511
+ log.info "Save: %s" % md5_path
512
+ File.write(md5_path, fetched_md5)
513
+ log.info "Save done: %s" % md5_path
514
+ else
515
+ log.info "MD5 missmatch: Fetched MD5 (%s) != New MD5 (%s) ; " % [fetched_md5, temp_md5]
516
+ end
517
+ end
518
+ end
519
+ end
520
+ end
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-filter-geoip2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.4
5
+ platform: ruby
6
+ authors:
7
+ - imcotop SOC
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-06-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fluentd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.12.32
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.12.32
27
+ - !ruby/object:Gem::Dependency
28
+ name: maxminddb
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.11
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.1.11
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 1.14.6
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 1.14.6
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 11.1.2
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 11.1.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: test-unit
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 3.1.5
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 3.1.5
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 5.8.3
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 5.8.3
97
+ description: Fluent filter plugin for adding GeoIP data to record. Supports the new
98
+ Maxmind v2 database formats.
99
+ email:
100
+ - imcotop@icloud.com
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - Gemfile
107
+ - LICENSE
108
+ - README.md
109
+ - Rakefile
110
+ - fluent-plugin-filter-geoip2.gemspec
111
+ - fluent.conf
112
+ - lib/fluent/plugin/filter_geoip2.rb
113
+ homepage: https://github.com/OlehPalanskyi/fluent-plugin-filter-geoip2
114
+ licenses:
115
+ - Apache-2.0
116
+ metadata: {}
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubygems_version: 3.2.5
133
+ signing_key:
134
+ specification_version: 4
135
+ summary: Fluent filter plugin for adding GeoIP data to record.
136
+ test_files: []