Securing Connections to an External MySQL 8 compliant database
Prerequisite
Prepare CA Certificate, Client Key, and Client Certificate.
Each DB vendor provides a guide to secure connections including how and where to get a CA certificate, client key, and client certificate.
Refer to the following references, which are subject to change by the vendors.
This document uses the following files:
| Type | File Name |
|---|---|
| CA certificate | db-ca.pem |
| Client key | db-client-key.pem |
| Client certificate | db-client-cert.pem |
| Client keystore | db-client-keystore.jks |
If you are using different file names, the reference instructions for creating Kubernetes secret and config map must be updated.
Prepare Client Keystore
This section for creating a client keystore is for reference.
Procedure
-
Based on client key and client certificate, generate client keystore in
PKCS#12formatInputs
client key: client-key.pem
client certificate: client-cert.pem
passout: password protecting the keystoreOutput
Client keystore in
PKCS#12format:client-keystore.p12openssl pkcs12 \
-export \
-in "client-cert.pem" \
-inkey "client-key.pem" \
-out "client-keystore.p12" \
-name "mariadbclient" \
-passout pass:changeme -
Convert the client keystore from
PKCS#12format to JKS formatInputs
srckeystore: client-keystore.p12
srcstoretype: PKCS12
srcstorepass: changeme
deststorepass: changeme
destkeypass: changemeOutput
destkeystore: client-keystore.jkskeytool \
-importkeystore \
-deststorepass changeme \
-destkeypass changeme \
-destkeystore "client-keystore.jks" \
-srckeystore client-keystore.p12 \
-srcstoretype PKCS12 \
-srcstorepass changeme \
-alias "mariadbclient"
Understanding SSL Mode for Securing Database Connection
Here is the list of SSL modes that the driver uses and what is required for each mode.
-
disable: Do not use SSL/TLS (default). -
trust: Only use TLS for encryption. Do not perform certificate or hostname verification. This mode is not safe for production applications. -
verify-ca: Use TLS for encryption and perform certificate verification, but do not perform hostname verification. -
verify-full: Use TLS for encryption, certificate verification, and hostname verification.
When SSL mode is disable or trust, no key or certificate is required by the MySQL client.
When SSL mode is verify-ca or verify-full, a CA certificate is required by the MySQL client.
In case you are using mutualTls mode, it has the following options:
-
disable: MySQL Client communicates with MySQL server in a secure or insecure way. -
enable: MySQL Client communicates with MySQL server in a secure way, CA certificate, client key, client keystore and client certificate are required.
Refer to your database server's documentation on how to make it mandatory to use X509 certs for clients.
The following table shows the settings required for each mode.
disable | trust |
|
|
|
| |
|---|---|---|---|---|---|---|
db_ca_configmap | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ |
db_ssl_secret | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ |
db_client_cert_configmap | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ |
db_client_key_secret | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ |
db_client_keystore_secret | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ |
The following table shows the valid combinations of db_ssl_modes and db_mutual_tls.
db_mutual_tls: disable | db_mutual_tls: enable | |
|---|---|---|
| disable | ✅ | ❌ |
| trust | ✅ | ❌ |
| verify-ca | ✅ | ✅ |
| verify-full | ✅ | ✅ |
Step 1: Replace Samples
The samples are present in the samples/database folder.
db-ca.pem
db-client-cert.pem
db-client-key.pem
db-client-keystore.jks
It is highly recommended to replace these with your own ones.
If a client keystore is needed, also update the following in db-ssl-secrets.yaml file:
-
Passwords protecting the client keystore.
-
Password protecting the client key in the client keystore.
apiVersion: v1
kind: Secret
metadata:
name: db-ssl-secret
namespace: default
stringData:
# echo -n changeme | base64
db-client-keystore-password: Y2hhbmdlbWU=
# echo -n changeme | base64
db-client-key-password: Y2hhbmdlbWU=
Step 2: Create Kubernetes ConfigMap / Secret
Depending on the choice of ssl-mode, the following configMaps and secrets must be created. Here are the reference instructions for Kubernetes (update namespace as needed) The configMap and secret names are used in the file deploy/values.yaml.
-
Create configMap for CA certificate.
kubectl create configmap db-ca-configmap --from-file=KEY_IN_CONFIGMAP=PATH_TO_CA_CERTIFICATE --namespace defaultKEY_IN_CONFIGMAP must be
db-ca.pem.Example: CA certificate file
db-ca.pem, configMap namedb-ca-configmapkubectl create configmap db-ca-configmap --from-file=db-ca.pem --namespace defaultExample: CA certificate file
gcp-ca.pem, configMap namegcp-ca-configmapkubectl create configmap gcp-ca-configmap --from-file=db-ca.pem=gcp/server-ca.pem --namespace default -
Create configMap for client certificate.
kubectl create configmap db-client-cert-configmap --from-file=KEY_IN_CONFIGMAP=PATH_TO_CLIENT_CERTIFICATE --namespace defaultKEY_IN_CONFIGMAP must be
db-client-cert.pem.Example: client certificate file
db-client-cert.pem, configMap namedb-client-cert-configmapkubectl create configmap db-client-cert-configmap --from-file=db-client-cert.pem --namespace defaultExample: client certificate file
client-cert.pem, configMap namegcp-client-cert-configmapkubectl create configmap gcp-client-cert-configmap --from-file=db-client-cert.pem=gcp/client-cert.pem --namespace default
-
Create secret for client key.
kubectl create secret generic db-client-key-secret --from-file=KEY_IN_SECRET=PATH_TO_CLIENT_KEY --namespace defaultKEY_IN_SECRET must be
db-client-key.pem.Example: client key file
db-client-key.pem, secret namedb-client-key-secretkubectl create secret generic db-client-key-secret --from-file=db-client-key.pem --namespace defaultExample: client key file
client-key.pem, secret namegcp-client-key-secretkubectl create secret generic gcp-client-key-secret --from-file=db-client-key.pem=gcp/client-key.pem --namespace default -
Create secret for client keystore.
kubectl create secret generic db-client-keystore-secret --from-file=KEY_IN_SECRET=PATH_TO_CLIENT_KEYSTORE --namespace defaultKEY_IN_SECRETmust bedb-client-keystore.jks.Example: client keystore file
db-client-keystore.jks, secret namedb-client-keystore-secretkubectl create secret generic db-client-keystore-secret --from-file=db-client-keystore.jks --namespace defaultExample: client keystore file
client-keystore.jks, secret namegcp-client-keystore-secretkubectl create secret generic gcp-client-keystore-secret --from-file=db-client-keystore.jks=gcp/client-keystore.jks --namespace default -
Create secret for SSL secret.
kubectl apply -f db-ssl-secrets.yaml --namespace default
Step 3: Update Values
Update the following entries in deploy/values.yaml.
Default entries related TLS connection.
Make the choice of sslMode and fill up other TLS settings as needed.
# sslMode value: disable, trust, verify-ca, verify-full
# disable: Do not use SSL/TLS; no key or certificate is required.
# trust: Only use SSL/TLS for encryption, do not perform certificate or hostname verification; no key
or certificate is required.
# verify-ca: Use SSL/TLS for encryption and perform certificates verification, but do not perform
hostname verification; CA certificate is needed.
# verify-full: Use SSL/TLS for encryption, certificate verification, and hostname verification; CA
certificate is required.
sslMode: 'disable'
# mutualTls value: disable, enable
# disable: MySQL Client communicates with MySQL server in secure or insecure way
# enable: MySQL Client communicates with MySQL server in secure way, CA certificate, client key,
client keystore and client certificate are required.
mutualTls: 'disable'
# caConfigmap: the name of configMap holding CA certificate
# null: when CA certificate is not in use
# caConfigmap: when CA certificate is in use, update the value with the name of configMap holding
CA certificate
caConfigmap: 'null'
# sslSecret: the name of secret holding SSL secret
# null: when no client key or client keystore is in use
# sslSecret: when client key or client keystore is in use, update the value with the name of secret
holding SSL secret
sslSecret: 'null'
# clientCertConfigmap: the name of configMap holding the client certificate
# null: when client certificate is not in use
# clientCertConfigmap: when client certificate is in use, update the value with the name of
configMap holding the client certificate
clientCertConfigmap: 'null'
# clientKeySecret: the name of secret holding the client key
# null: when client key is not in use
# clientKeySecret: when client key is in use, update the value with the name of secret holding the
client key
clientKeySecret: 'null'
# clientKeystoreSecret: the name of secret holding the client keystore
# null: when client keystore is not in use
# clientKeystoreSecret: when client keystore is in use, update the value with the name of secret
holding the client keystore
clientKeystoreSecret: 'null'
Example: db_ssl_mode: trust and db_mutual_tls: disable
Set db_ssl_mode to trust. Nothing else is needed for TLS.
# sslMode value: disable, trust, verify-ca, verify-full
# disable: Do not use SSL/TLS; no key or certificate is required.
# trust: Only use SSL/TLS for encryption, do not perform certificate or hostname verification; no key
or certificate is required.
# verify-ca: Use SSL/TLS for encryption and perform certificates verification, but do not perform
hostname verification; CA certificate is needed.
# verify-full: Use SSL/TLS for encryption, certificate verification, and hostname verification; CA
certificate is required.
sslMode: 'trust'
# mutualTls value: disable, enable
# disable: MySQL Client communicates with MySQL server in secure or insecure way
# enable: MySQL Client communicates with MySQL server in secure way, CA certificate, client key,
client keystore and client certificate are required.
mutualTls: 'disable'
# caConfigmap: the name of configMap holding CA certificate
# null: when CA certificate is not in use
# caConfigmap: when CA certificate is in use, update the value with the name of configMap holding
CA certificate
caConfigmap: 'null'
# sslSecret: the name of secret holding SSL secret
# null: when no client key or client keystore is in use
# sslSecret: when client key or client keystore is in use, update the value with the name of secret
holding SSL secret
sslSecret: 'null'
# clientCertConfigmap: the name of configMap holding the client certificate
# null: when client certificate is not in use
# clientCertConfigmap: when client certificate is in use, update the value with the name of
configMap holding the client certificate
clientCertConfigmap: 'null'
# clientKeySecret: the name of secret holding the client key
# null: when client key is not in use
# clientKeySecret: when client key is in use, update the value with the name of secret holding the
client key
clientKeySecret: 'null'
# clientKeystoreSecret: the name of secret holding the client keystore
# null: when client keystore is not in use
# clientKeystoreSecret: when client keystore is in use, update the value with the name of secret
holding the client keystore
clientKeystoreSecret: 'null'
Example: db_ssl_mode: verify-full and db_mutual_tls: enable
Set db_ssl_mode to verify-full and mutualTls to enable. All settings of TLS must be updated.
# sslMode value: disable, trust, verify-ca, verify-full
# disable: Do not use SSL/TLS; no key or certificate is required.
# trust: Only use SSL/TLS for encryption, do not perform certificate or hostname verification; no key
or certificate is required.
# verify-ca: Use SSL/TLS for encryption and perform certificates verification, but do not perform
hostname verification; CA certificate is needed.
# verify-full: Use SSL/TLS for encryption, certificate verification, and hostname verification; CA
certificate is required.
sslMode: 'verify-full'
# mutualTls value: disable, enable
# disable: MySQL Client communicates with MySQL server in secure or insecure way
# enable: MySQL Client communicates with MySQL server in secure way, CA certificate, client key,
client keystore and client certificate are required.
mutualTls: 'enable'
# caConfigmap: the name of configMap holding CA certificate
# null: when CA certificate is not in use
# caConfigmap: when CA certificate is in use, update the value with the name of configMap holding
CA certificate
caConfigmap: 'db-ca-configmap'
# sslSecret: the name of secret holding SSL secret
# null: when no client key or client keystore is in use
# sslSecret: when client key or client keystore is in use, update the value with the name of secret
holding SSL secret
sslSecret: 'db-ssl-secret'
# clientCertConfigmap: the name of configMap holding the client certificate
# null: when client certificate is not in use
# clientCertConfigmap: when client certificate is in use, update the value with the name of
configMap holding the client certificate
clientCertConfigmap: 'db-client-cert-configmap'
# clientKeySecret: the name of secret holding the client key
# null: when client key is not in use
# clientKeySecret: when client key is in use, update the value with the name of secret holding the client key
clientKeySecret: 'db-client-key-secret'
# clientKeystoreSecret: the name of secret holding the client keystore
# null: when client keystore is not in use
# clientKeystoreSecret: when client keystore is in use, update the value with the name of secret
holding the client keystore
clientKeystoreSecret: 'db-client-keystore-secret'