Enable Keycloak DB (PostgreSQL) Connectivity Over TLS
Introduction
This document outlines the steps required to enable TLS (Trasnport Layer Security) on a Bitnami PostgreSQL deployment in a Kubernetes environment using Helm. Enabling TLS on PostgreSQL involves configuring the server to use SSL certificates for secure connections. TLS secures communication by encrypting data, authenticating the identities of communicating parties using certificates, and ensuring data integrity. It prevents eavesdropping, tampering, and forgery in data transmission.
Prerequisites
Kubernetes cluster setup and configured.
Helm installed and configured.
A Bitnami PostgreSQL Helm chart repository added to Helm.
A BItnami Keycloak Helm chart repository added to Helm.
Steps Required
Here’s a step-by-step guide to enable TLS on PostgreSQL deployed on a Kubernetes cluster using the Helm chart.
1. Prepare SSL/TLS Certificate
First, you need SSL certificates for PostgreSQL. You can either generate self-signed certificates or obtain them from a trusted certificate authority (CA). If you are in development environment, you can use OpenSSL to generate a self-signed certificate and key. Run the following commands on your local machine:
openssl genrsa -out postgresql.key 2048
openssl req -new -key postgresql.key -out postgresql.csr
openssl x509 -req -in postgresql.csr -signkey postgresql.key -out postgresql.crt -days 365
This will generate three files:
postgresql.key (private key)
postgresql.csr (certificate signing request)
postgresql.crt (certificate)
For a production environment, obtain SSL certificates from a trusted CA and place them in a secure directory accessible to PostgreSQL.
2. Create a Kubernetes Secret for TLS
Now, you will need to create a Kubernetes secret to store the TLS certificate and key. Run the following command in the directory where certificate file and key are stored:
kubectl create secret generic -n ef-external postgres-tls --from-file=postgresql.crt=postgresql.crt --from-file=postgresql.key=postgresql.key
This command will generate a Kubernetes secret named postgres-tls
which contains certificate and key for TLS. If you are in a production environment and you have an intermediate certificate file ca.crt
, which is used for verifying certificates presented by server, then you should also add this file in the command given above, i.e. :
kubectl create secret generic -n ef-external postgres-tls --from-file=postgresql.crt=postgresql.crt --from-file=postgresql.key=postgresql.key --from-file=ca.crt=ca.crt
3. Modify the Helm Chart Values
To modify the Helm chart values of your Bitnami PostgreSQL, you need to edit the values.yaml
file. You can locate this file in the “cim-solution/kubernetes/external/bitnami/postgresql” directory. Find the 'tls'
section in values.yaml
. It will resemble the snippet below:
## TLS configuration
##
tls:
## @param tls.enabled Enable TLS traffic support
##
enabled: false
## @param tls.autoGenerated Generate automatically self-signed TLS certificates
##
autoGenerated: false
## @param tls.preferServerCiphers Whether to use the server's TLS cipher preferences rather than the client's
##
preferServerCiphers: true
## @param tls.certificatesSecret Name of an existing secret that contains the certificates
##
certificatesSecret: ""
## @param tls.certFilename Certificate filename
##
certFilename: ""
## @param tls.certKeyFilename Certificate key filename
##
certKeyFilename: ""
## @param tls.certCAFilename CA Certificate filename
## If provided, PostgreSQL will authenticate TLS/SSL clients by requesting them a certificate
## ref: https://www.postgresql.org/docs/9.6/auth-methods.html
##
certCAFilename: ""
## @param tls.crlFilename File containing a Certificate Revocation List
##
crlFilename: ""
Modify below given values in TLS section and leave other values as they are.
tls:
enabled: true
certificatesSecret: "postgres-tls"
certFilename: "postgresql.crt"
certKeyFilename: "postgresql.key"
certificatesSecret will be the name of Kubernetes secret where certificate and key are stored.
certFilename will be the name of the certificate file.
certKeyFilename will be the name of the key file.
3a. Only Allow Connections Over TLS (Optional)
If you want to allow connections only over TLS then you should modify the pgHbaConfiguration
section also. It may look like this:
primary:
## @param primary.pgHbaConfiguration PostgreSQL Primary client authentication configuration
## ref: https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html
## e.g:#
## pgHbaConfiguration: |-
## local all all trust
## host all all localhost trust
## host mydatabase mysuser 192.168.0.0/24 md5
##
pgHbaConfiguration: ""
Add following values to the section:
primary:
pgHbaConfiguration:
hostssl all all 0.0.0.0/0 md5
hostssl all all ::0/0 md5
hostssl: Specifies that this rule applies only to SSL connections.
all: Applies to all users.
all: Applies to all databases.
0.0.0.0/0: Allows connections from any IPv4 address.
::0/0: Allows connections from any IPv6 address.
md5: Specifies the authentication method.
You can learn more about these parameters and configurations here.
If you want to allow both SSL and non-SSL connections to your database, you don’t need to make any changes in the pgHbaConfiguration section.
4. Deploy or Upgrade the PostgreSQL Release with Helm
Deploy or upgrade your PostgreSQL release using the values.yaml
file by running the following command:
helm upgrade --install=true --wait=true --timeout=10m0s --debug --namespace=ef-external --values=external/bitnami/postgresql/values.yaml ef-postgresql external/bitnami/postgresql
5. Verify the TLS Configuration
After the deployment, verify that PostgreSQL is configured to use TLS. You need to enable remote access to your PostgreSQL database before verifying the TLS configuration. Once remote access is enabled, you can use the psql
client to connect to database with SSL/TLS. Run the following command:
psql -h <ip-of-host> -p <port> -U <user> -d <database>
psql: The PostgreSQL interactive terminal.
-h <ip-of-host>: The hostname or IP address of the PostgreSQL server.
-p <port>: The port number where the PostgreSQL server is listening.
-U <user>: The username to connect with.
-d <database>: The database name to connect to.
Make sure to replace the placeholders (<ip-of-host>, <port>, <user>, and <database>) with the actual values for your PostgreSQL setup.
For example:
psql -h 192.168.1.100 -p 5432 -U myuser -d mydatabase
This command will prompt you for the password of the specified user before establishing the connection. Once you enter the password, you can check the connection status by running \conninfo
command. It will return following result:
You are connected to database "mydatabase" as user "myuser" on host "192.168.1.100" at port "5432".
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
The second line ensures that SSL/TLS is enabled on PostgreSQL. You can also use PGSSLMODE
for more secure connections. Learn more about PGSSLMODE
here.
Enabling Keycloak Connectivity To PostgreSQL Over TLS
By default, PostgreSQL uses sslmode=prefer
, which attempts to establish a connection over TLS. If TLS is properly configured on the PostgreSQL server, the connection is established over SSL/TLS and data in transit is encrypted; otherwise, a non-SSL (non-encrypted) connection is established.
Keycloak will try to establish a connection with PostgreSQL over TLS by default. If you want to:
Ensure that only TLS connections are established to the database.
Fail the connection if TLS is not properly configured on the PostgreSQL server.
Verify the certificate provided by the server against a trusted CA.
Then you need to use sslmode=verify-ca
and provide a ca.crt
file for verifying the server certificate. Below are the steps required for configuring these options in Keycloak’s values.yaml
file.
1. Create a Kubernetes Secret for the CA Certificate
Create a Kubernetes secret to store your ca.crt
file, provided to you by your certificate authority (CA). Run the following command in the directory where ca.crt
file is stored, replacing <your-namespace>
with your Kubernetes namespace and <your-secret-name>
with any name you want for your secret:
kubectl create secret generic -n <your-namespace> <your-secret-name> --from-file=ca.crt=ca.crt
For example, for ef-external
namespace and postgres-tls-cert
, run following command:
kubectl create secret generic -n ef-external postgres-tls-cert --from-file=ca.crt=ca.crt
You can skip this step entirely if you have already mounted “ca.crt” in Kubernetes secret (as given is step 2 of above section).
2. Update Keycloak Helm Chart Values
To update the Helm chart values of your Bitnami Keycloak, you need to edit the values.yaml
file. You can locate this file in the “cim-solution/kubernetes/external/bitnami/keycloak” directory. You need to modify the database connection string to include SSL parameters and mount the secret containing the certificates. Find the 'extraEnv'
, 'extraVolumes'
and 'extraVolumeMounts'
sections in values.yaml
. Add the following properties to specified sections:
## Add TLS parameters
extraEnvVars:
- name: KEYCLOAK_JDBC_PARAMS
value: "sslmode=verify-ca&sslrootcert=/opt/keycloak/certs/ca.crt"
## Mount the secret containing the TLS certificates
extraVolumes:
- name: postgres-tls-cert
secret:
secretName: postgres-tls-cert
extraVolumeMounts:
- name: postgres-tls-cert
mountPath: /opt/keycloak/certs/
readOnly: true
Replace postgres-tls-cert
with your secret’s name.
3. Deploy or Upgrade the Keycloak Release with Helm
Deploy or upgrade your Keycloak release using the values.yaml
file by running the following command:
helm upgrade --install=true --wait=true --timeout=10m0s --debug --namespace=ef-external --values=external/bitnami/keycloak/values.yaml keycloak external/bitnami/keycloak/
This is all you need to establish a secure TLS connection between Keycloak and PostgreSQL. This configuration mounts the TLS certificates into the Keycloak container and updates the JDBC connection string to use SSL with the required certificates.
The DevOps commands (related to Kubernetes & Helm) may vary depending upon the Kubernetes setup/configuration.