logstash-output-elasticsearch 2.4.2-java → 2.5.0-java

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 22b9b67e7eada407308a8da6bb3ab1c9dabe4e11
4
- data.tar.gz: e434712af48381f69dbd6eb75a3556614ea40e93
3
+ metadata.gz: 94080174a41d46422a7f94b0e9354554d3e0d66a
4
+ data.tar.gz: bddb86d2a5bbbae75734c41610588c3cf5c04f71
5
5
  SHA512:
6
- metadata.gz: b4046883d73f45496ad777cf3e3708a619e4172a07d7c8c682e459a859eac562ce130346f0164de8b8477ce14080d3bfc1bf4b5584111ac861ee0eff961d4b89
7
- data.tar.gz: 1ece9c0def2d670ebd7ffd49308c6838aa1b0c4f1c12a3aef226cda00ebf0f3e348673b68720cc396ad4ddd45f9fa7200d6017afc3867cd6bc5342c17a9c488a
6
+ metadata.gz: 4d59bc4d44c2b1918519e286efb995805abd63dd8d411ae87b82551750182b743ee56ed453d557e12769c21a3535496aa02d79ff77580ba9508499914edc61e2
7
+ data.tar.gz: fdba23ed47b9414ca87d2d7bd75a3c07c440fce5d86c49adcdb4be1a95884266e908f0b73ef55a1c895947714cd2fc19ec6bf0c8887274b9dc9ffab5c51190cc
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 2.5.0
2
+ - Host settings now are more robust to bad input
3
+ - Host settings can now take full URLs
4
+
1
5
  ## 2.4.2
2
6
  - Make flush_size actually cap the batch size in LS 2.2+
3
7
 
@@ -16,7 +16,7 @@ require "uri" # for escaping user input
16
16
  # We strongly encourage the use of HTTP over the node protocol for a number of reasons. HTTP is only marginally slower,
17
17
  # yet far easier to administer and work with. When using the HTTP protocol one may upgrade Elasticsearch versions without having
18
18
  # to upgrade Logstash in lock-step. For those still wishing to use the node or transport protocols please see
19
- # the https://www.elastic.co/guide/en/logstash/2.0/plugins-outputs-elasticsearch_java.html[logstash-output-elasticsearch_java] plugin.
19
+ # the <<plugins-outputs-elasticsearch_java,elasticsearch_java output plugin>>.
20
20
  #
21
21
  # You can learn more about Elasticsearch at <https://www.elastic.co/products/elasticsearch>
22
22
  #
@@ -81,8 +81,10 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
81
81
  # the root path for the Elasticsearch HTTP API lives.
82
82
  config :path, :validate => :string, :default => "/"
83
83
 
84
- # Enable SSL/TLS secured communication to Elasticsearch cluster
85
- config :ssl, :validate => :boolean, :default => false
84
+ # Enable SSL/TLS secured communication to Elasticsearch cluster. Leaving this unspecified will use whatever scheme
85
+ # is specified in the URLs listed in 'hosts'. If no explicit protocol is specified plain HTTP will be used.
86
+ # If SSL is explicitly disabled here the plugin will refuse to start if an HTTPS URL is given in 'hosts'
87
+ config :ssl, :validate => :boolean
86
88
 
87
89
  # Option to validate the server's certificate. Disabling this severely compromises security.
88
90
  # For more information on disabling certificate verification please read
@@ -74,6 +74,9 @@ module LogStash; module Outputs; class ElasticSearch
74
74
  # Remember the `http` protocol uses the http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-http.html#modules-http[http] address (eg. 9200, not 9300).
75
75
  # `"127.0.0.1"`
76
76
  # `["127.0.0.1:9200","127.0.0.2:9200"]`
77
+ # `["http://127.0.0.1"]`
78
+ # `["https://127.0.0.1:9200"]`
79
+ # `["https://127.0.0.1:9200/mypath"]` (If using a proxy on a subpath)
77
80
  # It is important to exclude http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-node.html[dedicated master nodes] from the `hosts` list
78
81
  # to prevent LS from sending bulk requests to the master nodes. So this parameter should only reference either data or client nodes in Elasticsearch.
79
82
  mod.config :hosts, :validate => :array, :default => ["127.0.0.1"]
@@ -105,18 +105,10 @@ module LogStash; module Outputs; class ElasticSearch;
105
105
  client_settings = options[:client_settings] || {}
106
106
  timeout = options[:timeout] || 0
107
107
 
108
- uris = hosts.map do |host|
109
- proto = client_settings[:ssl] ? "https" : "http"
110
- if host =~ /:\d+\z/
111
- "#{proto}://#{host}#{client_settings[:path]}"
112
- else
113
- # Use default port of 9200 if none provided with host.
114
- "#{proto}://#{host}:9200#{client_settings[:path]}"
115
- end
116
- end
108
+ urls = hosts.map {|host| host_to_url(host, client_settings[:ssl], client_settings[:path])}
117
109
 
118
110
  @client_options = {
119
- :hosts => uris,
111
+ :hosts => urls,
120
112
  :ssl => client_settings[:ssl],
121
113
  :transport_options => {
122
114
  :socket_timeout => timeout,
@@ -136,6 +128,61 @@ module LogStash; module Outputs; class ElasticSearch;
136
128
  Elasticsearch::Client.new(client_options)
137
129
  end
138
130
 
131
+ HOSTNAME_PORT_REGEX=/\A(?<hostname>([A-Za-z0-9\.\-]+)|\[[0-9A-Fa-f\:]+\])(:(?<port>\d+))?\Z/
132
+ URL_REGEX=/\A#{URI::regexp(['http', 'https'])}\z/
133
+ # Parse a configuration host to a normalized URL
134
+ def host_to_url(host, ssl=nil, path=nil)
135
+ explicit_scheme = case ssl
136
+ when true
137
+ "https"
138
+ when false
139
+ "http"
140
+ else
141
+ nil
142
+ end
143
+
144
+ # Ensure path starts with a /
145
+ if path && path[0] != '/'
146
+ path = "/#{path}"
147
+ end
148
+
149
+ url = nil
150
+ if host =~ URL_REGEX
151
+ url = URI.parse(host)
152
+
153
+ # Please note that the ssl == nil case is different! If you didn't make an explicit
154
+ # choice we don't complain!
155
+ if url.scheme == "http" && ssl == true
156
+ raise LogStash::ConfigurationError, "You specified a plain 'http' URL '#{host}' but set 'ssl' to true! Aborting!"
157
+ elsif url.scheme == "https" && ssl == false
158
+ raise LogStash::ConfigurationError, "You have explicitly disabled SSL but passed in an https URL '#{host}'! Aborting!"
159
+ end
160
+
161
+ url.scheme = explicit_scheme if explicit_scheme
162
+ elsif (match_results = HOSTNAME_PORT_REGEX.match(host))
163
+ hostname = match_results["hostname"]
164
+ port = match_results["port"] || 9200
165
+ url = URI.parse("#{explicit_scheme || 'http'}://#{hostname}:#{port}")
166
+ else
167
+ raise LogStash::ConfigurationError, "Host '#{host}' was specified, but is not valid! Use either a full URL or a hostname:port string!"
168
+ end
169
+
170
+ if path && url.path && url.path != "/" && url.path != ''
171
+ raise LogStash::ConfigurationError, "A path '#{url.path}' has been explicitly specified in the url '#{url}', but you also specified a path of '#{path}'. This is probably a mistake, please remove one setting."
172
+ end
173
+
174
+ if path
175
+ url.path = path # The URI library cannot stringify if it holds a nil
176
+ end
177
+
178
+ if url.password || url.user
179
+ raise LogStash::ConfigurationError, "We do not support setting the user password in the URL directly as " +
180
+ "this may be logged to disk thus leaking credentials. Use the 'user' and 'password' options respectively"
181
+ end
182
+
183
+ url.to_s
184
+ end
185
+
139
186
  def template_exists?(name)
140
187
  @client.indices.get_template(:name => name)
141
188
  return true
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-output-elasticsearch'
4
- s.version = '2.4.2'
4
+ s.version = '2.5.0'
5
5
  s.licenses = ['apache-2.0']
6
6
  s.summary = "Logstash Output to Elasticsearch"
7
7
  s.description = "Output events to elasticsearch"
@@ -0,0 +1,129 @@
1
+ require "logstash/devutils/rspec/spec_helper"
2
+ require "logstash/outputs/elasticsearch/http_client"
3
+ require "java"
4
+
5
+ describe LogStash::Outputs::ElasticSearch::HttpClient do
6
+ let(:base_options) { {:hosts => ["127.0.0.1"], :logger => Cabin::Channel.get }}
7
+
8
+ describe "Host/URL Parsing" do
9
+ subject { described_class.new(base_options) }
10
+
11
+ let(:true_hostname) { "my-dash.hostname" }
12
+ let(:ipv6_hostname) { "[::1]" }
13
+ let(:ipv4_hostname) { "127.0.0.1" }
14
+ let(:port) { 9202 }
15
+ let(:hostname_port) { "#{hostname}:#{port}"}
16
+ let(:http_hostname_port) { "http://#{hostname_port}"}
17
+ let(:https_hostname_port) { "https://#{hostname_port}"}
18
+ let(:http_hostname_port_path) { "http://#{hostname_port}/path"}
19
+
20
+ shared_examples("proper host handling") do
21
+ it "should properly transform a host:port string to a URL" do
22
+ expect(subject.send(:host_to_url, hostname_port)).to eql(http_hostname_port)
23
+ end
24
+
25
+ it "should raise an error when a partial URL is an invalid format" do
26
+ expect {
27
+ subject.send(:host_to_url, "#{hostname_port}/")
28
+ }.to raise_error(LogStash::ConfigurationError)
29
+ end
30
+
31
+ it "should not raise an error with a / for a path" do
32
+ expect(subject.send(:host_to_url, "#{http_hostname_port}/")).to eql("#{http_hostname_port}/")
33
+ end
34
+
35
+ it "should parse full URLs correctly" do
36
+ expect(subject.send(:host_to_url, http_hostname_port)).to eql(http_hostname_port)
37
+ end
38
+
39
+ it "should reject full URLs with usernames and passwords" do
40
+ expect {
41
+ subject.send(:host_to_url, "http://user:password@host.domain")
42
+ }.to raise_error(LogStash::ConfigurationError)
43
+ end
44
+
45
+ describe "ssl" do
46
+ it "should refuse to handle an http url when ssl is true" do
47
+ expect {
48
+ subject.send(:host_to_url, http_hostname_port, true)
49
+ }.to raise_error(LogStash::ConfigurationError)
50
+ end
51
+
52
+ it "should refuse to handle an https url when ssl is false" do
53
+ expect {
54
+ subject.send(:host_to_url, https_hostname_port, false)
55
+ }.to raise_error(LogStash::ConfigurationError)
56
+ end
57
+
58
+ it "should handle an ssl url correctly when SSL is nil" do
59
+ expect(subject.send(:host_to_url, https_hostname_port, nil)).to eql(https_hostname_port)
60
+ end
61
+ end
62
+
63
+ describe "path" do
64
+ it "should allow paths in a url" do
65
+ expect(subject.send(:host_to_url, http_hostname_port_path, nil)).to eql(http_hostname_port_path)
66
+ end
67
+
68
+ it "should not allow paths in two places" do
69
+ expect {
70
+ subject.send(:host_to_url, http_hostname_port_path, false, "/otherpath")
71
+ }.to raise_error(LogStash::ConfigurationError)
72
+ end
73
+
74
+ it "should automatically insert a / in front of path overlays if needed" do
75
+ expect(subject.send(:host_to_url, http_hostname_port, false, "otherpath")).to eql(http_hostname_port + "/otherpath")
76
+ end
77
+ end
78
+ end
79
+
80
+ describe "an regular hostname" do
81
+ let(:hostname) { true_hostname }
82
+ include_examples("proper host handling")
83
+ end
84
+
85
+ describe "an ipv4 host" do
86
+ let(:hostname) { ipv4_hostname }
87
+ include_examples("proper host handling")
88
+ end
89
+
90
+ describe "an ipv6 host" do
91
+ let(:hostname) { ipv6_hostname }
92
+ include_examples("proper host handling")
93
+ end
94
+ end
95
+
96
+ describe "sniffing" do
97
+ let(:client) { LogStash::Outputs::ElasticSearch::HttpClient.new(base_options.merge(client_opts)) }
98
+ let(:transport) { client.client.transport }
99
+
100
+ before do
101
+ allow(transport).to receive(:reload_connections!)
102
+ end
103
+
104
+ context "with sniffing enabled" do
105
+ let(:client_opts) { {:sniffing => true, :sniffing_delay => 1 } }
106
+
107
+ after do
108
+ client.stop_sniffing!
109
+ end
110
+
111
+ it "should start the sniffer" do
112
+ expect(client.sniffer_thread).to be_a(Thread)
113
+ end
114
+
115
+ it "should periodically sniff the client" do
116
+ sleep 2
117
+ expect(transport).to have_received(:reload_connections!).at_least(:once)
118
+ end
119
+ end
120
+
121
+ context "with sniffing disabled" do
122
+ let(:client_opts) { {:sniffing => false} }
123
+
124
+ it "should not start the sniffer" do
125
+ expect(client.sniffer_thread).to be_nil
126
+ end
127
+ end
128
+ end
129
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-output-elasticsearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.2
4
+ version: 2.5.0
5
5
  platform: java
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-02 00:00:00.000000000 Z
11
+ date: 2016-02-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -223,7 +223,7 @@ files:
223
223
  - spec/integration/outputs/update_spec.rb
224
224
  - spec/unit/buffer_spec.rb
225
225
  - spec/unit/http_client_builder_spec.rb
226
- - spec/unit/outputs/elasticsearch/protocol_spec.rb
226
+ - spec/unit/outputs/elasticsearch/http_client_spec.rb
227
227
  - spec/unit/outputs/elasticsearch_proxy_spec.rb
228
228
  - spec/unit/outputs/elasticsearch_spec.rb
229
229
  - spec/unit/outputs/elasticsearch_ssl_spec.rb
@@ -268,7 +268,7 @@ test_files:
268
268
  - spec/integration/outputs/update_spec.rb
269
269
  - spec/unit/buffer_spec.rb
270
270
  - spec/unit/http_client_builder_spec.rb
271
- - spec/unit/outputs/elasticsearch/protocol_spec.rb
271
+ - spec/unit/outputs/elasticsearch/http_client_spec.rb
272
272
  - spec/unit/outputs/elasticsearch_proxy_spec.rb
273
273
  - spec/unit/outputs/elasticsearch_spec.rb
274
274
  - spec/unit/outputs/elasticsearch_ssl_spec.rb
@@ -1,41 +0,0 @@
1
- require "logstash/devutils/rspec/spec_helper"
2
- require "logstash/outputs/elasticsearch/http_client"
3
- require "java"
4
-
5
- describe LogStash::Outputs::ElasticSearch::HttpClient do
6
- describe "sniffing" do
7
- let(:base_options) { {:hosts => ["127.0.0.1"], :logger => Cabin::Channel.get }}
8
- let(:client) { LogStash::Outputs::ElasticSearch::HttpClient.new(base_options.merge(client_opts)) }
9
- let(:transport) { client.client.transport }
10
-
11
- before do
12
- allow(transport).to receive(:reload_connections!)
13
- end
14
-
15
- context "with sniffing enabled" do
16
- let(:client_opts) { {:sniffing => true, :sniffing_delay => 1 } }
17
-
18
- after do
19
- client.stop_sniffing!
20
- end
21
-
22
- it "should start the sniffer" do
23
- expect(client.sniffer_thread).to be_a(Thread)
24
- end
25
-
26
- it "should periodically sniff the client" do
27
- sleep 2
28
- expect(transport).to have_received(:reload_connections!).at_least(:once)
29
- end
30
- end
31
-
32
- context "with sniffing disabled" do
33
- let(:client_opts) { {:sniffing => false} }
34
-
35
- it "should not start the sniffer" do
36
- expect(client.sniffer_thread).to be_nil
37
- end
38
- end
39
-
40
- end
41
- end