logstash-filter-schema_check 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: df4d2d0e171441ff522ca54efa4ae55cfedd9bf722e1c35a2b89282e1a5138e0
4
+ data.tar.gz: 1247588c62c88bccc3075ff5c5396e9b9397719d5a796dc2bb19e1711c0ebddb
5
+ SHA512:
6
+ metadata.gz: 6ab3ef261ed8e59097a6824616e73e394ce798f50f36aeb7ec8e8249b63af5b1444b8d9d822e1f182549ddc9ede72fe374bf2cdc7a48d74996a81e5818b763d7
7
+ data.tar.gz: 639675dfe6fc2250dc8102f13bada82683c8187a0f9ee7504200f16a52a5287efc00a970e849ffdcc5c1ac1110cda3b83f59e8eb837f603c0bb656b559e4f62c
@@ -0,0 +1,2 @@
1
+ ## 0.1.0
2
+ - Initial Generation of logstash-filter-schema_check
@@ -0,0 +1,24 @@
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 and maintainers:
5
+ * Aaron Mildenstein (untergeek)
6
+ * Darren Foo (stonith)
7
+ * Jordan Sissel (jordansissel)
8
+ * Kurt Hurtado (kurtado)
9
+ * Paul Czarkowski (paulczar)
10
+ * Pier-Hugues Pellerin (ph)
11
+ * Richard Pijnenburg (electrical)
12
+ * Suyog Rao (suyograo)
13
+ * piavlo
14
+
15
+
16
+ Target Team:
17
+ * Justin Bovee (thehybridtechnician)
18
+ * Andrew Orr (andreworr)
19
+ * Thao Vo (tnvo)
20
+
21
+ Note: If you've sent us patches, bug reports, or otherwise contributed to
22
+ Logstash, and you aren't on the list above and want to be, please let us know
23
+ and we'll make sure you're here. Contributions from folks like you are what make
24
+ open source awesome.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (C) 2018 Target Brands, Inc.
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.
@@ -0,0 +1,116 @@
1
+ # Schema Check Filter for Logstash
2
+
3
+ * This is a plugin for [Logstash](https://github.com/elastic/logstash).
4
+ * This plugin have to be installed on top of the Logstash core pipeline. It is not a stand-alone program.
5
+
6
+ [![Target’s CFC-Open-Source Slack](https://cfc-slack-inv.herokuapp.com/badge.svg?colorA=155799&colorB=159953)](https://cfc-slack-inv.herokuapp.com/)
7
+
8
+
9
+ ## Installing
10
+
11
+ This plugin is to be used with the Logstash system. It is used to check whether an event is compliant with a provided schema.
12
+
13
+ ## Installing plugin
14
+
15
+ ```sh
16
+ bin/logstash-plugin install logstash-filter-schema_check
17
+ ```
18
+
19
+ ### Example Configuration
20
+ ```ruby
21
+ input {
22
+ stdin {}
23
+ }
24
+
25
+ filter {
26
+ schema_check {
27
+ schema_path => "test.json"
28
+
29
+ }
30
+ }
31
+ }
32
+ }
33
+
34
+ ```
35
+
36
+ ### JSON Schema Example
37
+
38
+ ```json
39
+ {
40
+ "type": "object",
41
+ "properties": {
42
+ "message": {
43
+ "oneOf":[
44
+ {
45
+ "format":"ipv4",
46
+ "type":"string"
47
+ },
48
+ {
49
+ "format":"ipv6",
50
+ "type":"string"
51
+ }
52
+ ]
53
+ }
54
+ }
55
+ }
56
+ ```
57
+
58
+ ### Example run and output
59
+ `logstash -e 'input { stdin {} } filter { schema_check { schema_path => "test.json" } } output { stdout {} }'`
60
+
61
+ ```ruby
62
+ ping
63
+ {
64
+ "message" => "ping",
65
+ "@version" => "1",
66
+ "tags" => [
67
+ [0] "schema_invalid"
68
+ ],
69
+ "@timestamp" => 2018-08-06T15:49:19.021Z
70
+ }
71
+ 192.168.10.1
72
+ {
73
+ "message" => "192.168.10.1",
74
+ "@version" => "1",
75
+ "tags" => [
76
+ [0] "schema_valid"
77
+ ],
78
+ "@timestamp" => 2018-08-06T15:49:19.021Z
79
+ }
80
+
81
+ ```
82
+
83
+ ### Example run with debug and output
84
+ `logstash -e 'input { stdin {} } filter { schema_check { schema_path => "test.json" debug_output => true } } output { stdout {} }'`
85
+
86
+ ```ruby
87
+ ping
88
+ {
89
+ "message" => "ping",
90
+ "schema_errors" => [
91
+ [0] "The property '#/message' of type String did not match any of the required schemas. The schema specific errors were:\n\n- oneOf #0:\n - The property '#/message' must be a valid IPv4 address\n- oneOf #1:\n - The property '#/message' must be a valid IPv6 address"
92
+ ],
93
+ "@timestamp" => 2018-08-06T15:53:07.835Z,
94
+ "@version" => "1"
95
+ }
96
+ ```
97
+
98
+ ## Configuration Parameters
99
+
100
+ ### schema
101
+ This is schema provided by hash in the configuration instead of a separate file.
102
+ This isn't as recommended as schemas can get very large, very quickly.
103
+
104
+ ### schema_path
105
+ Path to file with schema
106
+
107
+ ### refresh_interval
108
+ Set refresh interval for reading json schema file for updates
109
+
110
+ ### debug_output
111
+ Enable debug output. This prints validation failures in an array under the
112
+ field schema_errors.
113
+
114
+
115
+ Logstash is a registered trademark of Elasticsearch BV.
116
+
@@ -0,0 +1,161 @@
1
+ # encoding: utf-8
2
+ require "logstash/filters/base"
3
+ require "logstash/namespace"
4
+ require "json"
5
+ require "json-schema"
6
+
7
+ java_import 'java.util.concurrent.locks.ReentrantReadWriteLock'
8
+
9
+ class LogStash::Filters::SchemaCheck < LogStash::Filters::Base
10
+ # configure this filter from your Logstash config.
11
+ #
12
+ # filter {
13
+ # schema_check {
14
+ # schema_path => "test.json"
15
+ # }
16
+ # }
17
+ #
18
+ # {
19
+ # "type": "object",
20
+ # "required": ["message","@version","@timestamp","host"],
21
+ # "properties": {
22
+ # "message": {
23
+ # "oneOf":[
24
+ # {
25
+ # "format":"ipv4",
26
+ # "type":"string"
27
+ # },
28
+ # {
29
+ # "format":"ipv6",
30
+ # "type":"string"
31
+ # }
32
+ # ]
33
+ # }
34
+ # }
35
+ # }
36
+ config_name "schema_check"
37
+
38
+ # Setup json schema in ruby hash inline logstash config
39
+ config :schema, :validate => :string, :default => ""
40
+ # Provide path to the json schema to use
41
+ config :schema_path, :validate => :path
42
+ # Set refresh interval for reading json schema file for updates
43
+ config :refresh_interval, :validate => :number, :default => 300
44
+ # Enable json-schema strict checking
45
+ config :strict, :validate => :boolean, :default => false
46
+ # JSON-Schema fragment option
47
+ config :fragment, :validate => :string
48
+ # JSON-Schema validate schema option
49
+ config :validate_schema, :validate => :boolean, :default => false
50
+ # Enable debug
51
+ config :debug_output, :validate => :boolean, :default => false
52
+ # Schema failures output field
53
+ config :failures_field, :validate => :string, :default => "schema_errors"
54
+ # Enable Schema Error Message
55
+ config :tag_on_failure, :validate => :array, :default => ["_schemacheckfailure"]
56
+
57
+ public
58
+ def register
59
+ rw_lock = java.util.concurrent.locks.ReentrantReadWriteLock.new
60
+ @read_lock = rw_lock.readLock
61
+ @write_lock = rw_lock.writeLock
62
+
63
+ if @schema_path && !@schema.empty?
64
+ raise LogStash::ConfigurationError, I18n.t(
65
+ "logstash.agent.configuration.invalid_plugin_register",
66
+ :plugin => "filter",
67
+ :type => "schema_check",
68
+ :error => "The configuration options 'schema' and 'schema_path' are mutually exclusive"
69
+ )
70
+ end
71
+
72
+ if @schema_path
73
+ @next_refresh = Time.now + @refresh_interval
74
+ raise_exception = true
75
+ lock_for_write { load_schema(raise_exception) }
76
+ end
77
+
78
+ @logger.debug? and @logger.debug("#{self.class.name}: schema - ", :schema => @schema)
79
+ end # def register
80
+
81
+ public
82
+ def filter(event)
83
+ if @schema_path
84
+ if needs_refresh?
85
+ lock_for_write do
86
+ if needs_refresh?
87
+ load_schema
88
+ @next_refresh = Time.now + @refresh_interval
89
+ @logger.info("refreshing schema file")
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ begin
96
+ event_obj = event.to_hash
97
+ if @debug_output
98
+ output = JSON::Validator.fully_validate(@schema, event_obj, :strict => @strict, :fragment => @fragment, :validate_schema => validate_schema)
99
+ unless output.empty?
100
+ @tag_on_failure.each {|tag| event.tag(tag)}
101
+ event.set(@failures_field, output)
102
+ end
103
+ else
104
+ unless JSON::Validator.validate(@schema, event_obj, :strict => @strict, :fragment => @fragment, :validate_schema => validate_schema)
105
+ @tag_on_failure.each {|tag| event.tag(tag)}
106
+ end
107
+ end
108
+ filter_matched(event)
109
+ rescue Exception => e
110
+ @logger.error("Something went wrong when checking schema", :exception => e, :event => event)
111
+ end
112
+ end # def filter
113
+
114
+ private
115
+ def lock_for_read
116
+ @read_lock.lock
117
+ begin
118
+ yield
119
+ ensure
120
+ @read_lock.unlock
121
+ end
122
+ end
123
+
124
+ private
125
+ def lock_for_write
126
+ @write_lock.lock
127
+ begin
128
+ yield
129
+ ensure
130
+ @write_lock.unlock
131
+ end
132
+ end
133
+
134
+ private
135
+ def load_schema(raise_exception=false)
136
+ if !File.exists?(@schema_path)
137
+ @logger.warn("schema file read failure", :path => @schema_path)
138
+ return
139
+ end
140
+ refresh_schema!(JSON.parse(File.read(@schema_path)))
141
+ end
142
+
143
+ private
144
+ def refresh_schema!(data)
145
+ @schema = data
146
+ end
147
+
148
+ def loading_exception(e, raise_exception=false)
149
+ msg = "#{self.class.name}: #{e.message} when loading schema file at #{@schema_path}"
150
+ if raise_exception
151
+ raise RuntimeError.new(msg)
152
+ else
153
+ @logger.warn("#{msg}, continuing with old schema", :schema_path => @schema_path)
154
+ end
155
+ end
156
+
157
+ private
158
+ def needs_refresh?
159
+ @next_refresh < Time.now
160
+ end
161
+ end # class LogStash::Filters::JsonSchema
@@ -0,0 +1,26 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "logstash-filter-schema_check"
3
+ s.version = "0.1.0"
4
+ s.licenses = ['Apache License (2.0)']
5
+ s.summary = 'A Logstash plugin to validate JSON schemas'
6
+ 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"
7
+ s.homepage = "http://www.elastic.co/guide/en/logstash/current/index.html"
8
+ s.authors = ["Elastic", "Justin Bovee"]
9
+ s.email = 'jbovee@thehybridtech.com'
10
+ s.require_paths = ['lib']
11
+
12
+ # Files
13
+ s.files = Dir['lib/**/*','spec/**/*','vendor/**/*','*.gemspec','*.md','CONTRIBUTORS','Gemfile','LICENSE','NOTICE.TXT']
14
+ # Tests
15
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
16
+
17
+ # Special flag to let us know this is actually a logstash plugin
18
+ s.metadata = { "logstash_plugin" => "true", "logstash_group" => "filter" }
19
+
20
+ # Gem dependencies
21
+ s.add_runtime_dependency "json-schema"
22
+ s.add_runtime_dependency 'logstash-core-plugin-api', '>= 2.1.1', '<= 2.99'
23
+
24
+ s.add_development_dependency 'rspec'
25
+ s.add_development_dependency 'logstash-devutils', "~> 1.3", ">= 1.3.1"
26
+ end
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+ require "logstash/devutils/rspec/spec_helper"
3
+ require "logstash/filters/schema_check"
4
+
5
+ describe LogStash::Filters::SchemaCheck do
6
+
7
+ context 'Inline Schema' do
8
+ describe "Test schema provided inline" do
9
+ config <<-CONFIG
10
+ filter {
11
+ schema_check {
12
+ schema => '{"type":"object","properties":{"ip_address":{"oneOf":[{"format":"ipv4","type":"string"},{"format":"ipv6","type":"string"}]}}}'
13
+ }
14
+ }
15
+ CONFIG
16
+
17
+ sample("ip_address" => "I_AM_NOT_AN_IP") do
18
+ insist { subject.get("tags") } == ["_schemacheckfailure"]
19
+ end
20
+ sample("ip_address" => "10.0.0.1") do
21
+ insist { subject.get("tags") } != ["_schemacheckfailure"]
22
+ end
23
+ end
24
+
25
+ describe "Test schema debug functionality inline" do
26
+ config <<-CONFIG
27
+ filter {
28
+ schema_check {
29
+ schema => '{"type":"object","properties":{"ip_address":{"oneOf":[{"format":"ipv4","type":"string"},{"format":"ipv6","type":"string"}]}}}'
30
+ debug_output => true
31
+ }
32
+ }
33
+ CONFIG
34
+
35
+ sample("ip_address" => "I_AM_NOT_AN_IP") do
36
+ insist { subject.get("tags") } == ["_schemacheckfailure"]
37
+ insist { subject.get("schema_errors").to be(Array) }
38
+ end
39
+ sample("ip_address" => "10.0.0.1") do
40
+ insist { subject.get("tags") } != ["_schemacheckfailure"]
41
+ end
42
+ end
43
+ end
44
+
45
+ context "File Schema" do
46
+ schema_file = File.join(File.dirname(__FILE__), "..", "fixtures", "test.json")
47
+ describe "Test schema provided from file" do
48
+ config <<-CONFIG
49
+ filter {
50
+ schema_check {
51
+ "schema_path" => "#{schema_file}"
52
+ }
53
+ }
54
+ CONFIG
55
+
56
+ sample("ip_address" => "I_AM_NOT_AN_IP") do
57
+ insist { subject.get("tags") } == ["_schemacheckfailure"]
58
+ end
59
+ sample("ip_address" => "10.0.0.1") do
60
+ insist { subject.get("tags") } != ["_schemacheckfailure"]
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,17 @@
1
+ {
2
+ "type": "object",
3
+ "properties": {
4
+ "ip_address": {
5
+ "oneOf":[
6
+ {
7
+ "format":"ipv4",
8
+ "type":"string"
9
+ },
10
+ {
11
+ "format":"ipv6",
12
+ "type":"string"
13
+ }
14
+ ]
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,2 @@
1
+ # encoding: utf-8
2
+ require "logstash/devutils/rspec/spec_helper"
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logstash-filter-schema_check
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Elastic
8
+ - Justin Bovee
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2018-10-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ name: json-schema
21
+ prerelease: false
22
+ type: :runtime
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.1.1
34
+ - - "<="
35
+ - !ruby/object:Gem::Version
36
+ version: '2.99'
37
+ name: logstash-core-plugin-api
38
+ prerelease: false
39
+ type: :runtime
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 2.1.1
45
+ - - "<="
46
+ - !ruby/object:Gem::Version
47
+ version: '2.99'
48
+ - !ruby/object:Gem::Dependency
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ name: rspec
55
+ prerelease: false
56
+ type: :development
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.3'
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 1.3.1
71
+ name: logstash-devutils
72
+ prerelease: false
73
+ type: :development
74
+ version_requirements: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - "~>"
77
+ - !ruby/object:Gem::Version
78
+ version: '1.3'
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: 1.3.1
82
+ description: This gem is a Logstash plugin required to be installed on top of the
83
+ Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This
84
+ gem is not a stand-alone program
85
+ email: jbovee@thehybridtech.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - CHANGELOG.md
91
+ - CONTRIBUTORS
92
+ - Gemfile
93
+ - LICENSE
94
+ - README.md
95
+ - lib/logstash/filters/schema_check.rb
96
+ - logstash-filter-schema_check.gemspec
97
+ - spec/filters/schema_check_spec.rb
98
+ - spec/fixtures/test.json
99
+ - spec/spec_helper.rb
100
+ homepage: http://www.elastic.co/guide/en/logstash/current/index.html
101
+ licenses:
102
+ - Apache License (2.0)
103
+ metadata:
104
+ logstash_plugin: 'true'
105
+ logstash_group: filter
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubyforge_project:
122
+ rubygems_version: 2.7.6
123
+ signing_key:
124
+ specification_version: 4
125
+ summary: A Logstash plugin to validate JSON schemas
126
+ test_files:
127
+ - spec/filters/schema_check_spec.rb
128
+ - spec/fixtures/test.json
129
+ - spec/spec_helper.rb