Skip to content

Commit 284e1b5

Browse files
committed
invoke post_connection_check on connect
1 parent 36ac9b5 commit 284e1b5

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+
## 6.2.2
2+
- Invoke post_connection_check on connect [#61](https://github.com/logstash-plugins/logstash-output-tcp/pull/61)
3+
14
## 6.2.1
25
- Document correct default plugin codec [#54](https://github.com/logstash-plugins/logstash-output-tcp/pull/54)
36

lib/logstash/outputs/tcp.rb

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ def run_as_client
279279
client_socket = nil
280280
@codec.on_event do |event, payload|
281281
begin
282-
client_socket = connect unless client_socket
282+
client_socket = retryable_connect unless client_socket
283283
while payload && payload.bytesize > 0
284284
begin
285285
written_bytes_size = client_socket.write_nonblock(payload)
@@ -331,32 +331,34 @@ def log_error(msg, e, backtrace: @logger.info?, **details)
331331
@logger.error(msg, details)
332332
end
333333

334-
private
335-
336334
def connect
337-
begin
338-
client_socket = TCPSocket.new(@host, @port)
339-
if @ssl_enabled
340-
client_socket = OpenSSL::SSL::SSLSocket.new(client_socket, @ssl_context)
341-
begin
342-
client_socket.connect
343-
rescue OpenSSL::SSL::SSLError => ssle
344-
log_error 'connect ssl failure:', ssle, backtrace: false
345-
# NOTE(mrichar1): Hack to prevent hammering peer
346-
sleep(5)
347-
raise
348-
end
335+
client_socket = TCPSocket.new(@host, @port)
336+
if @ssl_enabled
337+
client_socket = OpenSSL::SSL::SSLSocket.new(client_socket, @ssl_context)
338+
begin
339+
client_socket.connect
340+
client_socket.post_connection_check(@host) if @ssl_verification_mode == 'full'
341+
rescue OpenSSL::SSL::SSLError => ssle
342+
log_error 'connect ssl failure:', ssle, backtrace: false
343+
client_socket.close rescue nil
344+
raise
349345
end
350-
client_socket.extend(::LogStash::Util::SocketPeer)
351-
@logger.debug("opened connection", :client => client_socket.peer)
352-
return client_socket
353-
rescue => e
354-
log_error 'failed to connect:', e
355-
sleep @reconnect_interval
356-
retry
357346
end
358-
end # def connect
347+
client_socket.extend(::LogStash::Util::SocketPeer)
348+
@logger.debug("opened connection", :client => client_socket.peer)
349+
client_socket
350+
end
359351

352+
private
353+
def retryable_connect
354+
connect
355+
rescue => e
356+
log_error 'failed to connect:', e
357+
sleep @reconnect_interval
358+
retry
359+
end
360+
361+
private
360362
def validate_ssl_config!
361363
unless @ssl_enabled
362364
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 = '6.2.1'
4+
s.version = '6.2.2'
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
@@ -125,7 +125,7 @@
125125
context "client mode" do
126126
before { subject.register }
127127

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

130130
it 'writes payload data' do
131131
Thread.start { sleep 0.25; subject.receive event }
@@ -229,28 +229,65 @@
229229
expect( read ).to end_with 'foo bar'
230230
end
231231

232+
context 'with ssl_verification_mode => full' do
233+
let(:config) do
234+
{
235+
"mode" => "client",
236+
"host" => "localhost",
237+
"port" => port,
238+
"ssl_enabled" => true,
239+
"ssl_certificate_authorities" => crt_file,
240+
"ssl_verification_mode" => "full",
241+
"codec" => "plain"
242+
}
243+
end
244+
245+
context "with right host name" do
246+
let(:config) { super().merge("host" => "localhost") }
247+
it 'reads plain data' do
248+
thread = Thread.start { sleep 0.25; subject.receive event }
249+
socket = secure_server.accept
250+
read = socket.sysread(100)
251+
expect( read.size ).to be > 0
252+
expect( read ).to end_with 'foo bar'
253+
end
254+
end
255+
256+
context "with wrong host name" do
257+
let(:config) { super().merge("host" => "127.0.0.1") }
258+
it 'closes the connection' do
259+
thread = Thread.start do
260+
sleep 0.25
261+
expect { subject.connect }.to raise_error(OpenSSL::SSL::SSLError, /hostname "127.0.0.1" does not match the server certificate/)
262+
end
263+
secure_server.accept rescue nil # the other side will close the connection potentially causing a "Socket closed" error
264+
thread.join
265+
end
266+
end
267+
end
268+
232269
end
233270

234271
context 'with unsupported protocol (on server)' do
235272

236-
let(:config) { super().merge("ssl_supported_protocols" => ['TLSv1.1']) }
273+
let(:config) { super().merge("ssl_supported_protocols" => ['TLSv1.1'], "reconnect_interval" => 1) }
237274

238275
let(:server_min_version) { 'TLS1_2' }
239276

240277
before { subject.register }
241278
after { secure_server.close }
242279

243280
it 'fails (and loops retrying)' do
244-
expect(subject.logger).to receive(:error).with(/connect ssl failure/i, hash_including(message: /No appropriate protocol/i)).and_call_original
245-
expect(subject.logger).to receive(:error).with(/failed to connect/i, hash_including(exception: OpenSSL::SSL::SSLError)).and_call_original
281+
expect(subject.logger).to receive(:error).twice.with(/connect ssl failure/i, hash_including(message: /No appropriate protocol/i)).and_call_original
282+
expect(subject.logger).to receive(:error).twice.with(/failed to connect/i, hash_including(exception: OpenSSL::SSL::SSLError)).and_call_original
246283
expect(subject).to receive(:sleep).once.and_call_original
247284
expect(subject).to receive(:sleep).once.and_throw :TEST_DONE # to be able to abort the retry loop
248285

249286
Thread.start { secure_server.accept rescue nil }
250-
expect { subject.receive event }.to throw_symbol(:TEST_DONE)
287+
expect { sleep 0.25; subject.receive event }.to throw_symbol(:TEST_DONE)
251288
end
252289

253-
end if LOGSTASH_VERSION > '7.0'
290+
end
254291

255292
end
256293

0 commit comments

Comments
 (0)