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

Parameters:

  • kms_client (Aws::KMS::Client) (defaults to: Aws::KMS::Client.new)

    optional



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.

Parameters:

  • ciphertext (String)

    encrypted and Base64 strict encoded string

Returns:

  • (String)

    decrypted string (i.e. plaintext)



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> }]

Parameters:

  • main_node

    the structure (Hash, Array) to decrypt

Returns:

  • a copy of the structure with additional atttribute-value pairs for the decrypted values



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.

Parameters:

  • plaintext (String)

    plaintext string to be encrypted

  • key_id (String) (defaults to: @kms_key_id)

    KMS key id to use for encryption (optional)

Returns:

  • (String)

    Encrypted and Base64 strict encoded ciphertext



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> }]

Parameters:

  • main_node

    the structure (Hash, Array) to encrypt_struct

  • key_id (String) (defaults to: @kms_key_id)

    KMS key id to use for encryption (optional)

Returns:

  • a copy of the structure with decrypted atttribute-value pairs replaced by encrypted atttribute-value pairs



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