Class: Cucloud::KmsUtils

Inherits:
Object
  • Object
show all
Defined in:
lib/cucloud/kms_utils.rb

Overview

Utilities library for interacting with KMS.

Defined Under Namespace

Classes: MissingKmsKey

Constant Summary collapse

ENCRYPTED_SUFFIX =

This is used in a sttuct to denote an encrypted field

'_encrypted'.freeze
DECRYPTED_SUFFIX =

This is used in a sttuct to denote an decrypted field

'_decrypted'.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(kms_client = Aws::KMS::Client.new) ⇒ KmsUtils

Initialize the class optionally providing an existing Aws::KMS::Client



17
18
19
# File 'lib/cucloud/kms_utils.rb', line 17

def initialize(kms_client = Aws::KMS::Client.new)
  @kms = kms_client
end

Instance Attribute Details

#kms_key_idObject

Returns the value of attribute kms_key_id.



13
14
15
# File 'lib/cucloud/kms_utils.rb', line 13

def kms_key_id
  @kms_key_id
end

Instance Method Details

#decrypt(ciphertext) ⇒ String

Decrypt the given Base64-strict-encoded ciphertext.



24
25
26
27
28
# File 'lib/cucloud/kms_utils.rb', line 24

def decrypt(ciphertext)
  return nil if ciphertext.nil?
  return '' if ciphertext.empty?
  @kms.decrypt(ciphertext_blob: Base64.strict_decode64(ciphertext)).plaintext
end

#decrypt_struct(main_node) ⇒ Object

Process the given structure and decrypt the values of any attributes with names suffixed by "_encrypted". For each such encrypted atttribute-value pair, adds a new attribute with suffix "_decrypted" and value consisting of the plaintext (i.e. decrypted value) of the encrypted value.

Examples:

decrypt_struct({ x_encrypted: <encrypted_value> }) =>
  { x_encrypted: <encrypted_value>, x_decrypted: <plaintext> }
decrypt_struct([{ x_encrypted: <encrypted_value> } ]) =>
  [{ x_encrypted: <encrypted_value>, x_decrypted: <plaintext> }]


53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/cucloud/kms_utils.rb', line 53

def decrypt_struct(main_node)
  return nil if main_node.nil?
  return main_node if main_node.is_a?(String)
  if main_node.is_a?(Hash)
    new_hash = {}
    main_node.each_pair do |key, value|
      if key_to_decrypt?(key)
        plaintext = decrypt(value)
        new_hash[decrypted_key_label(key)] = plaintext
        new_hash[key] = value
      else
        result = decrypt_struct(value)
        new_hash[key] = result
      end
    end
    return new_hash
  elsif main_node.is_a?(Array)
    new_array = []
    main_node.each do |element|
      result = decrypt_struct(element)
      new_array << result
    end
    return new_array
  else
    return main_node
  end
end

#encrypt(plaintext, key_id = @kms_key_id) ⇒ String

Encrypt the given plaintext. Uses provided the KMS key provided, or the KMS key configured at initialization if none is provided.



35
36
37
38
39
# File 'lib/cucloud/kms_utils.rb', line 35

def encrypt(plaintext, key_id = @kms_key_id)
  return nil if plaintext.nil?
  return '' if plaintext.empty?
  Base64.strict_encode64(@kms.encrypt(key_id: key_id, plaintext: plaintext).ciphertext_blob)
end

#encrypt_struct(main_node, key_id = @kms_key_id) ⇒ Object

Process the given structure and encrypt the values of any attributes with names suffixed by "_decrypted". For each such plaintext atttribute-value pair, adds a new attribute with suffix "_encrypted" and value consisting of the encrypted value. The "_decrypted" atttribute-value pair is removed from the structure. Uses the provided the KMS key provided, or the KMS key configured at initialization if none is provided.

Examples:

encrypt_struct({ x_decrypted: <plaintext> }) =>
  { x_encrypted: <encrypted_value> }
encrypt_struct([{ x_decrypted: <plaintext> }]) =>
  [{ x_encrypted: <encrypted_value> }]


96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/cucloud/kms_utils.rb', line 96

def encrypt_struct(main_node, key_id = @kms_key_id)
  return nil if main_node.nil?
  if main_node.is_a?(Hash)
    new_hash = {}
    remove_keys = []
    main_node.each_pair do |key, value|
      if key_to_encrypt?(key)
        ciphertext = encrypt(value, key_id)
        new_hash[encrypted_key_label(key)] = ciphertext
        remove_keys << key
      else
        result = encrypt_struct(value, key_id)
        new_hash[key] = result
      end
    end
    main_node.merge!(new_hash)
    main_node.delete_if do |key, _|
      remove_keys.include?(key)
    end
    return main_node
  elsif main_node.is_a?(Array)
    main_node.map do |element|
      encrypt_struct(element, key_id)
    end
  else
    return main_node
  end
end