nats-pure 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.