logstash-output-elasticsearch 10.4.2-java → 10.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
  SHA256:
3
- metadata.gz: 7f27a5838e3f5abb53fb561802f1fa6f88e25b43f252951f6a2e8a1a8402d11a
4
- data.tar.gz: d77d44f5f208793751f7e026a47806523158f490fd0872f739aea9102acae7a5
3
+ metadata.gz: 71b5bb8d2a918b37ee594c9bcbe11ec872dbfb2ee30094a6b2ede8ea4550fb46
4
+ data.tar.gz: fc4c5cba1d3cc99cfbdf17f3658723d97889e7d0c824dc430986f5f64ea652e0
5
5
  SHA512:
6
- metadata.gz: a64c0b9981fb551cba3a566a6c519d99579b5827128c3320ea77cd9c47932a54f0bcfcba9f94ca57c8570e428f8efde54f1e94d5351ec21ce91a95bf70999bce
7
- data.tar.gz: dd082458727f7b7bfaa8273606e12b131efe6fbd035f25f881d118e59e15fa0d556db1f4675baede6955827b89a1f127d05e16a86d11bf2f97b39861a68df945
6
+ metadata.gz: 036130a59c31c2634db172b37a918fdcb29ca93d608f1cfb80a54a5f0e3620b0766acec221f0c2ef0c65e7f764085ac67f16d5263fea9b72d5b5256f8ac7be98
7
+ data.tar.gz: 0b27c6975420f0390d945bc7bdabd9fd5afabe12d8a5a20a4ccb6cc2d2ea5da2946942c76b8fc67de5bee97063b5771770a74e89a7f40f846df1979c798e9499
data/CHANGELOG.md CHANGED
@@ -1,5 +1,5 @@
1
- ## 10.4.2
2
- - Changed cloud id, credential and host setup to happen in `build_client` [#939](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/939)
1
+ ## 10.5.0
2
+ - Added api_key support [#934](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/934)
3
3
 
4
4
  ## 10.4.1
5
5
  - [DOC] Added note about `_type` setting change from `doc` to `_doc` [#884](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/884)
data/docs/index.asciidoc CHANGED
@@ -232,6 +232,9 @@ Elasticsearch] to take advantage of response compression when using this plugin
232
232
  For requests compression, regardless of the Elasticsearch version, users have to enable `http_compression`
233
233
  setting in their Logstash config file.
234
234
 
235
+ ==== Authentication
236
+
237
+ Authentication to a secure Elasticsearch cluster is possible using one of the `user`/`password`, `cloud_auth` or `api_key` options.
235
238
 
236
239
  [id="plugins-{type}s-{plugin}-options"]
237
240
  ==== Elasticsearch Output Configuration Options
@@ -242,6 +245,7 @@ This plugin supports the following configuration options plus the <<plugins-{typ
242
245
  |=======================================================================
243
246
  |Setting |Input type|Required
244
247
  | <<plugins-{type}s-{plugin}-action>> |<<string,string>>|No
248
+ | <<plugins-{type}s-{plugin}-api_key>> |<<password,password>>|No
245
249
  | <<plugins-{type}s-{plugin}-bulk_path>> |<<string,string>>|No
246
250
  | <<plugins-{type}s-{plugin}-cacert>> |a valid filesystem path|No
247
251
  | <<plugins-{type}s-{plugin}-cloud_auth>> |<<password,password>>|No
@@ -324,6 +328,16 @@ The Elasticsearch action to perform. Valid actions are:
324
328
 
325
329
  For more details on actions, check out the http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html[Elasticsearch bulk API documentation]
326
330
 
331
+ [id="plugins-{type}s-{plugin}-api_key"]
332
+ ===== `api_key`
333
+
334
+ * Value type is <<password,password>>
335
+ * There is no default value for this setting.
336
+
337
+ Authenticate using Elasticsearch API key. Note that this option also requires enabling the `ssl` option.
338
+
339
+ Format is `id:api_key` where `id` and `api_key` are as returned by the Elasticsearch https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html[Create API key API].
340
+
327
341
  [id="plugins-{type}s-{plugin}-bulk_path"]
328
342
  ===== `bulk_path`
329
343
 
@@ -122,6 +122,10 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
122
122
  # Password to authenticate to a secure Elasticsearch cluster
123
123
  config :password, :validate => :password
124
124
 
125
+ # Authenticate using Elasticsearch API key.
126
+ # format is id:api_key (as returned by https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html[Create API key])
127
+ config :api_key, :validate => :password
128
+
125
129
  # Cloud authentication string ("<username>:<password>" format) is an alternative for the `user`/`password` configuration.
126
130
  #
127
131
  # For more details, check out the https://www.elastic.co/guide/en/logstash/current/connecting-to-cloud.html#_cloud_auth[cloud documentation]
@@ -255,7 +259,11 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
255
259
  end
256
260
 
257
261
  def build_client
258
- fill_user_password_from_cloud_auth
262
+ # the following 3 options validation & setup methods are called inside build_client
263
+ # because they must be executed prior to building the client and logstash
264
+ # monitoring and management rely on directly calling build_client
265
+ # see https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/934#pullrequestreview-396203307
266
+ validate_authentication
259
267
  fill_hosts_from_cloud_id
260
268
  setup_hosts
261
269
 
@@ -20,7 +20,6 @@ module LogStash; module Outputs; class ElasticSearch;
20
20
  @stopping = Concurrent::AtomicBoolean.new(false)
21
21
  # To support BWC, we check if DLQ exists in core (< 5.4). If it doesn't, we use nil to resort to previous behavior.
22
22
  @dlq_writer = dlq_enabled? ? execution_context.dlq_writer : nil
23
-
24
23
  build_client
25
24
  setup_after_successful_connection
26
25
  check_action_validity
@@ -109,6 +108,28 @@ module LogStash; module Outputs; class ElasticSearch;
109
108
  [action, params, event]
110
109
  end
111
110
 
111
+ def validate_authentication
112
+ authn_options = 0
113
+ authn_options += 1 if @cloud_auth
114
+ authn_options += 1 if (@api_key && @api_key.value)
115
+ authn_options += 1 if (@user || (@password && @password.value))
116
+
117
+ if authn_options > 1
118
+ raise LogStash::ConfigurationError, 'Multiple authentication options are specified, please only use one of user/password, cloud_auth or api_key'
119
+ end
120
+
121
+ if @api_key && @api_key.value && @ssl != true
122
+ raise(LogStash::ConfigurationError, "Using api_key authentication requires SSL/TLS secured communication using the `ssl => true` option")
123
+ end
124
+
125
+ if @cloud_auth
126
+ @user, @password = parse_user_password_from_cloud_auth(@cloud_auth)
127
+ # params is the plugin global params hash which will be passed to HttpClientBuilder.build
128
+ params['user'], params['password'] = @user, @password
129
+ end
130
+ end
131
+ private :validate_authentication
132
+
112
133
  def setup_hosts
113
134
  @hosts = Array(@hosts)
114
135
  if @hosts.empty?
@@ -132,16 +153,6 @@ module LogStash; module Outputs; class ElasticSearch;
132
153
  @hosts = parse_host_uri_from_cloud_id(@cloud_id)
133
154
  end
134
155
 
135
- def fill_user_password_from_cloud_auth
136
- return unless @cloud_auth
137
-
138
- if @user || @password
139
- raise LogStash::ConfigurationError, 'Both cloud_auth and user/password specified, please only use one.'
140
- end
141
- @user, @password = parse_user_password_from_cloud_auth(@cloud_auth)
142
- params['user'], params['password'] = @user, @password
143
- end
144
-
145
156
  def parse_host_uri_from_cloud_id(cloud_id)
146
157
  begin # might not be available on older LS
147
158
  require 'logstash/util/cloud_setting_id'
@@ -1,4 +1,5 @@
1
1
  require 'cgi'
2
+ require "base64"
2
3
 
3
4
  module LogStash; module Outputs; class ElasticSearch;
4
5
  module HttpClientBuilder
@@ -8,7 +9,7 @@ module LogStash; module Outputs; class ElasticSearch;
8
9
  :pool_max_per_route => params["pool_max_per_route"],
9
10
  :check_connection_timeout => params["validate_after_inactivity"],
10
11
  :http_compression => params["http_compression"],
11
- :headers => params["custom_headers"]
12
+ :headers => params["custom_headers"] || {}
12
13
  }
13
14
 
14
15
  client_settings[:proxy] = params["proxy"] if params["proxy"]
@@ -56,6 +57,7 @@ module LogStash; module Outputs; class ElasticSearch;
56
57
 
57
58
  client_settings.merge! setup_ssl(logger, params)
58
59
  common_options.merge! setup_basic_auth(logger, params)
60
+ client_settings[:headers].merge! setup_api_key(logger, params)
59
61
 
60
62
  external_version_types = ["external", "external_gt", "external_gte"]
61
63
  # External Version validation
@@ -151,6 +153,14 @@ module LogStash; module Outputs; class ElasticSearch;
151
153
  }
152
154
  end
153
155
 
156
+ def self.setup_api_key(logger, params)
157
+ api_key = params["api_key"]
158
+
159
+ return {} unless (api_key && api_key.value)
160
+
161
+ { "Authorization" => "ApiKey " + Base64.strict_encode64(api_key.value) }
162
+ end
163
+
154
164
  private
155
165
  def self.dedup_slashes(url)
156
166
  url.gsub(/\/+/, "/")
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-output-elasticsearch'
3
- s.version = '10.4.2'
3
+ s.version = '10.5.0'
4
4
 
5
5
  s.licenses = ['apache-2.0']
6
6
  s.summary = "Stores logs in Elasticsearch"
@@ -1,4 +1,5 @@
1
1
  require_relative "../../../spec/es_spec_helper"
2
+ require "base64"
2
3
  require "flores/random"
3
4
  require "logstash/outputs/elasticsearch"
4
5
 
@@ -142,6 +143,25 @@ describe LogStash::Outputs::ElasticSearch do
142
143
 
143
144
  include_examples("an authenticated config")
144
145
  end
146
+
147
+ context 'claud_auth also set' do
148
+ let(:do_register) { false } # this is what we want to test, so we disable the before(:each) call
149
+ let(:options) { { "user" => user, "password" => password, "cloud_auth" => "elastic:my-passwd-00" } }
150
+
151
+ it "should fail" do
152
+ expect { subject.register }.to raise_error LogStash::ConfigurationError, /Multiple authentication options are specified/
153
+ end
154
+ end
155
+
156
+ context 'api_key also set' do
157
+ let(:do_register) { false } # this is what we want to test, so we disable the before(:each) call
158
+ let(:options) { { "user" => user, "password" => password, "api_key" => "some_key" } }
159
+
160
+ it "should fail" do
161
+ expect { subject.register }.to raise_error LogStash::ConfigurationError, /Multiple authentication options are specified/
162
+ end
163
+ end
164
+
145
165
  end
146
166
 
147
167
  describe "with path" do
@@ -577,7 +597,15 @@ describe LogStash::Outputs::ElasticSearch do
577
597
  let(:options) { { 'cloud_auth' => 'elastic:my-passwd-00', 'user' => 'another' } }
578
598
 
579
599
  it "should fail" do
580
- expect { subject.register }.to raise_error LogStash::ConfigurationError, /cloud_auth and user/
600
+ expect { subject.register }.to raise_error LogStash::ConfigurationError, /Multiple authentication options are specified/
601
+ end
602
+ end
603
+
604
+ context 'api_key also set' do
605
+ let(:options) { { 'cloud_auth' => 'elastic:my-passwd-00', 'api_key' => 'some_key' } }
606
+
607
+ it "should fail" do
608
+ expect { subject.register }.to raise_error LogStash::ConfigurationError, /Multiple authentication options are specified/
581
609
  end
582
610
  end
583
611
  end if LOGSTASH_VERSION > '6.0'
@@ -659,6 +687,62 @@ describe LogStash::Outputs::ElasticSearch do
659
687
  end
660
688
  end
661
689
 
690
+ describe "API key" do
691
+ let(:manticore_options) { subject.client.pool.adapter.manticore.instance_variable_get(:@options) }
692
+ let(:api_key) { "some_id:some_api_key" }
693
+ let(:base64_api_key) { "ApiKey c29tZV9pZDpzb21lX2FwaV9rZXk=" }
694
+
695
+ context "when set without ssl" do
696
+ let(:do_register) { false } # this is what we want to test, so we disable the before(:each) call
697
+ let(:options) { { "api_key" => api_key } }
698
+
699
+ it "should raise a configuration error" do
700
+ expect { subject.register }.to raise_error LogStash::ConfigurationError, /requires SSL\/TLS/
701
+ end
702
+ end
703
+
704
+ context "when set without ssl but with a https host" do
705
+ let(:do_register) { false } # this is what we want to test, so we disable the before(:each) call
706
+ let(:options) { { "hosts" => ["https://some.host.com"], "api_key" => api_key } }
707
+
708
+ it "should raise a configuration error" do
709
+ expect { subject.register }.to raise_error LogStash::ConfigurationError, /requires SSL\/TLS/
710
+ end
711
+ end
712
+
713
+ context "when set" do
714
+ let(:options) { { "ssl" => true, "api_key" => ::LogStash::Util::Password.new(api_key) } }
715
+
716
+ it "should use the custom headers in the adapter options" do
717
+ expect(manticore_options[:headers]).to eq({ "Authorization" => base64_api_key })
718
+ end
719
+ end
720
+
721
+ context "when not set" do
722
+ it "should have no headers" do
723
+ expect(manticore_options[:headers]).to be_empty
724
+ end
725
+ end
726
+
727
+ context 'user also set' do
728
+ let(:do_register) { false } # this is what we want to test, so we disable the before(:each) call
729
+ let(:options) { { "ssl" => true, "api_key" => api_key, 'user' => 'another' } }
730
+
731
+ it "should fail" do
732
+ expect { subject.register }.to raise_error LogStash::ConfigurationError, /Multiple authentication options are specified/
733
+ end
734
+ end
735
+
736
+ context 'cloud_auth also set' do
737
+ let(:do_register) { false } # this is what we want to test, so we disable the before(:each) call
738
+ let(:options) { { "ssl" => true, "api_key" => api_key, 'cloud_auth' => 'foobar' } }
739
+
740
+ it "should fail" do
741
+ expect { subject.register }.to raise_error LogStash::ConfigurationError, /Multiple authentication options are specified/
742
+ end
743
+ end
744
+ end
745
+
662
746
  @private
663
747
 
664
748
  def stub_manticore_client!(manticore_double = nil)
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: 10.4.2
4
+ version: 10.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: 2020-04-23 00:00:00.000000000 Z
11
+ date: 2020-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement