New to KubeDB? Please start here.

Run MongoDB with TLS/SSL (Transport Encryption)

KubeDB supports providing TLS/SSL encryption (via, sslMode and clusterAuthMode) for MongoDB. This tutorial will show you how to use KubeDB to run a MongoDB database with TLS/SSL encryption.

Before You Begin

  • At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using kind.

  • Install cert-manger v1.0.0 or later to your cluster to manage your SSL/TLS certificates.

  • Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps here.

  • To keep things isolated, this tutorial uses a separate namespace called demo throughout this tutorial.

    $ kubectl create ns demo
    namespace/demo created
    

Note: YAML files used in this tutorial are stored in docs/examples/mongodb folder in GitHub repository kubedb/docs.

Overview

KubeDB uses following crd fields to enable SSL/TLS encryption in Mongodb.

  • spec:
    • sslMode
    • tls:
      • issuerRef
      • certificate
    • clusterAuthMode

Read about the fields in details in mongodb concept,

sslMode, and tls is applicable for all types of MongoDB (i.e., standalone, replicaset and sharding), while clusterAuthMode provides ClusterAuthMode for MongoDB clusters (i.e., replicaset and sharding).

When, SSLMode is anything other than disabled, users must specify the tls.issuerRef field. KubeDB uses the issuer or clusterIssuer referenced in the tls.issuerRef field, and the certificate specs provided in tls.certificate to generate certificate secrets. These certificate secrets are then used to generate required certificates including ca.crt, mongo.pem and client.pem.

The subject of client.pem certificate is added as root user in $external mongodb database. So, user can use this client certificate for MONGODB-X509 authenticationMechanism.

Create Issuer/ ClusterIssuer

We are going to create an example Issuer that will be used throughout the duration of this tutorial to enable SSL/TLS in MongoDB. Alternatively, you can follow this cert-manager tutorial to create your own Issuer.

  • Start off by generating you ca certificates using openssl.
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=mongo/O=kubedb"
  • Now create a ca-secret using the certificate files you have just generated.
kubectl create secret tls mongo-ca \
     --cert=ca.crt \
     --key=ca.key \
     --namespace=demo

Now, create an Issuer using the ca-secret you have just created. The YAML file looks like this:

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: mongo-ca-issuer
  namespace: demo
spec:
  ca:
    name: mongo-ca

Apply the YAML file:

$ kubectl create -f https://github.com/kubedb/docs/raw/v2020.11.12/docs/examples/mongodb/tls/issuer.yaml
issuer.cert-manager.io/mongo-ca-issuer created

TLS/SSL encryption in MongoDB Sharding

Below is the YAML for MongoDB Sharding. Here, spec.sslMode specifies sslMode for sharding and spec.clusterAuthMode provides clusterAuthMode for sharding servers.

apiVersion: kubedb.com/v1alpha2
kind: MongoDB
metadata:
  name: mongo-sh-tls
  namespace: demo
spec:
  version: "4.1.13-v1"
  sslMode: requireSSL
  tls:
    issuerRef:
      apiGroup: "cert-manager.io"
      kind: Issuer
      name: mongo-ca-issuer
  clusterAuthMode: x509
  shardTopology:
    configServer:
      replicas: 2
      storage:
        resources:
          requests:
            storage: 1Gi
        storageClassName: standard
    mongos:
      replicas: 2
    shard:
      replicas: 2
      shards: 2
      storage:
        resources:
          requests:
            storage: 1Gi
        storageClassName: standard
  storageType: Durable
  terminationPolicy: WipeOut

Deploy MongoDB Sharding

$ kubectl create -f https://github.com/kubedb/docs/raw/v2020.11.12/docs/examples/mongodb/tls/mg-shard-ssl.yaml
mongodb.kubedb.com/mongo-sh-tls created

Now, wait until mongo-sh-tls created has status Running. ie,

$ watch kubectl get mg -n demo
Every 2.0s: kubectl get mongodb -n demo
NAME           VERSION     STATUS     AGE
mongo-sh-tls   4.1.13-v1   Creating   4m24s

Verify TLS/SSL in MongoDB Sharding

Now, connect to mongos component of this database through mongo-shell and verify if SSLMode and ClusterAuthMode has been set up as intended.

$ kubectl describe secret -n demo mongo-sh-tls-client-cert
Name:         mongo-sh-tls-client-cert
Namespace:    demo
Labels:       <none>
Annotations:  cert-manager.io/alt-names:
              cert-manager.io/certificate-name: mongo-sh-tls-client-cert
              cert-manager.io/common-name: root
              cert-manager.io/ip-sans:
              cert-manager.io/issuer-group: cert-manager.io
              cert-manager.io/issuer-kind: Issuer
              cert-manager.io/issuer-name: mongo-ca-issuer
              cert-manager.io/uri-sans:

Type:  kubernetes.io/tls

Data
====
ca.crt:   1147 bytes
tls.crt:  1172 bytes
tls.key:  1679 bytes

Now, Let’s exec into a mongodb container and find out the username to connect in a mongo shell,

$ kubectl exec -it mongo-sh-tls-mongos-0 -n demo bash
[email protected]:/$ ls /var/run/mongodb/tls
ca.crt  client.pem  mongo.pem
[email protected]:/$ openssl x509 -in /var/run/mongodb/tls/client.pem -inform PEM -subject -nameopt RFC2253 -noout
subject=CN=root,OU=client,O=kubedb

Now, we can connect using CN=root,OU=client,O=kubedb as root to connect to the mongo shell,

[email protected]:/# mongo --tls --tlsCAFile /var/run/mongodb/tls/ca.crt --tlsCertificateKeyFile /var/run/mongodb/tls/client.pem admin --host localhost --authenticationMechanism MONGODB-X509 --authenticationDatabase='$external' -u "CN=root,OU=client,O=kubedb" --quiet
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
	http://docs.mongodb.org/
Questions? Try the support group
	http://groups.google.com/group/mongodb-user
mongos>

We are connected to the mongo shell. Let’s run some command to verify the sslMode and the user,

mongos> db.adminCommand({ getParameter:1, sslMode:1 })
{
	"sslMode" : "requireSSL",
	"ok" : 1,
	"operationTime" : Timestamp(1599491398, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1599491398, 1),
		"signature" : {
			"hash" : BinData(0,"cn2Mhfy2blonon3jPz6Daen0nnc="),
			"keyId" : NumberLong("6869760899591176209")
		}
	}
}
mongos> use $external
switched to db $external
mongos> show users
{
	"_id" : "$external.CN=root,OU=client,O=kubedb",
	"userId" : UUID("4865dda6-5e31-4b79-a085-7d6fea51c9be"),
	"user" : "CN=root,OU=client,O=kubedb",
	"db" : "$external",
	"roles" : [
		{
			"role" : "root",
			"db" : "admin"
		}
	],
	"mechanisms" : [
		"external"
	]
}
> exit
bye

You can see here that, sslMode is set to requireSSL and clusterAuthMode is set to x509 and also an user is created in $external with name "CN=root,OU=client,O=kubedb".

Changing the SSLMode & ClusterAuthMode

User can update sslMode & ClusterAuthMode if needed. Some changes may be invalid from mongodb end, like using sslMode: disabled with clusterAuthMode: x509.

Good thing is, KubeDB operator will throw error for invalid SSL specs while creating/updating the MongoDB object. i.e.,

$ kubectl patch -n demo mg/mgo-sh-tls -p '{"spec":{"sslMode": "disabled","clusterAuthMode": "x509"}}' --type="merge"
Error from server (Forbidden): admission webhook "mongodb.validators.kubedb.com" denied the request: can't have disabled set to mongodb.spec.sslMode when mongodb.spec.clusterAuthMode is set to x509

To upgrade from Keyfile Authentication to x.509 Authentication, change the sslMode and clusterAuthMode in recommended sequence as suggested in official documentation. Each time after changing the specs, follow the procedure that is described above to verify the changes of sslMode and clusterAuthMode inside the database.

Cleaning up

To cleanup the Kubernetes resources created by this tutorial, run:

kubectl delete mongodb -n demo mongo-sh-tls
kubectl delete issuer -n demo mongo-ca-issuer
kubectl delete ns demo

Next Steps