DEV Community

keploy
keploy

Posted on • Originally published at keploy.io

Securing Databases with SSL in Docker Containers

Image description

Why Enable SSL for Databases?

Security is critical for any application, especially when dealing with sensitive data like financial records or user information. Databases such as MongoDB and PostgreSQL communicate over the network, making them vulnerable to interception.

SSL (Secure Sockets Layer) encrypts the communication between the client and the database server to prevent data exposure. This encryption ensures that:

1. Data Integrity: No third party can modify the data in transit.

2. Data Confidentiality: Only authorized clients can access the database.

3. Authentication: Servers and clients can verify each other’s identities through certificates.

Why Use Docker for Database SSL Setup?

In production, cloud services such as MongoDB Atlas, Amazon RDS, or Azure Database provide SSL-enabled databases. However, for local development and testing, setting up cloud databases can be overkill, time-consuming, and sometimes costly. Docker offers a quick and consistent way to spin up containers replicating production environments. This helps developers:

1. Avoid cloud dependency during development.

2. Test SSL setups locally before deploying to production.

3. Standardize environments across development machines.

Enabling SSL in Docker Containers

Let’s walk through how to configure SSL for MongoDB and PostgreSQL within Docker containers.

Generating Certificates with OpenSSL

Before we can enable SSL for databases, we need certificates. Below is the script to generate the required files using OpenSSL.

#! /bin/bash

# Create a Certificate Authority (CA):
openssl genrsa -out ca.key 4096
openssl req -x509 -new -nodes -key ca.key -sha256 -days 365 -out ca.crt -subj "/C=US/ST=NewYork/L=NewYork/O=Keploy/OU=DevOps/CN=ca"

# Create a Certificate for MongoDB Server:
openssl genrsa -out mongodb.key 4096
openssl req -new -key mongodb.key -out mongodb.csr -subj "/C=US/ST=NewYork/L=NewYork/O=Keploy/OU=MongoDB/CN=localhost"
openssl x509 -req -in mongodb.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out mongodb.crt -days 365 -sha256

# Combine the Server Certificate and Key:
cat mongodb.crt mongodb.key > mongodb.pem

chmod 600 mongodb.pem
chmod 600 ca.crt
Enter fullscreen mode Exit fullscreen mode

Explanation of Commands and Files

1. Certificate Authority (CA) Creation:

openssl genrsa -out ca.key 4096: Generates a 4096-bit private key for the CA

openssl req -x509 -new -nodes -key ca.key -sha256 -days 365 -out ca.crt: Creates a self-signed CA certificate valid for 365 days. This CA will sign the server certificates.

Why CA?

A CA certifies the legitimacy of the server by signing its certificate. This avoids the need for clients to trust individual certificates directly.

2. Server Certificate Generation:

openssl genrsa -out mongodb.key 4096: Creates the MongoDB server’s private key.

openssl req -new -key mongodb.key -out mongodb.csr: Generates a certificate signing request (CSR) using the private key.

openssl x509 -req -in mongodb.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out mongodb.crt -days 365: Uses the CA to sign the server’s CSR, issuing a certificate valid for 365 days.

3. Combining Certificate and Key:

cat mongodb.crt mongodb.key > mongodb.pem: Merges the server’s certificate and private key into a single file (mongodb.pem) for easy use.

4. File Permissions:

chmod 600 mongodb.pem and chmod 600 ca.crt: Sets strict permissions, ensuring only authorized users can read the files.

Generated Files:

  • ca.crt: CA certificate (used by clients to trust the server).

  • ca.key: CA private key.

  • mongodb.key: MongoDB server private key.

  • mongodb.csr: Certificate signing request for the server.

  • mongodb.crt: Signed server certificate.

  • mongodb.pem: Combined key and certificate for the server.

Adding the CA Certificate to the Trust Store

To ensure the client trusts the server certificate, the CA certificate (ca.crt) needs to be added to the root CA store.

Java Example

  1. Check the Java home directory:

    java -XshowSettings:properties -version 2>&1 | grep "^    java.home ="
    
  2. Add the CA to Java’s keystore:

    sudo keytool -import -trustcacerts -file ca.crt -alias mongoCA -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit -noprompt
    

Other Languages:

  • Node.js: Use the environment variable NODE_EXTRA_CA_CERTS to specify the CA certificate.

  • For other systems, this guide can help you install the certificate.

Running MongoDB with SSL in Docker

Use the following command to run the MongoDB container with SSL enabled.

docker run --rm --name mongo-tls \
  -v $(pwd)/ca.crt:/etc/ssl/mongodb/ca.crt \
  -v $(pwd)/mongodb.pem:/etc/ssl/mongodb/mongodb.pem \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=password \
  -p 27017:27017 \
  mongo --tlsMode requireTLS \
        --tlsCertificateKeyFile /etc/ssl/mongodb/mongodb.pem \
        --tlsCAFile /etc/ssl/mongodb/ca.crt \
        --tlsAllowConnectionsWithoutCertificates \
        --bind_ip_all
Enter fullscreen mode Exit fullscreen mode

Explanation of Docker Command

  1. Mounts (-v):
* `$(pwd)/ca.crt` and `$(pwd)/mongodb.pem` are mounted into the container to provide the CA and server certificates.
Enter fullscreen mode Exit fullscreen mode
  1. Environment Variables (-e):
* `MONGO_INITDB_ROOT_USERNAME` and `MONGO_INITDB_ROOT_PASSWORD` are used to set up a root user.
Enter fullscreen mode Exit fullscreen mode
  1. Port Mapping (-p):
* Maps the container’s port `27017` to the host.
Enter fullscreen mode Exit fullscreen mode

MongoDB TLS Flags

  • --tlsMode requireTLS: Enforces encrypted communication.

  • --tlsCertificateKeyFile: Specifies the server’s certificate and key.

  • --tlsCAFile: Provides the CA certificate to verify the server certificate.

  • --tlsAllowConnectionsWithoutCertificates: Allows clients to connect without their own certificates.

    • Without this flag: MongoDB expects mutual TLS, where both client and server provide certificates to authenticate each other

Using SSL with PostgreSQL and Other Databases

The setup for other databases, such as PostgreSQL, is very similar to the one for MongoDB. Here’s how you can run a PostgreSQL container with SSL enabled using Docker:

docker run --rm --name postgres-tls \
  -v $(pwd)/ca.crt:/etc/ssl/postgresql/ca.crt \
  -v $(pwd)/postgres.pem:/etc/ssl/postgresql/postgres.pem \
  -v /Users/gouravkumar/Desktop/Keploy/SampleProjects/samples-java/employee-manager/src/main/resources/data.sql:/docker-entrypoint-datadb.d/data.sql \
  -e POSTGRES_USER=keploy-user \
  -e POSTGRES_PASSWORD=keploy \
  -e POSTGRES_DB=keploy-test \
  -p 5432:5432 \
  postgres:latest \
  -c ssl=on \
  -c ssl_cert_file=/etc/ssl/postgresql/postgres.pem \
  -c ssl_key_file=/etc/ssl/postgresql/postgres.pem \
  -c ssl_ca_file=/etc/ssl/postgresql/ca.crt \
  -c ssl_prefer_server_ciphers=on \
  -c listen_addresses='*'
Enter fullscreen mode Exit fullscreen mode

Explanation of PostgreSQL Docker Command

  1. Mounts (-v):
* Mounts the CA certificate and the combined certificate/key file into the container.

* Loads the initial SQL script (`data.sql`) to prepopulate the database.
Enter fullscreen mode Exit fullscreen mode
  1. Environment Variables (-e):
* Sets up the PostgreSQL user, password, and database.
Enter fullscreen mode Exit fullscreen mode
  1. PostgreSQL Configuration (-c):
* `ssl=on`: Enables SSL for database.

* `ssl_cert_file` and `ssl_key_file`: Provide the server's certificate and key.

* `ssl_ca_file`: Specifies the CA certificate to authenticate the server’s certificate.

* `ssl_prefer_server_ciphers=on`: Enforces server-side ciphers for enhanced security.

* `listen_addresses='*'`: Configures PostgreSQL to accept connections from all IP addresses.
Enter fullscreen mode Exit fullscreen mode

The steps to enable SSL for databases such as MySQL, also follow a similar pattern:

  1. Generate certificates with OpenSSL.

  2. Mount the certificates into the container.

  3. Enable SSL in the database configuration.

Conclusion

Enabling SSL in Docker containers ensures encrypted communication between clients and the database server, enhancing data security. Using Docker for local development allows developers to test configurations quickly without relying on cloud environments.

Whether you are working with MongoDB, PostgreSQL, MySQL, or other databases, the SSL setup remains largely similar. Docker makes it easy to replicate production-like environments and validate SSL configurations before deployment.

FAQs

What is the primary benefit of enabling SSL for databases?

SSL ensures secure communication between the client and database server by encrypting data, guaranteeing data integrity, confidentiality, and mutual authentication.

Why use Docker for setting up SSL in databases?

Docker provides a consistent, lightweight, and efficient way to simulate production environments for local development and testing without cloud dependency.

What are the key components needed to enable SSL for database?

A Certificate Authority (CA) certificate, a private key for the server, and a server certificate signed by the CA are essential for enabling SSL.

Can I test mutual TLS (mTLS) using Dockerized databases?

Yes, you can enable mutual TLS by requiring both server and client certificates in the Docker container configurations for MongoDB, PostgreSQL, or other databases.

How do I add a CA certificate to my programming environment?

For Java, use the keytool command to import the CA into the keystore. For Node.js, use the NODE_EXTRA_CA_CERTS environment variable. The process varies depending on the programming language.

Top comments (0)