Securing YugabyteDB: Part 2 – Client-to-Server Encryption in Transit
In the first post in this series, we covered how to secure YugabyteDB’s internal RPC protocol using the TLS encryption protocol, also referred to as server-to-server encryption in transit. In this post, we secure the communication between SQL clients and the PostgresQL query interface of YugabyteDB, also called client-to-server encryption in transit.
YugabyteDB—a 100% open source, distributed SQL database built to accelerate cloud native agility—stores important user and customer data at an organization. More specifically, this means encryption in transit is a common requirement for client-to-server communication.
As covered in the first post, YugabyteDB has three primary client-to-server communication protocols.
- The internal RPC protocol between masters and tserver processes.
- PostgreSQL-compatible YSQL clients talking to the default port 5433 on the tserver hosts.
- CQL-compatible YCQL clients talking to the default port 9042 on the tserver hosts.
In this post, we will demonstrate how to set up client-to-server encryption in transit for the second option above.
There are three different goals organizations may choose to achieve with encryption in transit.
- Make it cryptographically impossible to snoop or modify network communications.
- Enable the client to identify and verify the server.
- Enable the server to identify and verify the client.
The first goal is typically a common minimum requirement, while the latter depends on the specific use case. However, a mutual TLS or mTLS occurs with the realization of Goal 2 and Goal 3.
To enable TLS communication for SQL client communication, the following command line flags need to be specified to the yb-tserver processes.
--certs_for_client_dir=<path to a directory>, e.g.,
The directory pointed to by this flag contains three files in PEM format.
- ca.crt – The public certificate of the Certificate Authority (CA) that this YugabyteDB server should trust. This is the CA that will verify other certificates. YugabyteDB does not trust any system CA certificates that might already be present on the host. A single file includes a chain of root and intermediate CA certificates.
- node.<host-ip-address>.crt – public server certificate for this host.
- node.<host-ip-address>.key – private key for the server certificate for this host.
Once these settings are specified, all SQL and CQL client connections to this yb-tserver will use TLS. This achieves Goal 1 above (i.e., resilience to snooping).
Achieving Goal 2 (i.e., client verifies server cert) requires additional settings. But the exact method depends on the kind of SQL client used. For the standard command line client, ysqlsh, there is no verification of server certificates by default. However, this can be enabled by setting the sslmode parameter to verify-ca as shown below.
./bin/ysqlsh -h <server ip/hostname> "sslrootcert=<path to ca.crt> sslmode=verify-ca"
This parameter will cause the ysqlsh client to verify that the tserver presents a valid cert signed by the CA and specified by the sslrootcert parameter (i.e., system CA certs in /etc/ssl/certs are not consulted).
For additional verification, sslmode can be set to verify-full. But this causes an additional check that the server certificate’s Common Name matches the server’s IP address or hostname. This check is highly recommended when connecting over unsafe networks like the public Internet. Yugabyte Cloud supports the verify-full mode of client authentication when connecting over public Internet using IP allow lists.
To achieve Goal 3 (i.e., server verifies the client certificate), enable client authentication using certificates.
- The yb-server has to be started with the following command line flags, in addition to the flags already set:
--ysql_hba_conf_csv="hostssl all all all trust clientcert=1” --ysql_enable_auth=true
This will cause the server to insist that the SQL client authenticate itself by presenting a certificate.
- The ysqlsh client will then need to be started as:
./bin/ysqlsh -h <server ip/host> “sslcert=<path to client.crt> sslkey=<path to client key>” -U <username>
The server will then verify that client.crt is a valid certificate signed by the CA specified in its ca.crt. Additionally, it will verify that the Common Name of the client.crt file contains the PostgreSQL username specified by the client. It will also authenticate the client directly without the need for any additional authentication mechanisms, such as a password.
When both Goal 2 and Goal 3 are achieved, the SQL client protocol achieves mutual TLS.
Note: To use both password and client certificates to authenticate the user, the ysql_hba_conf_csv parameter would be set to –ysql_hba_conf_csv=”hostssl all all all md5 clientcert=1” instead.
Organizations may wish to disallow older versions of the TLS protocol. For the postgresQL protocol, specify the ssl_min_protocol_version to the tserver process to allow all versions of the protocol above or equal to this parameter.
Note the difference compared to the equivalent specification for the RPC protocol. The RPC protocol requires a full protocol list, not just the minimum.
In the next post, we’ll explain how these different dimensions of encryption in transit work for the CQL client protocol.
Yugabyte Platform, a private DBaaS version of YugabyteDB for enterprises, helps companies manage their encryption in transit requirements. It does this by supporting custom CAs and CA-signed certificates. It also enables encryption in transit and rotating server and CA certificates seamlessly on managed database clusters.
Finally, you can build your own YugabyteDB-as-a-service on any cloud with Yugabyte Platform, the best fit for mission-critical deployments. Sign up today for a free 30-day trial!