Module: Jerakia::Encryption::Vault

Defined in:
lib/jerakia/encryption/vault.rb

Defined Under Namespace

Classes: AuthenticationError

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#approle_tokenObject (readonly)

Returns the value of attribute approle_token.



11
12
13
# File 'lib/jerakia/encryption/vault.rb', line 11

def approle_token
  @approle_token
end

#vault_ssl_certObject (readonly)

Returns the value of attribute vault_ssl_cert.



13
14
15
# File 'lib/jerakia/encryption/vault.rb', line 13

def vault_ssl_cert
  @vault_ssl_cert
end

#vault_ssl_keyObject (readonly)

Returns the value of attribute vault_ssl_key.



12
13
14
# File 'lib/jerakia/encryption/vault.rb', line 12

def vault_ssl_key
  @vault_ssl_key
end

Instance Method Details

#authenticateObject



84
85
86
87
88
# File 'lib/jerakia/encryption/vault.rb', line 84

def authenticate
  unless token_configured?
     if approle_token.nil?
  end
end

#configObject



19
20
21
22
23
24
25
26
27
28
# File 'lib/jerakia/encryption/vault.rb', line 19

def config
  {
    "vault_keyname" => "jerakia",
    "vault_addr" => "https://127.0.0.1:8200",
    "vault_use_ssl" => true,
    "vault_ssl_verify" => true,
    "vault_token" => ENV['VAULT_TOKEN'] || nil,
    "vault_api_version" => 1
 }.merge(self.class.config)
end

#decrypt(string) ⇒ Object



151
152
153
154
155
# File 'lib/jerakia/encryption/vault.rb', line 151

def decrypt(string)
  response = vault_post({ 'ciphertext' => string}, :decrypt)
  response_data=response['data']
  Base64.decode64(response_data['plaintext'])
end

#encrypt(plain) ⇒ Object



157
158
159
160
161
162
# File 'lib/jerakia/encryption/vault.rb', line 157

def encrypt(plain)
  encoded = Base64.encode64(plain)
  response = vault_post({ 'plaintext' => encoded}, :encrypt)
  response_data=response['data']
  response_data['ciphertext']
end

#endpoint(action) ⇒ Object



90
91
92
93
94
95
96
# File 'lib/jerakia/encryption/vault.rb', line 90

def endpoint(action)
  {
    :decrypt => "transit/decrypt/#{config['vault_keyname']}",
    :encrypt => "transit/encrypt/#{config['vault_keyname']}",
    :login   => "auth/approle/login"
  }[action]
end

#loginObject



40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/jerakia/encryption/vault.rb', line 40

def 
  Jerakia.log.debug('Requesting new token from Vault server')
  role_id = config['vault_role_id']
  secret_id = config['vault_secret_id']

   = { "role_id" => role_id }
  ['secret_id'] = secret_id unless secret_id.nil?

  response = vault_post(, :login, false)
  @approle_token = response['auth']['client_token']
  Jerakia.log.debug("Recieved authentication token from vault server, ttl: #{response['auth']['lease_duration']}")
end

#parse_response(response) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/jerakia/encryption/vault.rb', line 104

def parse_response(response)
  body = JSON.load(response.body)
  if response.code_type == Net::HTTPOK
    return body
  else
    if response.code == "403"
      raise Jerakia::Encryption::Vault::AuthenticationError, body
    end
    if body['errors'].is_a?(Array)
      message = body['errors'].join("\n")
    else
      message = "Failed to decrypt entry #{body}"
    end
    raise Jerakia::EncryptionError, "Error decrypting data from Vault: #{message}"
  end
end

#read_file(file) ⇒ Object



57
58
59
60
# File 'lib/jerakia/encryption/vault.rb', line 57

def read_file(file)
  raise Jerakia::EncryptionError, "Cannot read #{file}" unless File.exists?(file)
  File.read(file)
end

#signitureObject



15
16
17
# File 'lib/jerakia/encryption/vault.rb', line 15

def signiture
  /^vault:v[0-9]:[^ ]+$/
end

#ssl?Boolean

Returns:

  • (Boolean)


53
54
55
# File 'lib/jerakia/encryption/vault.rb', line 53

def ssl?
  config['vault_use_ssl']
end

#ssl_certObject



68
69
70
71
72
# File 'lib/jerakia/encryption/vault.rb', line 68

def ssl_cert
  return nil if config['vault_ssl_cert'].nil?
  @vault_ssl_cert ||= read_file(config['vault_ssl_cert'])
  vault_ssl_cert
end

#ssl_keyObject



62
63
64
65
66
# File 'lib/jerakia/encryption/vault.rb', line 62

def ssl_key
  return nil if config['vault_ssl_key'].nil?
  @vault_ssl_key ||= read_file(config['vault_ssl_key'])
  vault_ssl_key
end

#tokenObject



79
80
81
82
# File 'lib/jerakia/encryption/vault.rb', line 79

def token
  authenticate
  config['vault_token'] || approle_token
end

#token_configured?Boolean

Returns:

  • (Boolean)


75
76
77
# File 'lib/jerakia/encryption/vault.rb', line 75

def token_configured?
  not config['vault_token'].nil?
end

#url_path(action) ⇒ Object



98
99
100
# File 'lib/jerakia/encryption/vault.rb', line 98

def url_path(action)
  vault_url(endpoint(action))
end

#vault_post(data, action, use_token = true, headers = {}) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/jerakia/encryption/vault.rb', line 121

def vault_post(data, action, use_token=true, headers={})
  url = url_path(action)
  http_options = {}

  if ssl?
    http_options = {
      :ssl        => true,
      :ssl_verify => config['vault_ssl_verify'],
      :ssl_cert   => ssl_cert,
      :ssl_key    => ssl_key,
    }
  end

  Jerakia.log.debug("Connecting to vault at #{url}")
  tries = 0
  begin
    headers['X-Vault-Token'] = token if use_token
    tries += 1
    parse_response Jerakia::Util::Http.post(url, data, headers, http_options)
  rescue Jerakia::Encryption::Vault::AuthenticationError => e
    Jerakia.log.debug("Encountered Jerakia::Encryption::Vault::AuthenticationError, retrying with new token (#{tries})")

    
    retry if tries < 2
    raise
  rescue Jerakia::HTTPError => e
    raise Jerakia::EncryptionError, "Error connecting to Vault service: #{e.message}"
  end
end

#vault_url(endpoint) ⇒ Object



32
33
34
35
36
37
38
# File 'lib/jerakia/encryption/vault.rb', line 32

def vault_url(endpoint)
  uri = []
  uri << config['vault_addr']
  uri << "v#{config['vault_api_version']}"
  uri << endpoint
  uri.flatten.join("/")
end