legion-crypt 1.4.3 → 1.4.4

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: 755c4278bc3e6f3ba845f5d46ba61b753a19b9a4fc0212f9da9827e6fefe3ac2
4
- data.tar.gz: '04585ab20ddb62568949ca90c33405b61bb477cd2750503944acadcf665925b9'
3
+ metadata.gz: 5999b5f3ac22f39690f9ee509cec95793e39619498615c6c92c28a509561d072
4
+ data.tar.gz: 942363ac4938f2f9f36436054d42be8202c16d81dfdfd9d5e66ed52763299fe4
5
5
  SHA512:
6
- metadata.gz: 53c5f43b6ab1ca2f0dad978a3cee6b1d3314b8aa57ffae077641d9882756f3a331b21258f3b45a9789639095facdff27baec911e6cbd066c7d2c2fc1058237bd
7
- data.tar.gz: f3b542c8ca98c768ddfae7763da33ddc3638fd46dbb174abf037cd0baca348fa6127c4ad1d3efa46c86a943b2cd3d2c6f2df5d8d179e0a64a5b94d5b3ec4f35c
6
+ metadata.gz: 2ef2a270e3cb979f98dc0e0796234841799e5a702836db38ee64aa2b16d9d467d57e850971a9260d430993cd710b1afc51562ba6efc1203d67e35ad85220a063
7
+ data.tar.gz: 58410cd7e95c2532f07969bc0a6150abc177249388db68080064311e9cb742633b30a45dbab5506731b30c29e520565ae53db6753d70fb5874322e8fbce4fbec
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Legion::Crypt
2
2
 
3
+ ## [1.4.4] - 2026-03-18
4
+
5
+ ### Added
6
+ - Multi-cluster Vault support: named clusters with `default` pointer in `crypt.vault.clusters`
7
+ - `VaultCluster` module: per-cluster `::Vault::Client` management, `connect_all_clusters`
8
+ - `LdapAuth` module: LDAP authentication via Vault HTTP API (`auth/ldap/login/:username`)
9
+ - `ldap_login_all` authenticates to all LDAP-configured clusters with single credentials
10
+ - `VaultRenewer` now renews tokens for all connected clusters
11
+ - Backward compatible: single-cluster config (`crypt.vault.address`) still works unchanged
12
+
3
13
  ## [1.4.3] - 2026-03-17
4
14
 
5
15
  ### Added
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Crypt
5
+ module LdapAuth
6
+ def ldap_login(cluster_name:, username:, password:)
7
+ cluster_name = cluster_name.to_sym
8
+ client = vault_client(cluster_name)
9
+ secret = client.logical.write("auth/ldap/login/#{username}", password: password)
10
+ auth = secret.auth
11
+ token = auth.client_token
12
+
13
+ clusters[cluster_name][:token] = token
14
+ clusters[cluster_name][:connected] = true
15
+
16
+ { token: token, lease_duration: auth.lease_duration,
17
+ renewable: auth.renewable, policies: auth.policies }
18
+ end
19
+
20
+ def ldap_login_all(username:, password:)
21
+ results = {}
22
+ clusters.each do |name, config|
23
+ next unless config[:auth_method] == 'ldap'
24
+
25
+ results[name] = ldap_login(cluster_name: name, username: username, password: password)
26
+ rescue StandardError => e
27
+ results[name] = { error: e.message }
28
+ end
29
+ results
30
+ end
31
+ end
32
+ end
33
+ end
@@ -39,7 +39,9 @@ module Legion
39
39
  push_cluster_secret: true,
40
40
  read_cluster_secret: true,
41
41
  kv_path: ENV['LEGION_VAULT_KV_PATH'] || 'legion',
42
- leases: {}
42
+ leases: {},
43
+ default: nil,
44
+ clusters: {}
43
45
  }
44
46
  end
45
47
  end
@@ -83,8 +83,21 @@ module Legion
83
83
  end
84
84
 
85
85
  def renew_sessions(**_opts)
86
- @sessions.each do |session|
87
- renew_session(session: session)
86
+ if respond_to?(:connected_clusters) && connected_clusters.any?
87
+ renew_cluster_tokens
88
+ else
89
+ @sessions.each do |session|
90
+ renew_session(session: session)
91
+ end
92
+ end
93
+ end
94
+
95
+ def renew_cluster_tokens
96
+ connected_clusters.each_key do |name|
97
+ client = vault_client(name)
98
+ client.auth_token.renew_self
99
+ rescue StandardError => e
100
+ log_vault_error(name, e)
88
101
  end
89
102
  end
90
103
 
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'vault'
4
+
5
+ module Legion
6
+ module Crypt
7
+ module VaultCluster
8
+ def vault_client(name = nil)
9
+ name = resolve_cluster_name(name)
10
+ @vault_clients ||= {}
11
+ @vault_clients[name] ||= build_vault_client(clusters[name])
12
+ end
13
+
14
+ def cluster(name = nil)
15
+ name = resolve_cluster_name(name)
16
+ clusters[name]
17
+ end
18
+
19
+ def default_cluster_name
20
+ name = vault_settings[:default]
21
+ name ? name.to_sym : clusters.keys.first
22
+ end
23
+
24
+ def clusters
25
+ vault_settings[:clusters] || {}
26
+ end
27
+
28
+ def connected_clusters
29
+ clusters.select { |_, config| config[:token] && config[:connected] }
30
+ end
31
+
32
+ def connect_all_clusters
33
+ results = {}
34
+ clusters.each do |name, config|
35
+ next unless config[:token]
36
+
37
+ client = vault_client(name)
38
+ config[:connected] = client.sys.health_status.initialized?
39
+ results[name] = config[:connected]
40
+ rescue StandardError => e
41
+ config[:connected] = false
42
+ results[name] = false
43
+ log_vault_error(name, e)
44
+ end
45
+ results
46
+ end
47
+
48
+ private
49
+
50
+ def resolve_cluster_name(name)
51
+ return name.to_sym if name
52
+
53
+ default_cluster_name
54
+ end
55
+
56
+ def build_vault_client(config)
57
+ return nil unless config.is_a?(Hash)
58
+
59
+ client = ::Vault::Client.new(
60
+ address: "#{config[:protocol]}://#{config[:address]}:#{config[:port]}",
61
+ token: config[:token]
62
+ )
63
+ client.namespace = config[:namespace] if config[:namespace]
64
+ client
65
+ end
66
+
67
+ def log_vault_error(name, error)
68
+ if defined?(Legion::Logging)
69
+ Legion::Logging.error("Vault cluster #{name}: #{error.message}")
70
+ else
71
+ warn("Vault cluster #{name}: #{error.message}")
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Crypt
5
+ module VaultKerberosAuth
6
+ DEFAULT_AUTH_PATH = 'auth/kerberos/login'
7
+
8
+ class AuthError < StandardError; end
9
+
10
+ def self.login(spnego_token:, auth_path: DEFAULT_AUTH_PATH)
11
+ raise AuthError, 'Vault is not connected' unless vault_connected?
12
+
13
+ response = ::Vault.logical.write(auth_path, authorization: "Negotiate #{spnego_token}")
14
+ raise AuthError, 'Vault Kerberos auth returned no auth data' unless response&.auth
15
+
16
+ {
17
+ token: response.auth.client_token,
18
+ lease_duration: response.auth.lease_duration,
19
+ renewable: response.auth.renewable,
20
+ policies: response.auth.policies,
21
+ metadata: response.auth.metadata
22
+ }
23
+ rescue ::Vault::HTTPClientError => e
24
+ raise AuthError, "Vault Kerberos auth failed: #{e.message}"
25
+ end
26
+
27
+ def self.login!(spnego_token:, auth_path: DEFAULT_AUTH_PATH)
28
+ result = login(spnego_token: spnego_token, auth_path: auth_path)
29
+ ::Vault.token = result[:token]
30
+ result
31
+ end
32
+
33
+ def self.vault_connected?
34
+ defined?(::Vault) && defined?(Legion::Settings) &&
35
+ Legion::Settings[:crypt][:vault][:connected] == true
36
+ rescue StandardError
37
+ false
38
+ end
39
+
40
+ private_class_method :vault_connected?
41
+ end
42
+ end
43
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Legion
4
4
  module Crypt
5
- VERSION = '1.4.3'
5
+ VERSION = '1.4.4'
6
6
  end
7
7
  end
data/lib/legion/crypt.rb CHANGED
@@ -8,9 +8,14 @@ require 'legion/crypt/cipher'
8
8
  require 'legion/crypt/jwt'
9
9
  require 'legion/crypt/vault_jwt_auth'
10
10
  require 'legion/crypt/lease_manager'
11
+ require 'legion/crypt/vault_cluster'
12
+ require 'legion/crypt/ldap_auth'
11
13
 
12
14
  module Legion
13
15
  module Crypt
16
+ extend Legion::Crypt::VaultCluster
17
+ extend Legion::Crypt::LdapAuth
18
+
14
19
  class << self
15
20
  attr_reader :sessions
16
21
 
@@ -21,11 +26,19 @@ module Legion
21
26
  include Legion::Crypt::Vault
22
27
  end
23
28
 
29
+ def vault_settings
30
+ Legion::Settings[:crypt][:vault]
31
+ end
32
+
24
33
  def start
25
34
  Legion::Logging.debug 'Legion::Crypt is running start'
26
35
  ::File.write('./legionio.key', private_key) if settings[:save_private_key]
27
36
 
28
- connect_vault unless settings[:vault][:token].nil?
37
+ if vault_settings[:clusters]&.any?
38
+ connect_all_clusters
39
+ else
40
+ connect_vault unless settings[:vault][:token].nil?
41
+ end
29
42
  start_lease_manager
30
43
  end
31
44
 
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.3
4
+ version: 1.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -78,13 +78,16 @@ files:
78
78
  - lib/legion/crypt/erasure.rb
79
79
  - lib/legion/crypt/jwks_client.rb
80
80
  - lib/legion/crypt/jwt.rb
81
+ - lib/legion/crypt/ldap_auth.rb
81
82
  - lib/legion/crypt/lease_manager.rb
82
83
  - lib/legion/crypt/mock_vault.rb
83
84
  - lib/legion/crypt/partition_keys.rb
84
85
  - lib/legion/crypt/settings.rb
85
86
  - lib/legion/crypt/tls.rb
86
87
  - lib/legion/crypt/vault.rb
88
+ - lib/legion/crypt/vault_cluster.rb
87
89
  - lib/legion/crypt/vault_jwt_auth.rb
90
+ - lib/legion/crypt/vault_kerberos_auth.rb
88
91
  - lib/legion/crypt/vault_renewer.rb
89
92
  - lib/legion/crypt/version.rb
90
93
  - sonar-project.properties