This article will walk you through using the SASL library to allow your Percona Server for MongoDB instance to authenticate with your company’s Active Directory server. Percona Server for MongoDB includes enterprise level features, such as LDAP authentication, audit logging and with the 3.6.8 release a beta version of data encryption at rest, all in its open source offering.
Pre set-up assumptions
In this article we will make a couple of assumptions:
- You have an Active Directory server up and running and that it is accessible to the server that you have Percona Server for MongoDB installed on.
- These machines are installed behind a firewall as the communications between the two servers will be in plain text. This is due the fact that we can only use the SASL mechanism of PLAIN when authenticating and credentials will be sent in plain text.
- You have
sudo
privilege on the server you are going to install Percona Server for MongoDB on.
Installing Percona Server for MongoDB
The first thing you are going to need to do is to install the Percona Server for MongoDB package. You can get this in a couple of different ways. You can either install from the Percona repositories, or you can download the packages and install them manually.
Once you have Percona Server for MongoDB installed, we want to start the mongod
service and make sure it is set to run on restart.
1 2 | sudo systemctl start mongod sudo systemctl enable mongod |
Now that the service is up and running, we want to open the mongo
shell and add a database administrator user. This user will be authenticated inside of the MongoDB server itself and will not have any interactions with the Active Directory server.
To start the mongo shell up, type mongo
from a terminal window. Once you do this you will see something similar to the following:
1 2 3 4 5 6 7 8 9 10 11 12 | Percona Server for MongoDB shell version v3.6.8-2.0 connecting to: mongodb://127.0.0.1:27017 Percona Server for MongoDB server version: v3.6.8-2.0 Server has startup warnings: 2018-12-11T17:48:47.471+0000 I STORAGE [initandlisten] 2018-12-11T17:48:47.471+0000 I STORAGE [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine 2018-12-11T17:48:47.471+0000 I STORAGE [initandlisten] ** See http://dochub.mongodb.org/core/prodnotes-filesystem 2018-12-11T17:48:48.197+0000 I CONTROL [initandlisten] 2018-12-11T17:48:48.197+0000 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2018-12-11T17:48:48.197+0000 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2018-12-11T17:48:48.197+0000 I CONTROL [initandlisten] ** You can use percona-server-mongodb-enable-auth.sh to fix it. 2018-12-11T17:48:48.197+0000 I CONTROL [initandlisten] |
Notice the second warning that access control is not enabled for the database. Percona Server for MongoDB comes with a script that you can run that will enable authentication for you, but we can also do this manually.
We will go ahead and manually add a user in MongoDB that has the root role assigned to it. This user will have permission to do anything on the server, so you will want to make sure to keep the password safe. You will also not want to use this user for doing your day to day work inside of MongoDB.
This user needs to be created in the admin
database as it needs to have access to the entire system. To do this run the following commands inside of the mongo
shell:
1 2 3 4 | > use admin switched to db admin > db.createUser({"user": "admin", "pwd": "$3cr3tP4ssw0rd", "roles": ["root"]}) Successfully added user: { "user" : "admin", "roles" : [ "root" ] } |
Now that we have a user created in MongoDB we can go ahead and enable authorization. To do this we need to modify the /etc/mongod.conf
file and add the following lines:
1 2 3 4 5 | security: authorization: enabled setParameter: authenticationMechanisms: PLAIN,SCRAM-SHA-1 |
Notice that we have two mechanisms set up for authentication. The first one, PLAIN, is used for authenticating with Active Directory. The second one, SCRAM-SHA-1 is used for internal authentication inside of MongoDB.
Once you’ve made the changes, you can restart the mongod
service by running the following command:
1 | sudo systemctl restart mongod |
Now if you were to run the mongo
shell again, you wouldn’t see the access control warning any more, and you would need to log in as your new user to be able to run any commands.
If you were to try to get a list of databases before logging in you would get an error:
1 2 3 4 5 6 7 8 9 10 11 12 | > show dbs; 2018-12-11T21:50:39.551+0000 E QUERY [thread1] Error: listDatabases failed:{ "ok" : 0, "errmsg" : "not authorized on admin to execute command { listDatabases: 1.0, $db: \"admin\" }", "code" : 13, "codeName" : "Unauthorized" } : _getErrorWithCode@src/mongo/shell/utils.js:25:13 Mongo.prototype.getDBs@src/mongo/shell/mongo.js:65:1 shellHelper.show@src/mongo/shell/utils.js:849:19 shellHelper@src/mongo/shell/utils.js:739:15 @(shellhelp2):1:1 |
Let’s go ahead and run the mongo
shell and then log in with our admin user:
1 2 3 4 | > use admin switched to db admin > db.auth("admin", "$3cr3tP4ssw0rd") 1 |
If you are successful you will get a return value of 1. If authentication fails, you will get a return value of 0. Failure is generally due to a mistyped username or password, but you could also be trying to authenticate in the wrong database. In MongoDB you must be in the database that the user was created in before trying to authenticate.
Now that we’ve logged in as the admin user, we will add a document that will be used to verify that our Active Directory based user can successfully access the data at the end of this post.
1 2 3 4 | > use percona switched to db percona > db.test.insert({"message": "Active Directory user success!"}) WriteResult({ "nInserted" : 1 }) |
Install the Cyrus SASL packages
Now that we have a Percona Server for MongoDB instance set up and it is secured, we need to add some packages that will allow us to communicate properly with the Active Directory server.
For RedHat use the following command
1 | sudo yum install -y cyrus-sasl cyrus-sasl-plain |
For Ubuntu use this command
1 | sudo app install -y sasl2-bin |
Next we need to update the SASL configuration to use LDAP instead of PAM, which is the default. To do this we need to edit the file /etc/sysconfig/saslauthd
, remembering to backup up your original file first.
For RedHat we use the following commands
1 2 | sudo cp /etc/sysconfig/saslauthd /etc/sysconfig/saslauthd.bak sudo sed -i -e s/^MECH=pam/MECH=ldap/g /etc/sysconfig/saslauthd |
For Ubuntu we use these commands instead
1 2 3 | sudo cp /etc/default/saslauthd /etc/default/saslauthd.bak sudo sed -i -e s/^MECHANISMS="pam"/MECHANISMS="ldap"/g /etc/default/saslauthd sudo sed -i -e s/^START=no/START=yes/g /etc/default/saslauthd |
We also need to create the file /etc/saslauthd.conf
with contents similar to the following (replace values as necessary for your Active Directory installation):
1 2 3 4 5 6 7 | ldap_servers: ldap://LDAP.EXAMPLE.COM ldap_mech: PLAIN ldap_filter: cn=%u,CN=Users,DC=EXAMPLE,DC=COM ldap_search_base:CN=Users,DC=EXAMPLE,DC=COM ldap_filter:(cn=%u) ldap_bind_dn:CN=ADADMIN,CN=Users,DC=EXAMPLE,DC=COM ldap_password:ADADMINPASSWORD |
Now that we’ve got SASL set up, we can start the saslauthd
process and set it to run on restart.
1 2 | sudo systemctl start saslauthd sudo systemctl enable saslauthd |
Next we need to allow the mongod process to write to the saslauthd mux socket and change the permissions on the owning directory to 755 so MongoDB can write to it. This is the default on RedHat, but not for Ubuntu.
On Ubuntu you can either change the permissions on the folder
1 | sudo chmod 755 /run/saslauthd |
Or you could add the mongod user to the sasl group
1 | sudo usermod -a -G sasl mongod |
Test the users
The SASL installation provides us with a tool to test that our Active Directory users can be logged in from this machine. Let’s go ahead and test to see if we can authenticate with our Active Directory user.
1 | sudo testsaslauthd -u aduser -p ADP@assword1 |
You should see 0: OK "Success."
if authentication worked.
Create a SASL config file for MongoDB
To allow MongoDB to use SASL to communicate with Active Direcory, we need to create a configuration file.
Create the requisite directory if it doesn’t exist:
1 | mkdir -p /etc/sasl2 |
And then we need to create the file /etc/sasl2/mongodb.conf
and place the following contents into it:
1 2 3 4 | pwcheck_method: saslauthd saslauthd_path: /var/run/saslauthd/mux log_level: 5 mech_list: plain |
Add Active Directory user to MongoDB
Now we can finally add our Active Directory user to our MongoDB instance:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | $ mongo Percona Server for MongoDB shell version v3.6.8-2.0 connecting to: mongodb://127.0.0.1:27017 Percona Server for MongoDB server version: v3.6.8-2.0 > use admin switched to db admin > db.auth("admin", "$3cr3tP4ssw0rd") 1 > use $external switched to db $external > db.createUser({"user": "aduser", "roles": [{"role": "read", "db": "percona"}]}) Successfully added user: { "user" : "aduser", "roles" : [ { "role" : "read", "db" : "percona" } ] } |
As you can see from the above, when we create the user that will be authenticated with Active Directory, we need to be in the special $external database and we don’t supply a password as we would when we create a MongoDB authenticated user.
Now let’s try to log in with our Active Directory based user. First we need exit our current mongo
shell and restart it, and then we can log in with our Active Directory user:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | > exit bye $ mongo Percona Server for MongoDB shell version v3.6.8-2.0 connecting to: mongodb://127.0.0.1:27017 Percona Server for MongoDB server version: v3.6.8-2.0 > use $external switched to db $external > db.auth({"mechanism": "PLAIN", "user": "aduser", "pwd": "adpassword", "digestPassword ": false}) 1 > use percona switched to db percona > db.test.find() { "_id" : ObjectId("5c12a47904a287e45fcb580e"), "message" : "Active Directory user success!" } |
As you can see above our Active Directory based user was able to authenticate and then change over to the percona
database and see the document we stored earlier.
You will notice that our auth()
call above is different than the one we used to log in with MongoDB based users. In this case we need to pass in a document with not only the user and password, but also the mechanism to use. We also want to set digestPassword
to false
.
You can also log in directly from the command line with the following:
1 | mongo percona --host localhost --port 27017 --authenticationMechanism PLAIN --authenticationDatabase \$external --username dduncan --p |
There are a couple of things to note here if you’re not used to using the command line to log in:
- We place the
--password
option at the end of the command line and do not provide a password here. This will cause the application to prompt us for a password. - You will also automatically be placed into the
percona
database, or whatever database name you provide aftermongo
. - You need to escape the
$external
database name with a backslash (\
) or the terminal will treat$external
as an environment variable and you will most likely get an error.
Conclusion
In conclusion, it is easy to connection your Percona Server for MongoDB instance to your corporate Active Directory server. This allows your MongoDB users to use the same credentials to log into MongoDB as they do their corporate email and workstation.
—
Photo by Steve Halama on Unsplash