7.2. Configuring TLS/SSL

Documentation

VoltDB Home » Documentation » VoltDB Kubernetes Administrator's Guide

7.2. Configuring TLS/SSL

Another important aspect of security is securing and authenticating the ports used to access the database. The most common way to do this is by enabling TLS/SSL to encrypt data and authenticate the servers using user-created certificates. The process for creating the private keystore and truststore using openssl is described in the section on "Creating the TLS/SSL Certificates" in the Using VoltDB guide. This process is the same whether you are running the cluster directly on bare metal servers or in Kubernetes.

Note

The following instructions describe creating and using TLS/SSL certificates in Privacy Enhanced Mail, or PEM, format. PEM is a text-based format that is easy to work with and is accepted by all Volt functions starting with Volt version 14.2.0 and Volt Operator 3.6.0. For earlier versions of Volt, certain functions require a JKS file instead of PEM. Please see the version 13 documentation for configuring TLS on Kubernetes for instructions on creating and using certificates acceptable to previous releases.

The following example uses YAML properties to enable TLS/SSL security, in much the same way you enable SSL encryption on bare metal. First you must enable SSL encryption, using the cluster.config.deployment.ssl.enabled property. Then you choose which ports will use SSL (in this example, the internal and external ports, but not XDCR). The YAML does not include the actual content of the truststore and keystore files. The example also chooses to have the operator authenticate the servers by setting cluster.clusterSpec.ssl.insecure to false.

cluster:
  config:
    deployment:
      ssl:
        enabled: true
        external: true
        internal: true
  clusterSpec:
    ssl:
      insecure: false

Note that the certificates themselves and associated key and trust stores are not specified in the YAML for the cluster deployment configuration. Instead, you pass the associated files to the Operator (and subsequently the server pods) in one of three ways:

  • Using the --set-file argument to the Helm install

  • Using Kubernetes secrets

  • Using cert-manager

The following sections describe the three methods for configuring encryption. Two additional sections describe alternate methods for configuring TLS/SSL for the Operator and VMC and how to update the certificates when they expire.

7.2.1. Configuring TLS/SSL With the Helm Install --set-file Argument

Using the example YAML file in Section 7.2, “Configuring TLS/SSL” (and calling it ssl.yaml), we can complete the SSL configuration by specifying the truststore and keystore files on the helm command line with the --set-file argument:

helm install mydb voltdb/voltdb                                           \
  --values myconfig.yaml                                                  \
  --values ssl.yaml                                                       \
  --set-file cluster.config.deployment.ssl.keystore.file=keystore.pem     \
  --set-file cluster.config.deployment.ssl.truststore.file=truststore.pem

Two important notes concerning TLS/SSL configuration:

  • If you enable SSL for the cluster's external interface and ports and you enable metrics, you must provide the appropriate SSL information to the Prometheus data retriever configuration so it can access the metrics port.

  • If you enable SSL for the cluster, you must repeat the specification of the truststore and keystore files every time you update the configuration. Using the --reuse-values argument on the helm upgrade command is not sufficient.

7.2.2. Using Kubernetes Secrets to Store and Reuse TLS/SSL Information

An alternative method is to store the key and trust stores in a Kubernetes secret. Secrets are a standard feature of Kubernetes that allow you to store sensitive information as key value pairs in a protected space. Three advantages of using a secret are:

  • You do not have to enter sensitive TLS/SSL information in plain text when configuring or updating your database.

  • The secret is used automatically for subsequent updates; you do not have to repeatedly specify the TLS/SSL files when updating the database configuration.

  • You can reuse the same secret for multiple database instances and services.

To use a Kubernetes secret to store the TLS/SSL information for your database, you must first create the necessary PEM files as described in the section on "Creating the TLS/SSL Certificates" in the Using VoltDB guide. Next you create your Kubernetes secret using the kubectl create secret command, specifying the key names and corresponding artifacts as arguments. For example:

$ kubectl create secret generic my-ssl-creds     \
    --from-file=keystore_data=keystore.pem       \
    --from-file=truststore_data=truststore.pem

It is critical you use the key names keystore_data and truststore_data (as well as keystore_password and truststore_password if you created a password for the certificate). If not, the Volt Operator will not be able to find them. Also, the secret must be in the same Kubernetes namespace as the Helm release you are configuring.

Once you create the secret you can use it to configure your database by not setting any of standard SSL properties such as the cluster.config.deployment.ssl... properties or cluster.clusterSpec.ssl.certificateFile. Instead, set the property cluster.config.deployment.ssl.sslSecret.certSecretName. Using the secret created in the preceding example, the configuration of your database will look something like this:

cluster:
  config:
    deployment:
      ssl:
        sslSecret:
          certSecretName: my-ssl-creds

7.2.3. Using Kubernetes cert-manager to Store TLS/SSL Certificates

Another alternative for maintaining the TLS/SSL information is to use the Kubernetes cert-manager (cert-manager.io). The cert-manager is an add-on for Kubernetes that helps you create and maintain certificates and other private information in Kubernetes. If you wish to use cert-manager for self-signed certificates, you not only use it to store the certificate and truststore, you create them with cert-manager as well. (For more detailed information concerning cert-manager, see the cert-manager documentation.)

The basic steps for storing self-signed TLS/SSL credentials in cert-manager are:

  1. Create an issuer resource in Kubernetes that will generate and authenticate the certificate. You only need to do this once for the namespace and multiple certificate requests can use the same issuer.

  2. Create a request for the issuer to generate the actual TLS/SSL certificate and store it in a Kubernetes secret.

  3. Specify the resulting certificate secret in the VoltDB configuration and start your cluster.

You create the cert-manager issuer and the certificate request using YAML properties. The easiest way to do this is by typing the property declarations into a YAML file. For example, the following two YAML files create a cert-manager issuer service and request a certificate.

create-issuer.yaml

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
   name: selfsigned-issuer
   namespace: mydb
spec:
   selfSigned: {}

request-cert.yaml

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: my-ssl-certificate
  namespace: mydb
spec:
  commonName: voltdb.com
  duration: 8766h
  secretName: my-ssl-creds
  issuerRef:
    name: selfsigned-issuer
    kind: Issuer
  privateKey:
    algorithm: RSA
    encoding: PKCS8
    size: 2048
  usages:
    - server auth

Three key points to note about the certificate request are:

  • The issuer must be in the same namespace as the database that uses the certificate.

  • You specify the duration of the certificate in hours. In this example, 8766 hours, or one year.

  • The encoding must be PKCS8

Once you create the YAML files, you can create the issuer and request the certificate:

$ kubectl apply -f create-issuer.yaml    # Do only once
$ kubectl apply -f request-cert.yaml 

Finally, in your database configuration, you point to the secret created by the certificate request (in this case, my-ssl-creds) the same way you would for a manually created secret:

cluster:
  config:
    deployment:
      ssl:
        sslSecret:
          certSecretName: my-ssl-creds

7.2.4. Using Certificate Revocation Lists (CRLs)

A certificate revocation list (CRL) lets you deny access to the server from certain clients based on their certificates, when using mutual TLS (mTLS). For example, say you had separate client certificates for each vendor with access to your database. If the partnership with a vendor ends, you want to now deny access to the vendor's clients by adding their certificate to the list of CRLs. Note that the CRL files must be in PEM format. See the section on Using CRLs in the Using VoltDB guide for instructions on converting files in other formats to PEM using the openssl utility.

In Kubernetes, you add CRLs to the server in one of two ways:

  • By specifying the CRLs, one at a time, using the --set-file qualifier when installing the database release. For example:

    helm install mydb voltdb/voltdb                                                    \
      --values myconfig.yaml                                                           \
      --set-file cluster.config.deployment.ssl.crl.file.a=/etc/ssl/local/crl/crl1.pem  \
      --set-file cluster.config.deployment.ssl.crl.file.b=/etc/ssl/local/crl/crl2.pem  \
      --set-file cluster.config.deployment.ssl.crl.file.c=/etc/ssl/local/crl/crl3.pem

    The last name of the cluster.config.deployment.ssl.crl.file.{name} property can be any name you choose as long as it is unique within the set of CRL file property names.

  • By creating a configuration map containing the CRLs. Create a directory with one or more CRL files in it. Then create a configuration map using the kubectl create configmap command pointing to the CRL directory. For example, using the directory name /etc/ssl/local/crl from the preceding example and naming the configuration map mycrlmap:

    kubectl create configmap mycrlmap --from-file /etc/ssl/local/crl

    Once you create the configuration map, you can add it to the Helm configuration using the cluster.config.deployment.ssl.crl.configName property when installing the database release:

    helm install mydb voltdb/voltdb                                                    \
      --values myconfig.yaml                                                           \
      --set cluster.config.deployment.ssl.crl.configName=mycrlmap 

7.2.5. Configuring TLS/SSL for the Volt Operator and VMC

By default, when you enable TLS/SSL, the Volt Operator and the Volt Management Console (VMC) automatically use the truststore configured for the servers as their truststore for authenticating the server. In other words, you do not have to set any SSL configuration properties yourself for these two services. VMC will also use the server keystore to define its own certificate for encrypting user access to its HTTP port. This way clients and interactive users can use the same truststore to access both the servers' client ports and the VMC web console.

Of course, you can choose to explicitly identify a separate truststore for these other services and provide the associated files yourself, if you wish. But by default, configuring SSL for the server automatically configures the Operator and VMC correctly to respond to the encrypted messages.

The same is true if you enable mutual TLS (mTLS) for the cluster. In this case, the Operator and VMC use the same certificate (and truststore) as the servers by default. If you want to have these services use a distinct client certificate, you need to specify that certificate using the appropriate YAML properties for those services. For example, the following Helm command loads a separate certificate for the Volt Operator and uses the root truststore for both the server and Operator:

helm install mydb voltdb/voltdb                                                \
  --values myconfig.yaml                                                       \
  --values ssl.yaml                                                            \
  --set-file cluster.config.deployment.ssl.keystore.file=server.keystore.pem   \
  --set-file cluster.config.deployment.ssl.truststore.file=root.truststore.pem \
  --set-file cluster.clusterSpec.ssl.clientCertFile=client.keystore.pem