logstash-input-tcp 5.1.0-java → 5.2.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile +4 -0
- data/docs/index.asciidoc +17 -5
- data/lib/logstash/inputs/tcp.rb +26 -62
- data/lib/logstash/inputs/tcp/compat_ssl_options.rb +103 -0
- data/spec/inputs/tcp_spec.rb +104 -79
- data/vendor/jar-dependencies/org/logstash/inputs/logstash-input-tcp/{5.1.0/logstash-input-tcp-5.1.0.jar → 5.2.0/logstash-input-tcp-5.2.0.jar} +0 -0
- data/version +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f821e3a9df2b90606b5fd46026262b5c7a0054d5e24bf7545d322efbedec40a
|
4
|
+
data.tar.gz: 202f4eeb3fe522d4df635599b7557faaab6884db8d80c1a92a17f140915c1d02
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cee3f82c41bfefea68c3e0337a5ad15f50e17ba6e72fe4fbcf004c6580d755107d47435667c73022938fe852a7e4a7401e793f6640c70bac0486f8fcbbd63642
|
7
|
+
data.tar.gz: a588b4ca240e7eb9e6cca0aec296999270c89b375d7b8038de989529447bf8f5df1c38faae49d71821f2051906e34e32e5f834f248ad2a2856583a7b16704caf
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 5.2.0
|
2
|
+
- Added support for pkcs1 and pkcs8 key formats [#122](https://github.com/logstash-plugins/logstash-input-tcp/issues/122)
|
3
|
+
- Changed server-mode SSL to run on top of Netty [#122](https://github.com/logstash-plugins/logstash-input-tcp/issues/122)
|
4
|
+
- Changed travis testing infra to use logstash tarballs [#122](https://github.com/logstash-plugins/logstash-input-tcp/issues/122)
|
5
|
+
- Fixed certificate chain handling and validation [#124](https://github.com/logstash-plugins/logstash-input-tcp/issues/124)
|
6
|
+
|
1
7
|
## 5.1.0
|
2
8
|
- Added new configuration option `dns_reverse_lookup_enabled` to allow users to disable costly DNS reverse lookups [#100](https://github.com/logstash-plugins/logstash-input-tcp/issues/100)
|
3
9
|
|
data/Gemfile
CHANGED
@@ -9,3 +9,7 @@ if Dir.exist?(logstash_path) && use_logstash_source
|
|
9
9
|
gem 'logstash-core', :path => "#{logstash_path}/logstash-core"
|
10
10
|
gem 'logstash-core-plugin-api', :path => "#{logstash_path}/logstash-core-plugin-api"
|
11
11
|
end
|
12
|
+
|
13
|
+
if RUBY_VERSION == "1.9.3"
|
14
|
+
gem 'rake', '12.2.1'
|
15
|
+
end
|
data/docs/index.asciidoc
CHANGED
@@ -83,6 +83,7 @@ This plugin supports the following configuration options plus the <<plugins-{typ
|
|
83
83
|
| <<plugins-{type}s-{plugin}-port>> |<<number,number>>|Yes
|
84
84
|
| <<plugins-{type}s-{plugin}-proxy_protocol>> |<<boolean,boolean>>|No
|
85
85
|
| <<plugins-{type}s-{plugin}-ssl_cert>> |a valid filesystem path|No
|
86
|
+
| <<plugins-{type}s-{plugin}-ssl_certificate_authorities>> |<<array,array>>|No
|
86
87
|
| <<plugins-{type}s-{plugin}-ssl_enable>> |<<boolean,boolean>>|No
|
87
88
|
| <<plugins-{type}s-{plugin}-ssl_extra_chain_certs>> |<<array,array>>|No
|
88
89
|
| <<plugins-{type}s-{plugin}-ssl_key>> |a valid filesystem path|No
|
@@ -140,7 +141,17 @@ http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt
|
|
140
141
|
* Value type is <<path,path>>
|
141
142
|
* There is no default value for this setting.
|
142
143
|
|
143
|
-
|
144
|
+
Path to certificate in PEM format. This certificate will be presented
|
145
|
+
to the connecting clients.
|
146
|
+
|
147
|
+
[id="plugins-{type}s-{plugin}-ssl_certificate_authorities"]
|
148
|
+
===== `ssl_extra_chain_certs`
|
149
|
+
|
150
|
+
* Value type is <<array,array>>
|
151
|
+
* Default value is `[]`
|
152
|
+
|
153
|
+
Validate client certificate or certificate chain against these authorities.
|
154
|
+
You can define multiple files or paths. All the certificates will be read and added to the trust store.
|
144
155
|
|
145
156
|
[id="plugins-{type}s-{plugin}-ssl_enable"]
|
146
157
|
===== `ssl_enable`
|
@@ -156,8 +167,9 @@ Enable SSL (must be set for other `ssl_` options to take effect).
|
|
156
167
|
* Value type is <<array,array>>
|
157
168
|
* Default value is `[]`
|
158
169
|
|
159
|
-
An Array of extra X509 certificates
|
160
|
-
|
170
|
+
An Array of paths to extra X509 certificates.
|
171
|
+
These are used together with the certificate to construct the certificate chain
|
172
|
+
presented to the client.
|
161
173
|
|
162
174
|
[id="plugins-{type}s-{plugin}-ssl_key"]
|
163
175
|
===== `ssl_key`
|
@@ -165,7 +177,7 @@ Useful when the CA chain is not necessary in the system store.
|
|
165
177
|
* Value type is <<path,path>>
|
166
178
|
* There is no default value for this setting.
|
167
179
|
|
168
|
-
|
180
|
+
The path to the private key corresponding to the specified certificate (PEM format).
|
169
181
|
|
170
182
|
[id="plugins-{type}s-{plugin}-ssl_key_passphrase"]
|
171
183
|
===== `ssl_key_passphrase`
|
@@ -173,7 +185,7 @@ SSL key path
|
|
173
185
|
* Value type is <<password,password>>
|
174
186
|
* Default value is `nil`
|
175
187
|
|
176
|
-
SSL key passphrase
|
188
|
+
SSL key passphrase for the private key.
|
177
189
|
|
178
190
|
[id="plugins-{type}s-{plugin}-ssl_verify"]
|
179
191
|
===== `ssl_verify`
|
data/lib/logstash/inputs/tcp.rb
CHANGED
@@ -6,6 +6,7 @@ require "logstash/inputs/base"
|
|
6
6
|
require "logstash/util/socket_peer"
|
7
7
|
require "logstash-input-tcp_jars"
|
8
8
|
require "logstash/inputs/tcp/decoder_impl"
|
9
|
+
require "logstash/inputs/tcp/compat_ssl_options"
|
9
10
|
|
10
11
|
require "socket"
|
11
12
|
require "openssl"
|
@@ -105,6 +106,9 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
105
106
|
# Useful when the CA chain is not necessary in the system store.
|
106
107
|
config :ssl_extra_chain_certs, :validate => :array, :default => []
|
107
108
|
|
109
|
+
# Validate client certificates against these authorities. You can define multiple files or paths. All the certificates will be read and added to the trust store.
|
110
|
+
config :ssl_certificate_authorities, :validate => :array, :default => []
|
111
|
+
|
108
112
|
# Instruct the socket to use TCP keep alives. Uses OS defaults for keep alive settings.
|
109
113
|
config :tcp_keep_alive, :validate => :boolean, :default => false
|
110
114
|
|
@@ -143,22 +147,17 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
143
147
|
|
144
148
|
@logger.info("Starting tcp input listener", :address => "#{@host}:#{@port}", :ssl_enable => "#{@ssl_enable}")
|
145
149
|
if server?
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
end
|
150
|
+
ssl_context = get_ssl_context(SslOptions)
|
151
|
+
|
152
|
+
@loop = InputLoop.new(@host, @port, DecoderImpl.new(@codec, self), @tcp_keep_alive,
|
153
|
+
ssl_context, @logger.to_java(org.apache.logging.log4j.Logger))
|
151
154
|
end
|
152
155
|
end
|
153
156
|
|
154
157
|
def run(output_queue)
|
155
158
|
@output_queue = output_queue
|
156
159
|
if server?
|
157
|
-
|
158
|
-
run_ssl_server
|
159
|
-
else
|
160
|
-
@loop.run
|
161
|
-
end
|
160
|
+
@loop.run
|
162
161
|
else
|
163
162
|
run_client()
|
164
163
|
end
|
@@ -206,30 +205,6 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
206
205
|
|
207
206
|
private
|
208
207
|
|
209
|
-
RUN_LOOP_ERROR_MESSAGE="TCP input server encountered error"
|
210
|
-
def run_ssl_server()
|
211
|
-
while !stop?
|
212
|
-
begin
|
213
|
-
socket = add_connection_socket(server_socket.accept)
|
214
|
-
# start a new thread for each connection.
|
215
|
-
server_connection_thread(socket)
|
216
|
-
rescue OpenSSL::SSL::SSLError => e
|
217
|
-
# log error, close socket, accept next connection
|
218
|
-
@logger.debug? && @logger.debug("SSL Error", :exception => e, :backtrace => e.backtrace)
|
219
|
-
rescue => e
|
220
|
-
@logger.error(
|
221
|
-
RUN_LOOP_ERROR_MESSAGE,
|
222
|
-
:message => e.message,
|
223
|
-
:class => e.class.name,
|
224
|
-
:backtrace => e.backtrace
|
225
|
-
)
|
226
|
-
end
|
227
|
-
end
|
228
|
-
ensure
|
229
|
-
# catch all rescue nil on close to discard any close errors or invalid socket
|
230
|
-
server_socket.close rescue nil
|
231
|
-
end
|
232
|
-
|
233
208
|
def run_client()
|
234
209
|
while !stop?
|
235
210
|
self.client_socket = new_client_socket
|
@@ -240,17 +215,6 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
240
215
|
client_socket.close rescue nil
|
241
216
|
end
|
242
217
|
|
243
|
-
def server_connection_thread(socket)
|
244
|
-
Thread.new(socket) do |s|
|
245
|
-
begin
|
246
|
-
@logger.debug? && @logger.debug("Accepted connection", :client => s.peer, :server => "#{@host}:#{@port}")
|
247
|
-
handle_socket(s)
|
248
|
-
ensure
|
249
|
-
delete_connection_socket(s)
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
218
|
def handle_socket(socket)
|
255
219
|
client_address = socket.peeraddr[3]
|
256
220
|
client_ip_address = socket.peeraddr[2]
|
@@ -317,6 +281,10 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
317
281
|
@ssl_context = OpenSSL::SSL::SSLContext.new
|
318
282
|
@ssl_context.cert = OpenSSL::X509::Certificate.new(File.read(@ssl_cert))
|
319
283
|
@ssl_context.key = OpenSSL::PKey::RSA.new(File.read(@ssl_key),@ssl_key_passphrase.value)
|
284
|
+
if @ssl_extra_chain_certs.any?
|
285
|
+
@ssl_context.extra_chain_cert = @ssl_extra_chain_certs.map {|cert_path| OpenSSL::X509::Certificate.new(File.read(cert_path)) }
|
286
|
+
@ssl_context.extra_chain_cert.unshift(OpenSSL::X509::Certificate.new(File.read(@ssl_cert)))
|
287
|
+
end
|
320
288
|
if @ssl_verify
|
321
289
|
@ssl_context.cert_store = load_cert_store
|
322
290
|
@ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
@@ -332,28 +300,12 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
332
300
|
def load_cert_store
|
333
301
|
cert_store = OpenSSL::X509::Store.new
|
334
302
|
cert_store.set_default_paths
|
335
|
-
@
|
303
|
+
@ssl_certificate_authorities.each do |cert|
|
336
304
|
cert_store.add_file(cert)
|
337
305
|
end
|
338
306
|
cert_store
|
339
307
|
end
|
340
308
|
|
341
|
-
def new_server_socket
|
342
|
-
begin
|
343
|
-
socket = TCPServer.new(@host, @port)
|
344
|
-
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, @tcp_keep_alive)
|
345
|
-
rescue Errno::EADDRINUSE
|
346
|
-
@logger.error("Could not start TCP server: Address in use", :host => @host, :port => @port)
|
347
|
-
raise
|
348
|
-
end
|
349
|
-
|
350
|
-
if @ssl_enable
|
351
|
-
socket = OpenSSL::SSL::SSLServer.new(socket, ssl_context)
|
352
|
-
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, @tcp_keep_alive)
|
353
|
-
end
|
354
|
-
socket
|
355
|
-
end
|
356
|
-
|
357
309
|
def new_client_socket
|
358
310
|
socket = TCPSocket.new(@host, @port)
|
359
311
|
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, @tcp_keep_alive)
|
@@ -409,4 +361,16 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
409
361
|
def connection_sockets
|
410
362
|
@socket_mutex.synchronize{@connection_sockets.keys.dup}
|
411
363
|
end
|
364
|
+
|
365
|
+
def get_ssl_context(options_class)
|
366
|
+
ssl_context = options_class.builder
|
367
|
+
.set_is_ssl_enabled(@ssl_enable)
|
368
|
+
.set_should_verify(@ssl_verify)
|
369
|
+
.set_ssl_cert(@ssl_cert)
|
370
|
+
.set_ssl_key(@ssl_key)
|
371
|
+
.set_ssl_key_passphrase(@ssl_key_passphrase.value)
|
372
|
+
.set_ssl_extra_chain_certs(@ssl_extra_chain_certs.to_java(:string))
|
373
|
+
.set_ssl_certificate_authorities(@ssl_certificate_authorities.to_java(:string))
|
374
|
+
.build.toSslContext()
|
375
|
+
end
|
412
376
|
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
java_import 'io.netty.handler.ssl.ClientAuth'
|
4
|
+
java_import 'io.netty.handler.ssl.SslContextBuilder'
|
5
|
+
java_import 'java.io.FileInputStream'
|
6
|
+
java_import 'java.io.FileReader'
|
7
|
+
java_import 'java.security.cert.CertificateFactory'
|
8
|
+
java_import 'java.security.cert.X509Certificate'
|
9
|
+
java_import 'org.bouncycastle.asn1.pkcs.PrivateKeyInfo'
|
10
|
+
java_import 'org.bouncycastle.openssl.PEMKeyPair'
|
11
|
+
java_import 'org.bouncycastle.openssl.PEMParser'
|
12
|
+
java_import 'org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter'
|
13
|
+
|
14
|
+
# Simulate a normal SslOptions builder:
|
15
|
+
#
|
16
|
+
# ssl_context = SslOptions.builder
|
17
|
+
# .set_is_ssl_enabled(@ssl_enable)
|
18
|
+
# .set_should_verify(@ssl_verify)
|
19
|
+
# .set_ssl_cert(@ssl_cert)
|
20
|
+
# .set_ssl_key(@ssl_key)
|
21
|
+
# .set_ssl_key_passphrase(@ssl_key_passphrase.value)
|
22
|
+
# .set_ssl_extra_chain_certs(@ssl_extra_chain_certs.to_java(:string))
|
23
|
+
# .set_ssl_certificate_authorities(@ssl_certificate_authorities.to_java(:string))
|
24
|
+
# .build.toSslContext()
|
25
|
+
class SslOptions
|
26
|
+
def self.builder
|
27
|
+
new
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_is_ssl_enabled(boolean)
|
31
|
+
@ssl_enabled = boolean
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def set_should_verify(boolean)
|
36
|
+
@ssl_verify = boolean
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def set_ssl_cert(path)
|
41
|
+
@ssl_cert_path = path
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
def set_ssl_key(path)
|
46
|
+
@ssl_key_path = path
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
def set_ssl_key_passphrase(passphrase)
|
51
|
+
@ssl_key_passphrase = passphrase
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
def set_ssl_extra_chain_certs(certs)
|
56
|
+
@ssl_extra_chain_certs = certs
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
def set_ssl_certificate_authorities(certs)
|
61
|
+
@ssl_certificate_authorities = certs
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
def build; self; end
|
66
|
+
|
67
|
+
def toSslContext
|
68
|
+
return nil unless @ssl_enabled
|
69
|
+
|
70
|
+
# create certificate object
|
71
|
+
cf = CertificateFactory.getInstance("X.509")
|
72
|
+
cert_chain = []
|
73
|
+
cert_chain << cf.generateCertificate(FileInputStream.new(@ssl_cert_path))
|
74
|
+
|
75
|
+
# convert key from pkcs1 to pkcs8 and get PrivateKey object
|
76
|
+
pem_parser = PEMParser.new(FileReader.new(@ssl_key_path))
|
77
|
+
|
78
|
+
case obj = pem_parser.read_object
|
79
|
+
when PEMKeyPair # likely pkcs#1
|
80
|
+
private_key = JcaPEMKeyConverter.new.get_key_pair(obj).private
|
81
|
+
when PrivateKeyInfo # likely pkcs#8
|
82
|
+
private_key = JcaPEMKeyConverter.new.get_private_key(obj)
|
83
|
+
else
|
84
|
+
raise "Could not recognize 'ssl_key' format. Class: #{obj.class}"
|
85
|
+
end
|
86
|
+
|
87
|
+
@ssl_extra_chain_certs.each do |cert|
|
88
|
+
cert_chain << cf.generateCertificate(FileInputStream.new(cert))
|
89
|
+
end
|
90
|
+
sslContextBuilder = SslContextBuilder.forServer(private_key, @ssl_key_passphrase, cert_chain.to_java(java.security.cert.X509Certificate))
|
91
|
+
|
92
|
+
trust_certs = @ssl_certificate_authorities.map do |cert|
|
93
|
+
cf.generateCertificate(FileInputStream.new(cert))
|
94
|
+
end
|
95
|
+
|
96
|
+
if trust_certs.any?
|
97
|
+
sslContextBuilder.trustManager(trust_certs.to_java(java.security.cert.X509Certificate))
|
98
|
+
end
|
99
|
+
|
100
|
+
sslContextBuilder.clientAuth(@ssl_verify ? ClientAuth::REQUIRE : ClientAuth::NONE)
|
101
|
+
sslContextBuilder.build()
|
102
|
+
end
|
103
|
+
end
|
data/spec/inputs/tcp_spec.rb
CHANGED
@@ -9,6 +9,8 @@ require "stud/task"
|
|
9
9
|
require "flores/pki"
|
10
10
|
require "openssl"
|
11
11
|
|
12
|
+
java_import "io.netty.handler.ssl.util.SelfSignedCertificate"
|
13
|
+
|
12
14
|
require_relative "../spec_helper"
|
13
15
|
|
14
16
|
#Cabin::Channel.get(LogStash).subscribe(STDOUT)
|
@@ -310,13 +312,14 @@ describe LogStash::Inputs::Tcp do
|
|
310
312
|
# - pipelineless_input has been basically copied from the udp input specs, it should be DRYied up
|
311
313
|
# - see if we should miminc the udp input UDPClient helper class instead of directly using TCPSocket
|
312
314
|
|
313
|
-
|
315
|
+
context "LogStash::Inputs::Tcp new specs style" do
|
314
316
|
|
315
317
|
before do
|
316
318
|
srand(RSpec.configuration.seed)
|
317
319
|
end
|
318
320
|
|
319
|
-
|
321
|
+
let(:config) { { "port" => port } }
|
322
|
+
subject { described_class.new(config) }
|
320
323
|
let!(:helper) { TcpHelpers.new }
|
321
324
|
|
322
325
|
after :each do
|
@@ -324,9 +327,62 @@ describe LogStash::Inputs::Tcp do
|
|
324
327
|
end
|
325
328
|
|
326
329
|
describe "#register" do
|
330
|
+
|
327
331
|
it "should register without errors" do
|
328
332
|
expect { subject.register }.to_not raise_error
|
329
333
|
end
|
334
|
+
|
335
|
+
context "when using ssl" do
|
336
|
+
let(:config) do
|
337
|
+
{
|
338
|
+
"host" => "127.0.0.1",
|
339
|
+
"port" => port,
|
340
|
+
"ssl_enable" => true,
|
341
|
+
"ssl_cert" => certificate_file.path,
|
342
|
+
"ssl_key" => key_file.path,
|
343
|
+
"ssl_extra_chain_certs" => certificate_file.path
|
344
|
+
}
|
345
|
+
end
|
346
|
+
|
347
|
+
context "with pkcs#1 keys" do
|
348
|
+
let(:pki) { Flores::PKI.generate }
|
349
|
+
let(:certificate) { pki[0] }
|
350
|
+
let(:key) { pki[1] }
|
351
|
+
let(:certificate_file) { Stud::Temporary.file }
|
352
|
+
let(:key_file) { Stud::Temporary.file }
|
353
|
+
|
354
|
+
before do
|
355
|
+
certificate_file.write(certificate)
|
356
|
+
key_file.write(key)
|
357
|
+
certificate_file.close
|
358
|
+
key_file.close
|
359
|
+
end
|
360
|
+
|
361
|
+
it "should configure ssl manager correctly without errors" do
|
362
|
+
expect { subject.register }.to_not raise_error
|
363
|
+
end
|
364
|
+
|
365
|
+
after do
|
366
|
+
File.unlink(certificate_file.path)
|
367
|
+
File.unlink(key_file.path)
|
368
|
+
end
|
369
|
+
|
370
|
+
end
|
371
|
+
|
372
|
+
context "with pkcs#8 keys" do
|
373
|
+
let(:ssc) { SelfSignedCertificate.new }
|
374
|
+
let(:certificate_file) { ssc.certificate }
|
375
|
+
let(:key_file) { ssc.private_key}
|
376
|
+
|
377
|
+
it "should configure ssl manager correctly without errors" do
|
378
|
+
expect { subject.register }.to_not raise_error
|
379
|
+
end
|
380
|
+
|
381
|
+
after do
|
382
|
+
ssc.delete
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
330
386
|
end
|
331
387
|
|
332
388
|
describe "#receive" do
|
@@ -335,11 +391,9 @@ describe LogStash::Inputs::Tcp do
|
|
335
391
|
end
|
336
392
|
|
337
393
|
context "when ssl_enable is true" do
|
338
|
-
let(:
|
339
|
-
let(:
|
340
|
-
let(:
|
341
|
-
let(:certificate_file) { Stud::Temporary.file }
|
342
|
-
let(:key_file) { Stud::Temporary.file }
|
394
|
+
let(:ssc) { SelfSignedCertificate.new }
|
395
|
+
let(:certificate_file) { ssc.certificate }
|
396
|
+
let(:key_file) { ssc.private_key}
|
343
397
|
let(:queue) { Queue.new }
|
344
398
|
|
345
399
|
let(:config) do
|
@@ -349,35 +403,60 @@ describe LogStash::Inputs::Tcp do
|
|
349
403
|
"ssl_enable" => true,
|
350
404
|
"ssl_cert" => certificate_file.path,
|
351
405
|
"ssl_key" => key_file.path,
|
352
|
-
|
353
|
-
# Trust our self-signed cert.
|
354
|
-
# TODO(sissel): Make this a separate certificate for the client
|
355
|
-
"ssl_extra_chain_certs" => certificate_file.path
|
406
|
+
"ssl_certificate_authorities" => [ certificate_file.path ]
|
356
407
|
}
|
357
408
|
end
|
358
409
|
|
359
|
-
|
410
|
+
let(:input) { subject }
|
411
|
+
before(:each) { input.register }
|
412
|
+
after(:each) { ssc.delete }
|
413
|
+
|
414
|
+
context "when using a certificate chain" do
|
415
|
+
let(:chain_of_certificates) { helper.chain_of_certificates }
|
416
|
+
let(:config) do
|
417
|
+
{
|
418
|
+
"host" => "127.0.0.1",
|
419
|
+
"port" => port,
|
420
|
+
"ssl_enable" => true,
|
421
|
+
"ssl_cert" => chain_of_certificates[:b_cert].path,
|
422
|
+
"ssl_key" => chain_of_certificates[:b_key].path,
|
423
|
+
"ssl_extra_chain_certs" => [ chain_of_certificates[:a_cert].path ],
|
424
|
+
"ssl_certificate_authorities" => [ chain_of_certificates[:root_ca].path ],
|
425
|
+
"ssl_verify" => true
|
426
|
+
}
|
427
|
+
end
|
428
|
+
let(:tcp) { TCPSocket.new("127.0.0.1", port) }
|
429
|
+
let(:sslcontext) do
|
430
|
+
sslcontext = OpenSSL::SSL::SSLContext.new
|
431
|
+
sslcontext.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
432
|
+
sslcontext.ca_file = chain_of_certificates[:root_ca].path
|
433
|
+
sslcontext.cert = OpenSSL::X509::Certificate.new(File.read(chain_of_certificates[:aa_cert].path))
|
434
|
+
sslcontext.key = OpenSSL::PKey::RSA.new(File.read(chain_of_certificates[:aa_key].path))
|
435
|
+
sslcontext
|
436
|
+
end
|
437
|
+
let(:sslsocket) { OpenSSL::SSL::SSLSocket.new(tcp, sslcontext) }
|
438
|
+
let(:input_task) { Stud::Task.new { input.run(queue) } }
|
360
439
|
|
361
|
-
|
362
|
-
|
363
|
-
|
440
|
+
before do
|
441
|
+
input_task
|
442
|
+
end
|
364
443
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
444
|
+
it "should be able to connect and write data" do
|
445
|
+
sslsocket.connect
|
446
|
+
sslsocket.write("Hello world\n")
|
447
|
+
tcp.flush
|
448
|
+
sslsocket.close
|
449
|
+
tcp.close
|
450
|
+
result = input_task.thread.join(0.5)
|
451
|
+
expect(result).to be_nil
|
452
|
+
expect(queue.size).to eq(1)
|
453
|
+
end
|
370
454
|
|
371
|
-
after do
|
372
|
-
File.unlink(certificate_file.path)
|
373
|
-
File.unlink(key_file.path)
|
374
455
|
end
|
375
456
|
|
376
457
|
context "with a poorly-behaving client" do
|
377
458
|
let!(:input_task) { Stud::Task.new { input.run(queue) } }
|
378
459
|
|
379
|
-
after { input.close }
|
380
|
-
|
381
460
|
context "that disconnects before doing TLS handshake" do
|
382
461
|
before do
|
383
462
|
client = TCPSocket.new("127.0.0.1", port)
|
@@ -402,29 +481,6 @@ describe LogStash::Inputs::Tcp do
|
|
402
481
|
raise StandardError, "blah"
|
403
482
|
end
|
404
483
|
end
|
405
|
-
|
406
|
-
it "should log the error on accept" do
|
407
|
-
allow(input.logger).to receive(:error).with(any_args)
|
408
|
-
|
409
|
-
stop = Thread.new {
|
410
|
-
sleep 2
|
411
|
-
input.do_stop
|
412
|
-
}
|
413
|
-
expect do
|
414
|
-
input.run(Queue.new)
|
415
|
-
end.not_to raise_error
|
416
|
-
|
417
|
-
expect(input.logger).to have_received(:error).with(
|
418
|
-
::LogStash::Inputs::Tcp::RUN_LOOP_ERROR_MESSAGE,
|
419
|
-
:message => "blah",
|
420
|
-
:class => "StandardError",
|
421
|
-
:backtrace => anything
|
422
|
-
).at_least(:once)
|
423
|
-
|
424
|
-
stop.join
|
425
|
-
# Wait for stop to actually happen
|
426
|
-
sleep 1
|
427
|
-
end
|
428
484
|
end
|
429
485
|
|
430
486
|
context "that sends garbage instead of TLS handshake" do
|
@@ -446,37 +502,6 @@ describe LogStash::Inputs::Tcp do
|
|
446
502
|
expect(result).to be_nil
|
447
503
|
end
|
448
504
|
end
|
449
|
-
|
450
|
-
context "connection was healthy but now has garbage or corruption" do
|
451
|
-
let!(:input_task) { Stud::Task.new { input.run(queue) } }
|
452
|
-
let(:tcp) { TCPSocket.new("127.0.0.1", port) }
|
453
|
-
let(:sslcontext) { OpenSSL::SSL::SSLContext.new }
|
454
|
-
let(:sslsocket) { OpenSSL::SSL::SSLSocket.new(tcp, sslcontext) }
|
455
|
-
let(:max_length) { 1000 }
|
456
|
-
let(:garbage) { Flores::Random.iterations(max_length).collect { Flores::Random.integer(1...255) }.pack("C*") }
|
457
|
-
|
458
|
-
before do
|
459
|
-
sslcontext.cert = certificate
|
460
|
-
sslcontext.key = key
|
461
|
-
sslcontext.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
462
|
-
|
463
|
-
sslsocket.connect
|
464
|
-
sslsocket.write("Hello world\n")
|
465
|
-
|
466
|
-
# Assertion to verify this test is actually sending something.
|
467
|
-
expect(garbage.length).to be > 0
|
468
|
-
tcp.write(garbage)
|
469
|
-
tcp.flush
|
470
|
-
sslsocket.close
|
471
|
-
tcp.close
|
472
|
-
end
|
473
|
-
|
474
|
-
it "should not negatively impact the plugin" do
|
475
|
-
# TODO(sissel): Look for a better way to detect this failure besides a sleep/wait.
|
476
|
-
result = input_task.thread.join(0.5)
|
477
|
-
expect(result).to be_nil
|
478
|
-
end
|
479
|
-
end
|
480
505
|
end
|
481
506
|
|
482
507
|
# TODO(sissel): Spec multiple clients where only one is bad.
|
Binary file
|
data/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
5.
|
1
|
+
5.2.0
|
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: 5.
|
4
|
+
version: 5.2.0
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-10-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -159,11 +159,12 @@ files:
|
|
159
159
|
- docs/index.asciidoc
|
160
160
|
- lib/logstash-input-tcp_jars.rb
|
161
161
|
- lib/logstash/inputs/tcp.rb
|
162
|
+
- lib/logstash/inputs/tcp/compat_ssl_options.rb
|
162
163
|
- lib/logstash/inputs/tcp/decoder_impl.rb
|
163
164
|
- logstash-input-tcp.gemspec
|
164
165
|
- spec/inputs/tcp_spec.rb
|
165
166
|
- spec/spec_helper.rb
|
166
|
-
- vendor/jar-dependencies/org/logstash/inputs/logstash-input-tcp/5.
|
167
|
+
- vendor/jar-dependencies/org/logstash/inputs/logstash-input-tcp/5.2.0/logstash-input-tcp-5.2.0.jar
|
167
168
|
- version
|
168
169
|
homepage: http://www.elastic.co/guide/en/logstash/current/index.html
|
169
170
|
licenses:
|