legion-crypt 1.5.8 → 1.5.9

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: b2c9243c14fe8bce1a6abb0de6a29681b08b8c8719ff592f2191581209131a38
4
- data.tar.gz: 3880aee6fb5c3c82606317dd82c80f64f3f3a84c984c72fcd23402a263f262a6
3
+ metadata.gz: 42200f56d577b407725621c56af4f7d191c1ad0219c33c99f5e4adc02568aac6
4
+ data.tar.gz: c231674d541726ab2fa3cf381e655a67be065e2481ce4f50c39d42b52875f6fa
5
5
  SHA512:
6
- metadata.gz: 1001efcac237f95827a8784886050e5047afca4830eec8cc962cf72e119c875694477c3dddad011c56dd643bdf42aab8eab8e4a027afda303ddf306c03eea7de
7
- data.tar.gz: fcb5bf8a7527a65221bd917ee1574ce633609f60d00dd070135e4316f05b6c5f0b95ddf251544230e3cf7d0740aa9fa2ea1f4975c638b8e440e50fa282ff5d6c
6
+ metadata.gz: 2ee34bea6a9a73af47707259d8b857dfc1c1eb8f9e3519ccbefd811bb43e182c734795d15732de82058acb1101f3ba14bc16c39feeae87873c290e2aad58c049
7
+ data.tar.gz: b4d4c72a242b0cfb229dcb27f654f41e6dfd6c3035c73901345588639ea102969e83edb31e5b9572705f674eeba8bd3a6fe89915b9db4ca2eedd33749c12fcf3
data/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [1.5.9] - 2026-04-10
6
+
7
+ ### Fixed
8
+ - Vault lease cascade revocation: all three service credentials (RabbitMQ, PostgreSQL, Redis) died at exactly 2 hours when the Vault Kerberos auth token expired — Vault cascade-revokes all child leases when the parent token dies, regardless of individual lease TTLs (closes #29)
9
+ - `TokenRenewer` now detects non-renewable tokens (`renewable=false`) and skips `renew_self` (which always fails for non-renewable tokens), going straight to `reauth_kerberos` before the token expires
10
+ - `TokenRenewer#reauth_kerberos` now triggers `LeaseManager.reissue_all` after obtaining a new token, re-issuing all active leases under the new token so they are not orphaned when the old token expires
11
+ - `LeaseManager#push_to_settings` symbol/string key mismatch: `resolve_secrets!` registers refs with string keys (`"rabbitmq"`) via `lease://` URI parsing, but `cache_lease` stores leases with symbol keys (`:rabbitmq` from `Legion::JSON.load`) — now tries both key types
12
+ - `LeaseManager#trigger_reconnect` for `:postgresql` — uses surgical Sequel pool `disconnect` + `test_connection` instead of `Data.shutdown + Data.setup` which tore down unrelated connections (Apollo SQLite, Local cache)
13
+ - `LeaseManager#trigger_reconnect` for `:redis` — uses `Cache.restart` (the actual method) instead of `Cache.reconnect` (which does not exist)
14
+
15
+ ### Added
16
+ - `LeaseManager#reissue_all` — re-issues all active leases under the current vault client token; called by `TokenRenewer` after successful Kerberos re-authentication to prevent cascade revocation of orphaned leases
17
+
5
18
  ## [1.5.8] - 2026-04-09
6
19
 
7
20
  ### Added
@@ -86,7 +86,9 @@ module Legion
86
86
 
87
87
  def push_to_settings(name)
88
88
  refs, data = @state_mutex.synchronize do
89
- [@refs[name]&.dup, @lease_cache[name]&.dup]
89
+ r = @refs[name] || @refs[name.to_s] || @refs[name.to_sym]
90
+ d = @lease_cache[name] || @lease_cache[name.to_s] || @lease_cache[name.to_sym]
91
+ [r&.dup, d&.dup]
90
92
  end
91
93
  return if refs.nil? || refs.empty?
92
94
  return unless data
@@ -109,6 +111,19 @@ module Legion
109
111
  sys
110
112
  end
111
113
 
114
+ def reissue_all
115
+ log.info('LeaseManager: reissue_all — re-issuing all active leases under new token')
116
+ lease_names = @state_mutex.synchronize { @active_leases.keys.dup }
117
+
118
+ lease_names.each do |name|
119
+ lease = @state_mutex.synchronize { @active_leases[name]&.dup }
120
+ next unless lease && lease[:path]
121
+
122
+ reissue_lease(name)
123
+ end
124
+ log.info('LeaseManager: reissue_all complete')
125
+ end
126
+
112
127
  def register_dynamic_lease(name:, path:, response:, settings_refs:)
113
128
  register_at_exit_hook
114
129
 
@@ -451,14 +466,19 @@ module Legion
451
466
  Legion::Transport::Connection.force_reconnect
452
467
  log.info("LeaseManager: triggered transport reconnect after '#{name}' reissue")
453
468
  when :postgresql
454
- return unless defined?(Legion::Data) && Legion::Data.respond_to?(:reconnect)
469
+ return unless defined?(Legion::Data::Connection) && Legion::Data::Connection.sequel
455
470
 
456
- Legion::Data.reconnect
457
- log.info("LeaseManager: triggered data reconnect after '#{name}' reissue")
471
+ Legion::Data::Connection.sequel.disconnect
472
+ Legion::Data::Connection.sequel.test_connection
473
+ log.info("LeaseManager: triggered data pool reconnect after '#{name}' reissue")
458
474
  when :redis
459
- return unless defined?(Legion::Cache) && Legion::Cache.respond_to?(:reconnect)
475
+ return unless defined?(Legion::Cache)
460
476
 
461
- Legion::Cache.reconnect
477
+ if Legion::Cache.respond_to?(:restart)
478
+ Legion::Cache.restart
479
+ elsif Legion::Cache.respond_to?(:reconnect)
480
+ Legion::Cache.reconnect
481
+ end
462
482
  log.info("LeaseManager: triggered cache reconnect after '#{name}' reissue")
463
483
  end
464
484
  rescue StandardError => e
@@ -72,7 +72,9 @@ module Legion
72
72
  @config[:renewable] = result[:renewable]
73
73
  @config[:connected] = true
74
74
  @vault_client.token = result[:token]
75
- log.info("TokenRenewer[#{@cluster_name}]: re-authenticated via Kerberos")
75
+ log.info("TokenRenewer[#{@cluster_name}]: re-authenticated via Kerberos, ttl=#{result[:lease_duration]}s")
76
+
77
+ reissue_all_leases
76
78
  true
77
79
  rescue StandardError => e
78
80
  handle_exception(e, level: :warn, operation: 'crypt.token_renewer.reauth_kerberos', cluster_name: @cluster_name)
@@ -104,10 +106,18 @@ module Legion
104
106
  interruptible_sleep(sleep_duration)
105
107
 
106
108
  until @stop
107
- if renew_token || reauth_kerberos
108
- on_renewal_success
109
+ if @config[:renewable]
110
+ if renew_token || reauth_kerberos
111
+ on_renewal_success
112
+ else
113
+ on_renewal_failure
114
+ end
109
115
  else
110
- on_renewal_failure
116
+ if reauth_kerberos # rubocop:disable Style/IfInsideElse
117
+ on_renewal_success
118
+ else
119
+ on_renewal_failure
120
+ end
111
121
  end
112
122
  end
113
123
  rescue StandardError => e
@@ -128,6 +138,15 @@ module Legion
128
138
  interruptible_sleep(delay)
129
139
  end
130
140
 
141
+ def reissue_all_leases
142
+ return unless defined?(Legion::Crypt::LeaseManager)
143
+
144
+ Legion::Crypt::LeaseManager.instance.reissue_all
145
+ rescue StandardError => e
146
+ handle_exception(e, level: :warn, operation: 'crypt.token_renewer.reissue_all_leases', cluster_name: @cluster_name)
147
+ log.warn("TokenRenewer[#{@cluster_name}]: failed to reissue leases after reauth: #{e.message}")
148
+ end
149
+
131
150
  def interruptible_sleep(seconds)
132
151
  deadline = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC) + seconds
133
152
  loop do
@@ -150,7 +169,7 @@ module Legion
150
169
  else
151
170
  @thread = nil
152
171
  revoke_token
153
- log.debug("TokenRenewer[#{@cluster_name}]: token renewal thread stopped")
172
+ log.info("TokenRenewer[#{@cluster_name}]: token renewal thread stopped")
154
173
  end
155
174
  end
156
175
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Legion
4
4
  module Crypt
5
- VERSION = '1.5.8'
5
+ VERSION = '1.5.9'
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.5.8
4
+ version: 1.5.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity