nats-pure 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 741d87f63f2851dc25639453f9cd5ed68b3e2bfb66f45f1b5fe6caa9b3e352dd
4
- data.tar.gz: 1af44d28a31788e37fbb50d14f966ff30805ee42614ae37a7ab3599edd0de4f0
3
+ metadata.gz: 23e0d5e7517e6747ba93d5e0f0941d2443bcce881936a7d986b9aeda9a668007
4
+ data.tar.gz: 1ee9d4e3277a283bc1a3eabefbb56bae81be9e32422311b9c9f48c4b2f369d07
5
5
  SHA512:
6
- metadata.gz: 432d3b3cf28752ec19c6278763ec5e1ef5992ee9d57796aeadb41b978028b3700c699795134f46297c982d9fc98fc3979d0760842f74fb528977e62b66431c9c
7
- data.tar.gz: 758a3b3deb4c2b14198bca42b647d2b11726c08d7150a914a8835a64fa6720d57d28c2207ddcd6ad40995427902ab1afd6705f2ab4c4ea1adbe9e131ccc1ea32
6
+ metadata.gz: 0eeae802740d61db43b624ffdd21996200befa37125fd04eda0e49474db17bdedbba3408da06ffec907076f935279df80901f4eb5c94a07e6cf26fa1e36ed649
7
+ data.tar.gz: a31a3936f8fafafb4b0ebfc47913021d62a208606193cc2566e2051dd06141011c75e0879f4cb69157677b2ef8f64bbac77f728c0e478bdc5f0ff116d1f26d81
@@ -174,16 +174,40 @@ module NATS
174
174
  # Hostname of current server; used for when TLS host
175
175
  # verification is enabled.
176
176
  @hostname = nil
177
+ @single_url_connect_used = false
177
178
 
178
179
  # New style request/response implementation.
179
180
  @resp_sub = nil
180
181
  @resp_map = nil
181
182
  @resp_sub_prefix = nil
182
183
  @nuid = NATS::NUID.new
184
+
185
+ # NKEYS
186
+ @user_credentials = nil
187
+ @nkeys_seed = nil
188
+ @user_nkey_cb = nil
189
+ @user_jwt_cb = nil
190
+ @signature_cb = nil
183
191
  end
184
192
 
185
193
  # Establishes connection to NATS.
186
- def connect(opts={})
194
+ def connect(uri=nil, opts={})
195
+ case uri
196
+ when String
197
+ # Initialize TLS defaults in case any url is using it.
198
+ srvs = opts[:servers] = process_uri(uri)
199
+ if srvs.any? {|u| u.scheme == 'tls'} and !opts[:tls]
200
+ tls_context = OpenSSL::SSL::SSLContext.new
201
+ tls_context.set_params
202
+ opts[:tls] = {
203
+ context: tls_context
204
+ }
205
+ end
206
+ @single_url_connect_used = true if srvs.size == 1
207
+ when Hash
208
+ opts = uri
209
+ end
210
+
187
211
  opts[:verbose] = false if opts[:verbose].nil?
188
212
  opts[:pedantic] = false if opts[:pedantic].nil?
189
213
  opts[:reconnect] = true if opts[:reconnect].nil?
@@ -226,6 +250,11 @@ module NATS
226
250
  class << self; alias_method :request, :old_request; end
227
251
  end
228
252
 
253
+ # NKEYS
254
+ @user_credentials ||= opts[:user_credentials]
255
+ @nkeys_seed ||= opts[:nkeys_seed]
256
+ setup_nkeys_connect if @user_credentials or @nkeys_seed
257
+
229
258
  # Check for TLS usage
230
259
  @tls = @options[:tls]
231
260
 
@@ -245,7 +274,12 @@ module NATS
245
274
  @status = CONNECTING
246
275
 
247
276
  # Use the hostname from the server for TLS hostname verification.
248
- @hostname = srv[:hostname]
277
+ if client_using_secure_connection? and single_url_connect_used?
278
+ # Always reuse the original hostname used to connect.
279
+ @hostname ||= srv[:hostname]
280
+ else
281
+ @hostname = srv[:hostname]
282
+ end
249
283
 
250
284
  # Established TCP connection successfully so can start connect
251
285
  process_connect_init
@@ -634,7 +668,8 @@ module NATS
634
668
  if connect_urls
635
669
  srvs = []
636
670
  connect_urls.each do |url|
637
- u = URI.parse("nats://#{url}")
671
+ scheme = client_using_secure_connection? ? "tls" : "nats"
672
+ u = URI.parse("#{scheme}://#{url}")
638
673
 
639
674
  # Skip in case it is the current server which we already know
640
675
  next if @uri.host == u.host && @uri.port == u.port
@@ -753,6 +788,10 @@ module NATS
753
788
  @uri.scheme == "tls" || @tls
754
789
  end
755
790
 
791
+ def single_url_connect_used?
792
+ @single_url_connect_used
793
+ end
794
+
756
795
  def send_command(command)
757
796
  @pending_size += command.bytesize
758
797
  @pending_queue << command
@@ -774,13 +813,22 @@ module NATS
774
813
  }
775
814
  cs[:name] = @options[:name] if @options[:name]
776
815
 
777
- if auth_connection?
816
+ case
817
+ when auth_connection?
778
818
  if @uri.password
779
819
  cs[:user] = @uri.user
780
820
  cs[:pass] = @uri.password
781
821
  else
782
822
  cs[:auth_token] = @uri.user
783
823
  end
824
+ when @user_credentials
825
+ nonce = @server_info[:nonce]
826
+ cs[:jwt] = @user_jwt_cb.call
827
+ cs[:sig] = @signature_cb.call(nonce)
828
+ when @nkeys_seed
829
+ nonce = @server_info[:nonce]
830
+ cs[:nkey] = @user_nkey_cb.call
831
+ cs[:sig] = @signature_cb.call(nonce)
784
832
  end
785
833
 
786
834
  "CONNECT #{cs.to_json}#{CR_LF}"
@@ -1021,7 +1069,12 @@ module NATS
1021
1069
  @stats[:reconnects] += 1
1022
1070
 
1023
1071
  # Set hostname to use for TLS hostname verification
1024
- @hostname = srv[:hostname]
1072
+ if client_using_secure_connection? and single_url_connect_used?
1073
+ # Reuse original hostname name in case of using TLS.
1074
+ @hostname ||= srv[:hostname]
1075
+ else
1076
+ @hostname = srv[:hostname]
1077
+ end
1025
1078
 
1026
1079
  # Established TCP connection successfully so can start connect
1027
1080
  process_connect_init
@@ -1241,6 +1294,115 @@ module NATS
1241
1294
  connect_timeout: DEFAULT_CONNECT_TIMEOUT
1242
1295
  })
1243
1296
  end
1297
+
1298
+ def setup_nkeys_connect
1299
+ begin
1300
+ require 'nkeys'
1301
+ require 'base64'
1302
+ rescue LoadError
1303
+ raise(Error, "nkeys is not installed")
1304
+ end
1305
+
1306
+ case
1307
+ when @nkeys_seed
1308
+ @user_nkey_cb = proc {
1309
+ seed = File.read(@nkeys_seed).chomp
1310
+ kp = NKEYS::from_seed(seed)
1311
+
1312
+ # Take a copy since original will be gone with the wipe.
1313
+ pub_key = kp.public_key.dup
1314
+ kp.wipe!
1315
+
1316
+ pub_key
1317
+ }
1318
+
1319
+ @signature_cb = proc { |nonce|
1320
+ seed = File.read(@nkeys_seed).chomp
1321
+ kp = NKEYS::from_seed(seed)
1322
+ raw_signed = kp.sign(nonce)
1323
+ kp.wipe!
1324
+ encoded = Base64.urlsafe_encode64(raw_signed)
1325
+ encoded.gsub('=', '')
1326
+ }
1327
+ when @user_credentials
1328
+ # When the credentials are within a single decorated file.
1329
+ @user_jwt_cb = proc {
1330
+ jwt_start = "BEGIN NATS USER JWT".freeze
1331
+ found = false
1332
+ jwt = nil
1333
+ File.readlines(@user_credentials).each do |line|
1334
+ case
1335
+ when found
1336
+ jwt = line.chomp
1337
+ break
1338
+ when line.include?(jwt_start)
1339
+ found = true
1340
+ end
1341
+ end
1342
+ raise(Error, "No JWT found in #{@user_credentials}") if not found
1343
+
1344
+ jwt
1345
+ }
1346
+
1347
+ @signature_cb = proc { |nonce|
1348
+ seed_start = "BEGIN USER NKEY SEED".freeze
1349
+ found = false
1350
+ seed = nil
1351
+ File.readlines(@user_credentials).each do |line|
1352
+ case
1353
+ when found
1354
+ seed = line.chomp
1355
+ break
1356
+ when line.include?(seed_start)
1357
+ found = true
1358
+ end
1359
+ end
1360
+ raise(Error, "No nkey user seed found in #{@user_credentials}") if not found
1361
+
1362
+ kp = NKEYS::from_seed(seed)
1363
+ raw_signed = kp.sign(nonce)
1364
+
1365
+ # seed is a reference so also cleared when doing wipe,
1366
+ # which can be done since Ruby strings are mutable.
1367
+ kp.wipe
1368
+ encoded = Base64.urlsafe_encode64(raw_signed)
1369
+
1370
+ # Remove padding
1371
+ encoded.gsub('=', '')
1372
+ }
1373
+ end
1374
+ end
1375
+
1376
+ def process_uri(uris)
1377
+ connect_uris = []
1378
+ uris.split(',').each do |uri|
1379
+ opts = {}
1380
+
1381
+ # Scheme
1382
+ if uri.include?("://")
1383
+ scheme, uri = uri.split("://")
1384
+ opts[:scheme] = scheme
1385
+ else
1386
+ opts[:scheme] = 'nats'
1387
+ end
1388
+
1389
+ # UserInfo
1390
+ if uri.include?("@")
1391
+ userinfo, endpoint = uri.split("@")
1392
+ host, port = endpoint.split(":")
1393
+ opts[:userinfo] = userinfo
1394
+ else
1395
+ host, port = uri.split(":")
1396
+ end
1397
+
1398
+ # Host and Port
1399
+ opts[:host] = host || "localhost"
1400
+ opts[:port] = port || DEFAULT_PORT
1401
+
1402
+ connect_uris << URI::Generic.build(opts)
1403
+ end
1404
+ connect_uris
1405
+ end
1244
1406
  end
1245
1407
 
1246
1408
  # Implementation adapted from https://github.com/redis/redis-rb
@@ -15,7 +15,7 @@
15
15
  module NATS
16
16
  module IO
17
17
  # NOTE: These are all announced to the server on CONNECT
18
- VERSION = "0.5.0"
18
+ VERSION = "0.6.0"
19
19
  LANG = "#{RUBY_ENGINE}2".freeze
20
20
  PROTOCOL = 1
21
21
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nats-pure
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Waldemar Quevedo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-04 00:00:00.000000000 Z
11
+ date: 2019-06-19 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: NATS is an open-source, high-performance, lightweight cloud messaging
14
14
  system.
@@ -41,8 +41,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
41
41
  - !ruby/object:Gem::Version
42
42
  version: '0'
43
43
  requirements: []
44
- rubyforge_project:
45
- rubygems_version: 2.7.3
44
+ rubygems_version: 3.0.3
46
45
  signing_key:
47
46
  specification_version: 4
48
47
  summary: NATS is an open-source, high-performance, lightweight cloud messaging system.