Maintaining a secure MongoDB deployment requires administrators to implement controls to ensure that users and applications have access to only the data that they require. MongoDB provides features that allow administrators to implement these controls and restrictions for any MongoDB deployment.
This article is reference the official documentation which can be found here. As the security context is pretty huge, in this short article, we will focus how to setup mongdb server to use on ssl and how client will access the database resource securely.
First, make sure you have install the server and client package. If you are on deb package linux distribution, it is as easy as sudo apt-get install mongodb-clients mongodb-server. Once both packages are install, you can check in the log file at /var/log/mongodb/mongodb.log similar such as the following. So our mongodb version is 2.6.3 and it has support using openssl library.
2015-09-27T16:04:48.849+0800 [initandlisten] db version v2.6.3
2015-09-27T16:04:48.849+0800 [initandlisten] git version: nogitversion
2015-09-27T16:04:48.849+0800 [initandlisten] OpenSSL version: OpenSSL 1.0.1f 6 Jan 2014
Next, let's generate a public and private key and a self sign certifcate.
user@localhost:~/test1$ openssl req -newkey rsa:2048 -new -x509 -days 365 -nodes -out mongodb-cert.crt -keyout mongodb-cert.key
Generating a 2048 bit RSA private key
.............................+++
..................................................................................................................................................................................................................+++
writing new private key to 'mongodb-cert.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:MY
State or Province Name (full name) [Some-State]:KL
Locality Name (eg, city) []:Kuala Lumpur
Organization Name (eg, company) [Internet Widgits Pty Ltd]:example.com
Organizational Unit Name (eg, section) []:Engineering
Common Name (e.g. server FQDN or YOUR name) []:Jason Wee
Email Address []:jason@example.com
user@localhost:~/test1$ ls
mongodb-cert.crt mongodb-cert.key
Now put everything into a file with extension .pem.
user@localhost:~/test1$ cat mongodb-cert.key mongodb-cert.crt > mongodb.pem
Now, stop mongodb instance if it is running. As we will now configured the server to use the certificate we generated previously.
user@localhost:~/test1$ sudo systemctl status mongodb
● mongodb.service - An object/document-oriented database
Loaded: loaded (/lib/systemd/system/mongodb.service; enabled; vendor preset: enabled)
Active: inactive (dead) since Sun 2015-09-27 16:13:34 MYT; 23min ago
Docs: man:mongod(1)
Main PID: 15343 (code=exited, status=0/SUCCESS)
Sep 27 16:04:48 localhost systemd[1]: Started An object/document-oriented database.
Sep 27 16:04:48 localhost systemd[1]: Starting An object/document-oriented database...
Sep 27 16:13:33 localhost systemd[1]: Stopping An object/document-oriented database...
Sep 27 16:13:34 localhost systemd[1]: Stopped An object/document-oriented database.
Sep 27 16:36:30 localhost systemd[1]: Stopped An object/document-oriented database.
user@localhost:~/test1$ sudo tail -10 /etc/mongodb.conf
# Size limit for in-memory storage of op ids.
#opIdMem = <bytes>
# SSL options
# Enable SSL on normal ports
sslOnNormalPorts = true
# SSL Key file and password
#sslPEMKeyFile = /etc/ssl/mongodb.pem
sslPEMKeyFile = /home/user/test1/mongodb.pem
#sslPEMKeyPassword = pass
user@localhost:~/test1$
In the above output, as an example, I have set the file mongodb.pem to the configuration sslPEMKeyFile and also set sslOnNormalPorts to true. Now if you start mongodb instance.
user@localhost:~/test1$ sudo systemctl start mongodb
user@localhost:~/test1$
In the log file, noticed that ssl is enabled and no ssl related error.
2015-09-27T16:46:41.648+0800 [initandlisten] options: { config: "/etc/mongodb.conf", net: { bindIp: "127.0.0.1", ssl: { PEMKeyFile: "/home/user/test1/mongodb.pem", mode: "requireSSL" } }, storage: { dbPath: "/var/lib/mongodb", journal: { enabled: true } }, systemLog: { destination: "file", logAppend: true, path: "/var/log/mongodb/mongodb.log" } }
2015-09-27T16:46:41.788+0800 [initandlisten] journal dir=/var/lib/mongodb/journal
2015-09-27T16:46:41.797+0800 [initandlisten] recover : no journal files present, no recovery needed
2015-09-27T16:46:42.162+0800 [initandlisten] waiting for connections on port 27017 ssl
On the server configuration and setup, it is now done. Now, we will focus on the mongdb client. If you connect to mongodb using its client, you will get error.
user@localhost:~/test1$ mongo foo
MongoDB shell version: 2.6.3
connecting to: foo
2015-09-27T17:22:54.300+0800 DBClientCursor::init call() failed
2015-09-27T17:22:54.302+0800 Error: DBClientBase::findN: transport error: 127.0.0.1:27017 ns: admin.$cmd query: { whatsmyuri: 1 } at src/mongo/shell/mongo.js:146
exception: connect failed
user@localhost:~/test1$ mongo --ssl --sslPEMKeyFile mongodb.pem
MongoDB shell version: 2.6.3
connecting to: test
Server has startup warnings:
2015-09-27T16:46:41.647+0800 [initandlisten]
2015-09-27T16:46:41.647+0800 [initandlisten] ** NOTE: This is a 32 bit MongoDB binary.
2015-09-27T16:46:41.647+0800 [initandlisten] ** 32 bit builds are limited to less than 2GB of data (or less with --journal).
2015-09-27T16:46:41.647+0800 [initandlisten] ** See http://dochub.mongodb.org/core/32bit
2015-09-27T16:46:41.647+0800 [initandlisten]
> show dbs
admin (empty)
local 0.078GB
>
As you can read above, you need to specify parameter ssl and the pem file. That's it for this article, if you want to go the distance, try using tcpdump to listen to this port traffic. Good luck!