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:
1 | sudo service mongod stop |
Install eCryptFS:
1 | sudo apt-get install ecryptfs-utils |
Create two new directories:
1 2 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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 [16]: 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:
1 2 | 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
1 | 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:
1 | 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:
1 | dbpath=/var/lib/mongo-encrypted |
Launch mongod and verify
So, it’s time to start mongod, connect with the mongo shell and verify that it’s working as usual:
1 | 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:
1 2 | root@psmdb1:~# cat /var/lib/mongo-encrypted/mongod.lock 6965 |
But if we look at the same file into /datastore, we see weird characters:
1 2 | root@psmdb1:~# cat /datastore/mongod.lock �0���k�"3DUfw`�Pp�Ku�����b�_CONSOLE�F�_�@��[�'�b��^�җfZ�7 |
As expected.
Make encrypted dbpath persistent
Finally, if you want to automatically mount the encrypted directory at startup, add the following line into /etc/fstab:
1 | /datastore /var/lib/mongo-encrypted ecryptfs defaults 0 0 |
Create the file .ecryptfsrc into /root directory with the following lines:
1 2 3 4 5 6 | 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:
1 | passphrase_passwd=mypassphrase |
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.
Conclusion
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.
Comments (5)
But isn’t anyone having access to machine can see non-encrypted /var/lib/mongo-encrypted files.
I agree with your point. The /var/lib/mongodb-encrypted folder is always in decrypted state and the /etc/mongod.conf file will give away the location of the source files.
How this procedure ensures that it keeps the data safeguarded as a replacement for Wired-tiger?
Yes, anyone that can have access to the machine using root account can read everything. Using root it’s very easy to have access to mongod too. So, having encryption at rest or encryption in the storage engine doesn’t make any difference, if you are root.
What you should do is to enforce security is to protect the encrypted data for the non-root users that can access the machine. You should allow only root (and mongo user) to access /var/lib/mongo-encrypted.
WiredTiger encryption could be a better solution, but it’s available only in the Enterprise version. Encryption at rest is just an alternative.
Error in
Mount the encrypted directory
Code Line 1 : sudo mount -t ecryptfs /datastore /var/lib/mongo-encrypted –> sudo mount -t ecryptfs /datastore /var/lib/mongodb-encrypted
Wrong folder name
Beautifully explained. I got this worked in no time. Thanks..
Comments are closed.
Use Percona's Technical Forum to ask any follow-up questions on this blog topic.