Skip to content

Instantly share code, notes, and snippets.

@pkdone
Last active April 20, 2022 18:42
Show Gist options
  • Save pkdone/8c37c217ce67247e8a7770884231ec7c to your computer and use it in GitHub Desktop.
Save pkdone/8c37c217ce67247e8a7770884231ec7c to your computer and use it in GitHub Desktop.

MongoDB Encryption-at-Rest Using KMIP

Assumptions

  • You have MongoDB Enterprise installed (but not configured or running) on your local workstation with the mongod binary and the other MongoDB binaries on your system path
  • You have the modern MongoDB Shell (mongosh) installed locally on your workstation
  • You have a KMIP Server running and accessible (for an example of running and configuring a Hashicorp Vault development instance, see: Hashicorp Vault Configuration For MongoDB KMIP Use)

Create a Shell Script to Start an Encrypted Replica Set and Launch It

From a terminal, execute the code below after first:

  • Changing KMIP_SERVER_HOST to match the host address of your KMIP server
  • Changing KMIP_SERVER_PORT to match the port of your KMIP server
# Clean out previously created file, if any
rm -f run-encrypted-mongo-repset.sh

# Create a script to configure and start a MongoDB replica-set which uses a KMIP server for the encrypted storage engine
tee run-encrypted-mongo-repset.sh <<EOF
#!/bin/sh
KMIP_SERVER_HOST=localhost
KMIP_SERVER_PORT=5696
CURR_DIR=\`pwd\`

# Clean up any old environment
echo "Killing any existing mongod files - may wait for a while for them to terminate gracefully"
killall -w mongod
rm -rf env/r0 env/r1 env/r2

# Create DB file & log directories for each replica
mkdir -p env/r0/log env/r1/log env/r2/log

# Start the 3 MongoDB replicas with encryption enabled then just wait for a few secs for servers to start
mongod --replSet TestRS --port 27017 --dbpath env/r0 --fork --logpath env/r0/log/mongod.log --enableEncryption --kmipServerName \${KMIP_SERVER_HOST} --kmipPort \${KMIP_SERVER_PORT} --kmipServerCAFile \${CURR_DIR}/ca.pem --kmipClientCertificateFile \${CURR_DIR}/client.pem
mongod --replSet TestRS --port 27027 --dbpath env/r1 --fork --logpath env/r1/log/mongod.log --enableEncryption --kmipServerName \${KMIP_SERVER_HOST} --kmipPort \${KMIP_SERVER_PORT} --kmipServerCAFile \${CURR_DIR}/ca.pem --kmipClientCertificateFile \${CURR_DIR}/client.pem
mongod --replSet TestRS --port 27037 --dbpath env/r2 --fork --logpath env/r2/log/mongod.log --enableEncryption --kmipServerName \${KMIP_SERVER_HOST} --kmipPort \${KMIP_SERVER_PORT} --kmipServerCAFile \${CURR_DIR}/ca.pem --kmipClientCertificateFile \${CURR_DIR}/client.pem
sleep 3

# Connect to first replica with Mongo Shell and configre the Replica Set containing the 3 replicas
mongosh --quiet --port 27017 --eval "
    rs.initiate({_id: 'TestRS', members: [
        {_id: 0, host: 'localhost:27017'},
        {_id: 1, host: 'localhost:27027'},
        {_id: 2, host: 'localhost:27037'},
    ], settings: {
        electionTimeoutMillis: 2000,
        heartbeatIntervalMillis: 5000,
        heartbeatTimeoutSecs: 30,
    }});
"

echo
echo "Mongo Shell command to connect to replica set:"
echo
echo "mongosh \"mongodb://localhost:27017,localhost:27027,localhost:27037/?replicaSet=TestRS\""
echo
EOF

# Make script executable
chmod u+x run-encrypted-mongo-repset.sh

# Run the script
./run-encrypted-mongo-repset.sh

Check Database Data Has Been Encrypted

From a terminal, execute:

mongosh "mongodb://localhost:27017,localhost:27027,localhost:27037/?replicaSet=TestRS"

use test
db.persons.insert({name: "Alice", location: "New York"});
db.persons.find();

exit();

From a terminal, execute:

# Kill the replica set's 3 mongod processes
killall -w mongod

# Inspect the data files for the stopped first replica to see if clear text values are present or not
find env/r0 -name "collection*.wt" | xargs strings | grep "New York"

In the output above NO matching lines should be found because field value New York will have been encrypted.

If you were to run the replica set without encryption, the above commands will find the matching line. You can try this by commenting out the encryption parameters in run-encrypted-mongo-repset.sh by putting a # character before --enableEncryption for the 3 lines which execute mongod and then running the script and the test again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment