@@ -31,6 +31,33 @@ class LogStash::Outputs::Tcp < LogStash::Outputs::Base
31
31
# `client` connects to a server.
32
32
config :mode , :validate => [ "server" , "client" ] , :default => "client"
33
33
34
+ # Enable SSL (must be set for other `ssl_` options to take effect).
35
+ config :ssl_enable , :validate => :boolean , :default => false
36
+
37
+ # Verify the identity of the other end of the SSL connection against the CA.
38
+ # For input, sets the field `sslsubject` to that of the client certificate.
39
+ config :ssl_verify , :validate => :boolean , :default => false
40
+
41
+ # The SSL CA certificate, chainfile or CA path. The system CA path is automatically included.
42
+ config :ssl_cacert , :validate => :path
43
+
44
+ # SSL certificate path
45
+ config :ssl_cert , :validate => :path
46
+
47
+ # SSL key path
48
+ config :ssl_key , :validate => :path
49
+
50
+ # SSL key passphrase
51
+ config :ssl_key_passphrase , :validate => :password , :default => nil
52
+
53
+ # The format to use when writing events to the file. This value
54
+ # supports any string and can include `%{name}` and other dynamic
55
+ # strings.
56
+ #
57
+ # If this setting is omitted, the full json representation of the
58
+ # event will be written as a single line.
59
+ config :message_format , :validate => :string , :deprecated => true
60
+
34
61
class Client
35
62
public
36
63
def initialize ( socket , logger )
@@ -62,6 +89,25 @@ def write(msg)
62
89
def register
63
90
require "socket"
64
91
require "stud/try"
92
+ require "openssl"
93
+ if @ssl_enable
94
+ @ssl_context = OpenSSL ::SSL ::SSLContext . new
95
+ @ssl_context . cert = OpenSSL ::X509 ::Certificate . new ( File . read ( @ssl_cert ) )
96
+ @ssl_context . key = OpenSSL ::PKey ::RSA . new ( File . read ( @ssl_key ) , @ssl_key_passphrase )
97
+ if @ssl_verify
98
+ @cert_store = OpenSSL ::X509 ::Store . new
99
+ # Load the system default certificate path to the store
100
+ @cert_store . set_default_paths
101
+ if File . directory? ( @ssl_cacert )
102
+ @cert_store . add_path ( @ssl_cacert )
103
+ else
104
+ @cert_store . add_file ( @ssl_cacert )
105
+ end
106
+ @ssl_context . cert_store = @cert_store
107
+ @ssl_context . verify_mode = OpenSSL ::SSL ::VERIFY_PEER |OpenSSL ::SSL ::VERIFY_FAIL_IF_NO_PEER_CERT
108
+ end
109
+ end # @ssl_enable
110
+
65
111
if server?
66
112
workers_not_supported
67
113
@@ -73,6 +119,9 @@ def register
73
119
:host => @host , :port => @port )
74
120
raise
75
121
end
122
+ if @ssl_enable
123
+ @server_socket = OpenSSL ::SSL ::SSLServer . new ( @server_socket , @ssl_context )
124
+ end # @ssl_enable
76
125
@client_threads = [ ]
77
126
78
127
@accept_thread = Thread . new ( @server_socket ) do |server_socket |
@@ -125,6 +174,18 @@ def register
125
174
def connect
126
175
Stud ::try do
127
176
client_socket = TCPSocket . new ( @host , @port )
177
+ if @ssl_enable
178
+ client_socket = OpenSSL ::SSL ::SSLSocket . new ( client_socket , @ssl_context )
179
+ begin
180
+ client_socket . connect
181
+ rescue OpenSSL ::SSL ::SSLError => ssle
182
+ @logger . error ( "SSL Error" , :exception => ssle ,
183
+ :backtrace => ssle . backtrace )
184
+ # NOTE(mrichar1): Hack to prevent hammering peer
185
+ sleep ( 5 )
186
+ raise
187
+ end
188
+ end
128
189
client_socket . instance_eval { class << self ; include ::LogStash ::Util ::SocketPeer end }
129
190
@logger . debug ( "Opened connection" , :client => "#{ client_socket . peer } " )
130
191
return client_socket
0 commit comments