@@ -34,6 +34,11 @@ local defaults = {
3434 port = 4222 ,
3535 tcp_nodelay = true ,
3636 path = nil ,
37+ tls = false ,
38+ tls_ca_path = nil ,
39+ tls_ca_file = nil ,
40+ tls_cert = nil ,
41+ tls_key = nil ,
3742}
3843
3944-- ### Create a properly formatted inbox subject.
@@ -76,10 +81,12 @@ local function load_methods(proto, commands)
7681 return client
7782end
7883
79- local function create_client (client_proto , client_socket , commands )
84+ local function create_client (client_proto , client_socket , commands , parameters )
8085 local client = load_methods (client_proto , commands )
8186 -- assign client error handler
8287 client .error = nats .error
88+ -- keep parameters around, for TLS
89+ client .parameters = parameters
8390 -- assign client network methods
8491 client .network = {
8592 socket = client_socket ,
@@ -224,6 +231,26 @@ client_prototype.get_server_info = function(client)
224231 return client .information
225232end
226233
234+ client_prototype .upgrade_to_tls = function (client )
235+ local status , luasec = pcall (require , ' ssl' )
236+ if not status then
237+ nats .error (' TLS is required but the luasec library is not available' )
238+ end
239+ local params = {
240+ capath = client .parameters .tls_ca_path ,
241+ cafile = client .parameters .tls_ca_file ,
242+ certificate = client .parameters .tls_cert ,
243+ key = client .parameters .tls_key ,
244+ mode = " client" ,
245+ options = {" all" , " no_sslv3" },
246+ protocol = " tlsv1_2" ,
247+ verify = " peer" ,
248+ }
249+
250+ client .network .socket = luasec .wrap (client .network .socket , params )
251+ client .network .socket :dohandshake ()
252+ end
253+
227254client_prototype .shutdown = function (client )
228255 client .network .socket :shutdown ()
229256end
@@ -265,7 +292,10 @@ local function create_connection(parameters)
265292 else
266293 if parameters .scheme then
267294 local scheme = parameters .scheme
268- assert (scheme == ' nats' or scheme == ' tcp' , ' invalid scheme: ' .. scheme )
295+ assert (scheme == ' nats' or scheme == ' tcp' or scheme == ' tls' , ' invalid scheme: ' .. scheme )
296+ if scheme == ' tls' then
297+ parameters .tls = true
298+ end
269299 end
270300 perform_connection , socket = connect_tcp , require (' socket' ).tcp
271301 end
@@ -295,7 +325,7 @@ function nats.connect(...)
295325 end
296326
297327 local socket = create_connection (merge_defaults (parameters ))
298- local client = create_client (client_prototype , socket , commands )
328+ local client = create_client (client_prototype , socket , commands , parameters )
299329
300330 return client
301331end
@@ -308,24 +338,32 @@ end
308338
309339function command .connect (client )
310340 local config = {
311- lang = client .lang ,
312- version = client .version ,
313- verbose = client .verbose ,
314- pedantic = client .pedantic ,
341+ lang = client .lang ,
342+ version = client .version ,
343+ verbose = client .verbose ,
344+ pedantic = client .pedantic ,
345+ tls_required = client .parameters .tls ,
315346 }
316347
317348 if client .user ~= nil and client .pass ~= nil then
318349 config .user = client .user
319350 config .pass = client .pass
320351 end
321352
322- request .raw (client , ' CONNECT ' .. cjson .encode (config ).. ' \r\n ' )
323-
324353 -- gather the server information
325354 local data = response .read (client )
326355 if data .action == ' INFO' then
327356 client .information = cjson .decode (data .content )
357+ if client .parameters .tls then
358+ if (client .information [' tls_available' ] or client .information [' tls_required' ]) then
359+ client :upgrade_to_tls ()
360+ else
361+ nats .error (' TLS is required but not offered by the server' )
362+ end
363+ end
328364 end
365+
366+ request .raw (client , ' CONNECT ' .. cjson .encode (config ).. ' \r\n ' )
329367end
330368
331369function command .ping (client )
0 commit comments