logstash-input-tcp 6.2.7-java → 6.3.1-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/docs/index.asciidoc +35 -7
- data/lib/logstash/inputs/tcp/decoder_impl.rb +17 -5
- data/lib/logstash/inputs/tcp.rb +42 -9
- data/lib/logstash-input-tcp_jars.rb +1 -1
- data/logstash-input-tcp.gemspec +2 -2
- data/spec/inputs/tcp_spec.rb +229 -8
- data/spec/spec_helper.rb +11 -0
- data/vendor/jar-dependencies/org/logstash/inputs/logstash-input-tcp/6.3.1/logstash-input-tcp-6.3.1.jar +0 -0
- data/version +1 -1
- metadata +7 -7
- data/vendor/jar-dependencies/org/logstash/inputs/logstash-input-tcp/6.2.7/logstash-input-tcp-6.2.7.jar +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2fb789cdfaf2019169729724b4ab5f0f330d7a136594310a5f823f90d59b807c
|
4
|
+
data.tar.gz: f385f458414136970b159cc1f4e20ff053da79ac55c9358a30e35a741969de0b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 990b51998a4229fd5638083df9ab64daad5dc5a1cf98f6d78fbd3b2e53cce22a8c2ecc0ee61afce2577901b9d68ded2fd27fe34504d92c1f03ee7efef7e885b7
|
7
|
+
data.tar.gz: 8495257bef6b00b3fd06e7bd8d5981adf688d268c531c10f9ae8bf24126f1a367e030d2622dd3a0a0b707b066e822bbc31628bc4f22d184494ceeb78e2987de4
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 6.3.1
|
2
|
+
- Fixes a regression in which the ssl_subject was missing for SSL-secured connections in server mode [#199](https://github.com/logstash-plugins/logstash-input-tcp/pull/199)
|
3
|
+
|
4
|
+
## 6.3.0
|
5
|
+
- Feat: ssl_supported_protocols (TLSv1.3) + ssl_cipher_suites [#198](https://github.com/logstash-plugins/logstash-input-tcp/pull/198)
|
6
|
+
|
1
7
|
## 6.2.7
|
2
8
|
- Build: skip shadowing jar dependencies [#187](https://github.com/logstash-plugins/logstash-input-tcp/pull/187)
|
3
9
|
* plugin no longer shadows dependencies into its *logstash-input-tcp.jar*
|
data/docs/index.asciidoc
CHANGED
@@ -132,10 +132,12 @@ This plugin supports the following configuration options plus the <<plugins-{typ
|
|
132
132
|
| <<plugins-{type}s-{plugin}-proxy_protocol>> |<<boolean,boolean>>|No
|
133
133
|
| <<plugins-{type}s-{plugin}-ssl_cert>> |a valid filesystem path|No
|
134
134
|
| <<plugins-{type}s-{plugin}-ssl_certificate_authorities>> |<<array,array>>|No
|
135
|
+
| <<plugins-{type}s-{plugin}-ssl_cipher_suites>> |<<string,string>>|No
|
135
136
|
| <<plugins-{type}s-{plugin}-ssl_enable>> |<<boolean,boolean>>|No
|
136
137
|
| <<plugins-{type}s-{plugin}-ssl_extra_chain_certs>> |<<array,array>>|No
|
137
138
|
| <<plugins-{type}s-{plugin}-ssl_key>> |a valid filesystem path|No
|
138
139
|
| <<plugins-{type}s-{plugin}-ssl_key_passphrase>> |<<password,password>>|No
|
140
|
+
| <<plugins-{type}s-{plugin}-ssl_supported_protocols>> |<<string,string>>|No
|
139
141
|
| <<plugins-{type}s-{plugin}-ssl_verify>> |<<boolean,boolean>>|No
|
140
142
|
| <<plugins-{type}s-{plugin}-tcp_keep_alive>> |<<boolean,boolean>>|No
|
141
143
|
|=======================================================================
|
@@ -158,13 +160,13 @@ at the TCP layer and IPs will not be resolved to hostnames.
|
|
158
160
|
[id="plugins-{type}s-{plugin}-ecs_compatibility"]
|
159
161
|
===== `ecs_compatibility`
|
160
162
|
|
161
|
-
* Value type is <<string,string>>
|
162
|
-
* Supported values are:
|
163
|
-
** `disabled`: unstructured connection metadata added at root level
|
164
|
-
** `v1`,`v8`: structured connection metadata added under `[@metadata][input][tcp]`
|
165
|
-
* Default value depends on which version of Logstash is running:
|
166
|
-
** When Logstash provides a `pipeline.ecs_compatibility` setting, its value is used as the default
|
167
|
-
** Otherwise, the default value is `disabled`.
|
163
|
+
* Value type is <<string,string>>
|
164
|
+
* Supported values are:
|
165
|
+
** `disabled`: unstructured connection metadata added at root level
|
166
|
+
** `v1`,`v8`: structured connection metadata added under `[@metadata][input][tcp]`
|
167
|
+
* Default value depends on which version of Logstash is running:
|
168
|
+
** When Logstash provides a `pipeline.ecs_compatibility` setting, its value is used as the default
|
169
|
+
** Otherwise, the default value is `disabled`.
|
168
170
|
|
169
171
|
Controls this plugin's compatibility with the https://www.elastic.co/guide/en/ecs/current/index.html[Elastic Common Schema (ECS)].
|
170
172
|
The value of this setting affects the <<plugins-{type}s-{plugin}-ecs_metadata,placement of a TCP connection's metadata>> on events.
|
@@ -224,6 +226,18 @@ to the connecting clients.
|
|
224
226
|
Validate client certificate or certificate chain against these authorities.
|
225
227
|
You can define multiple files or paths. All the certificates will be read and added to the trust store.
|
226
228
|
|
229
|
+
[id="plugins-{type}s-{plugin}-ssl_cipher_suites"]
|
230
|
+
===== `ssl_cipher_suites`
|
231
|
+
|
232
|
+
* Value type is <<string,string>>
|
233
|
+
* Default value includes _all_ cipher suites enabled by the JDK and depends on JDK configuration
|
234
|
+
|
235
|
+
Supported cipher suites vary depending on Java version used, and entries look like `TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384`.
|
236
|
+
For more information, see Oracle’s https://docs.oracle.com/en/java/javase/11/security/oracle-providers.html#GUID-7093246A-31A3-4304-AC5F-5FB6400405E2[JDK SunJSSE provider documentation] and
|
237
|
+
the table of supported https://docs.oracle.com/en/java/javase/11/docs/specs/security/standard-names.html#jsse-cipher-suite-names[Java cipher suite names].
|
238
|
+
|
239
|
+
NOTE: To check the supported cipher suites locally run the following script: `$LS_HOME/bin/ruby -e 'p javax.net.ssl.SSLServerSocketFactory.getDefault.getSupportedCipherSuites'`.
|
240
|
+
|
227
241
|
[id="plugins-{type}s-{plugin}-ssl_enable"]
|
228
242
|
===== `ssl_enable`
|
229
243
|
|
@@ -258,6 +272,20 @@ The path to the private key corresponding to the specified certificate (PEM form
|
|
258
272
|
|
259
273
|
SSL key passphrase for the private key.
|
260
274
|
|
275
|
+
[id="plugins-{type}s-{plugin}-ssl_supported_protocols"]
|
276
|
+
===== `ssl_supported_protocols`
|
277
|
+
|
278
|
+
* Value type is <<string,string>>
|
279
|
+
* Allowed values are: `'TLSv1.1'`, `'TLSv1.2'`, `'TLSv1.3'`
|
280
|
+
* Default depends on the JDK being used. With up-to-date Logstash, the default is `['TLSv1.2', 'TLSv1.3']`.
|
281
|
+
`'TLSv1.1'` is not considered secure and is only provided for legacy applications.
|
282
|
+
|
283
|
+
List of allowed SSL/TLS versions to use when establishing a secure connection.
|
284
|
+
|
285
|
+
NOTE: If you configure the plugin to use `'TLSv1.1'` on any recent JVM, such as the one packaged with Logstash,
|
286
|
+
the protocol is disabled by default and needs to be enabled manually by changing `jdk.tls.disabledAlgorithms` in
|
287
|
+
the *$JDK_HOME/conf/security/java.security* configuration file. That is, `TLSv1.1` needs to be removed from the list.
|
288
|
+
|
261
289
|
[id="plugins-{type}s-{plugin}-ssl_verify"]
|
262
290
|
===== `ssl_verify`
|
263
291
|
|
@@ -11,16 +11,17 @@ class LogStash::Inputs::Tcp::DecoderImpl
|
|
11
11
|
@first_read = true
|
12
12
|
end
|
13
13
|
|
14
|
-
def decode(
|
14
|
+
def decode(ctx, data)
|
15
|
+
channel = ctx.channel()
|
15
16
|
bytes = Java::byte[data.readableBytes].new
|
16
17
|
data.getBytes(0, bytes)
|
17
18
|
data.release
|
18
19
|
tbuf = String.from_java_bytes bytes, "ASCII-8BIT"
|
19
20
|
if @first_read
|
20
|
-
tbuf = init_first_read(
|
21
|
+
tbuf = init_first_read(channel, tbuf)
|
21
22
|
end
|
22
23
|
@tcp.decode_buffer(@ip_address, @address, @port, @codec,
|
23
|
-
|
24
|
+
@proxy_address, @proxy_port, tbuf, @sslsubject)
|
24
25
|
end
|
25
26
|
|
26
27
|
def copy
|
@@ -28,11 +29,12 @@ class LogStash::Inputs::Tcp::DecoderImpl
|
|
28
29
|
end
|
29
30
|
|
30
31
|
def flush
|
31
|
-
@tcp.flush_codec(@codec, @ip_address, @address, @port,
|
32
|
+
@tcp.flush_codec(@codec, @ip_address, @address, @port, @sslsubject)
|
32
33
|
end
|
33
34
|
|
34
35
|
private
|
35
|
-
def init_first_read(
|
36
|
+
def init_first_read(channel, received)
|
37
|
+
channel_addr = channel.remoteAddress()
|
36
38
|
if @tcp.proxy_protocol
|
37
39
|
pp_hdr, filtered = received.split("\r\n", 2)
|
38
40
|
pp_info = pp_hdr.split(/\s/)
|
@@ -53,10 +55,20 @@ class LogStash::Inputs::Tcp::DecoderImpl
|
|
53
55
|
@address = extract_host_name(channel_addr) # name _or_ address of sender
|
54
56
|
@port = channel_addr.get_port # outgoing port of sender (probably random)
|
55
57
|
end
|
58
|
+
@sslsubject = extract_sslsubject(channel)
|
56
59
|
@first_read = false
|
57
60
|
filtered
|
58
61
|
end
|
59
62
|
|
63
|
+
private
|
64
|
+
def extract_sslsubject(channel)
|
65
|
+
return nil unless @tcp.ssl_enable && @tcp.ssl_verify
|
66
|
+
|
67
|
+
channel.pipeline().get("ssl-handler").engine().getSession().getPeerPrincipal().getName()
|
68
|
+
rescue Exception => e
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
|
60
72
|
private
|
61
73
|
def extract_host_name(channel_addr)
|
62
74
|
channel_addr = java.net.InetSocketAddress.new(channel_addr, 0) if channel_addr.kind_of?(String)
|
data/lib/logstash/inputs/tcp.rb
CHANGED
@@ -112,6 +112,13 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
112
112
|
# All the certificates will be read and added to the trust store.
|
113
113
|
config :ssl_certificate_authorities, :validate => :array, :default => []
|
114
114
|
|
115
|
+
# NOTE: the default setting [] uses Java SSL engine defaults.
|
116
|
+
config :ssl_supported_protocols, :validate => ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'], :default => [], :list => true
|
117
|
+
|
118
|
+
# The list of ciphers suite to use, listed by priorities.
|
119
|
+
# NOTE: the default setting [] uses Java SSL defaults.
|
120
|
+
config :ssl_cipher_suites, :validate => SslContextBuilder.getSupportedCipherSuites.to_a, :default => [], :list => true
|
121
|
+
|
115
122
|
# Instruct the socket to use TCP keep alives. Uses OS defaults for keep alive settings.
|
116
123
|
config :tcp_keep_alive, :validate => :boolean, :default => false
|
117
124
|
|
@@ -183,19 +190,19 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
183
190
|
end
|
184
191
|
|
185
192
|
def decode_buffer(client_ip_address, client_address, client_port, codec, proxy_address,
|
186
|
-
proxy_port, tbuf,
|
193
|
+
proxy_port, tbuf, ssl_subject)
|
187
194
|
codec.decode(tbuf) do |event|
|
188
195
|
if @proxy_protocol
|
189
196
|
event.set(@field_proxy_host, proxy_address) unless event.get(@field_proxy_host)
|
190
197
|
event.set(@field_proxy_port, proxy_port) unless event.get(@field_proxy_port)
|
191
198
|
end
|
192
|
-
enqueue_decorated(event, client_ip_address, client_address, client_port,
|
199
|
+
enqueue_decorated(event, client_ip_address, client_address, client_port, ssl_subject)
|
193
200
|
end
|
194
201
|
end
|
195
202
|
|
196
|
-
def flush_codec(codec, client_ip_address, client_address, client_port,
|
203
|
+
def flush_codec(codec, client_ip_address, client_address, client_port, ssl_subject)
|
197
204
|
codec.flush do |event|
|
198
|
-
enqueue_decorated(event, client_ip_address, client_address, client_port,
|
205
|
+
enqueue_decorated(event, client_ip_address, client_address, client_port, ssl_subject)
|
199
206
|
end
|
200
207
|
end
|
201
208
|
|
@@ -215,10 +222,14 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
215
222
|
client_socket.close rescue nil
|
216
223
|
end
|
217
224
|
|
225
|
+
# only called in client mode
|
218
226
|
def handle_socket(socket)
|
219
227
|
client_address = socket.peeraddr[3]
|
220
228
|
client_ip_address = socket.peeraddr[2]
|
221
229
|
client_port = socket.peeraddr[1]
|
230
|
+
|
231
|
+
# Client mode sslsubject extraction, server mode happens in DecoderImpl#decode
|
232
|
+
ssl_subject = socket.peer_cert.subject.to_s if @ssl_enable && @ssl_verify
|
222
233
|
peer = "#{client_address}:#{client_port}"
|
223
234
|
first_read = true
|
224
235
|
codec = @codec.clone
|
@@ -242,7 +253,7 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
242
253
|
end
|
243
254
|
end
|
244
255
|
decode_buffer(client_ip_address, client_address, client_port, codec, proxy_address,
|
245
|
-
proxy_port, tbuf,
|
256
|
+
proxy_port, tbuf, ssl_subject)
|
246
257
|
end
|
247
258
|
rescue EOFError
|
248
259
|
@logger.debug? && @logger.debug("Connection closed", :client => peer)
|
@@ -256,14 +267,14 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
256
267
|
ensure
|
257
268
|
# catch all rescue nil on close to discard any close errors or invalid socket
|
258
269
|
socket.close rescue nil
|
259
|
-
flush_codec(codec, client_ip_address, client_address, client_port,
|
270
|
+
flush_codec(codec, client_ip_address, client_address, client_port, ssl_subject)
|
260
271
|
end
|
261
272
|
|
262
|
-
def enqueue_decorated(event, client_ip_address, client_address, client_port,
|
273
|
+
def enqueue_decorated(event, client_ip_address, client_address, client_port, ssl_subject)
|
263
274
|
event.set(@field_host, client_address) unless event.get(@field_host)
|
264
275
|
event.set(@field_host_ip, client_ip_address) unless event.get(@field_host_ip)
|
265
276
|
event.set(@field_port, client_port) unless event.get(@field_port)
|
266
|
-
event.set(@field_sslsubject,
|
277
|
+
event.set(@field_sslsubject, ssl_subject) unless ssl_subject.nil? || event.get(@field_sslsubject)
|
267
278
|
decorate(event)
|
268
279
|
@output_queue << event
|
269
280
|
end
|
@@ -286,7 +297,7 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
286
297
|
return @ssl_context if @ssl_context
|
287
298
|
|
288
299
|
begin
|
289
|
-
@ssl_context =
|
300
|
+
@ssl_context = new_ssl_context
|
290
301
|
@ssl_context.cert = OpenSSL::X509::Certificate.new(File.read(@ssl_cert))
|
291
302
|
@ssl_context.key = OpenSSL::PKey::RSA.new(File.read(@ssl_key),@ssl_key_passphrase.value)
|
292
303
|
if @ssl_extra_chain_certs.any?
|
@@ -297,6 +308,21 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
297
308
|
@ssl_context.cert_store = load_cert_store
|
298
309
|
@ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
299
310
|
end
|
311
|
+
|
312
|
+
@ssl_context.min_version = :TLS1_1 # not strictly required - JVM should have disabled TLSv1
|
313
|
+
if ssl_supported_protocols.any?
|
314
|
+
disabled_protocols = ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'] - ssl_supported_protocols
|
315
|
+
unless OpenSSL::SSL.const_defined? :OP_NO_TLSv1_3 # work-around JRuby-OpenSSL bug - missing constant
|
316
|
+
@ssl_context.max_version = :TLS1_2 if disabled_protocols.delete('TLSv1.3')
|
317
|
+
end
|
318
|
+
# mapping 'TLSv1.2' -> OpenSSL::SSL::OP_NO_TLSv1_2
|
319
|
+
disabled_protocols.map! { |v| OpenSSL::SSL.const_get "OP_NO_#{v.sub('.', '_')}" }
|
320
|
+
@ssl_context.options = disabled_protocols.reduce(@ssl_context.options, :|)
|
321
|
+
end
|
322
|
+
|
323
|
+
if ssl_cipher_suites.any?
|
324
|
+
@ssl_context.ciphers = ssl_cipher_suites # Java cipher names work with JOSSL >= 0.12.2
|
325
|
+
end
|
300
326
|
rescue => e
|
301
327
|
@logger.error("Could not inititalize SSL context", :message => e.message, :exception => e.class, :backtrace => e.backtrace)
|
302
328
|
raise e
|
@@ -305,6 +331,11 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
305
331
|
@ssl_context
|
306
332
|
end
|
307
333
|
|
334
|
+
# @note to be able to hook up into #ssl_context from tests
|
335
|
+
def new_ssl_context
|
336
|
+
OpenSSL::SSL::SSLContext.new
|
337
|
+
end
|
338
|
+
|
308
339
|
def load_cert_store
|
309
340
|
cert_store = OpenSSL::X509::Store.new
|
310
341
|
cert_store.set_default_paths
|
@@ -379,6 +410,8 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
379
410
|
.set_ssl_key_password(@ssl_key_passphrase.value)
|
380
411
|
.set_ssl_extra_chain_certs(@ssl_extra_chain_certs.to_java(:string))
|
381
412
|
.set_ssl_certificate_authorities(@ssl_certificate_authorities.to_java(:string))
|
413
|
+
.set_ssl_supported_protocols(ssl_supported_protocols.to_java(:string))
|
414
|
+
.set_ssl_cipher_suites(ssl_cipher_suites.to_java(:string))
|
382
415
|
.build_context
|
383
416
|
rescue java.lang.IllegalArgumentException => e
|
384
417
|
@logger.error("SSL configuration invalid", error_details(e))
|
data/logstash-input-tcp.gemspec
CHANGED
@@ -23,10 +23,10 @@ Gem::Specification.new do |s|
|
|
23
23
|
s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
|
24
24
|
s.add_runtime_dependency 'logstash-mixin-ecs_compatibility_support', '~>1.2'
|
25
25
|
|
26
|
-
s.add_runtime_dependency 'logstash-core', '>=
|
26
|
+
s.add_runtime_dependency 'logstash-core', '>= 8.1.0'
|
27
27
|
|
28
28
|
# we depend on bouncycastle's bcpkix-jdk15on being on the class-path
|
29
|
-
s.add_runtime_dependency 'jruby-openssl', '>= 0.
|
29
|
+
s.add_runtime_dependency 'jruby-openssl', '>= 0.12.2' # 0.12 supports TLSv1.3
|
30
30
|
|
31
31
|
# line vs streaming codecs required for fix_streaming_codecs
|
32
32
|
# TODO: fix_streaming_codecs should be refactored to not
|
data/spec/inputs/tcp_spec.rb
CHANGED
@@ -541,7 +541,7 @@ describe LogStash::Inputs::Tcp, :ecs_compatibility_support do
|
|
541
541
|
end
|
542
542
|
end
|
543
543
|
|
544
|
-
describe "#receive" do
|
544
|
+
describe "#receive", :ecs_compatibility_support do
|
545
545
|
shared_examples "receiving events" do
|
546
546
|
# TODO(sissel): Implement normal event-receipt tests as as a shared example
|
547
547
|
end
|
@@ -549,7 +549,10 @@ describe LogStash::Inputs::Tcp, :ecs_compatibility_support do
|
|
549
549
|
context "when ssl_enable is true" do
|
550
550
|
let(:input) { subject }
|
551
551
|
let(:queue) { Queue.new }
|
552
|
-
before(:each)
|
552
|
+
before(:each) do
|
553
|
+
allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility) if defined?(ecs_compatibility)
|
554
|
+
subject.register
|
555
|
+
end
|
553
556
|
|
554
557
|
context "when using a certificate chain" do
|
555
558
|
chain_of_certificates = TcpHelpers.new.chain_of_certificates
|
@@ -568,18 +571,21 @@ describe LogStash::Inputs::Tcp, :ecs_compatibility_support do
|
|
568
571
|
let(:sslsocket) { OpenSSL::SSL::SSLSocket.new(tcp, sslcontext) }
|
569
572
|
let(:message) { "message to #{port}" }
|
570
573
|
|
571
|
-
|
572
|
-
|
573
|
-
{
|
574
|
+
let(:base_config) do
|
575
|
+
{
|
574
576
|
"host" => "127.0.0.1",
|
575
577
|
"port" => port,
|
576
578
|
"ssl_enable" => true,
|
577
579
|
"ssl_cert" => chain_of_certificates[:b_cert].path,
|
578
580
|
"ssl_key" => chain_of_certificates[:b_key].path,
|
579
581
|
"ssl_extra_chain_certs" => [ chain_of_certificates[:a_cert].path ],
|
580
|
-
"ssl_certificate_authorities" => [ chain_of_certificates[:root_ca].path ]
|
581
|
-
|
582
|
-
|
582
|
+
"ssl_certificate_authorities" => [ chain_of_certificates[:root_ca].path ]
|
583
|
+
}
|
584
|
+
end
|
585
|
+
|
586
|
+
context "with a non encrypted private key" do
|
587
|
+
let(:config) do
|
588
|
+
base_config.merge "ssl_verify" => true
|
583
589
|
end
|
584
590
|
it "should be able to connect and write data" do
|
585
591
|
result = TcpHelpers.pipelineless_input(subject, 1) do
|
@@ -620,6 +626,7 @@ describe LogStash::Inputs::Tcp, :ecs_compatibility_support do
|
|
620
626
|
expect(result.first.get("message")).to eq(message)
|
621
627
|
end
|
622
628
|
end
|
629
|
+
|
623
630
|
context "when using an encrypted private pkcs8 key" do
|
624
631
|
let(:config) do
|
625
632
|
{
|
@@ -646,6 +653,141 @@ describe LogStash::Inputs::Tcp, :ecs_compatibility_support do
|
|
646
653
|
expect(result.first.get("message")).to eq(message)
|
647
654
|
end
|
648
655
|
end
|
656
|
+
|
657
|
+
context "with a regular TLS setup" do
|
658
|
+
let(:config) do
|
659
|
+
{
|
660
|
+
"host" => "127.0.0.1",
|
661
|
+
"port" => port,
|
662
|
+
"ssl_enable" => true,
|
663
|
+
"ssl_cert" => chain_of_certificates[:b_cert].path,
|
664
|
+
"ssl_key" => chain_of_certificates[:b_key].path,
|
665
|
+
"ssl_extra_chain_certs" => [ chain_of_certificates[:a_cert].path ],
|
666
|
+
"ssl_certificate_authorities" => [ chain_of_certificates[:root_ca].path ],
|
667
|
+
"ssl_verify" => true
|
668
|
+
}
|
669
|
+
end
|
670
|
+
|
671
|
+
ecs_compatibility_matrix(:disabled,:v1, :v8 => :v1) do |ecs_select|
|
672
|
+
it "extracts the TLS subject from connections" do
|
673
|
+
result = TcpHelpers.pipelineless_input(subject, 1) do
|
674
|
+
sslsocket.connect
|
675
|
+
sslsocket.write("#{message}\n")
|
676
|
+
tcp.flush
|
677
|
+
sslsocket.close
|
678
|
+
tcp.close
|
679
|
+
end
|
680
|
+
expect(result.size).to eq(1)
|
681
|
+
event = result.first
|
682
|
+
|
683
|
+
ssl_subject_field = ecs_select[disabled: 'sslsubject', v1:'[@metadata][input][tcp][tls][client][subject]']
|
684
|
+
expect(event.get(ssl_subject_field)).to eq("CN=RubyAA_Cert,DC=ruby-lang,DC=org")
|
685
|
+
end
|
686
|
+
end
|
687
|
+
end
|
688
|
+
|
689
|
+
context "with enforced protocol version" do
|
690
|
+
let(:config) do
|
691
|
+
base_config.merge 'ssl_supported_protocols' => [ tls_version ]
|
692
|
+
end
|
693
|
+
|
694
|
+
let(:tls_version) { 'TLSv1.3' }
|
695
|
+
|
696
|
+
it "should be able to connect and write data" do
|
697
|
+
used_tls_protocol = nil
|
698
|
+
result = TcpHelpers.pipelineless_input(subject, 1) do
|
699
|
+
sslsocket.connect
|
700
|
+
sslsocket.write("#{message}\n")
|
701
|
+
used_tls_protocol = sslsocket.session.to_java(javax.net.ssl.SSLSession).getProtocol
|
702
|
+
tcp.flush
|
703
|
+
sslsocket.close
|
704
|
+
tcp.close
|
705
|
+
end
|
706
|
+
expect(result.size).to eq(1)
|
707
|
+
expect(used_tls_protocol).to eql tls_version
|
708
|
+
end
|
709
|
+
end
|
710
|
+
|
711
|
+
context "with enforced protocol range" do
|
712
|
+
let(:config) do
|
713
|
+
base_config.merge 'ssl_supported_protocols' => [ 'TLSv1.3', 'TLSv1.2' ]
|
714
|
+
end
|
715
|
+
let(:sslcontext) do
|
716
|
+
super().tap { |ctx| ctx.ssl_version = 'TLSv1.2' }
|
717
|
+
end
|
718
|
+
|
719
|
+
it "should be able to connect and write data" do
|
720
|
+
used_tls_protocol = nil
|
721
|
+
result = TcpHelpers.pipelineless_input(subject, 1) do
|
722
|
+
sslsocket.connect
|
723
|
+
sslsocket.write("#{message}\n")
|
724
|
+
used_tls_protocol = sslsocket.session.to_java(javax.net.ssl.SSLSession).getProtocol
|
725
|
+
tcp.flush
|
726
|
+
sslsocket.close
|
727
|
+
tcp.close
|
728
|
+
end
|
729
|
+
expect(result.size).to eq(1)
|
730
|
+
expect(used_tls_protocol).to eql 'TLSv1.2'
|
731
|
+
end
|
732
|
+
end if TcpHelpers.tls13_available_by_default? # till CI testing against 6.x
|
733
|
+
|
734
|
+
context "with unsupported client protocol" do
|
735
|
+
let(:config) do
|
736
|
+
base_config.merge 'ssl_supported_protocols' => [ 'TLSv1.2' ]
|
737
|
+
end
|
738
|
+
let(:sslcontext) do
|
739
|
+
super().tap { |ctx| ctx.ssl_version = 'TLSv1.1' }
|
740
|
+
end
|
741
|
+
|
742
|
+
it "should not be able to connect" do
|
743
|
+
TcpHelpers.pipelineless_input(subject, 0) do
|
744
|
+
expect { sslsocket.connect }.to raise_error(OpenSSL::SSL::SSLError, /No appropriate protocol|protocol_version/i)
|
745
|
+
sslsocket.close
|
746
|
+
tcp.close
|
747
|
+
end
|
748
|
+
end
|
749
|
+
end
|
750
|
+
|
751
|
+
context "with specified cipher suites" do
|
752
|
+
let(:config) do
|
753
|
+
base_config.merge 'ssl_cipher_suites' => [ cipher_suite ]
|
754
|
+
end
|
755
|
+
|
756
|
+
let(:cipher_suite) { 'TLS_RSA_WITH_AES_128_GCM_SHA256' }
|
757
|
+
|
758
|
+
it "should be able to connect and write data" do
|
759
|
+
used_cipher_suite = nil
|
760
|
+
result = TcpHelpers.pipelineless_input(subject, 1) do
|
761
|
+
sslsocket.connect
|
762
|
+
sslsocket.write("#{message}\n")
|
763
|
+
used_cipher_suite = sslsocket.session.to_java(javax.net.ssl.SSLSession).getCipherSuite
|
764
|
+
tcp.flush
|
765
|
+
sslsocket.close
|
766
|
+
tcp.close
|
767
|
+
end
|
768
|
+
expect(result.size).to eq(1)
|
769
|
+
expect(used_cipher_suite).to eql cipher_suite
|
770
|
+
end
|
771
|
+
end
|
772
|
+
|
773
|
+
context "with unsupported client cipher" do
|
774
|
+
let(:config) do
|
775
|
+
base_config.merge 'ssl_cipher_suites' => [ 'TLS_RSA_WITH_AES_128_GCM_SHA256', 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256' ]
|
776
|
+
end
|
777
|
+
|
778
|
+
let(:sslcontext) do
|
779
|
+
super().tap { |ctx| ctx.ciphers = [ 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384', 'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256' ] }
|
780
|
+
end
|
781
|
+
|
782
|
+
it "should not be able to connect" do
|
783
|
+
TcpHelpers.pipelineless_input(subject, 0) do
|
784
|
+
expect { sslsocket.connect }.to raise_error(OpenSSL::SSL::SSLError, /handshake_failure|no cipher match/i)
|
785
|
+
sslsocket.close
|
786
|
+
tcp.close
|
787
|
+
end
|
788
|
+
end
|
789
|
+
end
|
790
|
+
|
649
791
|
end
|
650
792
|
|
651
793
|
context "with a poorly-behaving client" do
|
@@ -717,4 +859,83 @@ describe LogStash::Inputs::Tcp, :ecs_compatibility_support do
|
|
717
859
|
let(:config) { { "port" => port } }
|
718
860
|
end
|
719
861
|
end
|
862
|
+
|
863
|
+
context 'ssl context (client mode)' do
|
864
|
+
|
865
|
+
let(:chain_of_certificates) do
|
866
|
+
TcpHelpers.new.chain_of_certificates
|
867
|
+
end
|
868
|
+
|
869
|
+
let(:config) do
|
870
|
+
{
|
871
|
+
"host" => "127.0.0.1",
|
872
|
+
"port" => port,
|
873
|
+
"mode" => 'client',
|
874
|
+
"ssl_enable" => true,
|
875
|
+
"ssl_cert" => chain_of_certificates[:b_cert].path,
|
876
|
+
"ssl_key" => chain_of_certificates[:b_key].path,
|
877
|
+
"ssl_extra_chain_certs" => [ chain_of_certificates[:a_cert].path ],
|
878
|
+
"ssl_certificate_authorities" => [ chain_of_certificates[:root_ca].path ]
|
879
|
+
}
|
880
|
+
end
|
881
|
+
|
882
|
+
subject(:plugin) { LogStash::Inputs::Tcp.new(config) }
|
883
|
+
|
884
|
+
let(:ssl_context) { plugin.send :ssl_context }
|
885
|
+
|
886
|
+
context "with cipher suites" do
|
887
|
+
let(:config) do
|
888
|
+
super().merge 'ssl_cipher_suites' => [ cipher_suite ]
|
889
|
+
end
|
890
|
+
|
891
|
+
let(:cipher_suite) { 'TLS_RSA_WITH_AES_128_GCM_SHA256' }
|
892
|
+
|
893
|
+
it "sets ciphers" do
|
894
|
+
cipher_ary = ssl_context.ciphers.first
|
895
|
+
expect( cipher_ary[0] ).to eql 'AES128-GCM-SHA256'
|
896
|
+
end
|
897
|
+
|
898
|
+
end
|
899
|
+
|
900
|
+
context "with forced protocol" do
|
901
|
+
let(:config) do
|
902
|
+
super().merge 'ssl_supported_protocols' => [ 'TLSv1.1' ]
|
903
|
+
end
|
904
|
+
|
905
|
+
it "limits protocol selection" do
|
906
|
+
if OpenSSL::SSL.const_defined? :OP_NO_TLSv1_3
|
907
|
+
ssl_context = subject.send :ssl_context
|
908
|
+
expect(ssl_context.options & OpenSSL::SSL::OP_NO_TLSv1_3).to_not eql 0
|
909
|
+
expect(ssl_context.options & OpenSSL::SSL::OP_NO_TLSv1_2).to_not eql 0
|
910
|
+
expect(ssl_context.options & OpenSSL::SSL::OP_NO_TLSv1_1).to eql 0
|
911
|
+
else
|
912
|
+
ssl_context = OpenSSL::SSL::SSLContext.new
|
913
|
+
allow(subject).to receive(:new_ssl_context).and_return(ssl_context)
|
914
|
+
expect(ssl_context).to receive(:max_version=).with(:'TLS1_2').and_call_original
|
915
|
+
ssl_context = subject.send :ssl_context
|
916
|
+
expect(ssl_context.options & OpenSSL::SSL::OP_NO_TLSv1_2).to_not eql 0
|
917
|
+
expect(ssl_context.options & OpenSSL::SSL::OP_NO_TLSv1_1).to eql 0
|
918
|
+
end
|
919
|
+
end
|
920
|
+
|
921
|
+
end
|
922
|
+
|
923
|
+
context "with protocol range" do
|
924
|
+
let(:config) do
|
925
|
+
super().merge 'ssl_supported_protocols' => [ 'TLSv1.3', 'TLSv1.1', 'TLSv1.2' ]
|
926
|
+
end
|
927
|
+
|
928
|
+
it "does not limit protocol selection (except min_version)" do
|
929
|
+
ssl_context = OpenSSL::SSL::SSLContext.new
|
930
|
+
allow(subject).to receive(:new_ssl_context).and_return(ssl_context)
|
931
|
+
expect(ssl_context).to receive(:min_version=).with(:'TLS1_1').and_call_original
|
932
|
+
ssl_context = subject.send :ssl_context
|
933
|
+
expect(ssl_context.options & OpenSSL::SSL::OP_NO_TLSv1_3).to eql 0 if OpenSSL::SSL.const_defined? :OP_NO_TLSv1_3
|
934
|
+
expect(ssl_context.options & OpenSSL::SSL::OP_NO_TLSv1_2).to eql 0
|
935
|
+
expect(ssl_context.options & OpenSSL::SSL::OP_NO_TLSv1_1).to eql 0
|
936
|
+
end
|
937
|
+
end
|
938
|
+
|
939
|
+
end
|
940
|
+
|
720
941
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -7,6 +7,17 @@ require "stud/temporary"
|
|
7
7
|
|
8
8
|
class TcpHelpers
|
9
9
|
|
10
|
+
def self.tls13_available_by_default?
|
11
|
+
begin
|
12
|
+
context = javax.net.ssl.SSLContext.getInstance('TLS')
|
13
|
+
context.init nil, nil, nil
|
14
|
+
context.getDefaultSSLParameters.getProtocols.include? 'TLSv1.3'
|
15
|
+
rescue => e
|
16
|
+
warn "failed to detect TLSv1.3 support: #{e.inspect}"
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
10
21
|
java_import 'org.bouncycastle.openssl.PEMParser'
|
11
22
|
java_import 'org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8EncryptorBuilder'
|
12
23
|
java_import 'org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter'
|
Binary file
|
data/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
6.
|
1
|
+
6.3.1
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-input-tcp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.3.1
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-10-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -49,7 +49,7 @@ dependencies:
|
|
49
49
|
requirements:
|
50
50
|
- - ">="
|
51
51
|
- !ruby/object:Gem::Version
|
52
|
-
version:
|
52
|
+
version: 8.1.0
|
53
53
|
name: logstash-core
|
54
54
|
prerelease: false
|
55
55
|
type: :runtime
|
@@ -57,13 +57,13 @@ dependencies:
|
|
57
57
|
requirements:
|
58
58
|
- - ">="
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version:
|
60
|
+
version: 8.1.0
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
requirement: !ruby/object:Gem::Requirement
|
63
63
|
requirements:
|
64
64
|
- - ">="
|
65
65
|
- !ruby/object:Gem::Version
|
66
|
-
version: 0.
|
66
|
+
version: 0.12.2
|
67
67
|
name: jruby-openssl
|
68
68
|
prerelease: false
|
69
69
|
type: :runtime
|
@@ -71,7 +71,7 @@ dependencies:
|
|
71
71
|
requirements:
|
72
72
|
- - ">="
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: 0.
|
74
|
+
version: 0.12.2
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
requirement: !ruby/object:Gem::Requirement
|
77
77
|
requirements:
|
@@ -233,7 +233,7 @@ files:
|
|
233
233
|
- spec/spec_helper.rb
|
234
234
|
- vendor/jar-dependencies/commons-io/commons-io/2.8.0/commons-io-2.8.0.jar
|
235
235
|
- vendor/jar-dependencies/io/netty/netty-all/4.1.65.Final/netty-all-4.1.65.Final.jar
|
236
|
-
- vendor/jar-dependencies/org/logstash/inputs/logstash-input-tcp/6.
|
236
|
+
- vendor/jar-dependencies/org/logstash/inputs/logstash-input-tcp/6.3.1/logstash-input-tcp-6.3.1.jar
|
237
237
|
- version
|
238
238
|
homepage: http://www.elastic.co/guide/en/logstash/current/index.html
|
239
239
|
licenses:
|