legion-crypt 1.4.13 → 1.4.15

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: 59b6f53757eb825da7b0c635589149793c015d59c422b90916706bae8e796e1d
4
- data.tar.gz: 4879d7e405f5bf0da54b488ac38c1bdba708280bd63d112da3ef487c467039f2
3
+ metadata.gz: 5f43eee9680197c62f53f2a7ed8c77eee725f7f01744c32e5ad0115fdfb2ad21
4
+ data.tar.gz: 3ba3cd7da0684d8a9ec68d23797d487240035dc2f5e07fdba7ab0cfb1727dafe
5
5
  SHA512:
6
- metadata.gz: 6fee90f414f31a34f7f75713c9856b2644a4a74986182d19921aa2731db4a13b6a346417bacccbf449ab2a29fe5b6562d1fd4ba77a6adbba1a9b03c8c04c93e3
7
- data.tar.gz: 36042a488a032df98488493270a9976d526400981ecb62277f9454dd5d6cdeac2be9425c1c9b755004fd3c8fe5814347a55659eb32baa95fd53437859150720b
6
+ metadata.gz: 79fe4cd8653f9a09c3c2f6acc7da403e00d8a8e05b6fb6f488fb25a3c8fadfcbee00cc1ffa7e31319840025a5d622d2b1b6a32210ff0cd9141a04aef26c27e59
7
+ data.tar.gz: b691e62e093b3504d7e7da0501cda48aca9ae705429ed1d5caf97dd3ab7a9b7f87826a8d0cf4dabbff01e1f755d7cee555d74dee85754f7206feb5cadbfdd8f8
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Legion::Crypt
2
2
 
3
+ ## [1.4.15] - 2026-03-26
4
+
5
+ ### Fixed
6
+ - Route `get`, `write`, `read`, `delete`, `exist?` through default cluster client when multi-cluster Vault is configured (#1)
7
+ - Previously these methods used the global `::Vault` singleton which was never initialized when clusters were present, causing 403 errors against the wrong Vault server
8
+
9
+ ## [1.4.14] - 2026-03-26
10
+
11
+ ### Fixed
12
+ - Vault Kerberos auth: send SPNEGO token as HTTP `Authorization` header instead of JSON body (Vault plugin reads headers, not body)
13
+ - Vault Kerberos auth: clear client namespace before auth request (Kerberos mount is at root namespace, not child)
14
+ - Vault Kerberos auth: use `Vault::SecretAuth#renewable?` accessor (not `#renewable`)
15
+
3
16
  ## [1.4.13] - 2026-03-25
4
17
 
5
18
  ### Added
data/CLAUDE.md CHANGED
@@ -8,7 +8,7 @@
8
8
  Handles encryption, decryption, secrets management, JWT token management, and HashiCorp Vault connectivity for the LegionIO framework. Provides AES-256-CBC message encryption, RSA key pair generation, cluster secret management, JWT issue/verify operations, and Vault token lifecycle management.
9
9
 
10
10
  **GitHub**: https://github.com/LegionIO/legion-crypt
11
- **Version**: 1.4.7
11
+ **Version**: 1.4.15
12
12
  **License**: Apache-2.0
13
13
 
14
14
  ## Architecture
@@ -43,17 +43,34 @@ module Legion
43
43
  end
44
44
 
45
45
  def exchange_token(vault_client, spnego_token, auth_path)
46
- response = vault_client.logical.write(auth_path, authorization: "Negotiate #{spnego_token}")
46
+ # Kerberos auth is mounted at the root namespace. Temporarily
47
+ # clear the client namespace so the request reaches the correct
48
+ # mount path, then restore it for subsequent operations.
49
+ saved_ns = vault_client.namespace
50
+ vault_client.namespace = nil
51
+
52
+ # The Vault Kerberos plugin reads the SPNEGO token from the HTTP
53
+ # Authorization header, not the JSON body.
54
+ json = vault_client.put(
55
+ "/v1/#{auth_path}",
56
+ '{}',
57
+ 'Authorization' => "Negotiate #{spnego_token}"
58
+ )
59
+ response = ::Vault::Secret.decode(json)
47
60
  raise AuthError, 'Vault Kerberos auth returned no auth data' unless response&.auth
48
61
 
62
+ vault_client.namespace = saved_ns
63
+
64
+ auth = response.auth
49
65
  {
50
- token: response.auth.client_token,
51
- lease_duration: response.auth.lease_duration,
52
- renewable: response.auth.renewable,
53
- policies: response.auth.policies,
54
- metadata: response.auth.metadata
66
+ token: auth.client_token,
67
+ lease_duration: auth.lease_duration,
68
+ renewable: auth.renewable?,
69
+ policies: auth.policies,
70
+ metadata: auth.metadata
55
71
  }
56
72
  rescue ::Vault::HTTPClientError => e
73
+ vault_client.namespace = saved_ns if saved_ns
57
74
  raise AuthError, "Vault Kerberos auth failed: #{e.message}"
58
75
  end
59
76
  end
@@ -45,7 +45,7 @@ module Legion
45
45
  def read(path, type = 'legion')
46
46
  full_path = type.nil? || type.empty? ? "#{type}/#{path}" : path
47
47
  Legion::Logging.debug "Vault read: #{full_path}" if defined?(Legion::Logging)
48
- lease = ::Vault.logical.read(full_path)
48
+ lease = logical_client.read(full_path)
49
49
  add_session(path: lease.lease_id) if lease.respond_to? :lease_id
50
50
  lease.data
51
51
  rescue StandardError => e
@@ -55,7 +55,7 @@ module Legion
55
55
 
56
56
  def get(path)
57
57
  Legion::Logging.debug "Vault kv get: #{path}" if defined?(Legion::Logging)
58
- result = ::Vault.kv(settings[:vault][:kv_path]).read(path)
58
+ result = kv_client.read(path)
59
59
  return nil if result.nil?
60
60
 
61
61
  result.data
@@ -66,14 +66,14 @@ module Legion
66
66
 
67
67
  def write(path, **hash)
68
68
  Legion::Logging.debug "Vault kv write: #{path}" if defined?(Legion::Logging)
69
- ::Vault.kv(settings[:vault][:kv_path]).write(path, **hash)
69
+ kv_client.write(path, **hash)
70
70
  rescue StandardError => e
71
71
  Legion::Logging.warn "Vault kv write failed at #{path}: #{e.message}" if defined?(Legion::Logging)
72
72
  raise
73
73
  end
74
74
 
75
75
  def delete(path)
76
- ::Vault.logical.delete(path)
76
+ logical_client.delete(path)
77
77
  { success: true, path: path }
78
78
  rescue StandardError => e
79
79
  Legion::Logging.warn "Vault delete failed for #{path}: #{e.message}" if defined?(Legion::Logging)
@@ -81,7 +81,7 @@ module Legion
81
81
  end
82
82
 
83
83
  def exist?(path)
84
- !::Vault.kv(settings[:vault][:kv_path]).read_metadata(path).nil?
84
+ !kv_client.read_metadata(path).nil?
85
85
  end
86
86
 
87
87
  def add_session(path:)
@@ -140,6 +140,24 @@ module Legion
140
140
  def vault_exists?(name)
141
141
  ::Vault.sys.mounts.key?(name.to_sym)
142
142
  end
143
+
144
+ private
145
+
146
+ def kv_client
147
+ if respond_to?(:connected_clusters) && connected_clusters.any?
148
+ vault_client.kv(settings[:vault][:kv_path])
149
+ else
150
+ ::Vault.kv(settings[:vault][:kv_path])
151
+ end
152
+ end
153
+
154
+ def logical_client
155
+ if respond_to?(:connected_clusters) && connected_clusters.any?
156
+ vault_client.logical
157
+ else
158
+ ::Vault.logical
159
+ end
160
+ end
143
161
  end
144
162
  end
145
163
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Legion
4
4
  module Crypt
5
- VERSION = '1.4.13'
5
+ VERSION = '1.4.15'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: legion-crypt
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.13
4
+ version: 1.4.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity