39 User Management: Security und Access Control

MongoDB out-of-the-box hat keine Authentication aktiviert. Eine fresh Installation akzeptiert Connections ohne Credentials – jeder mit Netzwerk-Zugriff hat vollen Admin-Access. Dies ist convenient für lokale Development, aber katastrophal für Production. Die erste Frage bei jedem Production-Deployment: “Ist Authentication aktiviert?” Wenn nicht, ist die Datenbank offen für die Welt – ein Sicherheits-Desaster.

User-Management in MongoDB basiert auf Role-Based Access Control (RBAC). Users haben Rollen, Rollen haben Privileges, Privileges definieren Actions auf Resources. Dies ist granular und flexibel – man kann einen User definieren, der nur Read-Access auf eine spezifische Collection hat, oder einen Admin mit Full-Cluster-Management. Aber Flexibilität kommt mit Komplexität. MongoDB hat dutzende Built-in-Rollen mit subtilen Unterschieden, und Custom-Roles können arbiträr komplex werden.

Dieses Kapitel behandelt User-Management systematisch – von Basics (User-Creation, Authentication) über Rollen-Design bis zu Production-Best-Practices für Security. Der Fokus ist nicht nur “wie erstellt man User”, sondern “wie designed man ein sicheres, auditbares Access-Control-System”.

39.1 Authentication vs. Authorization: Die fundamentale Dichotomie

Diese Begriffe werden oft verwechselt, aber sie sind fundamental unterschiedlich.

Authentication: “Wer bist du?” – Verification der Identity. MongoDB prüft: Ist dieser Username+Password valid? Ist dieses Certificate korrekt signiert? Dies ist der erste Schritt bei jeder Connection.

Authorization: “Was darfst du?” – Control of Actions. Nachdem Identity verified ist, prüft MongoDB: Hat dieser User Permission für diese Action (read, write, createIndex, etc.) auf dieser Resource (Database, Collection)?

Beide sind essentiell. Authentication ohne Authorization ist sinnlos – jeder kann alles. Authorization ohne Authentication ist unmöglich – man kann Permissions nicht enforcem ohne zu wissen, wer connected.

MongoDB’s RBAC-System handelt Authorization. User-Accounts mit Credentials handeln Authentication. Beides zusammen bildet MongoDB’s Security-Model.

39.2 Der admin-User: Root-Access und Bootstrap

Bevor man Users erstellen kann, muss ein Admin-User existieren. Bei einer fresh Installation mit aktivierter Authentication kann niemand connecten – ein Chicken-and-Egg-Problem. MongoDB’s Lösung: Die localhost-Exception.

Localhost Exception:

Wenn MongoDB Authentication aktiviert hat aber noch keine Users existieren, erlaubt es Connections von localhost, um den ersten Admin-User zu erstellen:

// Von localhost, bevor irgendein User existiert
mongosh --host localhost

use admin
db.createUser({
  user: "admin",
  pwd: "SecureAdminPassword123!",
  roles: [{ role: "root", db: "admin" }]
})

Nach diesem ersten User-Create ist die Localhost-Exception disabled. Alle weiteren Connections erfordern Authentication.

Die root-Rolle:

root ist die mächtigste Rolle – Full-Access auf alles. Sie kombiniert alle Admin-Rollen und erlaubt jede Action. Für Production sollte der root-User extrem restricted sein – nur von Admins in Notfällen genutzt. Day-to-Day-Operations sollten Least-Privilege-Users nutzen.

39.3 User-Creation: Die Anatomie eines Users

Ein MongoDB-User hat mehrere Components:

db.createUser({
  user: "appUser",                           // Username
  pwd: "Password123!",                       // Password
  roles: [                                    // Roles array
    { role: "readWrite", db: "productionDB" },
    { role: "read", db: "analyticsDB" }
  ],
  mechanisms: ["SCRAM-SHA-256"],             // Auth mechanism
  customData: {                               // Optional metadata
    department: "Engineering",
    createdBy: "admin@company.com"
  }
})

User ist Database-spezifisch:

Users werden in einer spezifischen Database erstellt – typischerweise admin. Dies ist die “Authentication Database” – wo MongoDB die User-Credentials speichert. Man connected zu MongoDB mit:

mongosh --username appUser --password Password123! --authenticationDatabase admin

Die --authenticationDatabase ist kritisch – ohne sie weiß MongoDB nicht, wo es den User suchen soll.

Warum admin als Auth-Database:

Per Convention speichert man alle Users in admin, auch wenn sie nur auf andere Databases zugreifen. Dies zentralisiert User-Management. Alternativ könnte man Users in jeder Database erstellen, aber das ist verwirrend und schwer zu maintainen.

Password-Hashing:

Passwords werden nie im Klartext gespeichert. MongoDB hasht sie mit SCRAM (Salted Challenge Response Authentication Mechanism). Das Password in createUser() wird automatisch gehasht – man gibt Plaintext, MongoDB speichert nur den Hash.

39.4 Built-in Roles: Die Standard-Permissions

MongoDB hat dutzende Built-in-Rollen für Common-Use-Cases. Die wichtigsten:

Database-Level-Rollen:

// Read-only auf eine Database
{ role: "read", db: "myDB" }

// Read-Write auf eine Database
{ role: "readWrite", db: "myDB" }

// Database-Administration (Indexes, Stats, aber kein Data-Access)
{ role: "dbAdmin", db: "myDB" }

// User-Administration für eine Database
{ role: "userAdmin", db: "myDB" }

// dbOwner = readWrite + dbAdmin + userAdmin
{ role: "dbOwner", db: "myDB" }

All-Databases-Rollen:

Für Users, die auf alle Databases zugreifen müssen (rare, meist nur Monitoring-Tools):

{ role: "readAnyDatabase", db: "admin" }
{ role: "readWriteAnyDatabase", db: "admin" }
{ role: "dbAdminAnyDatabase", db: "admin" }
{ role: "userAdminAnyDatabase", db: "admin" }

Diese gelten für alle Databases im Cluster. Die db: "admin"-Spec ist Pflicht – sie definiert, wo die Rolle stored ist, nicht worauf sie zugreift.

Cluster-Management-Rollen:

Für Replica-Sets und Sharded-Clusters:

{ role: "clusterAdmin", db: "admin" }      // Full Cluster-Management
{ role: "clusterManager", db: "admin" }    // Shard/Replica-Management
{ role: "clusterMonitor", db: "admin" }    // Read-only Cluster-Metrics
{ role: "hostManager", db: "admin" }       // Server-Process-Management

Backup/Restore-Rollen:

{ role: "backup", db: "admin" }
{ role: "restore", db: "admin" }

Diese erlauben mongodump/mongorestore, aber keinen normalen Data-Access – perfect für Backup-Scripts.

Die root-Rolle:

{ role: "root", db: "admin" }

Superuser – kann alles. Nur für Admins, nie für Applications.

39.5 Practical User-Scenarios: Wer braucht welche Rolle?

Scenario 1: Application-User

Eine Web-App braucht Read-Write auf ihre Database, sonst nichts:

db.createUser({
  user: "webApp",
  pwd: "AppPassword123!",
  roles: [
    { role: "readWrite", db: "productionDB" }
  ]
})

Dies ist Least-Privilege – die App kann weder andere Databases sehen noch Admin-Actions ausführen.

Scenario 2: Analytics-User

Ein Analytics-Tool braucht Read-only über mehrere Databases:

db.createUser({
  user: "analyticsUser",
  pwd: "AnalyticsPass123!",
  roles: [
    { role: "read", db: "productionDB" },
    { role: "read", db: "logsDB" },
    { role: "read", db: "metricsDB" }
  ]
})

Read-only verhindert versehentliche Writes durch Analytics-Queries.

Scenario 3: DevOps-Engineer

Ein Engineer braucht Admin-Access für Maintenance, aber kein Data-Access:

db.createUser({
  user: "devopsEngineer",
  pwd: "DevOpsPass123!",
  roles: [
    { role: "dbAdmin", db: "productionDB" },  // Index-Management, Stats
    { role: "clusterMonitor", db: "admin" },  // Cluster-Health
    { role: "backup", db: "admin" }           // Backups
  ]
})

Kein readWrite – der Engineer kann keine Daten sehen oder ändern, nur Infrastructure managen.

Scenario 4: Monitoring-System

Prometheus, Grafana oder andere Monitoring-Tools brauchen Read-only auf Metrics:

db.createUser({
  user: "monitoring",
  pwd: "MonitorPass123!",
  roles: [
    { role: "clusterMonitor", db: "admin" }
  ]
})

Dies erlaubt das Lesen von serverStatus, dbStats, Replica-Set-Health, aber keinen Data-Access.

Scenario 5: Temporary Admin

Ein Consultant braucht temporären Full-Access:

db.createUser({
  user: "consultant",
  pwd: "TempPass123!",
  roles: [
    { role: "root", db: "admin" }
  ]
})

// Nach dem Consulting-Engagement
db.dropUser("consultant")

Temporary-Accounts sollten immer time-limited sein und promptly deleted.

39.6 Custom Roles: Granulare Permissions

Für spezifische Requirements, die Built-in-Rollen nicht abdecken, kann man Custom-Roles erstellen.

Example: Marketing-Team-Read-Access auf spezifische Collections

db.createRole({
  role: "marketingReader",
  privileges: [
    {
      resource: { db: "productionDB", collection: "campaigns" },
      actions: ["find", "aggregate"]
    },
    {
      resource: { db: "productionDB", collection: "customers" },
      actions: ["find"]
    }
  ],
  roles: []  // Kann auch andere Rollen inheriten
})

// User mit dieser Role
db.createUser({
  user: "marketingUser",
  pwd: "MarketingPass123!",
  roles: [
    { role: "marketingReader", db: "admin" }
  ]
})

Dieser User kann nur zwei Collections sehen – campaigns und customers – und nur Read-Actions (find, aggregate) ausführen.

Privilege-Components:

Jedes Privilege hat: - resource: Was wird kontrolliert? (Database, Collection, Cluster) - actions: Welche Actions sind erlaubt? (find, insert, update, remove, createIndex, etc.)

MongoDB hat hunderte Actions. Die wichtigsten:

Action Beschreibung
find Query-Documents
insert Insert-Documents
update Update-Documents
remove Delete-Documents
createIndex Index-Creation
dropIndex Index-Deletion
createCollection Collection-Creation
dropCollection Collection-Deletion
viewRole View-Roles
createUser User-Creation
dropUser User-Deletion

Für eine komplette Liste: MongoDB-Dokumentation unter “Privilege Actions”.

Role-Inheritance:

Custom-Roles können andere Rollen inheriten:

db.createRole({
  role: "dataScientist",
  privileges: [
    {
      resource: { db: "analyticsDB", collection: "" },  // Alle Collections
      actions: ["find", "aggregate"]
    }
  ],
  roles: [
    { role: "read", db: "productionDB" }  // Inherit read auf production
  ]
})

Dies kombiniert Custom-Privileges mit Built-in-Rollen – flexibel und maintainable.

39.7 Password-Management: Security-Best-Practices

Password-Complexity:

MongoDB enforced keine Password-Policies (anders als manche SQL-Datenbanken). Es akzeptiert jeden String als Password. Die Enforcement ist Application-Responsibility:

// Schlecht - weak password
db.createUser({
  user: "app",
  pwd: "123",
  roles: [...]
})

// Gut - strong password
db.createUser({
  user: "app",
  pwd: "Kj$9mL#pQ2wX!vN8",
  roles: [...]
})

Best Practice: Mindestens 16 Zeichen, Mix aus Upper/Lower/Digits/Symbols, keine Dictionary-Words.

Password-Rotation:

Passwords sollten regelmäßig rotated werden:

db.updateUser("appUser", {
  pwd: "NewSecurePassword456!"
})

Dies updated nur das Password, Roles bleiben unverändert. Für Production-Applications sollte man Password-Rotation automatisieren – etwa quarterly oder after Security-Incidents.

Externe Password-Management:

Für Enterprise-Environments sollte man Passwords nicht in Scripts hardcoden. Optionen:

  1. Environment Variables:
   export MONGODB_PASSWORD="SecurePass123!"
   mongosh --username app --password "$MONGODB_PASSWORD"
  1. Secrets-Management-Systems: HashiCorp Vault, AWS Secrets Manager, Azure Key Vault – diese speichern Credentials encrypted und rotaten sie automatisch.

  2. Certificate-Based-Authentication: Statt Passwords nutzt man X.509-Certificates. Kein Password-Management nötig.

39.8 Authentication-Mechanisms: Beyond Passwords

MongoDB unterstützt mehrere Authentication-Mechanisms für unterschiedliche Security-Requirements.

SCRAM-SHA-256 (Default):

Salted Challenge-Response – secure gegen Password-Sniffing und Rainbow-Tables. Dies ist der Default seit MongoDB 4.0:

db.createUser({
  user: "app",
  pwd: "Password123!",
  mechanisms: ["SCRAM-SHA-256"],  // Explicit, aber Default
  roles: [...]
})

SCRAM-SHA-1 (Legacy):

Weniger secure als SHA-256, aber für Compatibility mit sehr alten Clients:

mechanisms: ["SCRAM-SHA-1"]

Nur nutzen wenn nötig für Backward-Compatibility.

X.509 Certificate Authentication:

Für höchste Security nutzt man Certificates statt Passwords:

db.createUser({
  user: "CN=myapp,OU=Engineering,O=Company,C=US",  // From certificate subject
  roles: [{ role: "readWrite", db: "productionDB" }]
})

Connection via Certificate:

mongosh --tls \
  --tlsCertificateKeyFile /path/to/client.pem \
  --tlsCAFile /path/to/ca.pem \
  --authenticationMechanism MONGODB-X509

Der Username ist aus dem Certificate-Subject extrahiert. Kein Password nötig – das Certificate ist die Identity.

Vorteile: - Kein Password-Management - Stärkere Crypto (RSA/ECC) - Automatisches Certificate-Rotation via PKI

Nachteile: - Komplexere Setup (Certificate-Authority, PKI) - Certificate-Lifecycle-Management

LDAP (Enterprise):

MongoDB Enterprise kann mit LDAP integrieren für centralized User-Management:

// LDAP-User
db.createUser({
  user: "alice@company.com",
  roles: [{ role: "readWrite", db: "myDB" }]
})

Das Password wird gegen LDAP validated, nicht lokal in MongoDB gespeichert. User-Management passiert in Active Directory oder anderen LDAP-Systemen.

Kerberos (Enterprise):

Für Single-Sign-On in Enterprise-Umgebungen:

mongosh --authenticationMechanism GSSAPI \
  --username user@REALM.COM

Dies nutzt Kerberos-Tickets – kein Password-Input nötig.

39.9 User-Administration: CRUD-Operations

Listing Users:

// Alle Users in aktueller DB
db.getUsers()

// Spezifischer User
db.getUser("username")

Output zeigt Username, Roles, customData, aber nie das Password (nur Hash).

Updating Roles:

// Roles komplett ersetzen
db.updateUser("appUser", {
  roles: [
    { role: "readWrite", db: "productionDB" },
    { role: "read", db: "analyticsDB" }
  ]
})

// Role hinzufügen
db.grantRolesToUser("appUser", [
  { role: "dbAdmin", db: "productionDB" }
])

// Role entfernen
db.revokeRolesFromUser("appUser", [
  { role: "dbAdmin", db: "productionDB" }
])

grantRolesToUser und revokeRolesFromUser sind granularer als updateUser – sie ändern nur spezifische Roles, nicht alle.

Deleting Users:

db.dropUser("username")

Dies löscht den User permanent. Für Audit-Trails sollte man User nicht löschen, sondern deaktivieren (via Custom-Flag in customData).

39.10 Security-Best-Practices: Production-Hardening

1. Principle of Least Privilege:

Jeder User sollte nur minimale Permissions haben. Applications sollten nie root oder admin-Roles haben:

// Schlecht - zu viele Permissions
db.createUser({
  user: "app",
  pwd: "...",
  roles: [{ role: "root", db: "admin" }]  // BAD!
})

// Gut - nur nötige Permissions
db.createUser({
  user: "app",
  pwd: "...",
  roles: [{ role: "readWrite", db: "productionDB" }]  // Good
})

2. Separate Users für separate Applications:

Nicht einen shared User für alle Apps. Jede Application sollte eigenen User haben:

db.createUser({ user: "webApp", roles: [...] })
db.createUser({ user: "mobileApp", roles: [...] })
db.createUser({ user: "batchJobs", roles: [...] })

Dies erlaubt granulare Auditing und einfacheres Credential-Rotation.

3. Audit-Logging aktivieren (Enterprise):

MongoDB Enterprise hat Audit-Logging, das alle Auth-Events logged:

# mongod.conf
auditLog:
  destination: file
  format: JSON
  path: /var/log/mongodb/audit.json

Dies logged alle Login-Attempts, Failed-Auths, User-Creation, Role-Changes – essentiell für Security-Audits.

4. Network-Restrictions:

Users sollten nur von spezifischen IP-Ranges connecten dürfen. MongoDB selbst hat kein IP-Whitelisting per User, aber Firewalls können dies enforcem:

# iptables - nur localhost und App-Servers
iptables -A INPUT -p tcp --dport 27017 -s 127.0.0.1 -j ACCEPT
iptables -A INPUT -p tcp --dport 27017 -s 10.0.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 27017 -j DROP

5. TLS für alle Connections:

Authentication ohne Encryption ist vulnerabel zu Man-in-the-Middle. Alle Production-Connections sollten TLS nutzen:

# mongod.conf
net:
  tls:
    mode: requireTLS
    certificateKeyFile: /path/to/server.pem
    CAFile: /path/to/ca.pem

Clients müssen dann mit --tls connecten.

6. Regular Security-Audits:

Periodisch reviewen, welche Users existieren und welche Permissions sie haben:

// List all users mit ihren Rollen
db.getUsers().forEach(user => {
  print(`User: ${user.user}`)
  user.roles.forEach(role => {
    print(`  Role: ${role.role} on ${role.db}`)
  })
})

Inactive Users sollten deaktiviert oder deleted werden.

7. Password-Expiration (Custom-Implementation):

MongoDB hat keine Built-in-Password-Expiration. Man kann es via customData implementieren:

db.createUser({
  user: "app",
  pwd: "...",
  roles: [...],
  customData: {
    passwordSetAt: new Date(),
    passwordExpiresAt: new Date(Date.now() + 90 * 24 * 60 * 60 * 1000)  // 90 days
  }
})

// Application-Logic prüft passwordExpiresAt bei Login

Die folgende Tabelle fasst Security-Levels zusammen:

Level Authentication Authorization Encryption Audit
Development Optional Basic (readWrite) No TLS No
Staging Required Role-based TLS Optional
Production Required (Strong) Least-Privilege TLS Required Required
High-Security Certificate/LDAP Custom Roles TLS + Client-Certs Full Audit

User-Management in MongoDB ist nicht nur technisch – es ist fundamental für Security. Eine Datenbank ohne Authentication ist ein offenes Tor. Eine Datenbank mit schwachen Passwords oder Over-Privileged-Users ist kaum besser. Die Best Practice: Authentication immer aktiviert, strong Passwords (oder Certificates), Least-Privilege-Principle rigoros enforced, Audit-Logging für Compliance, und regelmäßige Security-Reviews. Mit diesen Practices wird User-Management von administrativem Overhead zu strategischem Security-Asset – die erste und wichtigste Defense-Line gegen unauthorized Access.