Skip to content

Commit 099f085

Browse files
authored
Feat: review and deprecate ssl protocol/cipher settings (#151)
1 parent e295446 commit 099f085

File tree

6 files changed

+163
-59
lines changed

6 files changed

+163
-59
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## 3.6.0
2+
- Feat: review and deprecate ssl protocol/cipher related settings [#151](https://github.com/logstash-plugins/logstash-input-http/pull/151)
3+
14
## 3.5.1
25
- Fix: codecs provided with `additional_codecs` now correctly run in the pipeline's context, which means that they respect the `pipeline.ecs_compatibility` setting [#152](https://github.com/logstash-plugins/logstash-input-http/pull/152)
36

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.5.1
1+
3.6.0

docs/index.asciidoc

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,11 @@ This plugin supports the following configuration options plus the <<plugins-{typ
104104
| <<plugins-{type}s-{plugin}-ssl>> |<<boolean,boolean>>|No
105105
| <<plugins-{type}s-{plugin}-ssl_certificate>> |a valid filesystem path|No
106106
| <<plugins-{type}s-{plugin}-ssl_certificate_authorities>> |<<array,array>>|No
107+
| <<plugins-{type}s-{plugin}-ssl_cipher_suites>> |<<array,array>>|No
107108
| <<plugins-{type}s-{plugin}-ssl_handshake_timeout>> |<<number,number>>|No
108109
| <<plugins-{type}s-{plugin}-ssl_key>> |a valid filesystem path|No
109110
| <<plugins-{type}s-{plugin}-ssl_key_passphrase>> |<<password,password>>|No
111+
| <<plugins-{type}s-{plugin}-ssl_supported_protocols>> |<<array,array>>|No
110112
| <<plugins-{type}s-{plugin}-ssl_verify_mode>> |<<string,string>>, one of `["none", "peer", "force_peer"]`|No
111113
| <<plugins-{type}s-{plugin}-threads>> |<<number,number>>|No
112114
| <<plugins-{type}s-{plugin}-tls_max_version>> |<<number,number>>|No
@@ -134,20 +136,20 @@ and no codec for the request's content-type is found
134136
===== `cipher_suites`
135137

136138
* Value type is <<array,array>>
137-
* Default value is `[TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256]`
139+
* This option is deprecated
138140

139141
The list of cipher suites to use, listed by priorities.
140-
This default list applies for OpenJDK 11.0.14 and higher.
141-
For older JDK versions, the default list includes only suites supported by that version.
142-
For example, the ChaCha20 family of ciphers is not supported in older versions.
142+
143+
NOTE: This option is deprecated and it will be removed in the next major version of Logstash.
144+
Use `ssl_cipher_suites` instead.
143145

144146
[id="plugins-{type}s-{plugin}-ecs_compatibility"]
145147
===== `ecs_compatibility`
146148

147-
* Value type is <<string,string>>
148-
* Supported values are:
149-
** `disabled`: unstructured connection metadata added at root level
150-
** `v1`,`v8`: headers added under `[@metadata][http][header]`. Some are copied to structured ECS fields `http`, `url`, `user_agent` and `host`
149+
* Value type is <<string,string>>
150+
* Supported values are:
151+
** `disabled`: unstructured connection metadata added at root level
152+
** `v1`,`v8`: headers added under `[@metadata][http][header]`. Some are copied to structured ECS fields `http`, `url`, `user_agent` and `host`
151153

152154
Controls this plugin's compatibility with the
153155
{ecs-ref}[Elastic Common Schema (ECS)].
@@ -345,6 +347,17 @@ be read and added to the trust store. You need to configure the `ssl_verify_mode
345347
to `peer` or `force_peer` to enable the verification.
346348

347349

350+
[id="plugins-{type}s-{plugin}-ssl_cipher_suites"]
351+
===== `ssl_cipher_suites`
352+
353+
* Value type is <<array,array>>
354+
* Default value is `['TLS_AES_256_GCM_SHA384', 'TLS_AES_128_GCM_SHA256', 'TLS_CHACHA20_POLY1305_SHA256', 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384', 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', 'TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256', 'TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256', 'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256', 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256', 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384', 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384', 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256', 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256']`
355+
356+
The list of cipher suites to use, listed by priorities.
357+
This default list applies for OpenJDK 11.0.14 and higher.
358+
For older JDK versions, the default list includes only suites supported by that version.
359+
For example, the ChaCha20 family of ciphers is not supported in older versions.
360+
348361
[id="plugins-{type}s-{plugin}-ssl_handshake_timeout"]
349362
===== `ssl_handshake_timeout`
350363

@@ -371,6 +384,23 @@ for more information.
371384

372385
SSL key passphrase to use.
373386

387+
[id="plugins-{type}s-{plugin}-ssl_supported_protocols"]
388+
===== `ssl_supported_protocols`
389+
390+
* Value type is <<array,array>>
391+
* Allowed values are: `'TLSv1.1'`, `'TLSv1.2'`, `'TLSv1.3'`
392+
* Default depends on the JDK being used. With up-to-date Logstash, the default is `['TLSv1.2', 'TLSv1.3']`.
393+
`'TLSv1.1'` is not considered secure and is only provided for legacy applications.
394+
395+
List of allowed SSL/TLS versions to use when establishing a connection to the HTTP endpoint.
396+
397+
For Java 8 `'TLSv1.3'` is supported only since **8u262** (AdoptOpenJDK), but requires that you set the
398+
`LS_JAVA_OPTS="-Djdk.tls.client.protocols=TLSv1.3"` system property in Logstash.
399+
400+
NOTE: If you configure the plugin to use `'TLSv1.1'` on any recent JVM, such as the one packaged with Logstash,
401+
the protocol is disabled by default and needs to be enabled manually by changing `jdk.tls.disabledAlgorithms` in
402+
the *$JDK_HOME/conf/security/java.security* configuration file. That is, `TLSv1.1` needs to be removed from the list.
403+
374404
[id="plugins-{type}s-{plugin}-ssl_verify_mode"]
375405
===== `ssl_verify_mode`
376406

@@ -399,7 +429,7 @@ Number of threads to use for both accepting connections and handling requests
399429
===== `tls_max_version`
400430

401431
* Value type is <<number,number>>
402-
* Default value is `1.3`
432+
* This option is deprecated
403433

404434
The maximum TLS version allowed for the encrypted connections.
405435
The value must be the one of the following: 1.1 for TLS 1.1, 1.2 for TLS 1.2, 1.3 for TLSv1.3
@@ -408,7 +438,7 @@ The value must be the one of the following: 1.1 for TLS 1.1, 1.2 for TLS 1.2, 1.
408438
===== `tls_min_version`
409439

410440
* Value type is <<number,number>>
411-
* Default value is `1.2`
441+
* This option is deprecated
412442

413443
The minimum TLS version allowed for the encrypted connections.
414444
The value must be one of the following: 1.1 for TLS 1.1, 1.2 for TLS 1.2, 1.3 for TLSv1.3
@@ -430,7 +460,7 @@ Username for basic authorization
430460

431461
Set the client certificate verification method. Valid methods: none, peer, force_peer
432462

433-
Note: This option is deprecated and it will be removed in the next major version of Logstash.
463+
NOTE: This option is deprecated and it will be removed in the next major version of Logstash.
434464
Use `ssl_verify_mode` instead.
435465

436466

lib/logstash/inputs/http.rb

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class LogStash::Inputs::Http < LogStash::Inputs::Base
3030
require "logstash/inputs/http/tls"
3131

3232
java_import "io.netty.handler.codec.http.HttpUtil"
33+
java_import 'org.logstash.plugins.inputs.http.util.SslSimpleBuilder'
3334

3435
config_name "http"
3536

@@ -86,16 +87,11 @@ class LogStash::Inputs::Http < LogStash::Inputs::Base
8687
# Time in milliseconds for an incomplete ssl handshake to timeout
8788
config :ssl_handshake_timeout, :validate => :number, :default => 10000
8889

89-
# The minimum TLS version allowed for the encrypted connections. The value must be one of the following:
90-
# 1.0 for TLS 1.0, 1.1 for TLS 1.1, 1.2 for TLS 1.2, 1.3 for TLS 1.3
91-
config :tls_min_version, :validate => :number, :default => TLS.min.version
92-
93-
# The maximum TLS version allowed for the encrypted connections. The value must be the one of the following:
94-
# 1.0 for TLS 1.0, 1.1 for TLS 1.1, 1.2 for TLS 1.2, 1.3 for TLS 1.3
95-
config :tls_max_version, :validate => :number, :default => TLS.max.version
96-
9790
# The list of ciphers suite to use, listed by priorities.
98-
config :cipher_suites, :validate => :array, :default => org.logstash.plugins.inputs.http.util.SslSimpleBuilder.getDefaultCiphers
91+
config :ssl_cipher_suites, :validate => SslSimpleBuilder::SUPPORTED_CIPHERS.to_a,
92+
:default => SslSimpleBuilder.getDefaultCiphers, :list => true
93+
94+
config :ssl_supported_protocols, :validate => ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'], :default => ['TLSv1.2', 'TLSv1.3'], :list => true
9995

10096
# Apply specific codecs for specific content types.
10197
# The default codec will be applied only after this list is checked
@@ -118,14 +114,23 @@ class LogStash::Inputs::Http < LogStash::Inputs::Base
118114
config :max_content_length, :validate => :number, :required => false, :default => 100 * 1024 * 1024
119115

120116
config :response_code, :validate => [200, 201, 202, 204], :default => 200
117+
121118
# Deprecated options
122119

123120
# The JKS keystore to validate the client's certificates
124121
config :keystore, :validate => :path, :deprecated => "Set 'ssl_certificate' and 'ssl_key' instead."
125122
config :keystore_password, :validate => :password, :deprecated => "Set 'ssl_key_passphrase' instead."
126123

127-
config :verify_mode, :validate => ['none', 'peer', 'force_peer'], :default => 'none',
128-
:deprecated => "Set 'ssl_verify_mode' instead."
124+
config :verify_mode, :validate => ['none', 'peer', 'force_peer'], :default => 'none', :deprecated => "Set 'ssl_verify_mode' instead."
125+
config :cipher_suites, :validate => :array, :default => [], :deprecated => "Set 'ssl_cipher_suites' instead."
126+
127+
# The minimum TLS version allowed for the encrypted connections. The value must be one of the following:
128+
# 1.0 for TLS 1.0, 1.1 for TLS 1.1, 1.2 for TLS 1.2, 1.3 for TLS 1.3
129+
config :tls_min_version, :validate => :number, :default => TLS.min.version, :deprecated => "Set 'ssl_supported_protocols' instead."
130+
131+
# The maximum TLS version allowed for the encrypted connections. The value must be the one of the following:
132+
# 1.0 for TLS 1.0, 1.1 for TLS 1.1, 1.2 for TLS 1.2, 1.3 for TLS 1.3
133+
config :tls_max_version, :validate => :number, :default => TLS.max.version, :deprecated => "Set 'ssl_supported_protocols' instead."
129134

130135
attr_reader :codecs
131136

@@ -233,24 +238,45 @@ def validate_ssl_settings!
233238
@logger.warn("SSL Certificate will not be used") if @ssl_certificate
234239
@logger.warn("SSL Key will not be used") if @ssl_key
235240
@logger.warn("SSL Java Key Store will not be used") if @keystore
236-
elsif !(ssl_key_configured? || ssl_jks_configured?)
241+
return # code bellow assumes `ssl => true`
242+
end
243+
244+
if !(ssl_key_configured? || ssl_jks_configured?)
237245
raise LogStash::ConfigurationError, "Certificate or JKS must be configured"
238246
end
239247

240-
if @ssl && (original_params.key?("verify_mode") && original_params.key?("ssl_verify_mode"))
241-
raise LogStash::ConfigurationError, "Both 'ssl_verify_mode' and 'verify_mode' were set. Use only 'ssl_verify_mode'."
248+
if original_params.key?("verify_mode") && original_params.key?("ssl_verify_mode")
249+
raise LogStash::ConfigurationError, "Both `ssl_verify_mode` and (deprecated) `verify_mode` were set. Use only `ssl_verify_mode`."
242250
elsif original_params.key?("verify_mode")
243251
@ssl_verify_mode_final = @verify_mode
244-
elsif original_params.key?("ssl_verify_mode")
245-
@ssl_verify_mode_final = @ssl_verify_mode
246252
else
247253
@ssl_verify_mode_final = @ssl_verify_mode
248254
end
249255

250-
if @ssl && require_certificate_authorities? && !client_authentication?
251-
raise LogStash::ConfigurationError, "Using `ssl_verify_mode` or `verify_mode` set to PEER or FORCE_PEER, requires the configuration of `ssl_certificate_authorities`"
252-
elsif @ssl && !require_certificate_authorities? && client_authentication?
253-
raise LogStash::ConfigurationError, "The configuration of `ssl_certificate_authorities` requires setting `ssl_verify_mode` or `verify_mode` to PEER or FORCE_PEER"
256+
if original_params.key?('cipher_suites') && original_params.key?('ssl_cipher_suites')
257+
raise LogStash::ConfigurationError, "Both `ssl_cipher_suites` and (deprecated) `cipher_suites` were set. Use only `ssl_cipher_suites`."
258+
elsif original_params.key?('cipher_suites')
259+
@ssl_cipher_suites_final = @cipher_suites
260+
else
261+
@ssl_cipher_suites_final = @ssl_cipher_suites
262+
end
263+
264+
if original_params.key?('tls_min_version') && original_params.key?('ssl_supported_protocols')
265+
raise LogStash::ConfigurationError, "Both `ssl_supported_protocols` and (deprecated) `tls_min_ciphers` were set. Use only `ssl_supported_protocols`."
266+
elsif original_params.key?('tls_max_version') && original_params.key?('ssl_supported_protocols')
267+
raise LogStash::ConfigurationError, "Both `ssl_supported_protocols` and (deprecated) `tls_max_ciphers` were set. Use only `ssl_supported_protocols`."
268+
else
269+
if original_params.key?('tls_min_version') || original_params.key?('tls_max_version')
270+
@ssl_supported_protocols_final = TLS.get_supported(tls_min_version..tls_max_version).map(&:name)
271+
else
272+
@ssl_supported_protocols_final = @ssl_supported_protocols
273+
end
274+
end
275+
276+
if require_certificate_authorities? && !client_authentication?
277+
raise LogStash::ConfigurationError, "Using `ssl_verify_mode` (or `verify_mode`) set to PEER or FORCE_PEER, requires the configuration of `ssl_certificate_authorities`"
278+
elsif !require_certificate_authorities? && client_authentication?
279+
raise LogStash::ConfigurationError, "The configuration of `ssl_certificate_authorities` requires setting `ssl_verify_mode` (or `verify_mode`) to PEER or FORCE_PEER"
254280
end
255281
end
256282

@@ -268,7 +294,7 @@ def build_ssl_params
268294
begin
269295
ssl_builder = org.logstash.plugins.inputs.http.util.SslSimpleBuilder
270296
.new(@ssl_certificate, @ssl_key, @ssl_key_passphrase.nil? ? nil : @ssl_key_passphrase.value)
271-
.setCipherSuites(normalized_ciphers)
297+
.setCipherSuites(normalized_cipher_suites)
272298
rescue java.lang.IllegalArgumentException => e
273299
@logger.error("SSL configuration invalid", error_details(e))
274300
raise LogStash::ConfigurationError, e
@@ -300,19 +326,15 @@ def require_certificate_authorities?
300326

301327
private
302328

303-
def normalized_ciphers
304-
@cipher_suites.map(&:upcase)
305-
end
306-
307-
def convert_protocols
308-
TLS.get_supported(@tls_min_version..@tls_max_version).map(&:name)
329+
def normalized_cipher_suites
330+
@ssl_cipher_suites_final.map(&:upcase)
309331
end
310332

311333
def new_ssl_handshake_provider(ssl_builder)
312334
begin
313335
ssl_handler_provider = org.logstash.plugins.inputs.http.util.SslHandlerProvider.new(ssl_builder.build())
314336
ssl_handler_provider.setVerifyMode(@ssl_verify_mode_final.upcase)
315-
ssl_handler_provider.setProtocols(convert_protocols)
337+
ssl_handler_provider.setProtocols(@ssl_supported_protocols_final)
316338
ssl_handler_provider.setHandshakeTimeoutMilliseconds(@ssl_handshake_timeout)
317339
ssl_handler_provider
318340
rescue java.lang.IllegalArgumentException => e

spec/inputs/http_spec.rb

Lines changed: 66 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,10 @@
169169

170170
let(:config) do
171171
super().merge 'ssl' => true,
172-
'ssl_certificate_authorities' => [ File.join(certs_dir, 'root.crt') ],
173-
'ssl_certificate' => File.join(certs_dir, 'server_from_root.crt'),
174-
'ssl_key' => File.join(certs_dir, 'server_from_root.key.pkcs8'),
175-
'ssl_verify_mode' => 'peer'
172+
'ssl_certificate_authorities' => [ File.join(certs_dir, 'root.crt') ],
173+
'ssl_certificate' => File.join(certs_dir, 'server_from_root.crt'),
174+
'ssl_key' => File.join(certs_dir, 'server_from_root.key.pkcs8'),
175+
'ssl_verify_mode' => 'peer'
176176
end
177177

178178
let(:client_options) do
@@ -219,7 +219,21 @@
219219

220220
context 'enforced TLSv1.3 in plugin' do
221221

222-
let(:config) { super().merge 'tls_min_version' => '1.3', 'cipher_suites' => [ 'TLS_AES_128_GCM_SHA256' ] }
222+
let(:config) { super().merge 'ssl_supported_protocols' => ['TLSv1.3'],
223+
'ssl_cipher_suites' => [ 'TLS_AES_128_GCM_SHA256' ] }
224+
225+
it "should parse the json body" do
226+
expect(response.code).to eq(200)
227+
event = logstash_queue.pop
228+
expect(event.get("message")).to eq("Hello")
229+
end
230+
231+
end
232+
233+
context 'enforced TLSv1.3 (deprecated options)' do
234+
235+
let(:config) { super().merge 'tls_min_version' => 1.3,
236+
'cipher_suites' => [ 'TLS_AES_128_GCM_SHA256' ] }
223237

224238
it "should parse the json body" do
225239
expect(response.code).to eq(200)
@@ -537,6 +551,12 @@ def setup_server_client(url = self.url)
537551
expect { subject.register }.to raise_exception(LogStash::ConfigurationError)
538552
end
539553
end
554+
context "with invalid cipher suites" do
555+
it "should raise a configuration error" do
556+
invalid_config = config.merge("ssl_cipher_suites" => "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA38")
557+
expect { LogStash::Inputs::Http.new(invalid_config) }.to raise_error(LogStash::ConfigurationError)
558+
end
559+
end
540560
context "with :ssl_certificate" do
541561
let(:ssc) { SelfSignedCertificate.new }
542562
let(:ssl_certificate) { ssc.certificate }
@@ -595,18 +615,6 @@ def setup_server_client(url = self.url)
595615
end
596616
end
597617

598-
context "with invalid cipher_suites" do
599-
let(:config) { super().merge("cipher_suites" => "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA38") }
600-
601-
it "should raise a configuration error" do
602-
expect( subject.logger ).to receive(:error) do |msg, opts|
603-
expect( msg ).to match /.*?configuration invalid/
604-
expect( opts[:message] ).to match /TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA38.*? not available/
605-
end
606-
expect { subject.register }.to raise_error(LogStash::ConfigurationError)
607-
end
608-
end
609-
610618
context "with invalid ssl certificate" do
611619
before do
612620
cert = File.readlines path = config["ssl_certificate"]
@@ -654,6 +662,47 @@ def setup_server_client(url = self.url)
654662
end
655663
end
656664

665+
context "with both verify_mode options set" do
666+
let(:config) do
667+
super().merge('ssl_verify_mode' => 'peer', 'verify_mode' => 'none')
668+
end
669+
670+
it "should raise a configuration error" do
671+
expect { subject.register }.to raise_error LogStash::ConfigurationError, /Use only .?ssl_verify_mode.?/i
672+
end
673+
end
674+
675+
context "with ssl_cipher_suites and cipher_suites set" do
676+
let(:config) do
677+
super().merge('ssl_cipher_suites' => ['TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384'],
678+
'cipher_suites' => ['TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384'])
679+
end
680+
681+
it "should raise a configuration error" do
682+
expect { subject.register }.to raise_error LogStash::ConfigurationError, /Use only .?ssl_cipher_suites.?/i
683+
end
684+
end
685+
686+
context "with ssl_supported_protocols and tls_min_version set" do
687+
let(:config) do
688+
super().merge('ssl_supported_protocols' => ['TLSv1.2'], 'tls_min_version' => 1.0)
689+
end
690+
691+
it "should raise a configuration error" do
692+
expect { subject.register }.to raise_error LogStash::ConfigurationError, /Use only .?ssl_supported_protocols.?/i
693+
end
694+
end
695+
696+
context "with ssl_supported_protocols and tls_max_version set" do
697+
let(:config) do
698+
super().merge('ssl_supported_protocols' => ['TLSv1.2'], 'tls_max_version' => 1.2)
699+
end
700+
701+
it "should raise a configuration error" do
702+
expect { subject.register }.to raise_error LogStash::ConfigurationError, /Use only .?ssl_supported_protocols.?/i
703+
end
704+
end
705+
657706
end
658707
end
659708
end

0 commit comments

Comments
 (0)