MongoDB Security¶
MongoDB ships with no authentication enabled by default — anyone who can reach the port has full access until you turn authorization on. See Overview for basic connection syntax referenced below.
Change the Bind IP¶
By default older versions bind to all interfaces; restrict this before exposing an instance beyond localhost:
net:
port: 27017
bindIp: 10.0.0.10 # a specific internal IP ...
# bindIp: 127.0.0.1 # ... or localhost-only
mongo --host <bind_ip>
mongo --host <bind_ip> --port <custom_port> # if you also changed the listen port
Create the First Admin User¶
Without authorization enabled yet, connect locally and create a root-role user (full superuser) or a narrower userAdminAnyDatabase user (can manage users/roles but not read/write arbitrary data — often the better first account to create):
use admin
db.createUser({
user: "mongoAdmin",
pwd: "a_strong_password",
roles: [ { role: "root", db: "admin" } ]
})
// Narrower alternative — can administer users but not read application data directly
db.createUser({
user: "userAdmin",
pwd: "a_strong_password",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
})
Enable Authorization¶
# mongod.conf
security:
authorization: enabled
sudo systemctl restart mongodb.service
Test It¶
use admin
db.auth("mongoAdmin", "a_strong_password") // returns 1 on success
db.system.users.find() // inspect stored user/role records
Connecting With Auth¶
# Connect directly to the admin database
mongo admin --host <bind_ip> -u mongoAdmin -p
# Connect to a different database, but authenticate against admin
mongo app_db --host <bind_ip> -u mongoAdmin -p --authenticationDatabase=admin
# Same, connecting to the default database
mongo --host <bind_ip> -u mongoAdmin -p --authenticationDatabase=admin
Create a Dedicated User Per Application/Database¶
Avoid handing out the admin account for routine application access — scope a user to just what it needs:
db.createUser({
user: "app_user",
pwd: "a_strong_password",
roles: [
{ role: "readWrite", db: "app_db" },
{ role: "read", db: "reporting" }
]
})
A user scoped this way can only see and use the databases it was granted — show dbs will correctly report not authorized for listDatabases unless it also has a role that includes that privilege. That's expected behavior, not a bug — it's the isolation the scoped grant is meant to provide.
Reset a User's Password¶
# Temporarily disable authorization to get in
# security:
# authorization: enabled
systemctl restart mongodb.service
use admin
db.updateUser("mongoAdmin", { pwd: "a_new_password" })
# Re-enable authorization
security:
authorization: enabled
systemctl restart mongodb.service
Delete a User¶
use target_db
db.dropUser("app_user")
Built-in Roles Reference¶
| Category | Roles |
|---|---|
| Database user | read, readWrite |
| Database admin | dbAdmin, userAdmin, dbOwner |
| All-database (cluster-wide) | readAnyDatabase, readWriteAnyDatabase, userAdminAnyDatabase, dbAdminAnyDatabase |
| Cluster admin | clusterManager, clusterMonitor, hostManager, clusterAdmin |
| Backup/restore | backup, restore |
| Superuser | root (implies most of the above) |
| Internal | __system (used by MongoDB itself, not for application accounts) |
Prefer the narrowest role that gets the job done — root for every service account defeats the purpose of having roles at all.
Enable TLS¶
Verify TLS support is compiled in:
mongod --version
Generate Certificates¶
Create a CA and a server certificate (or use a properly issued one from an internal/external CA — self-signed is shown here for reference):
mkdir /home/mongodb
# ... generate ca.crt and a combined server cert+key (mongodb-cert.pem) here ...
mv mongodb-cert.pem ca.crt /home/mongodb
chown -R mongodb:mongodb /home/mongodb
# mongod.conf, under net:
net:
ssl:
mode: requireSSL
PEMKeyFile: /home/mongodb/mongodb-cert.pem
CAFile: /home/mongodb/ca.crt
sudo systemctl restart mongodb.service
Important: once TLS is enabled, connect using the certificate's hostname, not a bare IP — connecting by IP against a cert issued for a hostname produces:
Error: socket exception [CONNECT_ERROR] for The server certificate does not match the host name <ip>
mongo --host mongo1.example.local --ssl --sslPEMKeyFile /home/mongodb/client.pem --sslCAFile /home/mongodb/ca.crt
x509 Client-Certificate Authentication¶
Rather than a username/password, a client can authenticate using the identity baked into its certificate. Get the certificate's subject line:
openssl x509 -in client.pem -inform PEM -subject -nameopt RFC2253 -noout
subject= CN=client1.example.local,O=Example Org,L=City,ST=State,C=US
Create a MongoDB user matching that exact subject string, in the special $external database:
db.getSiblingDB("$external").runCommand({
createUser: "subject= CN=client1.example.local,O=Example Org,L=City,ST=State,C=US",
roles: [ { role: "root", db: "admin" } ]
})
db.getSiblingDB("$external").auth({
user: "subject= CN=client1.example.local,O=Example Org,L=City,ST=State,C=US",
mechanism: "MONGODB-X509"
})
Disable the Localhost Exception¶
By default, MongoDB allows an unauthenticated connection from localhost to create the very first user (a bootstrapping convenience). Once real users exist, disable this explicitly rather than relying on it closing itself automatically:
mongod --setParameter enableLocalhostAuthBypass=false
Related¶
- Overview — basic connection syntax
- Replication — keyfile- and TLS-secured replica sets, which build on the certificate setup above
- General MongoDB security hardening: MongoDB Security Checklist