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 +4 -4
- data/CHANGELOG.md +10 -0
- data/lib/legion/crypt/ldap_auth.rb +33 -0
- data/lib/legion/crypt/settings.rb +3 -1
- data/lib/legion/crypt/vault.rb +15 -2
- data/lib/legion/crypt/vault_cluster.rb +76 -0
- data/lib/legion/crypt/vault_kerberos_auth.rb +43 -0
- data/lib/legion/crypt/version.rb +1 -1
- data/lib/legion/crypt.rb +14 -1
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5999b5f3ac22f39690f9ee509cec95793e39619498615c6c92c28a509561d072
|
|
4
|
+
data.tar.gz: 942363ac4938f2f9f36436054d42be8202c16d81dfdfd9d5e66ed52763299fe4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
data/lib/legion/crypt/vault.rb
CHANGED
|
@@ -83,8 +83,21 @@ module Legion
|
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
def renew_sessions(**_opts)
|
|
86
|
-
|
|
87
|
-
|
|
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
|
data/lib/legion/crypt/version.rb
CHANGED
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
|
-
|
|
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.
|
|
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
|