Database Connection Encryption deprecated
Introduction
This guide will help you to setup TLS encryption for database connections and configure it within Middleware pods running in Kubernetes.
Further reading
- MariaDB and SSL
- Ubuntu and MySQL
- MySQL with user privileges (German)
- Official MySQL guide for SSL setup (JDBC)
- Command Options for Encrypted Connections
- MariaDB Bitnami chart
Prerequisites
- Helm v3.13.2
- Kubernetes v1.27
- Kubectl v1.27
- Middleware Chart
- MariaDB Chart
Database
In this guide, MariaDB is used as a database. If you use an other database, please read the vendors documentation to find equal configuration.
Officially, MariaDB is shipped as a Docker image and not as a Helm chart. So, to get a Helm chart for MariaDB, we will use the MariaDB chart provided by Bitnami, see https://github.com/bitnami/charts/blob/main/bitnami/mariadb/README.md. The Bitnami chart offers a easy way to configure MariaDB, by utilizing a section called configuration
. Within the section, all configuration must be set, as known from previous "installations" that used the file my.cnf
.
Therefore, configuring TLS for MariaDB is as simple as this:
mariadb:
enabled: true
architecture: standalone
primary:
extraVolumes:
- name: certs
secret:
secretName: certs
extraVolumeMounts:
- name: certs
mountPath: /certs
configuration: |-
[mysqld]
ssl_cert=/certs/server-cert.pem
ssl_key=/certs/server-key.pem
ssl_ca=/certs/ca-cert.pem
require_secure_transport=ON
...
Please note that in this example, it is assumed that the actual certificates will be mounted to the MariaDB pod. Therefore, extra volume mounts to a folder containing the valid certificates are defined. The mounted certificates are then referenced in the configuration section.
Test the connection
To make sure that connections to MariaDB are now secured by TLS encryption, we can manually observe the connection. For example, use Wireshark and DBeaver from your local machine. Create a new connection within DBeaver to the MariaDB pod. Make sure to configure the connection to use TLS. Therefore, go to the SSL
tab and toggle Use SSL
, configure the certificates and toggle require TLS
and Verify server certificate
. Afterwards, configure Wireshark to observe the connection, by e.g. using the filter tcp.port == 3306
on the fitting network interface. Once everything is configured, connect to the database. Now
- the connection should be established without any error
- the message content is NOT readable
Configure your Middleware
Middleware pods are using the JDBC connector to connect to a database. The JDBC connector uses a Java KeyStore to manage different certificates. Therefore, we need to create keystores based on the CA and client certificates.
Currently, certificates and keystores must be passed down to Middleware pods as BASE64 decoded files. This is subject to change and might be replaced by Kubernetes internal mechanisms in the future. However, for now the following has to be done, to enable TLS protected connections between the database and the Middleware:
Create key stores
Keystores need to be created locally. Therefore, we create
- A truststore file for the CA certificate
- A keystore file for the client certificate
for example with:
keytool -importcert -alias MariaDBCACert -file ca-cert.pem -keystore truststore -storepass changeit
openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem -name "mariadbclient" -passout pass:changeit -out client-keystore.p12
keytool -importkeystore -srckeystore client-keystore.p12 -srcstoretype pkcs12 -srcstorepass changeit -destkeystore keystore -deststoretype JKS -deststorepass changeit
# Verify client certificate in key store
keytool -list -v -keystore keystore
Afterwards, the stores can be converted into BASE64
base64 --input truststore --output truststore.base64
The content of the BASE64 decoded file need to be copied into the values.yaml
file.
Middleware Configuration
To configure the Middleware to use encryption towards the database, the following properties must be set within the values.yaml
file:
core-mw:
enabled: true
yamlFiles:
dbconnector.yaml:
com.mysql.jdbc:
useSSL: true
requireSSL: true
verifyServerCertificate: true
clientCertificateKeyStoreUrl: file:/opt/open-xchange/etc/mariadb-keystore
clientCertificateKeyStorePassword: changeit
clientCertificateKeyStoreType: JKS
trustCertificateKeyStoreUrl: file:/opt/open-xchange/etc/mariadb-truststore
trustCertificateKeyStorePassword: changeit
trustCertificateKeyStoreType: JKS
etcBinaries:
- name: mariadb-keystore
filename: mariadb-keystore
b64Content: <BASE64_CONTENT_OF_THE_KEYSTORE>
- name: mariadb-truststore
filename: mariadb-truststore
b64Content: <BASE64_CONTENT_OF_THE_TRUSTSTORE>
Please replace the placeholder <BASE64_CONTENT_OF_THE_KEYSTORE>
with the actual content of the keystores. Read the section above for more information.
Reload properties and certificates in production
The server is capable to reload JDBC properties as well as the used certificates. To trigger a certificate rotation, the command line tool "reloadConfiguration" can be used. However, when using Kubernetes, simply overwrite the properties in the values.yaml
and let Kubernetes schedule new pods with the updated configuration.
If you still want to use the command line tool, a reload will clear all unused connection instances held in the connection pools and updates the properties used to spawn new connections with the JDBC client. After that, all new connections will automatically use the updated properties. Connections that are still in use will get marked as deprecated, so that these connections will be replaced by updated ones after they finish their work.
Example
For a full working example on TLS encrypted database connections, please have a look here