Class: Mongo::ClientEncryption

Inherits:
Object
  • Object
show all
Defined in:
lib/mongo/client_encryption.rb

Overview

ClientEncryption encapsulates explicit operations on a key vault collection that cannot be done directly on a MongoClient. It provides an API for explicitly encrypting and decrypting values, and creating data keys.

Instance Method Summary collapse

Constructor Details

#initialize(key_vault_client, options = {}) ⇒ ClientEncryption

Create a new ClientEncryption object with the provided options.

Options Hash (options):

  • :key_vault_namespace (String)

    The name of the key vault collection in the format "database.collection".

  • :kms_providers (Hash)

    A hash of key management service configuration information. @see Mongo::Crypt::KMS::Credentials for list of options for every supported provider. @note There may be more than one KMS provider specified.

  • :kms_tls_options (Hash)

    TLS options to connect to KMS providers. Keys of the hash should be KSM provider names; values should be hashes of TLS connection options. The options are equivalent to TLS connection options of Mongo::Client. @see Mongo::Client#initialize for list of TLS options.

  • :timeout_ms (Integer)

    The operation timeout in milliseconds. Must be a non-negative integer. An explicit value of 0 means infinite. The default value is unset which means the feature is disabled.

  • :key_expiration_ms (Integer)

    The lifetime of the data encryption key cache, in milliseconds. Must be a non-negative integer. An explicit value of 0 means the cache never expires. The default is 60000.

Raises:

  • (ArgumentError)

    If required options are missing or incorrectly formatted.



52
53
54
55
56
57
58
59
60
61
# File 'lib/mongo/client_encryption.rb', line 52

def initialize(key_vault_client, options = {})
  @encrypter = Crypt::ExplicitEncrypter.new(
    key_vault_client,
    options[:key_vault_namespace],
    Crypt::KMS::Credentials.new(options[:kms_providers]),
    Crypt::KMS::Validations.validate_tls_options(options[:kms_tls_options]),
    options[:timeout_ms],
    options[:key_expiration_ms]
  )
end

Instance Method Details

#add_key_alt_name(id, key_alt_name) ⇒ BSON::Document | nil

Adds a key_alt_name for the key in the key vault collection with the given id.



207
208
209
# File 'lib/mongo/client_encryption.rb', line 207

def add_key_alt_name(id, key_alt_name)
  @encrypter.add_key_alt_name(id, key_alt_name)
end

#create_data_key(kms_provider, options = {}) ⇒ BSON::Binary

Generates a data key used for encryption/decryption and stores that key in the KMS collection. The generated key is encrypted with the KMS master key.

Options Hash (options):

  • :master_key (Hash)

    Information about the AWS master key. Required if kms_provider is "aws".

    • :region [ String ] The The AWS region of the master key (required).
    • :key [ String ] The Amazon Resource Name (ARN) of the master key (required).
    • :endpoint [ String ] An alternate host to send KMS requests to (optional). endpoint should be a host name with an optional port number separated by a colon (e.g. "kms.us-east-1.amazonaws.com" or "kms.us-east-1.amazonaws.com:443"). An endpoint in any other format will not be properly parsed.
  • :key_alt_names (Array<String>)

    An optional array of strings specifying alternate names for the new data key.

  • :key_material (String | nil)

    Optional 96 bytes to use as custom key material for the data key being created. If :key_material option is given, the custom key material is used for encrypting and decrypting data.



89
90
91
92
93
94
95
# File 'lib/mongo/client_encryption.rb', line 89

def create_data_key(kms_provider, options = {})
  key_document = Crypt::KMS::MasterKeyDocument.new(kms_provider, options)

  key_alt_names = options[:key_alt_names]
  key_material = options[:key_material]
  @encrypter.create_and_insert_data_key(key_document, key_alt_names, key_material)
end

#create_encrypted_collection(database, coll_name, coll_opts, kms_provider, master_key) ⇒ Array<Operation::Result, Hash>

Note:

This method does not update the :encrypted_fields_map in the client's :auto_encryption_options. Therefore, in order to use the collection created by this method with automatic encryption, the user must create a new client after calling this function with the :encrypted_fields returned.

Create collection with encrypted fields.

If :encryption_fields contains a keyId with a null value, a data key will be automatically generated and assigned to keyId value.

Raises:

  • (ArgumentError)


294
295
296
297
298
299
300
301
302
303
304
305
# File 'lib/mongo/client_encryption.rb', line 294

def create_encrypted_collection(database, coll_name, coll_opts, kms_provider, master_key)
  raise ArgumentError, 'coll_opts must contain :encrypted_fields' unless coll_opts[:encrypted_fields]

  encrypted_fields = create_data_keys(coll_opts[:encrypted_fields], kms_provider, master_key)
  begin
    new_coll_opts = coll_opts.dup.merge(encrypted_fields: encrypted_fields)
    [ database[coll_name].create(new_coll_opts), encrypted_fields ]
  rescue Mongo::Error => e
    raise Error::CryptError, "Error creating collection with encrypted fields \
          #{encrypted_fields}: #{e.class}: #{e.message}"
  end
end

#decrypt(value) ⇒ Object

Decrypts a value that has already been encrypted.



196
197
198
# File 'lib/mongo/client_encryption.rb', line 196

def decrypt(value)
  @encrypter.decrypt(value)
end

#delete_key(id) ⇒ Operation::Result

Removes the key with the given id from the key vault collection.



217
218
219
# File 'lib/mongo/client_encryption.rb', line 217

def delete_key(id)
  @encrypter.delete_key(id)
end

#encrypt(value, options = {}) ⇒ BSON::Binary

Note:

The result of explicit encryption with the "Indexed", "Range", or "String" algorithm must be processed by the server to insert or query. To insert or query with such a payload, use a Mongo::Client configured with :auto_encryption_options. The :bypass_query_analysis option may be true; the :bypass_auto_encryption option must be false.

Note:

The "substring" query type is unstable and subject to backwards breaking changes.

Note:

The :key_id and :key_alt_name options are mutually exclusive. Only one is required to perform explicit encryption.

Encrypts a value using the specified encryption key and algorithm.

Options Hash (options):

  • :key_id (BSON::Binary)

    A BSON::Binary object of type :uuid representing the UUID of the encryption key as it is stored in the key vault collection.

  • :key_alt_name (String)

    The alternate name for the encryption key.

  • :algorithm (String)

    The algorithm used to encrypt the value. Valid algorithms are "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "Indexed", "Unindexed", "Range", "String".

  • :contention_factor (Integer | nil)

    Contention factor to be applied if encryption algorithm is set to "Indexed", "Range", or "String". If not provided, it defaults to a value of 0. Contention factor should be set only if encryption algorithm is set to "Indexed", "Range", or "String".

  • query_type (String | nil)

    Query type to be applied if encryption algorithm is set to "Indexed", "Range", or "String". Allowed values are "equality" (for "Indexed"), "range" (for "Range"), and "prefix", "suffix", "substring" (for "String").

  • :range_opts (Hash | nil)

    Specifies index options for a Queryable Encryption field supporting "range" queries. Required when algorithm is "Range". Allowed options are :min, :max, :trim_factor, :sparsity, :precision.

  • :string_opts (Hash | nil)

    Specifies index options for a Queryable Encryption field supporting "prefix", "suffix", or "substring" queries. Required when algorithm is "String". Allowed options are :case_sensitive, :diacritic_sensitive, :prefix, :suffix, :substring.

Raises:

  • (ArgumentError)

    if either contention_factor or query_type is set, and algorithm is not "Indexed", "Range", or "String".



146
147
148
# File 'lib/mongo/client_encryption.rb', line 146

def encrypt(value, options = {})
  @encrypter.encrypt(value, options)
end

#encrypt_expression(expression, options = {}) ⇒ BSON::Binary

Note:

The :key_id and :key_alt_name options are mutually exclusive. Only one is required to perform explicit encryption.

Encrypts a Match Expression or Aggregate Expression to query a range index.

Only supported when queryType is "range" and algorithm is "Range". @note: The Range algorithm is experimental only. It is not intended for public use. It is subject to breaking changes.

@param [ Hash ] options

Examples:

Encrypt Match Expression.

encryption.encrypt_expression(
  {'$and' =>  [{'field' => {'$gt' => 10}}, {'field' =>  {'$lt' => 20 }}]}
)

Encrypt Aggregate Expression.

encryption.encrypt_expression(
  {'$and' =>  [{'$gt' => ['$field', 10]}, {'$lt' => ['$field', 20]}}
)
{$and: [{$gt: [<fieldpath>, <value1>]}, {$lt: [<fieldpath>, <value2>]}]

Options Hash (options):

  • :key_id (BSON::Binary)

    A BSON::Binary object of type :uuid representing the UUID of the encryption key as it is stored in the key vault collection.

  • :key_alt_name (String)

    The alternate name for the encryption key.

  • :algorithm (String)

    The algorithm used to encrypt the expression. The only allowed value is "Range"

  • :contention_factor (Integer | nil)

    Contention factor to be applied If not provided, it defaults to a value of 0.

  • :query_type (String | nil)

    Query type to be applied. The only allowed value is "range".

Raises:

  • (ArgumentError)

    if disallowed values in options are set.



186
187
188
# File 'lib/mongo/client_encryption.rb', line 186

def encrypt_expression(expression, options = {})
  @encrypter.encrypt_expression(expression, options)
end

#get_key(id) ⇒ BSON::Document | nil

Finds a single key with the given id.



227
228
229
# File 'lib/mongo/client_encryption.rb', line 227

def get_key(id)
  @encrypter.get_key(id)
end

#get_key_by_alt_name(key_alt_name) ⇒ BSON::Document | nil

Returns a key in the key vault collection with the given key_alt_name.



237
238
239
# File 'lib/mongo/client_encryption.rb', line 237

def get_key_by_alt_name(key_alt_name)
  @encrypter.get_key_by_alt_name(key_alt_name)
end

#get_keysCollection::View Also known as: keys

Returns all keys in the key vault collection.



244
245
246
# File 'lib/mongo/client_encryption.rb', line 244

def get_keys
  @encrypter.get_keys
end

#remove_key_alt_name(id, key_alt_name) ⇒ BSON::Document | nil

Removes a key_alt_name from a key in the key vault collection with the given id.



256
257
258
# File 'lib/mongo/client_encryption.rb', line 256

def remove_key_alt_name(id, key_alt_name)
  @encrypter.remove_key_alt_name(id, key_alt_name)
end

#rewrap_many_data_key(filter, opts = {}) ⇒ Crypt::RewrapManyDataKeyResult

Decrypts multiple data keys and (re-)encrypts them with a new master_key, or with their current master_key if a new one is not given.



271
272
273
# File 'lib/mongo/client_encryption.rb', line 271

def rewrap_many_data_key(filter, opts = {})
  @encrypter.rewrap_many_data_key(filter, opts)
end