In this post, we’ll look at MongoDB data at rest encryption using eCryptFS, and how to deploy a MongoDB server using encrypted data files.
When dealing with data, a good security policy should enforce the use of “no trivial” passwords, the use of encrypted connections and hopefully encrypted files on the disks.
Only the MongoDB Enterprise edition has an “engine encryption” feature. The Community edition and Percona Server for MongoDB don’t (yet). This is why I’m going to introduce a useful way to achieve data encryption at rest for MongoDB, using a simple but effective tool: eCryptFS.
eCryptFS is an enterprise-class stacked cryptographic filesystem for Linux. You can use it to encrypt partitions or even any folder that doesn’t use a partition of its own, no matter the underlying filesystem or partition type. For more information about this too, visit the official website: http://ecryptfs.org/.
I’m using Ubuntu 16.04 and I have Percona Server for MongoDB already installed on the system. The data directory (dbpath) is in /var/lib/mongodb.
Preparation of the encrypted directory
First, let’s stop mongod if it’s running:
sudo service mongod stop
sudo apt-get install ecryptfs-utils
Create two new directories:
sudo mkdir /datastore sudo mkdir /var/lib/mongodb-encrypted
We’ll use the /datastore directory as the folder where we copy all the mongo’s files, and have them automatically encrypted. It’s also useful to test later that everything is working correctly. The folder /var/lib/mongodb_encrypted is the mount point we’ll use as the new data directory for mongod.
Mount the encrypted directory
Now it’s time to use eCryptFS to mount the /datastore folder and define it as encrypted. Launch the command as follows, choose a passphrase and respond to all the questions with the default proposed value. In a real case, choose the answers that best fit for you, and a complex passphrase:
root@psmdb1:~# sudo mount -t ecryptfs /datastore /var/lib/mongo-encrypted Passphrase: Select cipher: 1) aes: blocksize = 16; min keysize = 16; max keysize = 32 2) blowfish: blocksize = 8; min keysize = 16; max keysize = 56 3) des3_ede: blocksize = 8; min keysize = 24; max keysize = 24 4) twofish: blocksize = 16; min keysize = 16; max keysize = 32 5) cast6: blocksize = 16; min keysize = 16; max keysize = 32 6) cast5: blocksize = 8; min keysize = 5; max keysize = 16 Selection [aes]: Select key bytes: 1) 16 2) 32 3) 24 Selection : Enable plaintext passthrough (y/n) [n]: Enable filename encryption (y/n) [n]: Attempting to mount with the following options: ecryptfs_unlink_sigs ecryptfs_key_bytes=16 ecryptfs_cipher=aes ecryptfs_sig=f946e4b85fd84010 Mounted eCryptfs
If you see Mounted eCryptfs as the last line, everything went well. Now you have the folder /datastore encrypted. Any file you create or copy into this folder is automatically encrypted by eCryptFS. Also, you have mounted the encrypted folder into the path /var/lib/mongo-encrypted.
For the sake of security, you can verify with the mount command that the directory is correctly mounted. You should see something similar to the following:
root@psmdb1:~# sudo mount | grep crypt /datastore on /var/lib/mongo-encrypted type ecryptfs (rw,relatime,ecryptfs_sig=f946e4b85fd84010,ecryptfs_cipher=aes,ecryptfs_key_bytes=16,ecryptfs_unlink_sigs)
Copy mongo files
sudo cp -r /var/lib/mongodb/* /var/lib/mongo-encrypted
We copy all the files from the existent mongo’s data directory into the new path.
Since we are working as root (or we used sudo -s at the beginning), we need to change the ownership of the files to the mongod user, the default user for the database server. Otherwise, mongod won’t start:
sudo chown -R mongod:mongod /var/lib/mongo-encrypted/
Modify mongo configuration
Before starting mongod, we have to change the configuration into /etc/mongod.conf to instruct the server to use the new folder. So, change the line with dbpath as follow and save the file:
Launch mongod and verify
So, it’s time to start mongod, connect with the mongo shell and verify that it’s working as usual:
root@psmdb1:~# sudo service mongod start
The server works correctly and is unaware of the encrypted files because eCryptFS itself takes care of encryption and decryption activities at a lower level. There’s a little price to pay in terms of performance, as in every system that uses encryption, but we won’t worry about that since our first goal is security. In any case, eCryptFS has some small footprint.
Now, let’s verify the files directly.
Since the encrypted folder is mounted and automatically managed by eCryptFS, we can see the content of the files. Let’s have a look:
root@psmdb1:~# cat /var/lib/mongo-encrypted/mongod.lock 6965
But if we look at the same file into /datastore, we see weird characters:
root@psmdb1:~# cat /datastore/mongod.lock �0���k�"3DUfw`�Pp�Ku�����b�_CONSOLE�F�_�@��[�'�b��^�җfZ�7
Make encrypted dbpath persistent
Finally, if you want to automatically mount the encrypted directory at startup, add the following line into /etc/fstab:
/datastore /var/lib/mongo-encrypted ecryptfs defaults 0 0
Create the file .ecryptfsrc into /root directory with the following lines:
key=passphrase:passphrase_passwd_file=/root/passphrase.txt ecryptfs_sig=f946e4b85fd84010 ecryptfs_cipher=aes ecryptfs_key_bytes=16 ecryptfs_passthrough=n ecryptfs_enable_filename_crypto=n
You can find the value of the variable ecryptfs_sig in the file /root/.ecryptfs/sig-cache.txt.
Create the file /root/passphrase.txt containing your secret passphrase. The format is as follows:
Now you can reboot the system and have the encrypted directory mounted at startup.
Tip: it is not a good idea to have a plain text file on your server with our passphrase. To have a better security level, you can place this file into a USB key (for example) that you can mount at startup, or you can use some sort of wallet tool to protect your passphrase.
Security is more and more a “must have” that customers are requesting of anyone managing their data. This how-to guide shows that achieving MongoDB data at rest encryption success is not so complicated.