Module: Legion::Crypt::ClusterSecret

Included in:
Cipher
Defined in:
lib/legion/crypt/cluster_secret.rb

Instance Method Summary collapse

Instance Method Details

#cluster_secret_timeoutObject



97
98
99
# File 'lib/legion/crypt/cluster_secret.rb', line 97

def cluster_secret_timeout
  Legion::Settings[:crypt][:cluster_secret_timeout] || 5
end

#csObject



109
110
111
112
113
114
# File 'lib/legion/crypt/cluster_secret.rb', line 109

def cs
  @cs ||= Digest::SHA256.digest(find_cluster_secret)
rescue StandardError => e
  Legion::Logging.error e.message
  Legion::Logging.error e.backtrace[0..10]
end

#find_cluster_secretObject



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/legion/crypt/cluster_secret.rb', line 6

def find_cluster_secret
  %i[from_settings from_vault from_transport generate_secure_random].each do |method|
    result = send(method)
    next if result.nil?

    unless validate_hex(result)
      Legion::Logging.warn("Legion::Crypt.#{method} gave a value but it isn't a valid hex")
      next
    end

    set_cluster_secret(result, method != :from_vault)
    return result
  end
  return unless only_member?

  key = generate_secure_random
  set_cluster_secret(key)
  key
end

#force_cluster_secretObject



67
68
69
# File 'lib/legion/crypt/cluster_secret.rb', line 67

def force_cluster_secret
  Legion::Settings[:crypt][:force_cluster_secret] || true
end

#from_settingsObject Also known as: cluster_secret



37
38
39
# File 'lib/legion/crypt/cluster_secret.rb', line 37

def from_settings
  Legion::Settings[:crypt][:cluster_secret]
end

#from_transportObject

rubocop:disable Metrics/AbcSize



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/legion/crypt/cluster_secret.rb', line 42

def from_transport # rubocop:disable Metrics/AbcSize
  return nil unless Legion::Settings[:transport][:connected]

  require 'legion/transport/messages/request_cluster_secret'
  Legion::Logging.info 'Requesting cluster secret via public key'
  Legion::Logging.warn 'cluster_secret already set but we are requesting a new value' unless from_settings.nil?
  start = Time.now
  Legion::Transport::Messages::RequestClusterSecret.new.publish
  sleep_time = 0.001
  until !Legion::Settings[:crypt][:cluster_secret].nil? || (Time.now - start) > cluster_secret_timeout
    sleep(sleep_time)
    sleep_time *= 2 unless sleep_time > 0.5
  end

  unless from_settings.nil?
    Legion::Logging.info "Received cluster secret in #{((Time.new - start) * 1000.0).round}ms"
    from_settings
  end

  Legion::Logging.error 'Cluster secret is still unknown!'
rescue StandardError => e
  Legion::Logging.error e.message
  Legion::Logging.error e.backtrace[0..10]
end

#from_vaultObject



26
27
28
29
30
31
32
33
34
35
# File 'lib/legion/crypt/cluster_secret.rb', line 26

def from_vault
  return nil unless method_defined? :get
  return nil unless Legion::Settings[:crypt][:vault][:read_cluster_secret]
  return nil unless Legion::Settings[:crypt][:vault][:connected]
  return nil unless Legion::Crypt.exist?('crypt')

  get('crypt')[:cluster_secret]
rescue StandardError
  nil
end

#generate_secure_random(length = secret_length) ⇒ Object



105
106
107
# File 'lib/legion/crypt/cluster_secret.rb', line 105

def generate_secure_random(length = secret_length)
  SecureRandom.hex(length)
end

#only_member?Boolean

Returns:

  • (Boolean)


75
76
77
78
79
# File 'lib/legion/crypt/cluster_secret.rb', line 75

def only_member?
  Legion::Transport::Queue.new('node.crypt', passive: true).consumer_count.zero?
rescue StandardError
  nil
end

#push_cs_to_vaultObject



90
91
92
93
94
95
# File 'lib/legion/crypt/cluster_secret.rb', line 90

def push_cs_to_vault
  return false unless Legion::Settings[:crypt][:vault][:connected] && Legion::Settings[:crypt][:cluster_secret]

  Legion::Logging.info 'Pushing Cluster Secret to Vault'
  Legion::Crypt.write('cluster', secret: Legion::Settings[:crypt][:cluster_secret])
end

#secret_lengthObject



101
102
103
# File 'lib/legion/crypt/cluster_secret.rb', line 101

def secret_length
  Legion::Settings[:crypt][:cluster_lenth] || 32
end

#set_cluster_secret(value, push_to_vault = true) ⇒ Object

rubocop:disable Style/OptionalBooleanParameter

Raises:

  • (TypeError)


81
82
83
84
85
86
87
88
# File 'lib/legion/crypt/cluster_secret.rb', line 81

def set_cluster_secret(value, push_to_vault = true) # rubocop:disable Style/OptionalBooleanParameter
  raise TypeError unless value.to_i(32).to_s(32) == value.downcase

  Legion::Settings[:crypt][:cs_encrypt_ready] = true
  push_cs_to_vault if push_to_vault && settings_push_vault

  Legion::Settings[:crypt][:cluster_secret] = value
end

#settings_push_vaultObject



71
72
73
# File 'lib/legion/crypt/cluster_secret.rb', line 71

def settings_push_vault
  Legion::Settings[:crypt][:vault][:push_cs_to_vault] || true
end

#validate_hex(value, length = secret_length) ⇒ Object



116
117
118
# File 'lib/legion/crypt/cluster_secret.rb', line 116

def validate_hex(value, length = secret_length)
  value.to_i(length).to_s(length) == value.downcase
end