Hi everyone! This is one of the most requested subjects to our support team and I’d like to share the steps as a tutorial blog post. Today, we will set up internal authentication using x.509 certificates as well as enabling TSL/SSL.
If using authentication in MongoDB, there are two ways to configure intra-cluster authentication:
- Using a Key File
- Using x509 certs
Key files are very straight forward; just create a random text file and share it with all the members in the replicaset/sharding. However, this is not the most secure way and for this reason, it is very common to use certificates instead.
It is perfectly possible to have self-signed certificates, but in this blog, we will use easy-rsa to make real certificates signed by one certificate authority. By the documentation, easy-rsa is a CLI utility to build and manage a PKI CA. In laymen’s terms, this means to create a root certificate authority, and request and sign certificates, including sub-CAs and certificate revocation lists (CRL). This project is hosted on GitHub on https://github.com/OpenVPN/easy-rsa and we are going to use release 2.x for this tutorial.
We will use Percona Server for MongoDB v3.6 – which is currently one of the most used versions – but this works for any MongoDB version starting at 3.2. The steps as to how to create a user will be omitted in this blog. We are considering the primary is configured with authentication and the first user was already created.
- Download and configure easy-rsa:
12345yum install git -ymkdir /usr/share/easy-rsagit clone -b release/2.x https://github.com/OpenVPN/easy-rsa.gitcp easy-rsa/easy-rsa/2.0/* /usr/share/easy-rsacd /usr/share/easy-rsa
- Edit the source files with information about your company:
1234567891011121314151617cd /usr/share/easy-rsanano vars# These are the default values for fields# which will be placed in the certificate.# Don't leave any of these fields blank.export KEY_COUNTRY="US" <your data>export KEY_PROVINCE="NC" <your data>export KEY_CITY="DURHAM" <your data>export KEY_ORG="Percona" <your data>export KEY_EMAIL="firstname.lastname@example.org" <your data>export KEY_OU="MongoDB" <your data>#You may need to add the following variable:#Bug: https://bugs.launchpad.net/serverguide/+bug/1504676export KEY_ALTNAMES=""
- Load the variables with the source command:
- Edit the openssl-1.0.0.cnf file commenting the keys right after [ usr_cert ]
12#extendedKeyUsage=clientAuth#keyUsage = digitalSignature
More info here on Extended Key Usage
- Now everything is prepared to create our CA file. Let’s create the CA and the members’ certificates:
1234567cd /usr/share/easy-rsa# this command will clean all the data in the ./keys folder./clean-all# It will generate a key for the CA as well as a certificate./built-ca# It will generate a key for the server as well as a certificate./built-key <server_name>
- We suggest keeping the default values for the CA and informing the FQN or the hostname in the certificates. (It will be validated by MongoDB.)This is the expected output:
1234567891011121314151617181920212223242526272829303132333435Generating a 2048 bit RSA private key......................................................................................+++............................+++writing new private key to 'server_name.key'-----You are about to be asked to enter information that will be incorporatedinto 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 blankFor some fields there will be a default value,If you enter '.', the field will be left blank.-----Country Name (2 letter code) [US]:State or Province Name (full name) [NC]:Locality Name (eg, city) [Durham]:Organization Name (eg, company) [Percona]:Organizational Unit Name (eg, section) [MongoDB]:Common Name (eg, your name or your server's hostname) [server_name]:Name [EasyRSA]:Email Address [email@example.com]:Please enter the following 'extra' attributesto be sent with your certificate requestA challenge password :An optional company name :Using configuration from /usr/share/easy-rsa/openssl-1.0.0.cnfCheck that the request matches the signatureSignature ok...Certificate is to be certified until Mar 9 11:29:40 2028 GMT (3650 days)Sign the certificate? [y/n]:y1 out of 1 certificate requests certified, commit? [y/n]yWrite out database with 1 new entriesData Base Updated
- After creating all the certificates, we need to combine the keys and its certificate in order to create the .pem file.
12345678910cd keys-rw-r--r-- 1 root root 1,7K Mar 9 09:35 ca.crt-rw------- 1 root root 1,7K Mar 9 09:35 ca.key-rw-r--r-- 1 root root 4,1K Mar 12 08:29 server_name.crt-rw-r--r-- 1 root root 1,1K Mar 12 08:29 server_name.csr-rw------- 1 root root 1,7K Mar 12 08:29 server_name.key# combining .key and .crt into a single file.cat server_name.key server_name.crt > server_name.pem
Repeat this process to all the server keys.
- Now that we have the server .pem files prepared we need to edit the mongod.conf, considering the keys were moved to /var/lib/mongodb/
123456789security.clusterAuthMode : x509security.authorization : enablednet:port: 27017bindIp: <ip_number>ssl:mode: requireSSLPEMKeyFile: /var/lib/mongodb/server_name.pemCAFile: /var/lib/mongodb/ca.crt
- Once the changes are made, the services must be started and the members should start normally.
- It is now time to configure the clients, as otherwise, no one will be able to log in to this environment. Again we need to edit the openssl-1.0.0.cnf removing the comments. Clients need to have those keys in the certificate.
123cd /usr/share/easy-rsaextendedKeyUsage=clientAuthkeyUsage = digitalSignature
- After editing the file, create the client file, it is as simple as creating a new key:
Shell12cd /usr/share/easy-rsa./build-key <client_name>
There is a caveat here, the Organization Unit must be different than MongoDB. I recommend calling as a MongoDBClient, and once the files are created repeat the process of linking the client_name.crt and the client_name.key file in a single file and using it to log in to the environment.