Skip to content

Commit e32bd16

Browse files
authored
invoke post_connection_check on connect (#61)
1 parent e322537 commit e32bd16

File tree

4 files changed

+72
-30
lines changed

4 files changed

+72
-30
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## 7.0.1
2+
- Invoke post_connection_check on connect [#61](https://github.com/logstash-plugins/logstash-output-tcp/pull/61)
3+
14
## 7.0.0
25
- SSL settings that were marked deprecated in version `6.2.0` are now marked obsolete, and will prevent the plugin from starting.
36
[#58](https://github.com/logstash-plugins/logstash-output-tcp/pull/58)

lib/logstash/outputs/tcp.rb

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ def run_as_client
264264
client_socket = nil
265265
@codec.on_event do |event, payload|
266266
begin
267-
client_socket = connect unless client_socket
267+
client_socket = retryable_connect unless client_socket
268268
while payload && payload.bytesize > 0
269269
begin
270270
written_bytes_size = client_socket.write_nonblock(payload)
@@ -316,32 +316,34 @@ def log_error(msg, e, backtrace: @logger.info?, **details)
316316
@logger.error(msg, details)
317317
end
318318

319-
private
320-
321319
def connect
322-
begin
323-
client_socket = TCPSocket.new(@host, @port)
324-
if @ssl_enabled
325-
client_socket = OpenSSL::SSL::SSLSocket.new(client_socket, @ssl_context)
326-
begin
327-
client_socket.connect
328-
rescue OpenSSL::SSL::SSLError => ssle
329-
log_error 'connect ssl failure:', ssle, backtrace: false
330-
# NOTE(mrichar1): Hack to prevent hammering peer
331-
sleep(5)
332-
raise
333-
end
320+
client_socket = TCPSocket.new(@host, @port)
321+
if @ssl_enabled
322+
client_socket = OpenSSL::SSL::SSLSocket.new(client_socket, @ssl_context)
323+
begin
324+
client_socket.connect
325+
client_socket.post_connection_check(@host) if @ssl_verification_mode == 'full'
326+
rescue OpenSSL::SSL::SSLError => ssle
327+
log_error 'connect ssl failure:', ssle, backtrace: false
328+
client_socket.close rescue nil
329+
raise
334330
end
335-
client_socket.extend(::LogStash::Util::SocketPeer)
336-
@logger.debug("opened connection", :client => client_socket.peer)
337-
return client_socket
338-
rescue => e
339-
log_error 'failed to connect:', e
340-
sleep @reconnect_interval
341-
retry
342331
end
343-
end # def connect
332+
client_socket.extend(::LogStash::Util::SocketPeer)
333+
@logger.debug("opened connection", :client => client_socket.peer)
334+
client_socket
335+
end
344336

337+
private
338+
def retryable_connect
339+
connect
340+
rescue => e
341+
log_error 'failed to connect:', e
342+
sleep @reconnect_interval
343+
retry
344+
end
345+
346+
private
345347
def validate_ssl_config!
346348
unless @ssl_enabled
347349
ignored_ssl_settings = original_params.select { |k| k != 'ssl_enabled' && k != 'ssl_enable' && k.start_with?('ssl_') }

logstash-output-tcp.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Gem::Specification.new do |s|
22

33
s.name = 'logstash-output-tcp'
4-
s.version = '7.0.0'
4+
s.version = '7.0.1'
55
s.licenses = ['Apache License (2.0)']
66
s.summary = "Writes events over a TCP socket"
77
s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"

spec/outputs/tcp_spec.rb

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@
144144
context "client mode" do
145145
before { subject.register }
146146

147-
let(:config) { super().merge 'mode' => 'client' }
147+
let(:config) { super().merge('mode' => 'client', 'host' => 'localhost') }
148148

149149
it 'writes payload data' do
150150
Thread.start { sleep 0.25; subject.receive event }
@@ -248,28 +248,65 @@
248248
expect( read ).to end_with 'foo bar'
249249
end
250250

251+
context 'with ssl_verification_mode => full' do
252+
let(:config) do
253+
{
254+
"mode" => "client",
255+
"host" => "localhost",
256+
"port" => port,
257+
"ssl_enabled" => true,
258+
"ssl_certificate_authorities" => crt_file,
259+
"ssl_verification_mode" => "full",
260+
"codec" => "plain"
261+
}
262+
end
263+
264+
context "with right host name" do
265+
let(:config) { super().merge("host" => "localhost") }
266+
it 'reads plain data' do
267+
thread = Thread.start { sleep 0.25; subject.receive event }
268+
socket = secure_server.accept
269+
read = socket.sysread(100)
270+
expect( read.size ).to be > 0
271+
expect( read ).to end_with 'foo bar'
272+
end
273+
end
274+
275+
context "with wrong host name" do
276+
let(:config) { super().merge("host" => "127.0.0.1") }
277+
it 'closes the connection' do
278+
thread = Thread.start do
279+
sleep 0.25
280+
expect { subject.connect }.to raise_error(OpenSSL::SSL::SSLError, /hostname "127.0.0.1" does not match the server certificate/)
281+
end
282+
secure_server.accept rescue nil # the other side will close the connection potentially causing a "Socket closed" error
283+
thread.join
284+
end
285+
end
286+
end
287+
251288
end
252289

253290
context 'with unsupported protocol (on server)' do
254291

255-
let(:config) { super().merge("ssl_supported_protocols" => ['TLSv1.1']) }
292+
let(:config) { super().merge("ssl_supported_protocols" => ['TLSv1.1'], "reconnect_interval" => 1) }
256293

257294
let(:server_min_version) { 'TLS1_2' }
258295

259296
before { subject.register }
260297
after { secure_server.close }
261298

262299
it 'fails (and loops retrying)' do
263-
expect(subject.logger).to receive(:error).with(/connect ssl failure/i, hash_including(message: /No appropriate protocol/i)).and_call_original
264-
expect(subject.logger).to receive(:error).with(/failed to connect/i, hash_including(exception: OpenSSL::SSL::SSLError)).and_call_original
300+
expect(subject.logger).to receive(:error).twice.with(/connect ssl failure/i, hash_including(message: /No appropriate protocol/i)).and_call_original
301+
expect(subject.logger).to receive(:error).twice.with(/failed to connect/i, hash_including(exception: OpenSSL::SSL::SSLError)).and_call_original
265302
expect(subject).to receive(:sleep).once.and_call_original
266303
expect(subject).to receive(:sleep).once.and_throw :TEST_DONE # to be able to abort the retry loop
267304

268305
Thread.start { secure_server.accept rescue nil }
269-
expect { subject.receive event }.to throw_symbol(:TEST_DONE)
306+
expect { sleep 0.25; subject.receive event }.to throw_symbol(:TEST_DONE)
270307
end
271308

272-
end if LOGSTASH_VERSION > '7.0'
309+
end
273310

274311
end
275312

0 commit comments

Comments
 (0)