Encryption configuration
You must use this configuration only if you want to use Client Side Field Level Encryption (CSFLE) provided by MongoDB.
Starting with version 4.4.0
, the crud-service
has introduced the support for the Client Side Field Level Encryption (CSFLE).
Be careful, CSFLE is a Mongo Enterprise feature, and requires at least MongoDB version 4.2.
With CSFLE, the CRUD Service can encrypt fields in documents before transmitting the data to Mongo: this allows to store on database already encrypted data and can be used to obfuscate sensible data.
CSFLE must not be used to store passwords.
The keys and the data are stored in different collections and can even be stored in different databases: only with access to the correct encryption keys it's possible to decrypt and read the protected data.
For some data types (Number
, String
, Date
and ObjectId
) it is also possible to guarantee their searchability even if encrypted.
Not all MongoDB operators are supported for encrypted fields. Take a look to the official documentation for more details.
Keys relations
The Key Management Service (KMS) is the system responsible to manage the master key, a specific key used to generate the data encryption key. The data encryption key is stored in a dedicated collection of the MongoDB instance and is used to perform the encryption and decryption of the data.
There is one data encryption key for each collection that has at least on encrypted field.
Deleting an encryption key renders all data inside a collection encrypted using that key permanently unreadable, as it won't be possible to decrypt them anymore.
Configuration
In order to guarantee a correct data encryption, it is necessary to configure a Key Management Service.
Currently, we support two different KMS: Local
and Google Cloud Key Management (available from Google Cloud Platform).
To configure the CRUD Service in order to enable CSFLE it is necessary to add some environment variables to the configuration. To add the environment variables, please refer to the dedicated section.
Configure CSFLE with the Google Cloud Platform (GCP)
Keep in mind that a KMS provided by GCP has additional costs. Take a look at the official documentation to find out the cost and the related billing logic.
In order to configure the encryption using the Google KMS, you need the KMS service account json configuration and the KMS endpoint.
And here is an example of the KMS endpoint:
projects/{project_id}/locations/{location}/keyRings/{keyRingName}/cryptoKeys/{keyName}
With these configurations at hand, you can now configure the environment variables for the CRUD Service:
- KMS_PROVIDER (enum:
gcp
): the Key Management Service will be hosted by Google Cloud Platform. - KMS_GCP_EMAIL: service account e-mail of the KMS.
It corresponds to theclient_email
in the KMS service account json configuration. - KMS_GCP_PROJECT_ID: GCP project id in which is configured the KMS.
It corresponds to theproject_id
in the KMS service account json configuration - KMS_GCP_LOCATION: Location in which the KMS is running.
It corresponds to thelocation
in the KMS endpoint.
Example: if the endpoint is projects/:projectId/locations/:location/keyRings/:keyRing/cryptoKeys/:cryptoKey
, you must enter as the value of the variable :location
.
- KMS_GCP_KEY_RING: GCP keyring used by the KMS.
It corresponds to thekeyRingName
in the KMS endpoint.
Example: if the endpoint is projects/:projectId/locations/:location/keyRings/:keyRing/cryptoKeys/:cryptoKey
, you must enter as the value of the variable :keyRing
.
- KMS_GCP_KEY_NAME: GCP key name.
It corresponds to thekeyName
in the KMS endpoint.
Example: if the endpoint is projects/:projectId/locations/:location/keyRings/:keyRing/cryptoKeys/:cryptoKey
, you must enter as the value of the variable :cryptoKey
- KMS_GCP_PRIVATE_KEY_PATH: Path in which is stored the private key, on the console you must mount it as
ConfigMap
.
The content of this private key corresponds to the formattedprivate_key
in the KMS service account json configuration. - KEY_VAULT_NAMESPACE: where the key used for the collection encryption will be stored. The required format is
{databaseName}.{collectionName}
.
Example: if the database name is qqq
and the collection name is www
, you must enter as the value of the variable qqq.www
.
If in the KEY_VAULT_NAMESPACE
you choose to store the encryption keys in a different database, be sure to have the rights to create it.
Configure CSFLE with Local Key
In order to configure the encryption using the Local KMS it's necessary to add these new variables:
The local
KMS is not recommended for production.
- KMS_PROVIDER (enum:
local
): the key is managed using a local master key. - LOCAL_MASTER_KEY_PATH: Path in which is stored the master key, on the console you must mount it as
ConfigMap
. To generate it, please read the following guide. - KEY_VAULT_NAMESPACE: where the key used for the collection encryption will be stored. The required format is
{databaseName}.{collectionName}
.
If in the KEY_VAULT_NAMESPACE
you choose to store the encryption keys in a different database, be sure to have the rights to create it.
Local master key generation
The local master key must have the exact size of 96 bytes.
You can generate it randomly with a NodeJS
script or with a shell command.
Alternatively, you can create your own string of length 96 characters.
How to generate a local master key using NodeJS
const fs = require('fs')
const characters ='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
function generateString(length) {
let result = ''
const charactersLength = characters.length
for ( let i = 0; i < length; i++ ) {
result += characters.charAt(Math.floor(Math.random() * charactersLength))
}
return result
}
try {
fs.writeFileSync('YOUR_KEY_PATH', generateString(96))
} catch (err) {
console.error(err)
}
How to generate a local master key using Shell Command
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 96 | head -n 1 > YOUR_KEY_PATH
Migration and change of the configurations
If you decide to enable or disable the encryption from already existing field, you must manage manually the encryption or decryption of its values in order to keep your application correctly up and running.
We suggest activating the encryption only for new fields.
Nested objects
Is possible to encrypt not only plain field, but also objects and its content; however, doing this we have some limitations:
- objects are encryptable but not searchable while encrypted
- to encrypt an object, all its properties must not be encrypted
Activate object encryption
In order to activate the object encryption, you must insert the encryption
object in your JSON schema, at same level of the properties
or type
key.
For example, if you have the following schema:
{
"type": "object",
"properties": {
"testProperty": {
"type": "string"
}
}
}
And you want to activate the encryption for the entire object (that is not searchable), you must add:
"encryption": {"enabled": true, "searchable": false}
So your final schema will be:
{
"type": "object",
"properties": {
"testProperty": {
"type": "string"
}
},
"encryption": {"enabled": true, "searchable": false}
}
While if you want to activate the encryption only for the property testProperty
, and make it searchable, you must add:
"encryption": {"enabled": true, "searchable": true}
inside the property definition.
So your final schema will be:
{
"type": "object",
"properties": {
"testProperty": {
"type": "string",
"encryption": {"enabled": true, "searchable": true}
}
}
}