nonnative 3.45.0 → 3.47.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: c8bbaf41c295455b428d4cd1d5c9ceafe3f22eac17edc737da0891e734b6ecfd
4
- data.tar.gz: e92602a876b24cafab6637fb1f9e0b9efb50f35fc8552d64694fb1bf78cb3148
3
+ metadata.gz: bc2bdb41b9c6411e257b89cb9a510170cde28cc454bac1680e1f0bfea546294c
4
+ data.tar.gz: f93f740ba3d1f67c299a392d2db7c31874c85331e935f0974f15e4e2094a85ef
5
5
  SHA512:
6
- metadata.gz: 3a07e6379755de0a404a7b2fb9790cdd407b3ee62f101d907ad110826d96b7ee7b36786d21b0ba53a8dc9e4b549537e7543b9e6d127f04b85974deaa2f02ae90
7
- data.tar.gz: e6db224d47bf126b1466ae74f7283bd4769aedf79317b044bd78911488bc005f1efa33b824ac08045efe0d2e6e5817de58e4525b89e5dee2419dae4cd33ef90c
6
+ metadata.gz: 50fd2d856178eaf96676746008cc4aa6477d3aee908a58c61375dc94e74675d3627c5020fd8125f1ba1ed15568d6dede9c1ae41efa2c5b0ac9e071e9f869d914
7
+ data.tar.gz: 40a613ee1b7553cecb51ef59d3834a14bfa15ba9659c8cdc41170f930be8d019a9c2147a40b01df83cbf35619ede80771cfb7266315d681477a2d580c9a22ea1
data/README.md CHANGED
@@ -221,10 +221,9 @@ headers = Nonnative::Header.auth_bearer(
221
221
  )
222
222
  ```
223
223
 
224
- Supported `kind` values (all Ed25519, generation only):
224
+ The supported `kind` is Ed25519 JWT generation only:
225
225
 
226
226
  - `jwt`: EdDSA JWT with the key id in the `kid` header. `private_key` is a PKCS#8 PEM file.
227
- - `paseto`: PASETO v4.public with the key id in a `{"kid":"..."}` footer. `private_key` is a PKCS#8 PEM file. Requires system **libsodium** (via `rbnacl`); it loads lazily, so `require 'nonnative'` works without libsodium until you generate a PASETO token.
228
227
 
229
228
  The audience is endpoint-scoped; build it with the helpers:
230
229
 
@@ -4,8 +4,7 @@ module Nonnative
4
4
  # Loads an Ed25519 private key from a PEM file for signing tokens.
5
5
  #
6
6
  # Verifiers such as go-service use Ed25519 keys encoded as PKCS#8 PEM. This reads the PEM once and
7
- # exposes it in the shapes the token backends need: the raw PEM for {Nonnative::PasetoToken} and the
8
- # 32-byte seed for {Nonnative::JwtToken}.
7
+ # exposes the 32-byte seed required by {Nonnative::JwtToken}.
9
8
  #
10
9
  # @example
11
10
  # key = Nonnative::Ed25519Key.new('config/ed25519.pem')
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nonnative
4
- # Builds signed JWT or PASETO tokens for authenticating against services under test.
4
+ # Builds signed JWT tokens for authenticating against services under test.
5
5
  #
6
6
  # The consumer passes in the signing parameters they parsed from their own configuration; this class
7
7
  # is not coupled to any particular service's configuration format. The generated token string is
@@ -12,16 +12,8 @@ module Nonnative
12
12
  # private_key: 'config/ed25519.pem', expiration: 3600)
13
13
  # header = Nonnative::Header.auth_bearer(token.generate(aud: 'GET /v1/things', sub: 'user-1'))
14
14
  #
15
- # @example PASETO
16
- # token = Nonnative::Token.new(kind: 'paseto', issuer: 'iss', key: 'key-1',
17
- # private_key: 'config/ed25519.pem', expiration: 3600)
18
- # token.generate(aud: Nonnative::Token.grpc_audience('/health.v1.Health/Check'), sub: 'user-1')
19
- #
20
15
  # @see Nonnative::Header.auth_bearer
21
16
  class Token
22
- # Supported token kinds mapped to their implementation.
23
- KINDS = { 'jwt' => Nonnative::JwtToken, 'paseto' => Nonnative::PasetoToken }.freeze
24
-
25
17
  class << self
26
18
  # Builds the audience string for an HTTP endpoint.
27
19
  #
@@ -41,15 +33,16 @@ module Nonnative
41
33
  end
42
34
  end
43
35
 
44
- # @param kind [String] token kind, one of `"jwt"` or `"paseto"`
36
+ # @param kind [String] token kind, `"jwt"`
45
37
  # @param issuer [String] the `iss` claim
46
- # @param key [String] the key id (JWT `kid` header or PASETO `kid` footer)
38
+ # @param key [String] the key id (JWT `kid` header)
47
39
  # @param private_key [String] path to a PKCS#8 Ed25519 private key PEM file
48
40
  # @param expiration [Integer] token lifetime in seconds (drives `exp`)
49
41
  # @raise [ArgumentError] if the kind is not supported
50
42
  def initialize(kind:, issuer:, key:, private_key:, expiration:)
51
- klass = KINDS.fetch(kind) { raise ArgumentError, "Unsupported token kind '#{kind}'" }
52
- @token = klass.new(issuer: issuer, key: key, private_key: private_key, expiration: expiration)
43
+ raise ArgumentError, "Unsupported token kind '#{kind}'" unless kind == 'jwt'
44
+
45
+ @token = Nonnative::JwtToken.new(issuer: issuer, key: key, private_key: private_key, expiration: expiration)
53
46
  end
54
47
 
55
48
  # Generates a signed token.
@@ -4,5 +4,5 @@ module Nonnative
4
4
  # The current gem version.
5
5
  #
6
6
  # @return [String]
7
- VERSION = '3.45.0'
7
+ VERSION = '3.47.0'
8
8
  end
data/lib/nonnative.rb CHANGED
@@ -52,7 +52,6 @@ require 'uri'
52
52
  require 'openssl'
53
53
  require 'json'
54
54
  require 'time'
55
- require 'singleton' # ruby-paseto depends on this stdlib, which Ruby no longer auto-loads
56
55
 
57
56
  require 'grpc'
58
57
  require 'grpc/health/v1/health_services_pb'
@@ -68,8 +67,6 @@ require 'rspec/wait'
68
67
  require 'puma'
69
68
  require 'puma/server'
70
69
 
71
- # jwt-eddsa (with the ed25519 gem) is pure Ruby and needs no system library, so it loads here.
72
- # PASETO's rbnacl needs system libsodium, so Nonnative::PasetoToken requires it lazily instead.
73
70
  require 'jwt/eddsa'
74
71
 
75
72
  require 'nonnative/version'
@@ -124,7 +121,6 @@ require 'nonnative/cucumber'
124
121
  require 'nonnative/header'
125
122
  require 'nonnative/ed25519_key'
126
123
  require 'nonnative/jwt_token'
127
- require 'nonnative/paseto_token'
128
124
  require 'nonnative/token'
129
125
 
130
126
  # The main namespace for the gem.
@@ -216,9 +212,9 @@ module Nonnative
216
212
  # The signing parameters are passed in directly; this is not coupled to any service's
217
213
  # configuration format. The generated token string is ready for {Nonnative::Header.auth_bearer}.
218
214
  #
219
- # @param kind [String] token kind, one of `"jwt"` or `"paseto"`
215
+ # @param kind [String] token kind, `"jwt"`
220
216
  # @param issuer [String] the `iss` claim
221
- # @param key [String] the key id (JWT `kid` header or PASETO `kid` footer)
217
+ # @param key [String] the key id (JWT `kid` header)
222
218
  # @param private_key [String] path to a PKCS#8 Ed25519 private key PEM file
223
219
  # @param expiration [Integer] token lifetime in seconds (drives `exp`)
224
220
  # @return [Nonnative::Token]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nonnative
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.45.0
4
+ version: 3.47.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alejandro Falkowski
@@ -144,67 +144,67 @@ dependencies:
144
144
  - !ruby/object:Gem::Version
145
145
  version: '2'
146
146
  - !ruby/object:Gem::Dependency
147
- name: jwt
147
+ name: json
148
148
  requirement: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
- version: '3'
152
+ version: '2'
153
153
  - - "<"
154
154
  - !ruby/object:Gem::Version
155
- version: '4'
155
+ version: '3'
156
156
  type: :runtime
157
157
  prerelease: false
158
158
  version_requirements: !ruby/object:Gem::Requirement
159
159
  requirements:
160
160
  - - ">="
161
161
  - !ruby/object:Gem::Version
162
- version: '3'
162
+ version: '2'
163
163
  - - "<"
164
164
  - !ruby/object:Gem::Version
165
- version: '4'
165
+ version: '3'
166
166
  - !ruby/object:Gem::Dependency
167
- name: jwt-eddsa
167
+ name: jwt
168
168
  requirement: !ruby/object:Gem::Requirement
169
169
  requirements:
170
170
  - - ">="
171
171
  - !ruby/object:Gem::Version
172
- version: '0'
172
+ version: '3'
173
173
  - - "<"
174
174
  - !ruby/object:Gem::Version
175
- version: '2'
175
+ version: '4'
176
176
  type: :runtime
177
177
  prerelease: false
178
178
  version_requirements: !ruby/object:Gem::Requirement
179
179
  requirements:
180
180
  - - ">="
181
181
  - !ruby/object:Gem::Version
182
- version: '0'
182
+ version: '3'
183
183
  - - "<"
184
184
  - !ruby/object:Gem::Version
185
- version: '2'
185
+ version: '4'
186
186
  - !ruby/object:Gem::Dependency
187
- name: puma
187
+ name: jwt-eddsa
188
188
  requirement: !ruby/object:Gem::Requirement
189
189
  requirements:
190
190
  - - ">="
191
191
  - !ruby/object:Gem::Version
192
- version: '7'
192
+ version: '0'
193
193
  - - "<"
194
194
  - !ruby/object:Gem::Version
195
- version: '9'
195
+ version: '2'
196
196
  type: :runtime
197
197
  prerelease: false
198
198
  version_requirements: !ruby/object:Gem::Requirement
199
199
  requirements:
200
200
  - - ">="
201
201
  - !ruby/object:Gem::Version
202
- version: '7'
202
+ version: '0'
203
203
  - - "<"
204
204
  - !ruby/object:Gem::Version
205
- version: '9'
205
+ version: '2'
206
206
  - !ruby/object:Gem::Dependency
207
- name: rbnacl
207
+ name: puma
208
208
  requirement: !ruby/object:Gem::Requirement
209
209
  requirements:
210
210
  - - ">="
@@ -212,7 +212,7 @@ dependencies:
212
212
  version: '7'
213
213
  - - "<"
214
214
  - !ruby/object:Gem::Version
215
- version: '8'
215
+ version: '9'
216
216
  type: :runtime
217
217
  prerelease: false
218
218
  version_requirements: !ruby/object:Gem::Requirement
@@ -222,7 +222,7 @@ dependencies:
222
222
  version: '7'
223
223
  - - "<"
224
224
  - !ruby/object:Gem::Version
225
- version: '8'
225
+ version: '9'
226
226
  - !ruby/object:Gem::Dependency
227
227
  name: rest-client
228
228
  requirement: !ruby/object:Gem::Requirement
@@ -323,26 +323,6 @@ dependencies:
323
323
  - - "<"
324
324
  - !ruby/object:Gem::Version
325
325
  version: '2'
326
- - !ruby/object:Gem::Dependency
327
- name: ruby-paseto
328
- requirement: !ruby/object:Gem::Requirement
329
- requirements:
330
- - - ">="
331
- - !ruby/object:Gem::Version
332
- version: '0'
333
- - - "<"
334
- - !ruby/object:Gem::Version
335
- version: '1'
336
- type: :runtime
337
- prerelease: false
338
- version_requirements: !ruby/object:Gem::Requirement
339
- requirements:
340
- - - ">="
341
- - !ruby/object:Gem::Version
342
- version: '0'
343
- - - "<"
344
- - !ruby/object:Gem::Version
345
- version: '1'
346
326
  - !ruby/object:Gem::Dependency
347
327
  name: sinatra
348
328
  requirement: !ruby/object:Gem::Requirement
@@ -407,7 +387,6 @@ files:
407
387
  - lib/nonnative/no_proxy.rb
408
388
  - lib/nonnative/not_found_error.rb
409
389
  - lib/nonnative/observability.rb
410
- - lib/nonnative/paseto_token.rb
411
390
  - lib/nonnative/pool.rb
412
391
  - lib/nonnative/port.rb
413
392
  - lib/nonnative/ports.rb
@@ -1,64 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nonnative
4
- # Generates Ed25519 PASETO v4.public tokens for authenticating against services under test.
5
- #
6
- # The key id is carried in a JSON footer (`{"kid":"..."}`), and the claims match the common
7
- # iss/aud/sub/iat/nbf/exp/jti set expected by verifiers such as go-service. The signing library is
8
- # required lazily so that requiring `nonnative` does not depend on `rbnacl`/libsodium being present.
9
- #
10
- # @example
11
- # paseto = Nonnative::PasetoToken.new(issuer: 'iss', key: 'key-1', private_key: 'config/ed25519.pem', expiration: 3600)
12
- # paseto.generate(aud: 'GET /v1/things', sub: 'user-1')
13
- #
14
- # @see https://github.com/bannable/paseto ruby-paseto
15
- class PasetoToken
16
- # @param issuer [String] the `iss` claim
17
- # @param key [String] the key id carried in the `kid` footer
18
- # @param private_key [String] path to a PKCS#8 Ed25519 private key PEM file
19
- # @param expiration [Integer] token lifetime in seconds (drives `exp`)
20
- def initialize(issuer:, key:, private_key:, expiration:)
21
- @issuer = issuer
22
- @key = key
23
- @ed25519 = Nonnative::Ed25519Key.new(private_key)
24
- @expiration = expiration
25
- end
26
-
27
- # Generates a signed PASETO v4.public token.
28
- #
29
- # @param aud [String] the `aud` claim (for example `"GET /v1/things"` or a gRPC full method)
30
- # @param sub [String] the `sub` claim
31
- # @param issued_at [Time, nil] overrides the `iat` claim (default: now)
32
- # @param not_before [Time, nil] overrides the `nbf` claim (default: `issued_at`)
33
- # @param expires_at [Time, nil] overrides the `exp` claim (default: `issued_at` plus `expiration`)
34
- # @return [String] the signed PASETO token
35
- def generate(aud:, sub:, issued_at: nil, not_before: nil, expires_at: nil)
36
- load_dependencies!
37
-
38
- now = (issued_at || Time.now).utc
39
- claims = {
40
- 'iss' => @issuer,
41
- 'aud' => aud,
42
- 'sub' => sub,
43
- 'iat' => now.iso8601,
44
- 'nbf' => (not_before || now).utc.iso8601,
45
- 'exp' => (expires_at || (now + @expiration)).utc.iso8601,
46
- 'jti' => SecureRandom.uuid
47
- }
48
-
49
- Paseto::V4::Public.new(@ed25519.pem).encode!(claims, footer: { 'kid' => @key }.to_json)
50
- end
51
-
52
- private
53
-
54
- # Loads the PASETO signing libraries lazily and raises a clear error if they are unavailable.
55
- # rbnacl loads system libsodium at runtime, which the gemspec cannot guarantee, so requiring it
56
- # here keeps `require 'nonnative'` working without libsodium for consumers that do not use PASETO.
57
- def load_dependencies!
58
- require 'rbnacl'
59
- require 'paseto'
60
- rescue LoadError => e
61
- raise Nonnative::Error, "PASETO token generation requires libsodium and the rbnacl and ruby-paseto gems (#{e.message})"
62
- end
63
- end
64
- end