logstash-input-tcp 6.2.7-java → 6.3.1-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 +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:
|