MongoDBDatabases

MongoDB Security: Authentication, RBAC, and TLS Configuration

Secure MongoDB with authentication, role-based access control (RBAC), network hardening, TLS/SSL, and field-level encryption. Lesson 8 of the MongoDB & NoSQL Mastery course.

TT
Sarah Mitchell
5 min read
MongoDB Security: Authentication, RBAC, and TLS Configuration

An unsecured MongoDB instance is one of the most common causes of data breaches in the NoSQL ecosystem. Thousands of databases have been exposed publicly with no authentication. This lesson covers the full security stack: enabling authentication, creating scoped users, configuring TLS, and hardening the network — transforming a default-open development instance into a production-ready deployment.

Previous: Lesson 7 — Indexes: Performance & Design


Enabling Authentication

MongoDB ships with authentication disabled by default for development convenience. Never expose this configuration beyond localhost.

Step 1: Create the First Admin User

Before enabling authentication, create the admin user while the database is still open:

javascript
// In mongosh (no auth required yet)
use admin
db.createUser({
  user: "admin",
  pwd: passwordPrompt(),   // prompts securely — never hardcode passwords
  roles: [
    { role: "userAdminAnyDatabase", db: "admin" },
    { role: "readWriteAnyDatabase", db: "admin" },
    { role: "dbAdminAnyDatabase",   db: "admin" },
    { role: "clusterAdmin",         db: "admin" }
  ]
})

Step 2: Enable Authentication in mongod.conf

yaml
# /etc/mongod.conf

security:
  authorization: enabled
bash
sudo systemctl restart mongod

Step 3: Connect with Credentials

bash
mongosh -u admin -p --authenticationDatabase admin

Role-Based Access Control (RBAC)

MongoDB's RBAC model: users are assigned roles; roles grant privileges (actions on resources).

Built-In Roles

RoleAccess Level
readRead documents and indexes in a specific database
readWriteRead and write documents in a specific database
dbAdminSchema management, index management, stats — no data access
userAdminCreate and modify users and roles in a specific database
clusterAdminSharding, replication management — admin database only
readAnyDatabaseRead across all databases
rootSuperuser — unrestricted access to everything

Creating Application Users

Follow the principle of least privilege: application users should only have access to their own database, with only the operations they need:

javascript
use myapp

// Read-only service account (e.g. for a reporting tool)
db.createUser({
  user: "reporting_service",
  pwd: passwordPrompt(),
  roles: [{ role: "read", db: "myapp" }]
})

// Application service account — read/write own database only
db.createUser({
  user: "app_service",
  pwd: passwordPrompt(),
  roles: [{ role: "readWrite", db: "myapp" }]
})

// Migration user — needs dbAdmin for index creation
db.createUser({
  user: "migration_runner",
  pwd: passwordPrompt(),
  roles: [
    { role: "readWrite", db: "myapp" },
    { role: "dbAdmin",   db: "myapp" }
  ]
})

Custom Roles

javascript
use myapp

db.createRole({
  role: "orderProcessor",
  privileges: [
    {
      resource: { db: "myapp", collection: "orders" },
      actions: ["find", "update"]
    },
    {
      resource: { db: "myapp", collection: "products" },
      actions: ["find"]
    }
  ],
  roles: []
})

db.createUser({
  user: "order_worker",
  pwd: passwordPrompt(),
  roles: [{ role: "orderProcessor", db: "myapp" }]
})

Managing Users

javascript
// List all users in the current database
db.getUsers()

// Update a user's password
db.changeUserPassword("app_service", passwordPrompt())

// Add a role to an existing user
db.grantRolesToUser("app_service", [{ role: "dbAdmin", db: "myapp" }])

// Remove a role
db.revokeRolesFromUser("app_service", [{ role: "dbAdmin", db: "myapp" }])

// Delete a user
db.dropUser("migration_runner")

Network Hardening

Bind to Specific Interfaces

By default, MongoDB 3.6+ binds only to 127.0.0.1. For a server accessible to application instances, bind to the specific private IP — never 0.0.0.0 in production:

yaml
# /etc/mongod.conf
net:
  bindIp: 127.0.0.1,10.0.1.15   # localhost + private network IP only
  port: 27017

Firewall Rules

bash
# Allow MongoDB access only from the application server (UFW example)
sudo ufw allow from 10.0.1.20 to any port 27017

# Deny all other access to port 27017
sudo ufw deny 27017

Change the Default Port

yaml
net:
  port: 27937    # Non-standard port — minor security-through-obscurity measure

TLS/SSL Configuration

TLS encrypts data in transit between MongoDB clients and the server.

Generate Certificates (Self-Signed for Testing)

bash
# Generate CA key and certificate
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 1826 -key ca.key -out ca.crt \
  -subj "/CN=MongoDB CA"

# Generate server key and certificate signed by the CA
openssl genrsa -out server.key 4096
openssl req -new -key server.key -out server.csr \
  -subj "/CN=mongodb.internal"
openssl x509 -req -days 730 -in server.csr \
  -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt

# Combine key and certificate into a PEM file (required by MongoDB)
cat server.key server.crt > server.pem

Enable TLS in mongod.conf

yaml
# /etc/mongod.conf
net:
  tls:
    mode: requireTLS
    certificateKeyFile: /etc/mongodb/tls/server.pem
    CAFile: /etc/mongodb/tls/ca.crt

Connect with TLS

bash
mongosh --tls \
  --tlsCertificateKeyFile /etc/mongodb/tls/client.pem \
  --tlsCAFile /etc/mongodb/tls/ca.crt \
  "mongodb://admin@mongodb.internal:27017/admin"

Auditing and Monitoring Security Events

javascript
// View active connections
db.currentOp(true)

// Check authentication mechanisms configured
db.adminCommand({ getParameter: 1, authenticationMechanisms: 1 })

// List all roles in the admin database
use admin
db.getRoles({ showBuiltinRoles: true })

// Check which roles a user has
db.getUser("app_service")

MongoDB Atlas Security (Managed)

On Atlas, security is configured via the UI or API:

  • Network access: IP allowlist or VPC peering — no public IP exposure
  • Database users: Scoped to specific databases with built-in or custom roles
  • TLS: Always enabled; certificates managed by Atlas
  • Encryption at rest: AES-256 by default on all clusters
  • Audit logging: Available on M10+ clusters — logs all operations to a queryable log