Shyam Arjarapu

Configure MongoDB with Kerberos Authentication

The MongoDB database administrators in a large enterprise may need to configure MongoDB to support Kerberos Authentication. The configuration of MongoDB with Kerberos authentication is very simple, provided you have some Kerberos knowledge. The MongoDB documentation article, Configure MongoDB with Kerberos Authentication on Linux, is pretty extensive on this topic. However, the article states — “Setting up and configuring a Kerberos deployment is beyond the scope of this document”, resulting in some of the starters/enthusiasts with limited knowledge in Kerberos not proceed any further. This article is geared more towards bridging that gap and to help you understand
  1. How Kerberos Works
  2. How to set up Kerberos and MongoDB in your lab
  3. Finally, How to integrate MongoDB with Kerberos authentication
This is one of the many articles in multi-part series, Mastering MongoDB — One tip a day, solely created for you to master MongoDB by learning ‘one tip a day’. In a few series of articles, I would like to give various tips to tighten the security on MongoDB. In this article, I would discuss “How to Integrate MongoDB with Kerberos Authentication”.

Mastering — MongoDB with Kerberos Authentication

What is a Kerberos

Kerberos is a computer network authentication protocol. It is designed to provide strong authentication for client/server applications by using secret-key cryptography. It works on the basis of tickets to allow nodes communicating over a non-secure network, to prove their identity to one another in a secure manner. The Kerberos protocol messages are protected against eavesdropping and replay attacks. The protocol was named after the character Kerberos (or Cerberus) from Greek mythology, the ferocious three-headed guard dog of Hades.

How does Kerberos work

Instead of asking the client to enter username/password credentials for every service they access, the Kerberos allows single sign-on by using the tickets. These proof of identity tickets are issued by a trusted 3rd party (Key Distribution Center) and are typically encrypted with a secret/symmetric key. This section discusses how various resources within the Kerberos Realm interacts with each other during the authentication process.

Key Distribution Center

In order to administer the access to a resource via Kerberos, all of the components, services, and users must be in the Kerberos Realm. The Kerberos Distribution Center (KDC) is at the core of the Kerberos Realm and has following key server components
  • Database Server — Stores secret keys of registered users and Services
  • Authentication Server — Provides a ticket to access Ticket-Granting Server
  • Ticket-Granting Server — Provides a ticket to access the service of interest
The KDC’s database stores all of the secret keys for user machines and services. The secret keys are in-turn a hash value of the password plus a salt. The database itself is further encrypted with a master key to prevent anyone stealing keys from the database’s file system.

The flow of events during the authentication process

Let’s say you want to access the MongoDB Service using Kerberos authentication. During the authentication process, the following resources process/exchange information with a defined objective
  • Client. Objective: Login using kinit
  • Client and Authentication Service. Objective: Get Ticket-Granting-Ticket
  • Client and Ticket-Granting Service. Objective: Get Service Ticket
  • Client and MongoDB Service. Objective: Get access to MongoDB Service
    The sequence of events occurring during Kerberos authentication process
The above diagram shows various resources/components involved in the Kerberos authentication process and illustrates how they interact with each other. Let’s try to understand the internal details of each step.
Please pay special attention to the color of the lock icon, an encrypted message. It can only be decrypted by the resource having the same colored secret key.

Login using kinit

The User (AKA Client/Principal) must introduce themselves to the Authentication Server by logging into the computer, or by running the command kinit <username>

Communication between the User and the Authentication Server

Every User must have a Ticket-Granting Ticket (TGT) issued by Authentication Server before accessing any Service. The TGT is a ticket that allows the user to get Tickets for accessing services of their interest.
The User’s objective is to get a Ticket-Granting Ticket by sending a request to Authentication Server. The request message contains
  • Username: Username / Client ID
    Service Requested: Ticket-Granting Service
    Network Address: Client’s IP Address
    Expiration: Lifetime of TGT
    Timestamp: When the request message was created
The Authentication Server processes the request and checks if Timestamp in the message is within 5 min, checks if the User and requested Service are in KDC. It finally issues a Ticket-Granting Ticket, generates and shares Ticket-Granting Session Key with the User.
The Authentication Server responds to the User’s request with two messages. The Response #1 is encrypted with Client Secret Key (Cyan color key) and the message has below contents —
  • Service: Ticket-Granting Service
    Timestamp: When it was created
    Validity: Lifetime of TGT
    TGS Session Key (Magenta color key )
The Response #2 is Ticket Granting Ticket, TGT, which is encrypted with TGS Secret Key (Yellow color key). It can only be decrypted by KDC. The message has below contents —
  • Username: Your Name / ID
    Service: Ticket-Granting Service
    Timestamp: When it was created
    Network Address: IP Address
    Validity: Lifetime of TGT
    TGS Session Key
The Client processes Authentication Service response and decrypts Response #1 using the User's Secret Key (Cyan color key). Upon successful decryption, both the User and the KDC has TGS Session Key (Magenta color key ). The TGS Session Key is used for encrypting the communication between the Client and the Ticket Granting Server. The Client cannot decrypt the Response #2, TGT, as it does not have TGS Secret Key but it would be stored within client’s credential cache.
Communication between the User and the Ticket-Granting Server
With the Ticket-Granting Ticket in hand, the client can request Ticket-Granting Server for a ticket to access the MongoDB Service. Upon validating the TGT, the Ticket Granting Server will issue a Service Ticket, STKT, to request access for MongoDB Server.
The User’s objective is to get a Service Ticket by sending a request to Ticket Granting Server. The Request #1 message has below contents —
  • Validity: Lifetime of TGT
    Service Requested: MongoDB Service
    Ticket-Granting Ticket (only KDC can decrypt)
The Request #2 is encrypted with TGS Secret Key (Magenta color key) and the message has below contents —
  • Username: Your Name / ID
    Timestamp: When it was created
The Ticket-Granting Server processes the request, checks if Timestamp in the message is within 5 min, checks if the service MongoDB Service is registered with KDC. It finally issues a Service Ticket, generates and shares MongoDB Service Session Key (Royal Blue color key) with the User.
The Ticket Granting Server responds to the User’s request with two messages. The Response #1 is encrypted with TGS Session Key (Magenta color key) and the message has below contents —
  • Service Requested: MongoDB Service
    Timestamp: When it was created
    Validity: Lifetime of TGT
    Service Session Key (Royal Blue key )
The Response #2 is encrypted with MongoDB Secret Key (Green color key) and can be decrypted only by MongoDB Server. The message has below message contents —
  • Username: Your Name / ID
    Service: MongoDB Service
    Timestamp: When it was created
    Network Address: IP Address
    Validity: Lifetime of STKT
    MongoDB Service Session Key
The MongoDB Service Session Key is used for encrypting the communication between the User and the MongoDB server. The Client cannot decrypt the Response #2, STKT, as it does not have MongoDB Secret Key but it would be stored within the client’s credential cache.
Communication between the User and the MongoDB Service
With the Service Ticket in hand, the client can send a login request to MongoDB Server. The MongoDB Server will validate the Service Ticket and sets the authorized roles and privileges for the User's login session.
The User’s objective is to get access to MongoDB Service by sending a login request to MongoDB Server. The Request #1 is encrypted with MongoDB Session Key (Royal Blue color key) and the message has below contents —
  • Username: Your Name / ID
    Timestamp: When it was created
The Request #2 is the Service Ticket itself which can be decrypted only by MongoDB Server using it’s Secret Key (Green color key). The message has below contents —
  • Username: Your Name / ID
    Service: MongoDB Service
    Timestamp: When it was created
    Network Address: IP Address
    Validity: Lifetime of STKT
    MongoDB Service Session Key
The MongoDB Server processes the request, checks if Timestamp in the message is within 5 min, checks if the User is registered with the database. It finally sets the roles and privileges for the User.
The MongoDB Server responds to the User’s request with a message. The Response #1 is encrypted with MongoDB Session Key (Royal Blue color key) and the message has below contents —
  • Username: Your Name / ID
    Service: MongoDB Service
The Client processes MongoDB Service response and decrypts Response #1 using the MongoDB Session Key (Royal Blue color key). Upon successful decryption, and validation, the Client would communicate directly with the MongoDB Server for further database requests.
I know it’s a lot of information to digest especially if you have no knowledge of Kerberos. For further reading on Kerberos, I strongly recommend you to read Lynn Root’s article Explain like I’m 5: Kerberos and/or watch the YouTube video Kerberos — CompTIA Security by Professor Messer.

Hands-On lab exercises

Now that you understood the theory and information flow during Kerberos authentication, let's work on setting up a lab environment. This lab exercise helps you understand how to set up Kerberos, MongoDB and configure a client to use them on a CentOS 7.5.

Setup environment

First, you would need an environment to play around. In this example, I have created 3 AWS EC2 instances, one for each server — KDC, MongoDB Server and User machine. If you are short on resources, you could potentially install them all on the same lab server.
Please make sure to configure your firewall/security groups to allow incoming traffic on ports 88, 749, 27017 for respective services.
# Run these commands on all 3 servers
# Install NTP to synchronize the clock on all three servers
sudo yum install -y ntp
sudo ntpdate 0.rhel.pool.ntp.org
sudo systemctl start  ntpd.service
sudo systemctl enable ntpd.service

# TODO: Fix the below ip addresses based on your lab environment
echo "172.31.10.101     kdc.mdbkrb5.net" | sudo tee -a /etc/hosts
echo "172.31.10.102     mdb01.mdbkrb5.net" | sudo tee -a /etc/hosts
echo "172.31.10.103     client01.mdbkrb5.net" | sudo tee -a /etc/hosts
A bash script to install ntpd service on all three servers (KDC, MongoDB Server and User machine)

Installing & Configuring KDC Server

Login to the KDC server to install/configure the Kerberos Server.
sudo yum install -y krb5-server

# Rename the Kerberos Realm name from EXAMPLE.COM to MDBKRB5.NET, or any name of your choice
sudo sed -i 's/EXAMPLE.COM/MDBKRB5.NET/g' /var/kerberos/krb5kdc/kdc.conf
sudo sed -i 's/EXAMPLE.COM/MDBKRB5.NET/g' /var/kerberos/krb5kdc/kadm5.acl
sudo sed -i 's/kerberos.example.com/kdc.mdbkrb5.net/g' /etc/krb5.conf
sudo sed -i 's/example.com/mdbkrb5.net/g' /etc/krb5.conf
sudo sed -i 's/EXAMPLE.COM/MDBKRB5.NET/g' /etc/krb5.conf
sudo sed -i 's/#//g' /etc/krb5.conf
sudo sed -i 's/^ Configuration/# Configuration/g' /etc/krb5.conf
A bash script to install Kerberos server on KDC server and configure the files with MDBKRB5.NET realm
For your convenience, I am illustrating how the file contents would look like after running the above commands.
# File: /etc/krb5.conf
# Configuration snippets may be placed in this directory as well
includedir /etc/krb5.conf.d/
[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log
[libdefaults]
 dns_lookup_realm = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true
 rdns = false
 default_realm = MDBKRB5.NET
 default_ccache_name = KEYRING:persistent:%{uid}
[realms]
 MDBKRB5.NET = {
  kdc = kdc.mdbkrb5.net
  admin_server = kdc.mdbkrb5.net
 }
[domain_realm]
 .mdbkrb5.net = MDBKRB5.NET
 mdbkrb5.net = MDBKRB5.NET



# File: /var/kerberos/krb5kdc/kdc.conf
[kdcdefaults]
 kdc_ports = 88
 kdc_tcp_ports = 88
[realms]
 MDBKRB5.NET = {
  #master_key_type = aes256-cts
  acl_file = /var/kerberos/krb5kdc/kadm5.acl
  dict_file = /usr/share/dict/words
  admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
  supported_enctypes = aes256-cts:normal aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal camellia256-cts:normal camellia128-cts:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal
 }



# File: /var/kerberos/krb5kdc/kadm5.acl
*/admin@MDBKRB5.NET	*
The file contents of Kerberos configuration files
Next, you need to create a Kerberos database for the Realm and create the Principal entries for the Users, Services etc
# Create Kerberos database for the realm
sudo kdb5_util create -s -r MDBKRB5.NET
# Loading random data
# Initializing database '/var/kerberos/krb5kdc/principal' for realm 'MDBKRB5.NET',
# master key name 'K/M@MDBKRB5.NET'
# You will be prompted for the database Master Password.
# It is important that you NOT FORGET this password.
# Enter KDC database master key:
# Re-enter KDC database master key to verify:

sudo systemctl start krb5kdc.service
sudo systemctl start kadmin.service
sudo systemctl enable krb5kdc.service
sudo systemctl enable kadmin.service

# Set up a Kerberos principal with admin privileges
# and principal for the users, KDC host, and MongoDB server
# for simplicity I used <user/service name>@123 as the password
# Commands you need to run
sudo kadmin.local
# Authenticating as principal root/admin@MDBKRB5.NET with password.
# kadmin.local:
# Run the below commands at kadmin.local prompt

addprinc root/admin
# Enter password for principal "root/admin@MDBKRB5.NET":
# Re-enter password for principal "root/admin@MDBKRB5.NET":
# Principal "root/admin@MDBKRB5.NET" created.
addprinc alex
# Enter password for principal "alex@MDBKRB5.NET":
# Re-enter password for principal "alex@MDBKRB5.NET":
# Principal "alex@MDBKRB5.NET" created.
addprinc bob
# Enter password for principal "bob@MDBKRB5.NET":
# Re-enter password for principal "bob@MDBKRB5.NET":
# Principal "bob@MDBKRB5.NET" created.
addprinc host/kdc.mdbkrb5.net
# Enter password for principal "host/kdc.mdbkrb5.net@MDBKRB5.NET":
# Re-enter password for principal "host/kdc.mdbkrb5.net@MDBKRB5.NET":
# Principal "host/kdc.mdbkrb5.net@MDBKRB5.NET" created.
addprinc mongodb/mdb01.mdbkrb5.net
# Enter password for principal "mongodb/mdb01.mdbkrb5.net@MDBKRB5.NET":
# Re-enter password for principal "mongodb/mdb01.mdbkrb5.net@MDBKRB5.NET":
# Principal "mongodb/mdb01.mdbkrb5.net@MDBKRB5.NET" created.

q
A bash script to create a Kerberos database for the Realm and create the Principal entries for the Users, Services etc

Setup the MongoDB Server

Login to the MongoDB server to install/configure the MongoDB Server, mdb01.mdbkrb5.net
# Install the Kerberos client
sudo yum install -y krb5-workstation

# TODO: Copy the /etc/krb5.conf file contents from
# Kerberos Server's config file to MongoDB server
sudo cat /etc/krb5.conf
A bash script to install the Kerberos client and display the Kerberos configuration file
Next, you would need to install the MongoDB Enterprise server, create the MongoDB keyfile, configure the /etc/mongod.conf file, etc
sudo tee /etc/yum.repos.d/mongodb-enterprise.repo << EOF
[mongodb-enterprise]
name=MongoDB Enterprise Repository
baseurl=https://repo.mongodb.com/yum/redhat/\$releasever/mongodb-enterprise/4.0/\$basearch/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.0.asc
EOF

# Install the MongoDB server
sudo yum install -y mongodb-enterprise

## Disable the selinux
sudo setenforce 0
sudo sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

# Configure mongod.conf with Kerberos settings
sudo tee /etc/mongod.conf << EOF
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log
storage:
  dbPath: /var/lib/mongo
  journal:
    enabled: true
processManagement:
  fork: true  # fork and run in background
  pidFilePath: /var/run/mongodb/mongod.pid  # location of pidfile
  timeZoneInfo: /usr/share/zoneinfo
net:
  port: 27017
  bindIp: 0.0.0.0 # <-- TODO: Exposes MongoDB to Public IP. Please use internal IPs instead
security:
  authorization: enabled
  keyFile: /var/lib/mongo/private/keyfile
  sasl:
    hostName: mdb01.mdbkrb5.net
replication:
  replSetName: rs0
setParameter:
  authenticationMechanisms: GSSAPI,SCRAM-SHA-256
EOF

# Create a directory to store MongoDB keyfile and Kerberos keytab file
sudo mkdir -p /var/lib/mongo/private
openssl rand -base64 756 | sudo tee /var/lib/mongo/private/keyfile
sudo chmod 400 /var/lib/mongo/private/keyfile
A bash script to install the MongoDB and set the MongoDB configuration files
Create a keytab file to store Kerberos service principals and encrypted keys
sudo ktutil
# ktutil:  
# Run the below commands at ktutil prompt

addent -password -p mongodb/mdb01.mdbkrb5.net -k 2 -e aes256-cts
# Password for mongodb/mdb01.mdbkrb5.net@MDBKRB5.NET:

write_kt /var/lib/mongo/private/mon01.keytab
q
A bash script to help you create the Kerberos keytab file
Set the folders permissions to only allow the user mongod to read them.
sudo klist -k /var/lib/mongo/private/mon01.keytab
# Keytab name: FILE:/var/lib/mongo/private/mon01.keytab
# KVNO Principal
# ---- ------------------------------------------
#    2 mongodb/mdb01.mdbkrb5.net@MDBKRB5.NET

# Set the keytab file location in environment variable
echo "KRB5_KTNAME=/var/lib/mongo/private/mon01.keytab" | sudo tee /etc/sysconfig/mongod

# Change the folder ownership to mongod
sudo chown -R mongod:mongod /var/lib/mongo/private
sudo systemctl start mongod
A bash script to configure environment variables and set permissions for the folders
Finally, let’s create the following in MongoDB server
  • superuser with root privileges
  • alex Principal with root role on admin database
  • bob Principal with readWrite role on social database
  • mongo --quiet admin <<EOF
    rs.initiate();
    sleep(10000);
    db.createUser({user: 'superuser', pwd: 'superuser', roles: ['root']});
    db.auth('superuser', 'superuser');
    use \$external;
    db.createUser({user: 'alex@MDBKRB5.NET', roles: [{ role: 'root', db: 'admin'}]});
    db.createUser({user: 'bob@MDBKRB5.NET', roles: [{ role: 'readWrite', db: 'social'}]});
    EOF
    
    # {
    #   "info2": "no configuration specified. Using a default configuration for the set",
    #   "me": "ip-172-31-10-102.us-west-2.compute.internal:27017",
    #   "ok": 1
    # }
    # Successfully added user: {
    #   "user": "superuser",
    #   "roles": ["root"]
    # }
    # 1
    # switched to db $external
    # Successfully added user: {
    #   "user": "alex@MDBKRB5.NET",
    #   "roles": [{
    #     "role": "root",
    #     "db": "admin"
    #   }]
    # }
    # Successfully added user: {
    #   "user": "bob@MDBKRB5.NET",
    #   "roles": [{
    #     "role": "readWrite",
    #     "db": "social"
    #   }]
    # }
    # bye
    A bash script using mongo client to create replica set and user privileges on $external database

Install MongoDB client on the client01.mdbkrb5.net

Login to the MongoDB client server to install the Kerberos and MongoDB clients.
# Install the Kerberos client
sudo yum install -y krb5-workstation

# TODO: Copy the /etc/krb5.conf file contents from
# Kerberos Server's config file to the Client's machine
sudo cat /etc/krb5.conf
A bash script to install the Kerberos client and display the Kerberos configuration file on the User machine
First, install the MongoDB shell and Enterprise dependencies using Yum.
sudo tee /etc/yum.repos.d/mongodb-enterprise.repo << EOF
[mongodb-enterprise]
name=MongoDB Enterprise Repository
baseurl=https://repo.mongodb.com/yum/redhat/\$releasever/mongodb-enterprise/4.0/\$basearch/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.0.asc
EOF

# Install the mongodb enterprise dependencies and mongodb shell
sudo yum install -y cyrus-sasl cyrus-sasl-gssapi cyrus-sasl-plain krb5-libs libcurl libpcap lm_sensors-libs net-snmp net-snmp-agent-libs openldap openssl rpm-libs tcp_wrappers-libs
sudo yum install -y mongodb-enterprise-shell-4.0.2
A bash script to install the MongoDB shell and the MongoDB Enterprise dependencies
Login to the Kerberos as bob and then log in to the MongoDB Server to test the readWrite permissions on the social database.
# Login into the Kerberos as bob
kinit -p bob
# Password for bob@MDBKRB5.NET:

klist
# Ticket cache: KEYRING:persistent:1000:1000
# Default principal: bob@MDBKRB5.NET
# Valid starting       Expires              Service principal
# 10/04/2018 16:58:49  10/05/2018 16:58:48  krbtgt/MDBKRB5.NET@MDBKRB5.NET

mongo social --quiet --host mdb01.mdbkrb5.net --authenticationMechanism=GSSAPI --authenticationDatabase='$external' --username bob@MDBKRB5.NET
# MongoDB Enterprise rs0:PRIMARY>
# Run the below commands at rs0:PRIMARY prompt

# db.runCommand({connectionStatus: 1}).authInfo
# {
#   "authenticatedUsers": [
#     {
#       "user": "bob@MDBKRB5.NET",
#       "db": "$external"
#     }
#   ],
#   "authenticatedUserRoles": [
#     {
#       "role": "readWrite",
#       "db": "social"
#     }
#   ]
# }

# Test the write privilege on social database
db.people.insert({fname: 'Shyam', lname: 'Arjarapu'})
# WriteResult({ "nInserted" : 1 })

# Test the read privilege on social database
db.people.findOne()
# {
# 	"_id" : ObjectId("5bb647a8315c61d11c361945"),
# 	"fname" : "Shyam",
# 	"lname" : "Arjarapu"
# }

# Note that bob has no previleges on admin database
use admin
# switched to db admin
show collections
# Warning: unable to run listCollections, attempting to approximate collection names by parsing connectionStatus
A bash script illustrating authentication to MongoDB via Kerberos SSO and authorization on MongoDB
If you run the same tests for the user, alex, then you would be able to query both social and admin databases because of his root role.

Summary

As stated at the beginning of the article — “Configuring MongoDB with Kerberos Authentication is very simple!”. However, without proper Kerberos knowledge, your hands are pretty much tied-down to do a simple POC.
Hopefully, this article has simplified the understanding of Kerberos events, and shed some light on “How to integrate MongoDB with Kerberos Authentication”.
The MongoDB Enterprise provides integration with Kerberos as well as LDAP authentication mechanisms. Although the MongoDB is using Kerberos Authentication, the user management still requires the User privileges to be created in the MongoDB. If your organization has 100s of users requiring access to MongoDB then you may to explore the use of LDAP for both authentication and authorization. But that’s a topic for another day. Hopefully, you learned something new today as you scale the path to “Mastering MongoDB — One tip a day”.

Previously published articles

Tip # 005: Getting started with MongoDB Enterprise Operator
Now you could deploy MongoDB in Kubernetes under a minute
Tip # 004: Faster elections
Measures to reduce the election time during the rolling maintenance
Tip # 003: Transactions
A long awaited and most requested feature for many, has finally arrived
Tip # 002: createRole
Ahhh …! Someone just dropped a collection
Tip # 001: currentOp
Know the operations currently executing on MongoDB server inside out

Tags

More by Shyam Arjarapu

Topics of interest