logstash-output-elasticsearch-test 11.16.0-x86_64-linux
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 +7 -0
- data/CHANGELOG.md +649 -0
- data/CONTRIBUTORS +34 -0
- data/Gemfile +16 -0
- data/LICENSE +202 -0
- data/NOTICE.TXT +5 -0
- data/README.md +106 -0
- data/docs/index.asciidoc +1369 -0
- data/lib/logstash/outputs/elasticsearch/data_stream_support.rb +282 -0
- data/lib/logstash/outputs/elasticsearch/default-ilm-policy.json +14 -0
- data/lib/logstash/outputs/elasticsearch/http_client/manticore_adapter.rb +155 -0
- data/lib/logstash/outputs/elasticsearch/http_client/pool.rb +534 -0
- data/lib/logstash/outputs/elasticsearch/http_client.rb +497 -0
- data/lib/logstash/outputs/elasticsearch/http_client_builder.rb +201 -0
- data/lib/logstash/outputs/elasticsearch/ilm.rb +92 -0
- data/lib/logstash/outputs/elasticsearch/license_checker.rb +52 -0
- data/lib/logstash/outputs/elasticsearch/template_manager.rb +131 -0
- data/lib/logstash/outputs/elasticsearch/templates/ecs-disabled/elasticsearch-6x.json +45 -0
- data/lib/logstash/outputs/elasticsearch/templates/ecs-disabled/elasticsearch-7x.json +44 -0
- data/lib/logstash/outputs/elasticsearch/templates/ecs-disabled/elasticsearch-8x.json +50 -0
- data/lib/logstash/outputs/elasticsearch.rb +699 -0
- data/lib/logstash/plugin_mixins/elasticsearch/api_configs.rb +237 -0
- data/lib/logstash/plugin_mixins/elasticsearch/common.rb +409 -0
- data/lib/logstash/plugin_mixins/elasticsearch/noop_license_checker.rb +9 -0
- data/logstash-output-elasticsearch.gemspec +40 -0
- data/spec/es_spec_helper.rb +225 -0
- data/spec/fixtures/_nodes/6x.json +81 -0
- data/spec/fixtures/_nodes/7x.json +92 -0
- data/spec/fixtures/htpasswd +2 -0
- data/spec/fixtures/license_check/active.json +16 -0
- data/spec/fixtures/license_check/inactive.json +5 -0
- data/spec/fixtures/nginx_reverse_proxy.conf +22 -0
- data/spec/fixtures/scripts/painless/scripted_update.painless +2 -0
- data/spec/fixtures/scripts/painless/scripted_update_nested.painless +1 -0
- data/spec/fixtures/scripts/painless/scripted_upsert.painless +1 -0
- data/spec/fixtures/template-with-policy-es6x.json +48 -0
- data/spec/fixtures/template-with-policy-es7x.json +45 -0
- data/spec/fixtures/template-with-policy-es8x.json +50 -0
- data/spec/fixtures/test_certs/ca.crt +29 -0
- data/spec/fixtures/test_certs/ca.der.sha256 +1 -0
- data/spec/fixtures/test_certs/ca.key +51 -0
- data/spec/fixtures/test_certs/renew.sh +13 -0
- data/spec/fixtures/test_certs/test.crt +30 -0
- data/spec/fixtures/test_certs/test.der.sha256 +1 -0
- data/spec/fixtures/test_certs/test.key +51 -0
- data/spec/fixtures/test_certs/test.p12 +0 -0
- data/spec/fixtures/test_certs/test_invalid.crt +36 -0
- data/spec/fixtures/test_certs/test_invalid.key +51 -0
- data/spec/fixtures/test_certs/test_invalid.p12 +0 -0
- data/spec/fixtures/test_certs/test_self_signed.crt +32 -0
- data/spec/fixtures/test_certs/test_self_signed.key +54 -0
- data/spec/fixtures/test_certs/test_self_signed.p12 +0 -0
- data/spec/integration/outputs/compressed_indexing_spec.rb +70 -0
- data/spec/integration/outputs/create_spec.rb +67 -0
- data/spec/integration/outputs/data_stream_spec.rb +68 -0
- data/spec/integration/outputs/delete_spec.rb +63 -0
- data/spec/integration/outputs/ilm_spec.rb +534 -0
- data/spec/integration/outputs/index_spec.rb +421 -0
- data/spec/integration/outputs/index_version_spec.rb +98 -0
- data/spec/integration/outputs/ingest_pipeline_spec.rb +75 -0
- data/spec/integration/outputs/metrics_spec.rb +66 -0
- data/spec/integration/outputs/no_es_on_startup_spec.rb +78 -0
- data/spec/integration/outputs/painless_update_spec.rb +99 -0
- data/spec/integration/outputs/parent_spec.rb +94 -0
- data/spec/integration/outputs/retry_spec.rb +182 -0
- data/spec/integration/outputs/routing_spec.rb +61 -0
- data/spec/integration/outputs/sniffer_spec.rb +94 -0
- data/spec/integration/outputs/templates_spec.rb +133 -0
- data/spec/integration/outputs/unsupported_actions_spec.rb +75 -0
- data/spec/integration/outputs/update_spec.rb +114 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/support/elasticsearch/api/actions/delete_ilm_policy.rb +19 -0
- data/spec/support/elasticsearch/api/actions/get_alias.rb +18 -0
- data/spec/support/elasticsearch/api/actions/get_ilm_policy.rb +18 -0
- data/spec/support/elasticsearch/api/actions/put_alias.rb +24 -0
- data/spec/support/elasticsearch/api/actions/put_ilm_policy.rb +25 -0
- data/spec/unit/http_client_builder_spec.rb +185 -0
- data/spec/unit/outputs/elasticsearch/data_stream_support_spec.rb +612 -0
- data/spec/unit/outputs/elasticsearch/http_client/manticore_adapter_spec.rb +151 -0
- data/spec/unit/outputs/elasticsearch/http_client/pool_spec.rb +501 -0
- data/spec/unit/outputs/elasticsearch/http_client_spec.rb +339 -0
- data/spec/unit/outputs/elasticsearch/template_manager_spec.rb +189 -0
- data/spec/unit/outputs/elasticsearch_proxy_spec.rb +103 -0
- data/spec/unit/outputs/elasticsearch_spec.rb +1573 -0
- data/spec/unit/outputs/elasticsearch_ssl_spec.rb +197 -0
- data/spec/unit/outputs/error_whitelist_spec.rb +56 -0
- data/spec/unit/outputs/license_check_spec.rb +57 -0
- metadata +423 -0
@@ -0,0 +1,197 @@
|
|
1
|
+
require_relative "../../../spec/spec_helper"
|
2
|
+
require 'stud/temporary'
|
3
|
+
|
4
|
+
describe "SSL options" do
|
5
|
+
let(:manticore_double) { double("manticoreSSL #{self.inspect}") }
|
6
|
+
|
7
|
+
let(:settings) { { "ssl_enabled" => true, "hosts" => "localhost", "pool_max" => 1, "pool_max_per_route" => 1 } }
|
8
|
+
|
9
|
+
subject do
|
10
|
+
require "logstash/outputs/elasticsearch"
|
11
|
+
LogStash::Outputs::ElasticSearch.new(settings)
|
12
|
+
end
|
13
|
+
|
14
|
+
before do
|
15
|
+
allow(manticore_double).to receive(:close)
|
16
|
+
|
17
|
+
response_double = double("manticore response").as_null_object
|
18
|
+
# Allow healtchecks
|
19
|
+
allow(manticore_double).to receive(:head).with(any_args).and_return(response_double)
|
20
|
+
allow(manticore_double).to receive(:get).with(any_args).and_return(response_double)
|
21
|
+
allow(::Manticore::Client).to receive(:new).and_return(manticore_double)
|
22
|
+
end
|
23
|
+
|
24
|
+
after do
|
25
|
+
subject.close
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when ssl_verification_mode" do
|
29
|
+
context "is set to none" do
|
30
|
+
let(:settings) { super().merge(
|
31
|
+
"ssl_verification_mode" => 'none',
|
32
|
+
) }
|
33
|
+
|
34
|
+
it "should print a warning" do
|
35
|
+
expect(subject.logger).to receive(:warn).with(/You have enabled encryption but DISABLED certificate verification/).at_least(:once)
|
36
|
+
allow(subject.logger).to receive(:warn).with(any_args)
|
37
|
+
|
38
|
+
subject.register
|
39
|
+
allow(LogStash::Outputs::ElasticSearch::HttpClient::Pool).to receive(:start)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should pass the flag to the ES client" do
|
43
|
+
expect(::Manticore::Client).to receive(:new) do |args|
|
44
|
+
expect(args[:ssl]).to match hash_including(:enabled => true, :verify => :disable)
|
45
|
+
end.and_return(manticore_double)
|
46
|
+
|
47
|
+
subject.register
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "is set to full" do
|
52
|
+
let(:settings) { super().merge(
|
53
|
+
"ssl_verification_mode" => 'full',
|
54
|
+
) }
|
55
|
+
|
56
|
+
it "should pass the flag to the ES client" do
|
57
|
+
expect(::Manticore::Client).to receive(:new) do |args|
|
58
|
+
expect(args[:ssl]).to match hash_including(:enabled => true, :verify => :default)
|
59
|
+
end.and_return(manticore_double)
|
60
|
+
|
61
|
+
subject.register
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "with the conflicting configs" do
|
67
|
+
context "ssl_certificate_authorities and ssl_truststore_path set" do
|
68
|
+
let(:ssl_truststore_path) { Stud::Temporary.file.path }
|
69
|
+
let(:ssl_certificate_authorities_path) { Stud::Temporary.file.path }
|
70
|
+
let(:settings) { super().merge(
|
71
|
+
"ssl_truststore_path" => ssl_truststore_path,
|
72
|
+
"ssl_certificate_authorities" => ssl_certificate_authorities_path
|
73
|
+
) }
|
74
|
+
|
75
|
+
after :each do
|
76
|
+
File.delete(ssl_truststore_path)
|
77
|
+
File.delete(ssl_certificate_authorities_path)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should raise a configuration error" do
|
81
|
+
expect { subject.register }.to raise_error(LogStash::ConfigurationError, /Use either "ssl_certificate_authorities\/cacert" or "ssl_truststore_path\/truststore"/)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "ssl_certificate and ssl_keystore_path set" do
|
86
|
+
let(:ssl_keystore_path) { Stud::Temporary.file.path }
|
87
|
+
let(:ssl_certificate_path) { Stud::Temporary.file.path }
|
88
|
+
let(:settings) { super().merge(
|
89
|
+
"ssl_certificate" => ssl_certificate_path,
|
90
|
+
"ssl_keystore_path" => ssl_keystore_path
|
91
|
+
) }
|
92
|
+
|
93
|
+
after :each do
|
94
|
+
File.delete(ssl_keystore_path)
|
95
|
+
File.delete(ssl_certificate_path)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should raise a configuration error" do
|
99
|
+
expect { subject.register }.to raise_error(LogStash::ConfigurationError, /Use either "ssl_certificate" or "ssl_keystore_path\/keystore"/)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context "when configured with Java store files" do
|
105
|
+
let(:ssl_truststore_path) { Stud::Temporary.file.path }
|
106
|
+
let(:ssl_keystore_path) { Stud::Temporary.file.path }
|
107
|
+
|
108
|
+
after :each do
|
109
|
+
File.delete(ssl_truststore_path)
|
110
|
+
File.delete(ssl_keystore_path)
|
111
|
+
end
|
112
|
+
|
113
|
+
let(:settings) { super().merge(
|
114
|
+
"ssl_truststore_path" => ssl_truststore_path,
|
115
|
+
"ssl_truststore_type" => "jks",
|
116
|
+
"ssl_truststore_password" => "foo",
|
117
|
+
"ssl_keystore_path" => ssl_keystore_path,
|
118
|
+
"ssl_keystore_type" => "jks",
|
119
|
+
"ssl_keystore_password" => "bar",
|
120
|
+
"ssl_verification_mode" => "full",
|
121
|
+
"ssl_cipher_suites" => ["TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"],
|
122
|
+
"ssl_supported_protocols" => ["TLSv1.3"]
|
123
|
+
) }
|
124
|
+
|
125
|
+
it "should pass the parameters to the ES client" do
|
126
|
+
expect(::Manticore::Client).to receive(:new) do |args|
|
127
|
+
expect(args[:ssl]).to match hash_including(
|
128
|
+
:enabled => true,
|
129
|
+
:keystore => ssl_keystore_path,
|
130
|
+
:keystore_type => "jks",
|
131
|
+
:keystore_password => "bar",
|
132
|
+
:truststore => ssl_truststore_path,
|
133
|
+
:truststore_type => "jks",
|
134
|
+
:truststore_password => "foo",
|
135
|
+
:verify => :default,
|
136
|
+
:cipher_suites => ["TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"],
|
137
|
+
:protocols => ["TLSv1.3"],
|
138
|
+
)
|
139
|
+
end.and_return(manticore_double)
|
140
|
+
|
141
|
+
subject.register
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context "when configured with certificate files" do
|
146
|
+
let(:ssl_certificate_authorities_path) { Stud::Temporary.file.path }
|
147
|
+
let(:ssl_certificate_path) { Stud::Temporary.file.path }
|
148
|
+
let(:ssl_key_path) { Stud::Temporary.file.path }
|
149
|
+
let(:settings) { super().merge(
|
150
|
+
"ssl_certificate_authorities" => [ssl_certificate_authorities_path],
|
151
|
+
"ssl_certificate" => ssl_certificate_path,
|
152
|
+
"ssl_key" => ssl_key_path,
|
153
|
+
"ssl_verification_mode" => "full",
|
154
|
+
"ssl_cipher_suites" => ["TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"],
|
155
|
+
"ssl_supported_protocols" => ["TLSv1.3"]
|
156
|
+
) }
|
157
|
+
|
158
|
+
after :each do
|
159
|
+
File.delete(ssl_certificate_authorities_path)
|
160
|
+
File.delete(ssl_certificate_path)
|
161
|
+
File.delete(ssl_key_path)
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should pass the parameters to the ES client" do
|
165
|
+
expect(::Manticore::Client).to receive(:new) do |args|
|
166
|
+
expect(args[:ssl]).to match hash_including(
|
167
|
+
:enabled => true,
|
168
|
+
:ca_file => ssl_certificate_authorities_path,
|
169
|
+
:client_cert => ssl_certificate_path,
|
170
|
+
:client_key => ssl_key_path,
|
171
|
+
:verify => :default,
|
172
|
+
:cipher_suites => ["TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"],
|
173
|
+
:protocols => ["TLSv1.3"],
|
174
|
+
)
|
175
|
+
end.and_return(manticore_double)
|
176
|
+
|
177
|
+
subject.register
|
178
|
+
end
|
179
|
+
|
180
|
+
context "and only the ssl_certificate is set" do
|
181
|
+
let(:settings) { super().reject { |k| "ssl_key".eql?(k) } }
|
182
|
+
|
183
|
+
it "should raise a configuration error" do
|
184
|
+
expect { subject.register }.to raise_error(LogStash::ConfigurationError, /Using an "ssl_certificate" requires an "ssl_key"/)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context "and only the ssl_key is set" do
|
189
|
+
let(:settings) { super().reject { |k| "ssl_certificate".eql?(k) } }
|
190
|
+
|
191
|
+
it "should raise a configuration error" do
|
192
|
+
expect { subject.register }.to raise_error(LogStash::ConfigurationError, /An "ssl_certificate" is required when using an "ssl_key"/)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "logstash/outputs/elasticsearch"
|
2
|
+
require_relative "../../../spec/es_spec_helper"
|
3
|
+
|
4
|
+
describe "whitelisting error types in expected behavior" do
|
5
|
+
let(:template) { '{"template" : "not important, will be updated by :index"}' }
|
6
|
+
let(:event1) { LogStash::Event.new("somevalue" => 100, "@timestamp" => "2014-11-17T20:37:17.223Z") }
|
7
|
+
let(:action1) { ["index", {:_id=>1, :routing=>nil, :_index=>"logstash-2014.11.17", :_type=> doc_type }, event1] }
|
8
|
+
let(:settings) { {"manage_template" => true, "index" => "logstash-2014.11.17", "template_overwrite" => true, "hosts" => get_host_port() } }
|
9
|
+
|
10
|
+
subject { LogStash::Outputs::ElasticSearch.new(settings) }
|
11
|
+
|
12
|
+
before :each do
|
13
|
+
allow(subject.logger).to receive(:warn)
|
14
|
+
allow(subject).to receive(:maximum_seen_major_version).and_return(0)
|
15
|
+
allow(subject).to receive(:alive_urls_count).and_return(1)
|
16
|
+
allow(subject).to receive(:finish_register)
|
17
|
+
|
18
|
+
subject.register
|
19
|
+
|
20
|
+
allow(subject.client).to receive(:get_xpack_info)
|
21
|
+
allow(subject.client).to receive(:bulk).and_return(
|
22
|
+
{
|
23
|
+
"errors" => true,
|
24
|
+
"items" => [{
|
25
|
+
"create" => {
|
26
|
+
"status" => 409,
|
27
|
+
"error" => {
|
28
|
+
"type" => "document_already_exists_exception",
|
29
|
+
"reason" => "[shard] document already exists"
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}]
|
33
|
+
})
|
34
|
+
|
35
|
+
subject.multi_receive([event1])
|
36
|
+
end
|
37
|
+
|
38
|
+
after :each do
|
39
|
+
subject.close
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "when failure logging is enabled for everything" do
|
43
|
+
it "should log a failure on the action" do
|
44
|
+
expect(subject.logger).to have_received(:warn).with("Failed action", anything)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "when failure logging is disabled for document exists error" do
|
49
|
+
let(:settings) { super().merge("silence_errors_in_log" => ["document_already_exists_exception"]) }
|
50
|
+
|
51
|
+
it "should log a failure on the action" do
|
52
|
+
expect(subject.logger).not_to have_received(:warn).with("Failed action", anything)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require "logstash/devutils/rspec/spec_helper"
|
2
|
+
require "logstash/outputs/elasticsearch/http_client"
|
3
|
+
require "logstash/outputs/elasticsearch/license_checker"
|
4
|
+
|
5
|
+
describe LogStash::Outputs::ElasticSearch::LicenseChecker do
|
6
|
+
|
7
|
+
# Note that the actual license checking logic is spec'ed in pool_spec.rb
|
8
|
+
|
9
|
+
context "LicenseChecker API required by Pool class" do
|
10
|
+
subject { described_class }
|
11
|
+
|
12
|
+
it "defines the appropriate_license? methods" do
|
13
|
+
expect(subject.instance_methods).to include(:appropriate_license?)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "Pool class API required by the LicenseChecker" do
|
18
|
+
subject { LogStash::Outputs::ElasticSearch::HttpClient::Pool }
|
19
|
+
|
20
|
+
it "contains the get_license method" do
|
21
|
+
expect(LogStash::Outputs::ElasticSearch::HttpClient::Pool.instance_methods).to include(:get_license)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "appropriate license" do
|
26
|
+
let(:logger) { double("logger") }
|
27
|
+
let(:url) { LogStash::Util::SafeURI.new("https://cloud.elastic.co") }
|
28
|
+
let(:pool) { double("pool") }
|
29
|
+
subject { described_class.new(logger) }
|
30
|
+
|
31
|
+
it "is true when connect to serverless" do
|
32
|
+
allow(pool).to receive(:serverless?).and_return(true)
|
33
|
+
expect(subject.appropriate_license?(pool, url)).to eq true
|
34
|
+
end
|
35
|
+
|
36
|
+
it "is true when license status is active" do
|
37
|
+
allow(pool).to receive(:serverless?).and_return(false)
|
38
|
+
allow(pool).to receive(:get_license).with(url).and_return(LogStash::Json.load File.read("spec/fixtures/license_check/active.json"))
|
39
|
+
expect(subject.appropriate_license?(pool, url)).to eq true
|
40
|
+
end
|
41
|
+
|
42
|
+
it "is true when license status is inactive" do
|
43
|
+
allow(logger).to receive(:warn).with(instance_of(String), anything)
|
44
|
+
allow(pool).to receive(:serverless?).and_return(false)
|
45
|
+
allow(pool).to receive(:get_license).with(url).and_return(LogStash::Json.load File.read("spec/fixtures/license_check/inactive.json"))
|
46
|
+
expect(subject.appropriate_license?(pool, url)).to eq true
|
47
|
+
end
|
48
|
+
|
49
|
+
it "is false when no license return" do
|
50
|
+
allow(logger).to receive(:error).with(instance_of(String), anything)
|
51
|
+
allow(pool).to receive(:serverless?).and_return(false)
|
52
|
+
allow(pool).to receive(:get_license).with(url).and_return(LogStash::Json.load('{}'))
|
53
|
+
expect(subject.appropriate_license?(pool, url)).to eq false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|