logstash-filter-geoip2 3.0.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +33 -0
- data/CONTRIBUTORS +26 -0
- data/Gemfile +2 -0
- data/LICENSE +13 -0
- data/NOTICE.TXT +5 -0
- data/README.md +110 -0
- data/lib/com/fasterxml/jackson/core/jackson-annotations/2.6.0/jackson-annotations-2.6.0.jar +0 -0
- data/lib/com/fasterxml/jackson/core/jackson-annotations/2.7.0/jackson-annotations-2.7.0.jar +0 -0
- data/lib/com/fasterxml/jackson/core/jackson-core/2.6.4/jackson-core-2.6.4.jar +0 -0
- data/lib/com/fasterxml/jackson/core/jackson-core/2.7.0/jackson-core-2.7.0.jar +0 -0
- data/lib/com/fasterxml/jackson/core/jackson-databind/2.6.4/jackson-databind-2.6.4.jar +0 -0
- data/lib/com/fasterxml/jackson/core/jackson-databind/2.7.0/jackson-databind-2.7.0.jar +0 -0
- data/lib/com/maxmind/db/maxmind-db/1.1.0/maxmind-db-1.1.0.jar +0 -0
- data/lib/com/maxmind/db/maxmind-db/1.2.0/maxmind-db-1.2.0.jar +0 -0
- data/lib/com/maxmind/geoip2/geoip2/2.5.0/geoip2-2.5.0.jar +0 -0
- data/lib/com/maxmind/geoip2/geoip2/2.6.0/geoip2-2.6.0.jar +0 -0
- data/lib/logstash-filter-geoip2_jars.rb +8 -0
- data/lib/logstash/filters/geoip2.rb +218 -0
- data/logstash-filter-geoip.gemspec +34 -0
- data/spec/filters/geoip_spec.rb +218 -0
- data/vendor/GeoLite2-City.mmdb +0 -0
- metadata +124 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f6d0a06e9957b67fa3340d637493e4411ac679c0
|
4
|
+
data.tar.gz: ce3978802ccf43fe78e5d0e22c6d7297c0a3345c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f3397663e70461a490f449b374c1d2251702408c516e7c266c13e1e22d767aa6aad21b9a721371eb91df281b1fb390763aeddd3f7463c9587d48039732d1f486
|
7
|
+
data.tar.gz: 15c9209954939b615a2018bac9b60cf4025ff182e3c90cb696fb8f905717a8eadc5c493af7b48e1c68a0fcb371c742d53fcc026b132d00cfbffac266fd95a507
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# 3.0.0-beta1
|
2
|
+
- Changed plugin to use GeoIP2 database. See http://dev.maxmind.com/geoip/geoip2/whats-new-in-geoip2/
|
3
|
+
|
4
|
+
# 2.0.7
|
5
|
+
- Depend on logstash-core-plugin-api instead of logstash-core, removing the need to mass update plugins on major releases of logstash
|
6
|
+
# 2.0.6
|
7
|
+
- New dependency requirements for logstash-core for the 5.0 release
|
8
|
+
## 2.0.5
|
9
|
+
- Use proper field references
|
10
|
+
|
11
|
+
## 2.0.4
|
12
|
+
- Refactor GeoIP Struct to hash conversion to minimise repeated manipulation
|
13
|
+
|
14
|
+
## 2.0.3
|
15
|
+
- Fix Issue 50, incorrect data returned when geo lookup fails
|
16
|
+
|
17
|
+
## 2.0.2
|
18
|
+
- Update core dependency in gemspec
|
19
|
+
|
20
|
+
## 2.0.1
|
21
|
+
- Remove filter? call
|
22
|
+
|
23
|
+
## 2.0.0
|
24
|
+
- Plugins were updated to follow the new shutdown semantic, this mainly allows Logstash to instruct input plugins to terminate gracefully,
|
25
|
+
instead of using Thread.raise on the plugins' threads. Ref: https://github.com/elastic/logstash/pull/3895
|
26
|
+
- Dependency on logstash-core update to 2.0
|
27
|
+
|
28
|
+
* 1.1.2
|
29
|
+
- Be more defensive with threadsafety, mostly for specs
|
30
|
+
* 1.1.1
|
31
|
+
- Lazy-load LRU cache
|
32
|
+
* 1.1.0
|
33
|
+
- Add LRU cache
|
data/CONTRIBUTORS
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
The following is a list of people who have contributed ideas, code, bug
|
2
|
+
reports, or in general have helped logstash along its way.
|
3
|
+
|
4
|
+
Contributors:
|
5
|
+
* Aaron Mildenstein (untergeek)
|
6
|
+
* Avishai Ish-Shalom (avishai-ish-shalom)
|
7
|
+
* Brad Fritz (bfritz)
|
8
|
+
* Colin Surprenant (colinsurprenant)
|
9
|
+
* Jordan Sissel (jordansissel)
|
10
|
+
* Kurt Hurtado (kurtado)
|
11
|
+
* Leandro Moreira (leandromoreira)
|
12
|
+
* Nick Ethier (nickethier)
|
13
|
+
* Pier-Hugues Pellerin (ph)
|
14
|
+
* Pieter Lexis (pieterlexis)
|
15
|
+
* Richard Pijnenburg (electrical)
|
16
|
+
* Suyog Rao (suyograo)
|
17
|
+
* Vincent Batts (vbatts)
|
18
|
+
* avleen
|
19
|
+
* Guy Boertje (guyboertje)
|
20
|
+
* Thomas Decaux (qwant)
|
21
|
+
* Gary Gao (garyelephant)
|
22
|
+
|
23
|
+
Note: If you've sent us patches, bug reports, or otherwise contributed to
|
24
|
+
Logstash, and you aren't on the list above and want to be, please let us know
|
25
|
+
and we'll make sure you're here. Contributions from folks like you are what make
|
26
|
+
open source awesome.
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2012–2016 Elasticsearch <http://www.elastic.co>
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/NOTICE.TXT
ADDED
data/README.md
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
# Logstash Plugin
|
2
|
+
|
3
|
+
[![Travis Build Status](https://travis-ci.org/logstash-plugins/logstash-filter-geoip.svg)](https://travis-ci.org/logstash-plugins/logstash-filter-geoip)
|
4
|
+
|
5
|
+
This is a plugin for [Logstash](https://github.com/elastic/logstash).
|
6
|
+
|
7
|
+
It is fully free and fully open source. The license is Apache 2.0, meaning you are pretty much free to use it however you want in whatever way.
|
8
|
+
|
9
|
+
## Documentation
|
10
|
+
|
11
|
+
Logstash provides infrastructure to automatically generate documentation for this plugin. We use the asciidoc format to write documentation so any comments in the source code will be first converted into asciidoc and then into html. All plugin documentation are placed under one [central location](http://www.elastic.co/guide/en/logstash/current/).
|
12
|
+
|
13
|
+
- For formatting code or config example, you can use the asciidoc `[source,ruby]` directive
|
14
|
+
- For more asciidoc formatting tips, see the excellent reference here https://github.com/elastic/docs#asciidoc-guide
|
15
|
+
|
16
|
+
## Need Help?
|
17
|
+
|
18
|
+
Need help? Try #logstash on freenode IRC or the https://discuss.elastic.co/c/logstash discussion forum.
|
19
|
+
|
20
|
+
## Developing
|
21
|
+
|
22
|
+
### 1. Plugin Developement and Testing
|
23
|
+
|
24
|
+
#### Code
|
25
|
+
- To get started, you'll need JRuby with the Bundler gem installed.
|
26
|
+
|
27
|
+
- Create a new plugin or clone and existing from the GitHub [logstash-plugins](https://github.com/logstash-plugins) organization. We also provide [example plugins](https://github.com/logstash-plugins?query=example).
|
28
|
+
|
29
|
+
- Install dependencies
|
30
|
+
```sh
|
31
|
+
bundle install
|
32
|
+
```
|
33
|
+
|
34
|
+
#### Test
|
35
|
+
|
36
|
+
- Update your dependencies
|
37
|
+
|
38
|
+
```sh
|
39
|
+
bundle install
|
40
|
+
```
|
41
|
+
|
42
|
+
- Pull down GeoIP database files
|
43
|
+
|
44
|
+
```sh
|
45
|
+
bundle exec rake vendor
|
46
|
+
```
|
47
|
+
|
48
|
+
- Install jar dependencies
|
49
|
+
|
50
|
+
```
|
51
|
+
bundle exec rake install_jars
|
52
|
+
```
|
53
|
+
|
54
|
+
- Run tests
|
55
|
+
|
56
|
+
```sh
|
57
|
+
bundle exec rspec
|
58
|
+
```
|
59
|
+
|
60
|
+
### 2. Running your unpublished Plugin in Logstash
|
61
|
+
|
62
|
+
#### 2.1 Run in a local Logstash clone
|
63
|
+
|
64
|
+
- Edit Logstash `Gemfile` and add the local plugin path, for example:
|
65
|
+
```ruby
|
66
|
+
gem "logstash-filter-awesome", :path => "/your/local/logstash-filter-awesome"
|
67
|
+
```
|
68
|
+
- Install plugin
|
69
|
+
```sh
|
70
|
+
# Logstash 2.3 and higher
|
71
|
+
bin/logstash-plugin install --no-verify
|
72
|
+
|
73
|
+
# Prior to Logstash 2.3
|
74
|
+
bin/plugin install --no-verify
|
75
|
+
|
76
|
+
```
|
77
|
+
- Run Logstash with your plugin
|
78
|
+
```sh
|
79
|
+
bin/logstash -e 'filter {awesome {}}'
|
80
|
+
```
|
81
|
+
At this point any modifications to the plugin code will be applied to this local Logstash setup. After modifying the plugin, simply rerun Logstash.
|
82
|
+
|
83
|
+
#### 2.2 Run in an installed Logstash
|
84
|
+
|
85
|
+
You can use the same **2.1** method to run your plugin in an installed Logstash by editing its `Gemfile` and pointing the `:path` to your local plugin development directory or you can build the gem and install it using:
|
86
|
+
|
87
|
+
- Build your plugin gem
|
88
|
+
```sh
|
89
|
+
gem build logstash-filter-awesome.gemspec
|
90
|
+
```
|
91
|
+
- Install the plugin from the Logstash home
|
92
|
+
```sh
|
93
|
+
# Logstash 2.3 and higher
|
94
|
+
bin/logstash-plugin install --no-verify
|
95
|
+
|
96
|
+
# Prior to Logstash 2.3
|
97
|
+
bin/plugin install --no-verify
|
98
|
+
|
99
|
+
```
|
100
|
+
- Start Logstash and proceed to test the plugin
|
101
|
+
|
102
|
+
## Contributing
|
103
|
+
|
104
|
+
All contributions are welcome: ideas, patches, documentation, bug reports, complaints, and even something you drew up on a napkin.
|
105
|
+
|
106
|
+
Programming is not a required skill. Whatever you've seen about open source and maintainers or community members saying "send patches or die" - you will not see that here.
|
107
|
+
|
108
|
+
It is more important to the community that you are able to contribute.
|
109
|
+
|
110
|
+
For more information about contributing, see the [CONTRIBUTING](https://github.com/elastic/logstash/blob/master/CONTRIBUTING.md) file.
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# this is a generated file, to avoid over-writing it just delete this comment
|
2
|
+
require 'jar_dependencies'
|
3
|
+
|
4
|
+
require_jar( 'com.fasterxml.jackson.core', 'jackson-databind', '2.6.4' )
|
5
|
+
require_jar( 'com.maxmind.db', 'maxmind-db', '1.1.0' )
|
6
|
+
require_jar( 'com.maxmind.geoip2', 'geoip2', '2.5.0' )
|
7
|
+
require_jar( 'com.fasterxml.jackson.core', 'jackson-annotations', '2.6.0' )
|
8
|
+
require_jar( 'com.fasterxml.jackson.core', 'jackson-core', '2.6.4' )
|
@@ -0,0 +1,218 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/filters/base"
|
3
|
+
require "logstash/namespace"
|
4
|
+
|
5
|
+
require "logstash-filter-geoip2_jars"
|
6
|
+
|
7
|
+
java_import "java.net.InetAddress"
|
8
|
+
java_import "com.maxmind.geoip2.DatabaseReader"
|
9
|
+
java_import "com.maxmind.geoip2.model.CityResponse"
|
10
|
+
java_import "com.maxmind.geoip2.record.Country"
|
11
|
+
java_import "com.maxmind.geoip2.record.Subdivision"
|
12
|
+
java_import "com.maxmind.geoip2.record.City"
|
13
|
+
java_import "com.maxmind.geoip2.record.Postal"
|
14
|
+
java_import "com.maxmind.geoip2.record.Location"
|
15
|
+
java_import "com.maxmind.db.CHMCache"
|
16
|
+
|
17
|
+
def suppress_all_warnings
|
18
|
+
old_verbose = $VERBOSE
|
19
|
+
begin
|
20
|
+
$VERBOSE = nil
|
21
|
+
yield if block_given?
|
22
|
+
ensure
|
23
|
+
# always re-set to old value, even if block raises an exception
|
24
|
+
$VERBOSE = old_verbose
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# create a new instance of the Java class File without shadowing the Ruby version of the File class
|
29
|
+
module JavaIO
|
30
|
+
include_package "java.io"
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
# The GeoIP2 filter adds information about the geographical location of IP addresses,
|
35
|
+
# based on data from the Maxmind database.
|
36
|
+
#
|
37
|
+
# Starting with version 1.3.0 of Logstash, a `[geoip][location]` field is created if
|
38
|
+
# the GeoIP lookup returns a latitude and longitude. The field is stored in
|
39
|
+
# http://geojson.org/geojson-spec.html[GeoJSON] format. Additionally,
|
40
|
+
# the default Elasticsearch template provided with the
|
41
|
+
# <<plugins-outputs-elasticsearch,`elasticsearch` output>> maps
|
42
|
+
# the `[geoip][location]` field to an http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping-geo-point-type.html#_mapping_options[Elasticsearch geo_point].
|
43
|
+
#
|
44
|
+
# As this field is a `geo_point` _and_ it is still valid GeoJSON, you get
|
45
|
+
# the awesomeness of Elasticsearch's geospatial query, facet and filter functions
|
46
|
+
# and the flexibility of having GeoJSON for all other applications (like Kibana's
|
47
|
+
# map visualization).
|
48
|
+
#
|
49
|
+
# This product includes GeoLite2 data created by MaxMind, available from
|
50
|
+
# <http://dev.maxmind.com/geoip/geoip2/geolite2/>.
|
51
|
+
class LogStash::Filters::GeoIP2 < LogStash::Filters::Base
|
52
|
+
config_name "geoip2"
|
53
|
+
|
54
|
+
# The path to the GeoIP2 database file which Logstash should use. Only City database is supported by now.
|
55
|
+
#
|
56
|
+
# If not specified, this will default to the GeoLiteCity database that ships
|
57
|
+
# with Logstash.
|
58
|
+
config :database, :validate => :path
|
59
|
+
|
60
|
+
# The field containing the IP address or hostname to map via geoip. If
|
61
|
+
# this field is an array, only the first value will be used.
|
62
|
+
config :source, :validate => :string, :required => true
|
63
|
+
|
64
|
+
# An array of geoip fields to be included in the event.
|
65
|
+
#
|
66
|
+
# Possible fields depend on the database type. By default, all geoip fields
|
67
|
+
# are included in the event.
|
68
|
+
#
|
69
|
+
# For the built-in GeoLiteCity database, the following are available:
|
70
|
+
# `city_name`, `continent_code`, `country_code2`, `country_code3`, `country_name`,
|
71
|
+
# `dma_code`, `ip`, `latitude`, `longitude`, `postal_code`, `region_name` and `timezone`.
|
72
|
+
config :fields, :validate => :array, :default => ['city_name', 'continent_code',
|
73
|
+
'country_code2', 'country_code3', 'country_name',
|
74
|
+
'dma_code', 'ip', 'latitude',
|
75
|
+
'longitude', 'postal_code', 'region_name',
|
76
|
+
'region_code', 'timezone', 'location']
|
77
|
+
|
78
|
+
# Specify the field into which Logstash should store the geoip data.
|
79
|
+
# This can be useful, for example, if you have `src\_ip` and `dst\_ip` fields and
|
80
|
+
# would like the GeoIP information of both IPs.
|
81
|
+
#
|
82
|
+
# If you save the data to a target field other than `geoip` and want to use the
|
83
|
+
# `geo\_point` related functions in Elasticsearch, you need to alter the template
|
84
|
+
# provided with the Elasticsearch output and configure the output to use the
|
85
|
+
# new template.
|
86
|
+
#
|
87
|
+
# Even if you don't use the `geo\_point` mapping, the `[target][location]` field
|
88
|
+
# is still valid GeoJSON.
|
89
|
+
config :target, :validate => :string, :default => 'geoip'
|
90
|
+
|
91
|
+
# GeoIP lookup is surprisingly expensive. This filter uses an cache to take advantage of the fact that
|
92
|
+
# IPs agents are often found adjacent to one another in log files and rarely have a random distribution.
|
93
|
+
# The higher you set this the more likely an item is to be in the cache and the faster this filter will run.
|
94
|
+
# However, if you set this too high you can use more memory than desired.
|
95
|
+
# Since the Geoip API upgraded to v2, there is not any eviction policy so far, if cache is full, no more record can be added.
|
96
|
+
# Experiment with different values for this option to find the best performance for your dataset.
|
97
|
+
#
|
98
|
+
# This MUST be set to a value > 0. There is really no reason to not want this behavior, the overhead is minimal
|
99
|
+
# and the speed gains are large.
|
100
|
+
#
|
101
|
+
# It is important to note that this config value is global to the geoip_type. That is to say all instances of the geoip filter
|
102
|
+
# of the same geoip_type share the same cache. The last declared cache size will 'win'. The reason for this is that there would be no benefit
|
103
|
+
# to having multiple caches for different instances at different points in the pipeline, that would just increase the
|
104
|
+
# number of cache misses and waste memory.
|
105
|
+
config :cache_size, :validate => :number, :default => 1000
|
106
|
+
|
107
|
+
# GeoIP lookup is surprisingly expensive. This filter uses an LRU cache to take advantage of the fact that
|
108
|
+
# IPs agents are often found adjacent to one another in log files and rarely have a random distribution.
|
109
|
+
# The higher you set this the more likely an item is to be in the cache and the faster this filter will run.
|
110
|
+
# However, if you set this too high you can use more memory than desired.
|
111
|
+
#
|
112
|
+
# Experiment with different values for this option to find the best performance for your dataset.
|
113
|
+
#
|
114
|
+
# This MUST be set to a value > 0. There is really no reason to not want this behavior, the overhead is minimal
|
115
|
+
# and the speed gains are large.
|
116
|
+
#
|
117
|
+
# It is important to note that this config value is global to the geoip_type. That is to say all instances of the geoip filter
|
118
|
+
# of the same geoip_type share the same cache. The last declared cache size will 'win'. The reason for this is that there would be no benefit
|
119
|
+
# to having multiple caches for different instances at different points in the pipeline, that would just increase the
|
120
|
+
# number of cache misses and waste memory.
|
121
|
+
config :lru_cache_size, :validate => :number, :default => 1000
|
122
|
+
|
123
|
+
public
|
124
|
+
def register
|
125
|
+
suppress_all_warnings do
|
126
|
+
if @database.nil?
|
127
|
+
@database = ::Dir.glob(::File.join(::File.expand_path("../../../vendor/", ::File.dirname(__FILE__)),"GeoLite2-City.mmdb")).first
|
128
|
+
|
129
|
+
if @database.nil? || !File.exists?(@database)
|
130
|
+
raise "You must specify 'database => ...' in your geoip filter (I looked for '#{@database}')"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
@logger.info("Using geoip database", :path => @database)
|
135
|
+
|
136
|
+
db_file = JavaIO::File.new(@database)
|
137
|
+
begin
|
138
|
+
@parser = DatabaseReader::Builder.new(db_file).withCache(CHMCache.new(@cache_size)).build();
|
139
|
+
rescue Java::ComMaxmindDb::InvalidDatabaseException => e
|
140
|
+
@logger.error("The Geoip2 MMDB database provided is invalid or corrupted.", :exception => e, :field => @source)
|
141
|
+
raise e
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end # def register
|
145
|
+
|
146
|
+
public
|
147
|
+
def filter(event)
|
148
|
+
return unless filter?(event)
|
149
|
+
|
150
|
+
begin
|
151
|
+
ip = event[@source]
|
152
|
+
ip = ip.first if ip.is_a? Array
|
153
|
+
ip_address = InetAddress.getByName(ip)
|
154
|
+
response = @parser.city(ip_address)
|
155
|
+
country = response.getCountry()
|
156
|
+
subdivision = response.getMostSpecificSubdivision()
|
157
|
+
city = response.getCity()
|
158
|
+
postal = response.getPostal()
|
159
|
+
location = response.getLocation()
|
160
|
+
|
161
|
+
geo_data_hash = Hash.new()
|
162
|
+
|
163
|
+
@fields.each do |field|
|
164
|
+
case field
|
165
|
+
when "city_name"
|
166
|
+
geo_data_hash["city_name"] = city.getName()
|
167
|
+
when "country_name"
|
168
|
+
geo_data_hash["country_name"] = country.getName()
|
169
|
+
when "continent_code"
|
170
|
+
geo_data_hash["continent_code"] = response.getContinent().getCode()
|
171
|
+
when "continent_name"
|
172
|
+
geo_data_hash["continent_name"] = response.getContinent().getName()
|
173
|
+
when "country_code2"
|
174
|
+
geo_data_hash["country_code2"] = country.getIsoCode()
|
175
|
+
when "country_code3"
|
176
|
+
geo_data_hash["country_code3"] = country.getIsoCode()
|
177
|
+
when "ip"
|
178
|
+
geo_data_hash["ip"] = ip_address.getHostAddress()
|
179
|
+
when "postal_code"
|
180
|
+
geo_data_hash["postal_code"] = postal.getCode()
|
181
|
+
when "dma_code"
|
182
|
+
geo_data_hash["dma_code"] = location.getMetroCode()
|
183
|
+
when "region_name"
|
184
|
+
geo_data_hash["region_name"] = subdivision.getName()
|
185
|
+
when "region_code"
|
186
|
+
geo_data_hash["region_code"] = subdivision.getIsoCode()
|
187
|
+
when "timezone"
|
188
|
+
geo_data_hash["timezone"] = location.getTimeZone()
|
189
|
+
when "location"
|
190
|
+
geo_data_hash["location"] = [ location.getLongitude(), location.getLatitude() ]
|
191
|
+
when "latitude"
|
192
|
+
geo_data_hash["latitude"] = location.getLatitude()
|
193
|
+
when "longitude"
|
194
|
+
geo_data_hash["longitude"] = location.getLongitude()
|
195
|
+
else
|
196
|
+
raise Exception.new("[#{field}] is not a supported field option.")
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
rescue com.maxmind.geoip2.exception.AddressNotFoundException => e
|
201
|
+
@logger.debug("IP not found!", :exception => e, :field => @source, :event => event)
|
202
|
+
event[@target] = {}
|
203
|
+
return
|
204
|
+
rescue java.net.UnknownHostException => e
|
205
|
+
@logger.error("IP Field contained invalid IP address or hostname", :exception => e, :field => @source, :event => event)
|
206
|
+
event[@target] = {}
|
207
|
+
return
|
208
|
+
rescue Exception => e
|
209
|
+
@logger.error("Unknown error while looking up GeoIP data", :exception => e, :field => @source, :event => event)
|
210
|
+
event[@target] = {}
|
211
|
+
return
|
212
|
+
end
|
213
|
+
|
214
|
+
event[@target] = geo_data_hash
|
215
|
+
|
216
|
+
filter_matched(event)
|
217
|
+
end # def filter
|
218
|
+
end # class LogStash::Filters::GeoIP
|
@@ -0,0 +1,34 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
|
3
|
+
s.name = 'logstash-filter-geoip2'
|
4
|
+
s.version = '3.0.0'
|
5
|
+
s.licenses = ['Apache License (2.0)']
|
6
|
+
s.summary = "$summary"
|
7
|
+
s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program. Config key is geoip2."
|
8
|
+
s.authors = ["Elastic"]
|
9
|
+
s.email = 'ebuildy@gmail.com'
|
10
|
+
s.homepage = "https://github.com/ebuildy/logstash-filter-geoip"
|
11
|
+
s.require_paths = ["lib"]
|
12
|
+
s.platform = "java"
|
13
|
+
|
14
|
+
# Files
|
15
|
+
s.files = Dir['lib/**/*','spec/**/*','vendor/**/*','*.gemspec','*.md','CONTRIBUTORS','Gemfile','LICENSE','NOTICE.TXT']
|
16
|
+
|
17
|
+
# Tests
|
18
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
19
|
+
|
20
|
+
# Special flag to let us know this is actually a logstash plugin
|
21
|
+
s.metadata = { "logstash_plugin" => "true", "logstash_group" => "filter" }
|
22
|
+
|
23
|
+
# Gem dependencies
|
24
|
+
s.add_runtime_dependency "logstash-core-plugin-api", "~> 1.0"
|
25
|
+
|
26
|
+
s.requirements << "jar com.maxmind.geoip2:geoip2, 2.5.0, :exclusions=> [com.google.http-client:google-http-client]"
|
27
|
+
|
28
|
+
s.add_development_dependency "jar-dependencies"
|
29
|
+
|
30
|
+
s.add_development_dependency 'ruby-maven', '~> 3.3'
|
31
|
+
|
32
|
+
s.add_development_dependency 'logstash-devutils'
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,218 @@
|
|
1
|
+
require "logstash/devutils/rspec/spec_helper"
|
2
|
+
require "logstash/filters/geoip"
|
3
|
+
|
4
|
+
CITYDB = ::Dir.glob(::File.expand_path("../../vendor/", ::File.dirname(__FILE__))+"/GeoLite2-City.mmdb").first
|
5
|
+
|
6
|
+
describe LogStash::Filters::GeoIP do
|
7
|
+
|
8
|
+
describe "defaults" do
|
9
|
+
config <<-CONFIG
|
10
|
+
filter {
|
11
|
+
geoip {
|
12
|
+
source => "ip"
|
13
|
+
#database => "#{CITYDB}"
|
14
|
+
}
|
15
|
+
}
|
16
|
+
CONFIG
|
17
|
+
|
18
|
+
sample("ip" => "8.8.8.8") do
|
19
|
+
insist { subject }.include?("geoip")
|
20
|
+
|
21
|
+
expected_fields = %w(ip country_code2 country_code3 country_name
|
22
|
+
continent_code region_name city_name postal_code
|
23
|
+
latitude longitude dma_code timezone
|
24
|
+
location )
|
25
|
+
expected_fields.each do |f|
|
26
|
+
insist { subject["geoip"] }.include?(f)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
sample("ip" => "127.0.0.1") do
|
31
|
+
# assume geoip fails on localhost lookups
|
32
|
+
expect(subject["geoip"]).to eq({})
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "normal operations" do
|
37
|
+
config <<-CONFIG
|
38
|
+
filter {
|
39
|
+
geoip {
|
40
|
+
source => "ip"
|
41
|
+
#database => "#{CITYDB}"
|
42
|
+
target => src_ip
|
43
|
+
add_tag => "done"
|
44
|
+
}
|
45
|
+
}
|
46
|
+
CONFIG
|
47
|
+
|
48
|
+
context "when specifying the target" do
|
49
|
+
|
50
|
+
sample("ip" => "8.8.8.8") do
|
51
|
+
expect(subject).to include("src_ip")
|
52
|
+
|
53
|
+
expected_fields = %w(ip country_code2 country_code3 country_name
|
54
|
+
continent_code region_name city_name postal_code
|
55
|
+
latitude longitude dma_code timezone
|
56
|
+
location )
|
57
|
+
expected_fields.each do |f|
|
58
|
+
expect(subject["src_ip"]).to include(f)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
sample("ip" => "127.0.0.1") do
|
63
|
+
# assume geoip fails on localhost lookups
|
64
|
+
expect(subject["src_ip"]).to eq({})
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "when specifying add_tag" do
|
69
|
+
sample("ip" => "8.8.8.8") do
|
70
|
+
expect(subject["tags"]).to include("done")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "correct encodings with default db" do
|
76
|
+
config <<-CONFIG
|
77
|
+
filter {
|
78
|
+
geoip {
|
79
|
+
source => "ip"
|
80
|
+
}
|
81
|
+
}
|
82
|
+
CONFIG
|
83
|
+
expected_fields = %w(ip country_code2 country_code3 country_name
|
84
|
+
continent_code region_name city_name postal_code
|
85
|
+
dma_code timezone)
|
86
|
+
|
87
|
+
sample("ip" => "1.1.1.1") do
|
88
|
+
checked = 0
|
89
|
+
expected_fields.each do |f|
|
90
|
+
next unless subject["geoip"][f]
|
91
|
+
checked += 1
|
92
|
+
insist { subject["geoip"][f].encoding } == Encoding::UTF_8
|
93
|
+
end
|
94
|
+
insist { checked } > 0
|
95
|
+
end
|
96
|
+
|
97
|
+
sample("ip" => "189.2.0.0") do
|
98
|
+
checked = 0
|
99
|
+
expected_fields.each do |f|
|
100
|
+
next unless subject["geoip"][f]
|
101
|
+
checked += 1
|
102
|
+
insist { subject["geoip"][f].encoding } == Encoding::UTF_8
|
103
|
+
end
|
104
|
+
insist { checked } > 0
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "location field" do
|
110
|
+
shared_examples_for "an event with a [geoip][location] field" do
|
111
|
+
subject(:event) { LogStash::Event.new("message" => "8.8.8.8") }
|
112
|
+
let(:plugin) { LogStash::Filters::GeoIP.new("source" => "message", "fields" => ["country_name", "location", "longitude"]) }
|
113
|
+
|
114
|
+
before do
|
115
|
+
plugin.register
|
116
|
+
plugin.filter(event)
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should have a location field" do
|
120
|
+
expect(event["[geoip][location]"]).not_to(be_nil)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context "when latitude field is excluded" do
|
125
|
+
let(:fields) { ["country_name", "location", "longitude"] }
|
126
|
+
it_behaves_like "an event with a [geoip][location] field"
|
127
|
+
end
|
128
|
+
|
129
|
+
context "when longitude field is excluded" do
|
130
|
+
let(:fields) { ["country_name", "location", "latitude"] }
|
131
|
+
it_behaves_like "an event with a [geoip][location] field"
|
132
|
+
end
|
133
|
+
|
134
|
+
context "when both latitude and longitude field are excluded" do
|
135
|
+
let(:fields) { ["country_name", "location"] }
|
136
|
+
it_behaves_like "an event with a [geoip][location] field"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe "an invalid IP" do
|
141
|
+
config <<-CONFIG
|
142
|
+
filter {
|
143
|
+
geoip {
|
144
|
+
source => "ip"
|
145
|
+
database => "#{CITYDB}"
|
146
|
+
}
|
147
|
+
}
|
148
|
+
CONFIG
|
149
|
+
describe "should not raise an error" do
|
150
|
+
sample("ip" => "-") do
|
151
|
+
expect{ subject }.to_not raise_error
|
152
|
+
end
|
153
|
+
|
154
|
+
sample("ip" => "~") do
|
155
|
+
expect{ subject }.to_not raise_error
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe "filter method outcomes" do
|
160
|
+
let(:plugin) { LogStash::Filters::GeoIP.new("source" => "message", "add_tag" => "done", "database" => CITYDB) }
|
161
|
+
let(:event) { LogStash::Event.new("message" => ipstring) }
|
162
|
+
|
163
|
+
before do
|
164
|
+
plugin.register
|
165
|
+
plugin.filter(event)
|
166
|
+
end
|
167
|
+
|
168
|
+
context "when the bad IP is N/A" do
|
169
|
+
# regression test for issue https://github.com/logstash-plugins/logstash-filter-geoip/issues/50
|
170
|
+
let(:ipstring) { "N/A" }
|
171
|
+
|
172
|
+
it "should set the target field to an empty hash" do
|
173
|
+
expect(event["geoip"]).to eq({})
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should not have added any tags" do
|
177
|
+
expect(event["tags"]).to be_nil
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
context "when the bad IP is two ip comma separated" do
|
182
|
+
# regression test for issue https://github.com/logstash-plugins/logstash-filter-geoip/issues/51
|
183
|
+
let(:ipstring) { "123.45.67.89,61.160.232.222" }
|
184
|
+
|
185
|
+
it "should set the target field to an empty hash" do
|
186
|
+
expect(event["geoip"]).to eq({})
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
context "should return the correct source field in the logging message" do
|
192
|
+
sample("ip" => "-") do
|
193
|
+
expect(LogStash::Filters::GeoIP.logger).to receive(:error).with(anything, include(:field => "ip"))
|
194
|
+
subject
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
describe "an invalid database" do
|
201
|
+
config <<-CONFIG
|
202
|
+
filter {
|
203
|
+
geoip {
|
204
|
+
source => "ip"
|
205
|
+
database => "./Gemfile"
|
206
|
+
}
|
207
|
+
}
|
208
|
+
CONFIG
|
209
|
+
|
210
|
+
context "should return the correct sourcefield in the logging message" do
|
211
|
+
sample("ip" => "8.8.8.8") do
|
212
|
+
expect(LogStash::Filters::GeoIP.logger).to receive(:error).with(anything, include(:field => "ip"))
|
213
|
+
expect { subject }.to raise_error
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
Binary file
|
metadata
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: logstash-filter-geoip2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 3.0.0
|
5
|
+
platform: java
|
6
|
+
authors:
|
7
|
+
- Elastic
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-04-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '1.0'
|
19
|
+
name: logstash-core-plugin-api
|
20
|
+
prerelease: false
|
21
|
+
type: :runtime
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
name: jar-dependencies
|
34
|
+
prerelease: false
|
35
|
+
type: :development
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '3.3'
|
47
|
+
name: ruby-maven
|
48
|
+
prerelease: false
|
49
|
+
type: :development
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
name: logstash-devutils
|
62
|
+
prerelease: false
|
63
|
+
type: :development
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program. Config key is geoip2.
|
70
|
+
email: ebuildy@gmail.com
|
71
|
+
executables: []
|
72
|
+
extensions: []
|
73
|
+
extra_rdoc_files: []
|
74
|
+
files:
|
75
|
+
- CHANGELOG.md
|
76
|
+
- CONTRIBUTORS
|
77
|
+
- Gemfile
|
78
|
+
- LICENSE
|
79
|
+
- NOTICE.TXT
|
80
|
+
- README.md
|
81
|
+
- lib/com/fasterxml/jackson/core/jackson-annotations/2.6.0/jackson-annotations-2.6.0.jar
|
82
|
+
- lib/com/fasterxml/jackson/core/jackson-annotations/2.7.0/jackson-annotations-2.7.0.jar
|
83
|
+
- lib/com/fasterxml/jackson/core/jackson-core/2.6.4/jackson-core-2.6.4.jar
|
84
|
+
- lib/com/fasterxml/jackson/core/jackson-core/2.7.0/jackson-core-2.7.0.jar
|
85
|
+
- lib/com/fasterxml/jackson/core/jackson-databind/2.6.4/jackson-databind-2.6.4.jar
|
86
|
+
- lib/com/fasterxml/jackson/core/jackson-databind/2.7.0/jackson-databind-2.7.0.jar
|
87
|
+
- lib/com/maxmind/db/maxmind-db/1.1.0/maxmind-db-1.1.0.jar
|
88
|
+
- lib/com/maxmind/db/maxmind-db/1.2.0/maxmind-db-1.2.0.jar
|
89
|
+
- lib/com/maxmind/geoip2/geoip2/2.5.0/geoip2-2.5.0.jar
|
90
|
+
- lib/com/maxmind/geoip2/geoip2/2.6.0/geoip2-2.6.0.jar
|
91
|
+
- lib/logstash-filter-geoip2_jars.rb
|
92
|
+
- lib/logstash/filters/geoip2.rb
|
93
|
+
- logstash-filter-geoip.gemspec
|
94
|
+
- spec/filters/geoip_spec.rb
|
95
|
+
- vendor/GeoLite2-City.mmdb
|
96
|
+
homepage: https://github.com/ebuildy/logstash-filter-geoip
|
97
|
+
licenses:
|
98
|
+
- Apache License (2.0)
|
99
|
+
metadata:
|
100
|
+
logstash_plugin: 'true'
|
101
|
+
logstash_group: filter
|
102
|
+
post_install_message:
|
103
|
+
rdoc_options: []
|
104
|
+
require_paths:
|
105
|
+
- lib
|
106
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
requirements:
|
117
|
+
- jar com.maxmind.geoip2:geoip2, 2.5.0, :exclusions=> [com.google.http-client:google-http-client]
|
118
|
+
rubyforge_project:
|
119
|
+
rubygems_version: 2.4.8
|
120
|
+
signing_key:
|
121
|
+
specification_version: 4
|
122
|
+
summary: "$summary"
|
123
|
+
test_files:
|
124
|
+
- spec/filters/geoip_spec.rb
|