legion-crypt 1.4.28 → 1.5.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.
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'legion/logging/helper'
3
4
  require 'singleton'
4
5
 
5
6
  module Legion
6
7
  module Crypt
7
8
  class LeaseManager
8
9
  include Singleton
10
+ include Legion::Logging::Helper
9
11
 
10
12
  RENEWAL_CHECK_INTERVAL = 5
11
13
 
@@ -15,18 +17,20 @@ module Legion
15
17
  @refs = {}
16
18
  @running = false
17
19
  @renewal_thread = nil
20
+ @state_mutex = Mutex.new
18
21
  end
19
22
 
20
23
  def start(definitions, vault_client: nil)
21
- @vault_client = vault_client
24
+ @state_mutex.synchronize { @vault_client = vault_client }
22
25
  return if definitions.nil? || definitions.empty?
23
26
 
27
+ log.info "LeaseManager start requested definitions=#{definitions.size}"
24
28
  definitions.each do |name, opts|
25
29
  path = opts['path'] || opts[:path]
26
30
  next unless path
27
31
 
28
32
  if lease_valid?(name)
29
- log_debug("LeaseManager: reusing valid cached lease for '#{name}'")
33
+ log.debug("LeaseManager: reusing valid cached lease for '#{name}'")
30
34
  next
31
35
  end
32
36
 
@@ -35,52 +39,59 @@ module Legion
35
39
  begin
36
40
  response = logical.read(path)
37
41
  unless response
38
- log_warn("LeaseManager: no data at '#{name}' (#{path}) — path may not exist or role not configured")
42
+ log.warn("LeaseManager: no data at '#{name}' (#{path}) — path may not exist or role not configured")
39
43
  next
40
44
  end
41
45
 
42
- @lease_cache[name] = response.data || {}
43
- @active_leases[name] = {
44
- lease_id: response.lease_id,
45
- lease_duration: response.lease_duration,
46
- renewable: response.renewable?,
47
- expires_at: Time.now + (response.lease_duration || 0),
48
- fetched_at: Time.now
49
- }
50
- log_debug("LeaseManager: fetched lease for '#{name}' from #{path}")
46
+ @state_mutex.synchronize do
47
+ @lease_cache[name] = response.data || {}
48
+ @active_leases[name] = {
49
+ lease_id: response.lease_id,
50
+ lease_duration: response.lease_duration,
51
+ renewable: response.renewable?,
52
+ expires_at: Time.now + (response.lease_duration || 0),
53
+ fetched_at: Time.now
54
+ }
55
+ end
56
+ log.info("LeaseManager: fetched lease for '#{name}' from #{path}")
51
57
  rescue StandardError => e
52
- log_warn("LeaseManager: failed to fetch lease '#{name}' from #{path}: #{e.message}")
58
+ handle_exception(e, level: :warn, operation: 'crypt.lease_manager.start', lease_name: name, path: path)
59
+ log.warn("LeaseManager: failed to fetch lease '#{name}' from #{path}: #{e.message}")
53
60
  end
54
61
  end
55
62
  end
56
63
 
57
64
  def fetched_count
58
- @active_leases.size
65
+ @state_mutex.synchronize { @active_leases.size }
59
66
  end
60
67
 
61
68
  def fetch(name, key)
62
- data = @lease_cache[name.to_sym] || @lease_cache[name.to_s]
69
+ data = @state_mutex.synchronize do
70
+ @lease_cache[name.to_sym] || @lease_cache[name.to_s]
71
+ end
63
72
  return nil unless data
64
73
 
65
74
  data[key.to_sym] || data[key.to_s]
66
75
  end
67
76
 
68
77
  def lease_data(name)
69
- @lease_cache[name]
78
+ @state_mutex.synchronize { @lease_cache[name] }
70
79
  end
71
80
 
72
81
  attr_reader :active_leases
73
82
 
74
83
  def register_ref(name, key, path)
75
- @refs[name] ||= {}
76
- @refs[name][key] = path
84
+ @state_mutex.synchronize do
85
+ @refs[name] ||= {}
86
+ @refs[name][key] = path
87
+ end
77
88
  end
78
89
 
79
90
  def push_to_settings(name)
80
- refs = @refs[name]
91
+ refs, data = @state_mutex.synchronize do
92
+ [@refs[name]&.dup, @lease_cache[name]&.dup]
93
+ end
81
94
  return if refs.nil? || refs.empty?
82
-
83
- data = @lease_cache[name]
84
95
  return unless data
85
96
 
86
97
  refs.each do |key, path|
@@ -88,80 +99,110 @@ module Legion
88
99
  write_setting(path, value)
89
100
  end
90
101
 
91
- log_debug("Lease '#{name}' rotated — updated #{refs.size} settings reference(s)")
102
+ log.info("Lease '#{name}' rotated — updated #{refs.size} settings reference(s)")
92
103
  end
93
104
 
94
105
  def start_renewal_thread
95
- return if renewal_thread_alive?
106
+ @state_mutex.synchronize do
107
+ return if @renewal_thread&.alive?
96
108
 
97
- @running = true
98
- @renewal_thread = Thread.new { renewal_loop }
109
+ @running = true
110
+ @renewal_thread = Thread.new { renewal_loop }
111
+ end
112
+ log.info 'LeaseManager renewal thread started'
99
113
  end
100
114
 
101
115
  def renewal_thread_alive?
102
- @renewal_thread&.alive? || false
116
+ @state_mutex.synchronize { @renewal_thread&.alive? || false }
103
117
  end
104
118
 
105
119
  def shutdown
120
+ log.info 'LeaseManager shutdown requested'
106
121
  stop_renewal_thread
107
122
 
108
- @active_leases.each do |name, meta|
123
+ leases = @state_mutex.synchronize { @active_leases.dup }
124
+ leases.each do |name, meta|
109
125
  lease_id = meta[:lease_id]
110
126
  next if lease_id.nil? || lease_id.empty?
111
127
 
112
128
  begin
113
129
  sys.revoke(lease_id)
114
- log_debug("LeaseManager: revoked lease '#{name}' (#{lease_id})")
130
+ log.debug("LeaseManager: revoked lease '#{name}' (#{lease_id})")
115
131
  rescue StandardError => e
116
- log_warn("LeaseManager: failed to revoke lease '#{name}' (#{lease_id}): #{e.message}")
132
+ handle_exception(e, level: :warn, operation: 'crypt.lease_manager.shutdown', lease_name: name)
133
+ log.warn("LeaseManager: failed to revoke lease '#{name}' (#{lease_id}): #{e.message}")
117
134
  end
118
135
  end
119
136
 
120
- @lease_cache.clear
121
- @active_leases.clear
122
- @refs.clear
123
- @vault_client = nil
137
+ @state_mutex.synchronize do
138
+ @lease_cache.clear
139
+ @active_leases.clear
140
+ @refs.clear
141
+ @vault_client = nil
142
+ end
143
+ log.info 'LeaseManager shutdown complete'
124
144
  end
125
145
 
126
146
  def reset!
127
- @running = false
128
- @lease_cache.clear
129
- @active_leases.clear
130
- @refs.clear
131
- @vault_client = nil
147
+ @state_mutex.synchronize do
148
+ @running = false
149
+ @lease_cache.clear
150
+ @active_leases.clear
151
+ @refs.clear
152
+ @vault_client = nil
153
+ @renewal_thread = nil
154
+ end
132
155
  end
133
156
 
134
157
  private
135
158
 
136
159
  def logical
137
- @vault_client ? @vault_client.logical : ::Vault.logical
160
+ client = @state_mutex.synchronize { @vault_client }
161
+ client ? client.logical : ::Vault.logical
138
162
  end
139
163
 
140
164
  def sys
141
- @vault_client ? @vault_client.sys : ::Vault.sys
165
+ client = @state_mutex.synchronize { @vault_client }
166
+ client ? client.sys : ::Vault.sys
142
167
  end
143
168
 
144
169
  def stop_renewal_thread
145
- @running = false
146
- if @renewal_thread&.alive?
147
- @renewal_thread.kill
148
- @renewal_thread.join(2)
170
+ thread = @state_mutex.synchronize do
171
+ @running = false
172
+ @renewal_thread
173
+ end
174
+ return unless thread
175
+
176
+ begin
177
+ thread.wakeup if thread.alive?
178
+ rescue ThreadError => e
179
+ handle_exception(e, level: :debug, operation: 'crypt.lease_manager.stop_renewal_thread')
180
+ end
181
+ thread.join(2)
182
+ if thread.alive?
183
+ log.warn 'LeaseManager renewal thread did not stop within timeout'
184
+ else
185
+ @state_mutex.synchronize { @renewal_thread = nil }
186
+ log.debug 'LeaseManager renewal thread stopped'
149
187
  end
150
- @renewal_thread = nil
151
188
  end
152
189
 
153
190
  def renewal_loop
154
- while @running
155
- sleep(RENEWAL_CHECK_INTERVAL)
156
- renew_approaching_leases if @running
191
+ while running?
192
+ interruptible_sleep(RENEWAL_CHECK_INTERVAL)
193
+ renew_approaching_leases if running?
157
194
  end
158
195
  rescue StandardError => e
159
- log_warn("LeaseManager: renewal loop error: #{e.message}")
160
- retry if @running
196
+ handle_exception(e, level: :error, operation: 'crypt.lease_manager.renewal_loop')
197
+ log.error("LeaseManager: renewal loop error: #{e.message}")
198
+ retry if running?
161
199
  end
162
200
 
163
201
  def renew_approaching_leases
164
- @active_leases.each do |name, lease|
202
+ leases = @state_mutex.synchronize { @active_leases.keys }
203
+ leases.each do |name|
204
+ lease = @state_mutex.synchronize { @active_leases[name]&.dup }
205
+ next unless lease
165
206
  next unless lease[:renewable]
166
207
  next unless approaching_expiry?(lease)
167
208
 
@@ -171,18 +212,28 @@ module Legion
171
212
 
172
213
  def renew_lease(name, lease)
173
214
  response = sys.renew(lease[:lease_id])
174
- lease[:expires_at] = Time.now + (response.lease_duration || 0)
215
+ @state_mutex.synchronize do
216
+ current_lease = @active_leases[name]
217
+ next unless current_lease
218
+
219
+ current_lease[:lease_duration] = response.lease_duration if response.respond_to?(:lease_duration)
220
+ current_lease[:renewable] = response.renewable? if response.respond_to?(:renewable?)
221
+ current_lease[:expires_at] = Time.now + (response.lease_duration || 0)
222
+ end
223
+ log.info("LeaseManager: renewed lease '#{name}'")
175
224
 
176
- if response.data && response.data != @lease_cache[name]
177
- @lease_cache[name] = response.data
225
+ cached_data = @state_mutex.synchronize { @lease_cache[name] }
226
+ if response.data && response.data != cached_data
227
+ @state_mutex.synchronize { @lease_cache[name] = response.data }
178
228
  push_to_settings(name)
179
229
  end
180
230
  rescue StandardError => e
181
- log_warn("LeaseManager: failed to renew lease '#{name}': #{e.message}")
231
+ handle_exception(e, level: :warn, operation: 'crypt.lease_manager.renew_lease', lease_name: name)
232
+ log.warn("LeaseManager: failed to renew lease '#{name}': #{e.message}")
182
233
  end
183
234
 
184
235
  def lease_valid?(name)
185
- meta = @active_leases[name]
236
+ meta = @state_mutex.synchronize { @active_leases[name]&.dup }
186
237
  return false unless meta
187
238
 
188
239
  expires_at = meta[:expires_at]
@@ -192,7 +243,7 @@ module Legion
192
243
  end
193
244
 
194
245
  def revoke_expired_lease(name)
195
- meta = @active_leases[name]
246
+ meta = @state_mutex.synchronize { @active_leases[name]&.dup }
196
247
  return unless meta
197
248
 
198
249
  lease_id = meta[:lease_id]
@@ -200,12 +251,15 @@ module Legion
200
251
 
201
252
  begin
202
253
  sys.revoke(lease_id)
203
- log_debug("LeaseManager: revoked expired lease '#{name}' (#{lease_id}) before re-fetch")
254
+ log.debug("LeaseManager: revoked expired lease '#{name}' (#{lease_id}) before re-fetch")
204
255
  rescue StandardError => e
205
- log_warn("LeaseManager: failed to revoke expired lease '#{name}' (#{lease_id}): #{e.message}")
256
+ handle_exception(e, level: :warn, operation: 'crypt.lease_manager.revoke_expired_lease', lease_name: name)
257
+ log.warn("LeaseManager: failed to revoke expired lease '#{name}' (#{lease_id}): #{e.message}")
206
258
  ensure
207
- @active_leases.delete(name)
208
- @lease_cache.delete(name)
259
+ @state_mutex.synchronize do
260
+ @active_leases.delete(name)
261
+ @lease_cache.delete(name)
262
+ end
209
263
  end
210
264
  end
211
265
 
@@ -229,22 +283,21 @@ module Legion
229
283
  end
230
284
  target[path.last] = value if target.is_a?(Hash)
231
285
  rescue StandardError => e
232
- log_warn("LeaseManager: failed to write setting at #{path.join('.')}: #{e.message}")
286
+ handle_exception(e, level: :warn, operation: 'crypt.lease_manager.write_setting', path: path.join('.'))
287
+ log.warn("LeaseManager: failed to write setting at #{path.join('.')}: #{e.message}")
233
288
  end
234
289
 
235
- def log_debug(message)
236
- if defined?(Legion::Logging)
237
- Legion::Logging.debug(message)
238
- else
239
- $stdout.puts("[DEBUG] #{message}")
240
- end
290
+ def running?
291
+ @state_mutex.synchronize { @running }
241
292
  end
242
293
 
243
- def log_warn(message)
244
- if defined?(Legion::Logging)
245
- Legion::Logging.warn(message)
246
- else
247
- warn("[WARN] #{message}")
294
+ def interruptible_sleep(seconds)
295
+ deadline = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC) + seconds
296
+ loop do
297
+ remaining = deadline - ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
298
+ break if remaining <= 0 || !running?
299
+
300
+ sleep([remaining, 1.0].min)
248
301
  end
249
302
  end
250
303
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'legion/logging/helper'
3
4
  require 'socket'
4
5
 
5
6
  module Legion
@@ -7,6 +8,7 @@ module Legion
7
8
  module Mtls
8
9
  DEFAULT_PKI_PATH = 'pki/issue/legion-internal'
9
10
  DEFAULT_TTL = '24h'
11
+ extend Legion::Logging::Helper
10
12
 
11
13
  class << self
12
14
  def enabled?
@@ -29,6 +31,7 @@ module Legion
29
31
 
30
32
  def issue_cert(common_name:, ttl: nil)
31
33
  resolved_ttl = ttl || cert_ttl_setting || DEFAULT_TTL
34
+ log.info "[mTLS] certificate issue requested common_name=#{common_name} ttl=#{resolved_ttl}"
32
35
 
33
36
  response = ::Vault.logical.write(
34
37
  pki_path,
@@ -49,10 +52,16 @@ module Legion
49
52
  serial: data[:serial_number],
50
53
  expiry: Time.at(data[:expiration].to_i)
51
54
  }
55
+ rescue StandardError => e
56
+ handle_exception(e, level: :error, operation: 'crypt.mtls.issue_cert', common_name: common_name, ttl: resolved_ttl)
57
+ raise
52
58
  end
53
59
 
54
60
  def local_ip
55
61
  Socket.ip_address_list.find { |a| a.ipv4? && !a.ipv4_loopback? }&.ip_address || '127.0.0.1'
62
+ rescue StandardError => e
63
+ handle_exception(e, level: :warn, operation: 'crypt.mtls.local_ip')
64
+ '127.0.0.1'
56
65
  end
57
66
 
58
67
  private
@@ -61,7 +70,8 @@ module Legion
61
70
  return nil unless defined?(Legion::Settings)
62
71
 
63
72
  Legion::Settings[:security]
64
- rescue StandardError
73
+ rescue StandardError => e
74
+ handle_exception(e, level: :debug, operation: 'crypt.mtls.safe_security_settings')
65
75
  nil
66
76
  end
67
77
 
@@ -71,6 +81,9 @@ module Legion
71
81
 
72
82
  mtls = security[:mtls] || security['mtls'] || {}
73
83
  mtls[:cert_ttl] || mtls['cert_ttl']
84
+ rescue StandardError => e
85
+ handle_exception(e, level: :debug, operation: 'crypt.mtls.cert_ttl_setting')
86
+ nil
74
87
  end
75
88
  end
76
89
  end
@@ -1,20 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'openssl'
4
+ require 'legion/logging/helper'
4
5
 
5
6
  module Legion
6
7
  module Crypt
7
8
  module PartitionKeys
9
+ extend Legion::Logging::Helper
10
+
8
11
  class << self
9
12
  def derive_key(master_key:, tenant_id:, context: nil)
10
13
  context ||= begin
11
14
  Legion::Settings[:crypt][:partition_keys][:derivation_context]
12
- rescue StandardError
15
+ rescue StandardError => e
16
+ handle_exception(e, level: :debug, operation: 'crypt.partition_keys.derivation_context', tenant_id: tenant_id)
13
17
  nil
14
18
  end || 'legion-partition'
15
- Legion::Logging.debug "PartitionKeys key derivation for tenant #{tenant_id}" if defined?(Legion::Logging)
19
+ log.debug "PartitionKeys deriving key for tenant #{tenant_id}"
16
20
  salt = OpenSSL::Digest::SHA256.digest(tenant_id.to_s)
17
21
  OpenSSL::KDF.hkdf(master_key, salt: salt, info: context, length: 32, hash: 'SHA256')
22
+ rescue StandardError => e
23
+ handle_exception(e, level: :error, operation: 'crypt.partition_keys.derive_key', tenant_id: tenant_id)
24
+ raise
18
25
  end
19
26
 
20
27
  def encrypt_for_tenant(plaintext:, tenant_id:, master_key:)
@@ -26,9 +33,10 @@ module Legion
26
33
  ciphertext = cipher.update(plaintext) + cipher.final
27
34
  auth_tag = cipher.auth_tag
28
35
 
36
+ log.debug "PartitionKeys encrypted payload for tenant #{tenant_id}"
29
37
  { ciphertext: ciphertext, iv: iv, auth_tag: auth_tag }
30
38
  rescue StandardError => e
31
- Legion::Logging.warn "PartitionKeys encrypt failed for tenant #{tenant_id}: #{e.message}" if defined?(Legion::Logging)
39
+ handle_exception(e, level: :error, operation: 'crypt.partition_keys.encrypt_for_tenant', tenant_id: tenant_id)
32
40
  raise
33
41
  end
34
42
 
@@ -39,9 +47,11 @@ module Legion
39
47
  decipher.key = key
40
48
  decipher.iv = init_vector
41
49
  decipher.auth_tag = auth_tag
42
- decipher.update(ciphertext) + decipher.final
50
+ plaintext = decipher.update(ciphertext) + decipher.final
51
+ log.debug "PartitionKeys decrypted payload for tenant #{tenant_id}"
52
+ plaintext
43
53
  rescue StandardError => e
44
- Legion::Logging.warn "PartitionKeys decrypt failed for tenant #{tenant_id}: #{e.message}" if defined?(Legion::Logging)
54
+ handle_exception(e, level: :error, operation: 'crypt.partition_keys.decrypt_for_tenant', tenant_id: tenant_id)
45
55
  raise
46
56
  end
47
57
  end
@@ -1,8 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'legion/logging/helper'
4
+
3
5
  module Legion
4
6
  module Crypt
5
7
  module Settings
8
+ extend Legion::Logging::Helper
9
+
6
10
  def self.tls
7
11
  {
8
12
  enabled: false,
@@ -15,11 +19,12 @@ module Legion
15
19
 
16
20
  def self.spiffe
17
21
  {
18
- enabled: false,
19
- socket_path: '/tmp/spire-agent/public/api.sock',
20
- trust_domain: 'legion.internal',
21
- workload_id: nil,
22
- renewal_window: 0.5
22
+ enabled: false,
23
+ socket_path: '/tmp/spire-agent/public/api.sock',
24
+ trust_domain: 'legion.internal',
25
+ workload_id: nil,
26
+ renewal_window: 0.5,
27
+ allow_x509_fallback: false
23
28
  }
24
29
  end
25
30
 
@@ -57,8 +62,8 @@ module Legion
57
62
  connected: false,
58
63
  renewer_time: 5,
59
64
  renewer: true,
60
- push_cluster_secret: true,
61
- read_cluster_secret: true,
65
+ push_cluster_secret: false,
66
+ read_cluster_secret: false,
62
67
  kv_path: ENV['LEGION_VAULT_KV_PATH'] || 'legion',
63
68
  leases: {},
64
69
  default: nil,
@@ -75,12 +80,13 @@ module Legion
75
80
  end
76
81
 
77
82
  begin
78
- Legion::Settings.merge_settings('crypt', Legion::Crypt::Settings.default) if Legion.const_defined?('Settings')
83
+ if Legion.const_defined?('Settings')
84
+ Legion::Settings.merge_settings('crypt', Legion::Crypt::Settings.default)
85
+ Legion::Crypt::Settings.log.info('Legion::Crypt settings defaults merged')
86
+ end
79
87
  rescue StandardError => e
80
- if Legion.const_defined?('Logging') && Legion::Logging.respond_to?(:log_exception)
81
- Legion::Logging.log_exception(e, lex: 'crypt', component_type: :helper, level: :fatal)
82
- elsif Legion.const_defined?('Logging') && Legion::Logging.respond_to?(:fatal)
83
- Legion::Logging.fatal("crypt settings merge error: #{e.class}: #{e.message}\n#{Array(e.backtrace).join("\n")}")
88
+ if Legion::Crypt::Settings.respond_to?(:handle_exception)
89
+ Legion::Crypt::Settings.handle_exception(e, level: :fatal, operation: 'crypt.settings.merge_defaults')
84
90
  else
85
91
  puts e.message
86
92
  puts e.backtrace
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'legion/logging/helper'
3
4
  require 'openssl'
4
5
  require 'base64'
5
6
 
@@ -12,6 +13,8 @@ module Legion
12
13
  # returned by WorkloadApiClient. No external gem is required —
13
14
  # all operations use the Ruby stdlib OpenSSL bindings.
14
15
  module IdentityHelpers
16
+ include Legion::Logging::Helper
17
+
15
18
  # Sign arbitrary data with the private key from an X.509 SVID.
16
19
  # Returns the signature as a Base64-encoded string.
17
20
  #
@@ -26,7 +29,11 @@ module Legion
26
29
  key = OpenSSL::PKey.read(svid.key_pem)
27
30
  digest = OpenSSL::Digest.new('SHA256')
28
31
  signature = key.sign(digest, data.b)
32
+ log.debug("SPIFFE signed payload with SVID id=#{svid.spiffe_id}")
29
33
  Base64.strict_encode64(signature)
34
+ rescue StandardError => e
35
+ handle_exception(e, level: :error, operation: 'crypt.spiffe.sign_with_svid', spiffe_id: svid&.spiffe_id&.to_s)
36
+ raise
30
37
  end
31
38
 
32
39
  # Verify a Base64-encoded signature produced by sign_with_svid.
@@ -43,9 +50,12 @@ module Legion
43
50
  cert = OpenSSL::X509::Certificate.new(svid.cert_pem)
44
51
  digest = OpenSSL::Digest.new('SHA256')
45
52
  signature = Base64.strict_decode64(signature_b64)
46
- cert.public_key.verify(digest, signature, data.b)
53
+ result = cert.public_key.verify(digest, signature, data.b)
54
+ log.debug("SPIFFE signature verification completed id=#{svid.spiffe_id} valid=#{result}")
55
+ result
47
56
  rescue OpenSSL::PKey::PKeyError, OpenSSL::X509::CertificateError, ArgumentError => e
48
- log_spiffe_warn("SVID signature verification error: #{e.message}")
57
+ handle_exception(e, level: :warn, operation: 'crypt.spiffe.verify_svid_signature', spiffe_id: svid&.spiffe_id&.to_s)
58
+ log.warn("[SPIFFE] SVID signature verification error: #{e.message}")
49
59
  false
50
60
  end
51
61
 
@@ -65,12 +75,14 @@ module Legion
65
75
 
66
76
  uri = entry.sub('URI:', '')
67
77
  return Legion::Crypt::Spiffe.parse_id(uri)
68
- rescue InvalidSpiffeIdError
78
+ rescue InvalidSpiffeIdError => e
79
+ handle_exception(e, level: :debug, operation: 'crypt.spiffe.extract_spiffe_id_from_cert', san_entry: entry)
69
80
  next
70
81
  end
71
82
 
72
83
  nil
73
- rescue OpenSSL::X509::CertificateError
84
+ rescue OpenSSL::X509::CertificateError => e
85
+ handle_exception(e, level: :debug, operation: 'crypt.spiffe.extract_spiffe_id_from_cert')
74
86
  nil
75
87
  end
76
88
 
@@ -90,7 +102,8 @@ module Legion
90
102
 
91
103
  leaf = OpenSSL::X509::Certificate.new(cert_pem)
92
104
  store.verify(leaf)
93
- rescue OpenSSL::X509::CertificateError, OpenSSL::X509::StoreError
105
+ rescue OpenSSL::X509::CertificateError, OpenSSL::X509::StoreError => e
106
+ handle_exception(e, level: :warn, operation: 'crypt.spiffe.trusted_cert?', spiffe_id: svid&.spiffe_id&.to_s)
94
107
  false
95
108
  end
96
109
 
@@ -118,12 +131,6 @@ module Legion
118
131
  base
119
132
  end
120
133
  end
121
-
122
- private
123
-
124
- def log_spiffe_warn(message)
125
- Legion::Logging.warn("[SPIFFE] #{message}") if defined?(Legion::Logging)
126
- end
127
134
  end
128
135
  end
129
136
  end