logstash-output-http_auth 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 183a95d1df45ea65b0402888c9a74258dac4d849
4
+ data.tar.gz: 53ec525af25f06370ec2e062dac4e41abd152425
5
+ SHA512:
6
+ metadata.gz: e288eb3dfe9e7363a1f09a9574c8725e36acfb59b6c7077a62933932649df500d32712a4af09aa783aec981b93170f3601af51f985c6b2d4d1404fadb416265c
7
+ data.tar.gz: 65731cca9d4e0d1c1201a115bebc0611df49f825a2f4f50f8207c8b7b68e70bd9c43e3a406ed1453f8a2b1a09c3583a6985a15f5a0b47d7641a9ff71c83e3fd8
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ Gemfile.lock
2
+ .ruby-version
3
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2012-2014 Elasticsearch <http://www.elasticsearch.org>
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/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ @files=[]
2
+
3
+ task :default do
4
+ system("rake -T")
5
+ end
6
+
7
+ require "logstash/devutils/rake"
@@ -0,0 +1,239 @@
1
+ # encoding: utf-8
2
+ require "logstash/outputs/base"
3
+ require "logstash/namespace"
4
+ require "logstash/json"
5
+
6
+ class LogStash::Outputs::HttpAuth < LogStash::Outputs::Base
7
+ # This output lets you `PUT` or `POST` events to a
8
+ # generic HTTP(S) endpoint
9
+ #
10
+ # Additionally, you are given the option to customize
11
+ # the headers sent as well as basic customization of the
12
+ # event json itself.
13
+ #
14
+ # In addition to default http-plugin, you need 2 way authentication
15
+ # with csrf_token verification? This is you plugin!
16
+
17
+ config_name "http_auth"
18
+
19
+ # If sign in is desired
20
+ config :sign_in, :validate => :boolean, :default => false
21
+
22
+ # Params to be sent within the body
23
+ config :sign_in_params, :validate => :hash
24
+
25
+ # Host-address of the server
26
+ config :host, :validate => :string
27
+
28
+ # Port of the server
29
+ config :port, :validate => :number
30
+
31
+ # Root path of the application to get the csrf-cookie
32
+ config :root_path, :validate => :string, :default => "/"
33
+
34
+ # Path of the action to be called
35
+ config :path, :validate => :string
36
+
37
+ # Sign-In path of the application to be authenticated
38
+ config :sign_in_path, :validate => :string, :default => "/users/sign_in"
39
+
40
+ # URL to use
41
+ config :url, :validate => :string
42
+
43
+ # validate SSL?
44
+ config :verify_ssl, :validate => :boolean, :default => true
45
+
46
+ # What verb to use
47
+ # only put and post are supported for now
48
+ config :http_method, :validate => ["put", "post"], :required => :true
49
+
50
+ # Custom headers to use
51
+ # format is `headers => ["X-My-Header", "%{host}"]
52
+ config :headers, :validate => :hash
53
+
54
+ # Content type
55
+ #
56
+ # If not specified, this defaults to the following:
57
+ #
58
+ # * if format is "json", "application/json"
59
+ # * if format is "form", "application/x-www-form-urlencoded"
60
+ config :content_type, :validate => :string
61
+
62
+ # This lets you choose the structure and parts of the event that are sent.
63
+ #
64
+ #
65
+ # For example:
66
+ #
67
+ # mapping => ["foo", "%{host}", "bar", "%{type}"]
68
+ config :mapping, :validate => :hash
69
+
70
+ # Set the format of the http body.
71
+ #
72
+ # If form, then the body will be the mapping (or whole event) converted
73
+ # into a query parameter string (foo=bar&baz=fizz...)
74
+ #
75
+ # If message, then the body will be the result of formatting the event according to message
76
+ #
77
+ # Otherwise, the event is sent as json.
78
+ config :format, :validate => ["json", "form", "message"], :default => "json"
79
+
80
+ config :message, :validate => :string
81
+
82
+ public
83
+ def register
84
+ require "ftw"
85
+ require "uri"
86
+ @agent = FTW::Agent.new
87
+
88
+ if @content_type.nil?
89
+ case @format
90
+ when "form" ; @content_type = "application/x-www-form-urlencoded"
91
+ when "json" ; @content_type = "application/json"
92
+ end
93
+ end
94
+
95
+ if @format == "message"
96
+ if @message.nil?
97
+ raise "message must be set if message format is used"
98
+ end
99
+ if @content_type.nil?
100
+ raise "content_type must be set if message format is used"
101
+ end
102
+ unless @mapping.nil?
103
+ @logger.warn "mapping is not supported and will be ignored if message format is used"
104
+ end
105
+ end
106
+
107
+ @signed_in = false
108
+ @csrf_token = nil
109
+ @cookies = nil
110
+ end # def register
111
+
112
+ public
113
+ def receive(event)
114
+ return unless output?(event)
115
+
116
+ sign_in() if @sign_in
117
+
118
+ if @mapping
119
+ evt = Hash.new
120
+ @mapping.each do |k,v|
121
+ evt[k] = event.sprintf(v)
122
+ end
123
+ else
124
+ evt = event.to_hash
125
+ end
126
+
127
+ @url = URI::HTTP.build({:host => @host, :port=> @port, :path => @path}) if @url.nil?
128
+
129
+ case @http_method
130
+ when "put"
131
+ request = @agent.put(event.sprintf(@url))
132
+ when "post"
133
+ request = @agent.post(event.sprintf(@url))
134
+ else
135
+ @logger.error("Unknown verb:", :verb => @http_method)
136
+ end
137
+
138
+ if @headers
139
+ @headers.each do |k,v|
140
+ request.headers[k] = event.sprintf(v)
141
+ end
142
+ end
143
+
144
+ request["Content-Type"] = @content_type
145
+
146
+ set_header(request)
147
+
148
+ begin
149
+ if @format == "json"
150
+ request.body = evt.to_json
151
+ elsif @format == "message"
152
+ request.body = event.sprintf(@message)
153
+ else
154
+ request.body = encode(evt)
155
+ end
156
+
157
+ response = @agent.execute(request)
158
+
159
+ @signed_in = status_success?(response.status)
160
+
161
+ @logger.warn("Response Status #{response.status} for request #{@http_method} to #{@url}") if !status_success?(response.status)
162
+
163
+ rescue Exception => e
164
+ @logger.warn("Unhandled exception", :request => request, :response => response, :exception => e, :stacktrace => e.backtrace)
165
+ end
166
+ end # def receive
167
+
168
+ private
169
+ def encode(hash)
170
+ return hash.collect do |key, value|
171
+ CGI.escape(key) + "=" + CGI.escape(value)
172
+ end.join("&")
173
+ end # def encode
174
+
175
+ def set_cookies(response)
176
+ set_cookie = response.headers['set-cookie']
177
+
178
+ if(!set_cookie.nil? && !set_cookie.empty?)
179
+ cookies = []
180
+ set_cookie.each do |c|
181
+ cookie = c.split('; ')[0]
182
+
183
+ @csrf_token = CGI.unescape(cookie.split('=')[1]) if cookie.start_with?('XSRF-TOKEN')
184
+
185
+ cookies << cookie
186
+ end
187
+ @cookies = cookies.join('; ') if !cookies.empty?
188
+ end
189
+ end
190
+
191
+ def sign_in
192
+ if(!@signed_in)
193
+ if(@cookies.nil?)
194
+ request = @agent.get(
195
+ URI::HTTP.build({:host => @host, :port=> @port, :path => @root_path})
196
+ )
197
+ request["Content-Type"] = @content_type
198
+ response = @agent.execute(request)
199
+
200
+ set_cookies(response)
201
+ end
202
+
203
+ request = @agent.post(
204
+ URI::HTTP.build({:host => @host, :port=> @port, :path => @sign_in_path})
205
+ )
206
+ request["Content-Type"] = @content_type
207
+
208
+ set_header(request)
209
+
210
+ body = Hash.new
211
+ @sign_in_params.each do |k,v|
212
+ body[k] = v
213
+ end
214
+
215
+ request.body = body.to_json
216
+
217
+ response = @agent.execute(request)
218
+
219
+ set_cookies(response)
220
+
221
+ # status 2xx success
222
+ @signed_in = status_success?(response.status)
223
+ end
224
+ end
225
+
226
+ def set_header(request)
227
+ request.headers['Cookie'] = @cookies if !@cookies.nil?
228
+
229
+ if !@csrf_token.nil?
230
+ request.headers['X-Requested-With'] = 'XMLHttpRequest'
231
+ request.headers['X-CSRF-Token'] = @csrf_token
232
+ request.headers['X-XSRF-Token'] = @csrf_token
233
+ end
234
+ end
235
+
236
+ def status_success?(status)
237
+ status >= 200 && status < 300
238
+ end
239
+ end
@@ -0,0 +1,29 @@
1
+ Gem::Specification.new do |s|
2
+
3
+ s.name = 'logstash-output-http_auth'
4
+ s.version = '0.1.0'
5
+ s.licenses = ['Apache License (2.0)']
6
+ s.summary = "This output lets you `PUT` or `POST` events to a generic HTTP(S) endpoint with 2 way authentication"
7
+ s.description = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program"
8
+ s.authors = ["Signify"]
9
+ s.email = 'dietmar@signifydata.com'
10
+ s.homepage = "http://www.signifydata.com"
11
+ s.require_paths = ["lib"]
12
+
13
+ # Files
14
+ s.files = `git ls-files`.split($\)+::Dir.glob('vendor/*')
15
+
16
+ # Tests
17
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
18
+
19
+ # Special flag to let us know this is actually a logstash plugin
20
+ s.metadata = { "logstash_plugin" => "true", "logstash_group" => "output" }
21
+
22
+ # Gem dependencies
23
+ s.add_runtime_dependency 'logstash-core', '>= 1.4.0', '< 2.0.0'
24
+
25
+ s.add_runtime_dependency 'ftw', ['~> 0.0.40']
26
+
27
+ s.add_development_dependency 'logstash-devutils'
28
+ end
29
+
@@ -0,0 +1,5 @@
1
+ require "logstash/devutils/rspec/spec_helper"
2
+ require 'logstash/outputs/http_auth'
3
+
4
+ describe LogStash::Outputs::HttpAuth do
5
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logstash-output-http_auth
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Signify
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-08-25 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.4.0
19
+ - - <
20
+ - !ruby/object:Gem::Version
21
+ version: 2.0.0
22
+ name: logstash-core
23
+ prerelease: false
24
+ type: :runtime
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.4.0
30
+ - - <
31
+ - !ruby/object:Gem::Version
32
+ version: 2.0.0
33
+ - !ruby/object:Gem::Dependency
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ~>
37
+ - !ruby/object:Gem::Version
38
+ version: 0.0.40
39
+ name: ftw
40
+ prerelease: false
41
+ type: :runtime
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: 0.0.40
47
+ - !ruby/object:Gem::Dependency
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ name: logstash-devutils
54
+ prerelease: false
55
+ type: :development
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ description: This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program
62
+ email: dietmar@signifydata.com
63
+ executables: []
64
+ extensions: []
65
+ extra_rdoc_files: []
66
+ files:
67
+ - .gitignore
68
+ - Gemfile
69
+ - LICENSE
70
+ - Rakefile
71
+ - lib/logstash/outputs/http_auth.rb
72
+ - logstash-output-http_auth.gemspec
73
+ - spec/outputs/http_auth_spec.rb
74
+ homepage: http://www.signifydata.com
75
+ licenses:
76
+ - Apache License (2.0)
77
+ metadata:
78
+ logstash_plugin: 'true'
79
+ logstash_group: output
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 2.1.9
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: This output lets you `PUT` or `POST` events to a generic HTTP(S) endpoint with 2 way authentication
100
+ test_files:
101
+ - spec/outputs/http_auth_spec.rb