Client-Side Field Level Encryption
On this page
- Overview
- Install Dependencies
- libmongocrypt
- Shared Library (Driver v2.19 or later)
- mongocryptd (Driver v2.18 or earlier)
- ffi
- Create a Customer Master Key
- Configure your Client
- Create a Data Encryption Key
- Configure Encryption Schema
- Limitations
- Working with Data
- Rotate Encryption Keys
- Add Automatic Encryption to Existing Project
- Additional Information
Overview
In this guide, you can learn how to encrypt your data by using client-side field level encryption (CSFLE). CSFLE allows you to encrypt data in your application before sending it over the network to MongoDB. This means that no MongoDB product has access to your data in unencrypted form.
You can set up CSFLE by using one of the following mechanisms:
Automatic encryption: Allows you to perform encrypted read and write operations without specifying how to encrypt fields
Explicit encryption: Allows you to perform encrypted read and write operations with specified encryption logic throughout your application.
This guide describes how to set up CSFLE with automatic encryption. To learn more about using explicit encryption, see the Explicit Encryption guide in the Ruby driver documentation.
Install Dependencies
To use CSFLE with Mongoid, you must first install the following dependencies:
libmongocrypt
Automatic Encryption Shared Library if you are using Ruby driver v2.19 or later. Or
mongocryptd
if you are using Ruby driver v2.18 or earlier.ffi
The following sections provide details on how to install these dependencies.
libmongocrypt
You can install libmongocrypt
by adding the libmongocrypt-helper gem to your Gemfile
or by downloading the library manually.
To install libmongocrypt
by adding the gem file, navigate to the folder in
which your application is located and run the following command in your shell:
gem install libmongocrypt-helper --pre
Note
Because the version number of libmongocrypt-helper
might contain letters,
which indicates a pre-release version in Ruby, the --pre
flag is
required.
To learn how to download and install the library manually, see the libmongocrypt installation guide in the Ruby driver documentation.
Shared Library (Driver v2.19 or later)
The following steps detail how to install the Automatic Encryption Shared Library:
In a browser, navigate to the MongoDB Download Center.
Select the latest current version in the
Version
dropdown, denoted by the(current)
tag.Select your platform in the
Platform
dropdown.Select
crypt_shared
in thePackage
dropdown.Click the
Download
button to download the shared library.
After you download the file, extract the contents and save the
file in a location that your application can access. Then, configure your
mongoid.yml
file in your application to point to the library, as shown in
the following example:
development: clients: default: options: auto_encryption_options: extra_options: crypt_shared_lib_path: '<Path to Shared Library>'
mongocryptd (Driver v2.18 or earlier)
If you are using Ruby driver version 2.18 or earlier, you must use mongocryptd
instead of the Automatic Encryption Shared Library. mongocryptd
comes
pre-packaged with enterprise builds of MongoDB Server. For instructions on how to
install and configure mongocryptd
, see the Install mongocryptd guide in the MongoDB
Server manual.
ffi
Mongoid uses the ffi gem to call functions from
libmongocrypt
. Add the gem to your Gemfile
by running the following
command in your shell:
gem 'ffi'
Create a Customer Master Key
To encrypt and decrypt data, you must first create a Customer Master Key (CMK). A CMK is a key that you use to encrypt your Data Encryption Key (DEK). Without access to a CMK, your client application cannot decrypt DEKs associated with your encrypted data.
You can create a locally-stored key to use as a local CMK for testing purposes by running the following Ruby code:
require 'securerandom' SecureRandom.hex(48)
Warning
Using a local CMK in a production environment is insecure. For production environments, use a remote key management service to create and store your CMK.
To learn more about key management service providers, see the KMS Providers guide in the MongoDB Server manual.
Configure your Client
You must configure your MongoDB client to implement CSFLE. To configure a
client for CSFLE, add the following code to your mongoid.yml
file:
development: clients: default: uri: "<connection string>" options: auto_encryption_options: # This key enables automatic encryption key_vault_namespace: 'encryption.__keyVault' # Database and collection in which to store data keys kms_providers: # Tells the driver where to obtain master keys local: # Specifies that the key is local key: "<Path to your CMK>" extra_options: crypt_shared_lib_path: '<Path to Shared Library>' # Only required for Ruby versions 2.19 or later
Note
Ensure that you replace the placeholders surrounded by brackets (<>
) in the preceding code
example.
Create a Data Encryption Key
A Data Encryption Key (DEK) is a key that you use to encrypt the fields in your documents. MongoDB stores DEKs, encrypted with your CMK, in the Key Vault collection as BSON documents. MongoDB can never decrypt the DEKs, as key management is client-side and customer controlled.
To create a DEK in Mongoid, you can use the
db:mongoid:encryption:create_data_key
rake task, as shown in the following
example:
rake db:mongoid:encryption:create_data_key
You can create multiple DEKs by repeating the preceding command for the number of keys you want to generate.
You can also provide an alternate name for your DEK. This allows you to reference the DEK by name when configuring encryption for your fields and to dynamically assign a DEK to a field at runtime.
The following example creates an alternate name when generating a new DEK:
rake db:mongoid:encryption:create_data_key -- --key-alt-name=<custom DEK name>
Configure Encryption Schema
You can specify which fields to encrypt by adding the encrypt
option to the
field definition in your models and specifying the deterministic
and
key_id
options, as shown in the following example:
class Patient include Mongoid::Document include Mongoid::Timestamps encrypt_with key_id: '<data encryption key>' # This field is not encrypted field :category, type: String # This field is encrypted by using AEAD_AES_256_CBC_HMAC_SHA_512-Random # algorithm field :passport_id, type: String, encrypt: { deterministic: false } # This field is encrypted by using AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic # algorithm field :blood_type, type: String, encrypt: { deterministic: true } # This field is encrypted by using AEAD_AES_256_CBC_HMAC_SHA_512-Random # algorithm and a different data key field :ssn, type: Integer, encrypt: { deterministic: false, key_id: '<New key ID' } embeds_one :insurance end class Insurance include Mongoid::Document include Mongoid::Timestamps field :insurer, type: String # This field is encrypted using AEAD_AES_256_CBC_HMAC_SHA_512-Random # algorithm using a key with an alternate name stored in the policy_number_key field field :policy_number, type: Integer, encrypt: { deterministic: false, key_name_field: :policy_number_key } embedded_in :patient end
Note
If you are developing a Rails application, we recommend setting the
preload_models
option to true
in your mongoid.yml
file. This
ensures that Mongoid loads all models and configures the encryption schema
before any data is read or written.
Limitations
The following limitations apply when using CSFLE with Mongoid:
Mongoid does not support encryption of
embeds_many
associations.If you use the
:key_name_field
option, you must encrypt the field by using a non-deterministic algorithm. To encrypt your field deterministically, you must specify the:key_id
option instead.The limitations listed on the CSFLE Limitations page in the MongoDB Server manual also apply to Mongoid.
Working with Data
Usually, automatic CSLFE works transparently in your application. After your application is configured for CSFLE, you can create documents as usual and Mongoid automatically encrypts and decrypts them according to your configuration.
The following example creates a new Patient
document in an application
configured for CSFLE. It then uses a client called unencrypted_client
that
is connected to the database but not configured for CSFLE to read the document.
Patient.create!( category: 'ER', passport_id: '123456', blood_type: 'AB+', ssn: 98765, insurance: Insurance.new(insurer: 'TK', policy_number: 123456, policy_number_key: 'my_data_key') ) # Fields are encrypted in the database unencrypted_client['patients'].find.first
{"_id"=>BSON::ObjectId('6446a1d046ebfd701f9f4292'), "category"=>"ER", "passport_id"=><BSON::Binary:0x404080 type=ciphertext data=0x012889b2cb0b1341...>, "blood_type"=><BSON::Binary:0x404560 type=ciphertext data=0x022889b2cb0b1341...>, "ssn"=><BSON::Binary:0x405040 type=ciphertext data=0x012889b2cb0b1341...>, "insurance"=>{"_id"=>BSON::ObjectId('6446a1d046ebfd701f9f4293'), "insurer"=>"TK", "policy_number"=><BSON::Binary:0x405920 type=ciphertext data=0x012889b2cb0b1341...>}, "policy_number_key"=>"my_data_key"}
In the preceding example, the unencrypted_client
client is unable to read
the encrypted fields. However, if you query the document with a client that is
configured for CSFLE, Mongoid automatically decrypts the fields.
Rotate Encryption Keys
You can rotate your encryption keys by using the rewrap_many_data_key
Ruby driver
method. This method automatically decrypts multiple data encryption keys
and re-encrypts them using a specified CMK. It then updates the rotated keys in
the key vault collection.
The rewrap_many_data_key
method takes the following parameters:
Filter, used to specify which fields to rotate. If no data key matches the given filter, no keys will be rotated. Omit the filter to rotate all keys in your key vault collection.
Object that represents a new CMK with which to re-encrypt the DEKs. Omit this object to rotate the data keys by using their current CMKs.
The following example rotates encryption keys by using the AWS KMS:
# Create a key vault client key_vault_client = Mongo::Client.new('<connection string>') # Create the encryption object encryption = Mongo::ClientEncryption.new( key_vault_client, key_vault_namespace: 'encryption.__keyVault', kms_providers: { aws: { "accessKeyId": "<IAM User Access Key ID>", "secretAccessKey": "<IAM User Secret Access Key>" } } ) encryption.rewrap_many_data_key( {}, # Empty filter to rewrap all keys { provider: 'aws', master_key: { region: 'us-east-2', key: 'arn:aws:kms:us-east-2:...' } } )
Add Automatic Encryption to Existing Project
Automatic CSFLE with Mongoid supports encryption in place. You can enable encryption on an existing database and still read unencrypted data. However, once you enable encryption, all new data is encrypted, and any query operation uses only the encrypted documents. This means that queries might not return all documents if some were saved before enabling encryption.
The following example queries a collection that has one encrypted document and one unencrypted document:
# Print all documents in the collection. The first document is unencrypted, and # the second is encrypted. Patient.all.to_a # => # [#<Patient _id: 644937ac46ebfd02468e58c8, category: "ER", passport_id: "DE-1257", blood_type: "AB+", ssn: 123456>, # #<Patient _id: 644937c946ebfd029309b912, category: "ER", passport_id: "AT-1545", blood_type: "AB+", ssn: 987654>] # Querying for documents with a CSFLE-enabled client returns only the encrypted document Patient.where(blood_type: 'AB+').to_a # => [#<Patient _id: 644937c946ebfd029309b912, category: "ER", passport_id: "AT-1545", blood_type: "AB+", ssn: 987654>]
You can encrypt existing data in a collection by reading and then writing back
all data with a CSFLE-enabled client. When doing so, ensure that all existing
data is the expected type and that empty values are not set as nil
.
Additional Information
To learn more about CSFLE, see the Client-Side Field Level Encryption guide in the MongoDB Server manual.
To learn more about using CSFLE with the Ruby driver, see the Client-Side Encryption guide in the Ruby driver documentation.
To learn more about configuring Mongoid in your application, see the Application Configuration guide.