Setting Up Security for a Distributed Mode Cluster¶
- Introduction
- Generating Certificates and Other TLS Artifacts
- Enabling TLS and Auth in Pravega
- Conclusion
Introduction¶
In the distributed mode of running a Pravega cluster, each service runs separately on one or more processes, usually spread across multiple machines. The deployment options of this mode include:
- A manual deployment in hardware or virtual machines
- Containerized deployments of these types:
- A Kubernetes native application deployed using the Pravega Operator
- A Docker Compose application deployment
- A Docker Swarm based distributed deployment
Regardless of the deployment option used, setting up Transport Layer Security (TLS) and Pravega Auth (short for authentication and authorization) are essential requirements of a secure Pravega deployment. TLS encrypts client-server as well as internal communication server components. TLS also enables clients to authenticate the services running on the server. Auth, on the other hand, enables the services to validate that the users accounts used for accessing them have requisite access permissions. Pravega strongly recommends enabling both TLS and Auth in production.
This document lists steps for enabling TLS and auth for manual deployments. Depending on the deployment option used and your environment, you might need to modify the steps and commands to suit your specific needs and policies.
Generating Certificates and Other TLS Artifacts¶
At a high-level, setting up TLS in Pravega comprises of two distinct activities:
- Generating TLS Certificates, private Keys, keystore, truststore and other artifacts, which involves steps that Pravega is oblivious to.
- Enabling and configuring TLS in Pravega.
Creating TLS Certificates, Keys and Other TLS Artifacts explains how to perform the first activity. The next section explains the second activity.
Enabling TLS and Auth in Pravega¶
The high-level steps for enabling TLS and Auth, are:
- Configuring TLS and auth on server side
- Configuring TLS and credentials on client Side
- Having TLS and auth take effect
These steps are discussed in the following sub-sections.
Configuring TLS and Auth on Server Side¶
You can configure the following services for TLS and Auth:
- Controller
- Segment Store
- Zookeeper (optional)
- Bookkeeper (optional)
For information about enabling TLS for Zookeeper and Bookeeper, refer to their documentation here: * ZooKeeper SSL Guide * BookKeeper - Encryption and Authentication using TLS
Controller
Controller services can be configured in two different ways:
- By specifying the configuration parameter values directly in the
controller.config.properties
file. For example,
controller.security.tls.enable=true controller.security.tls.server.certificate.location=/etc/secrets/server-cert.crt
- By specifying configuration parameters as JVM system properties when starting the Controller service instance.
# Example: docker-compose.yml file ... services: ... controller: environment: ... JAVA_OPTS: -dcontroller.security.tls.enable=true -dcontroller.security.tls.server.certificate.location=... ... ...
The following table lists the Controller service's TLS and auth parameters as well as samples values, for quick reference. For a detailed description of these parameters, refer to the Pravega Security Configurations document.
Configuration Parameter | Example Value |
---|---|
controller.security.tls.enable |
true |
controller.security.tls.server.certificate.location |
/etc/secrets/server-cert.crt |
controller.security.tls.server.privateKey.location |
/etc/secrets/server-key.key |
controller.security.tls.trustStore.location |
/etc/secrets/ca-cert.crt |
controller.security.tls.server.keyStore.location |
/etc/secrets/server.keystore.jks |
controller.security.tls.server.keyStore.pwd.location |
/etc/secrets/server.keystore.jks.password 1 |
controller.zk.connect.security.enable |
false 2 |
controller.zk.connect.security.tls.trustStore.location |
Unspecified 2 |
controller.zk.connect.security.tls.trustStore.pwd.location |
Unspecified 2 |
controller.security.auth.enable |
true |
controller.security.pwdAuthHandler.accountsDb.location 3 |
/etc/secrets/password-auth-handler.database |
controller.security.auth.delegationToken.signingKey.basis |
a-secret-value |
[1]: This and other .password
files are text files containing the password for the corresponding store.
[2]: It is assumed here that Zookeeper TLS is disabled. You may enable it and specify the corresponding client-side
TLS configuration properties via the controller.zk.*
properties.
[3]: This configuration property is required when using the default Password Auth Handler only.
Segment Store
Segment store supports security configuration via a properties file (config.properties
) or JVM system properties. The table
below lists its TLS and auth parameters and sample values. For a detailed discription of these parameters refer to
Pravega Security Configurations document.
Configuration Parameter | Example Value |
---|---|
pravegaservice.security.tls.enable |
true |
pravegaservice.security.tls.server.certificate.location |
/etc/secrets/server-cert.crt |
pravegaservice.security.tls.certificate.autoReload.enable |
false |
pravegaservice.security.tls.server.privateKey.location |
/etc/secrets/server-key.key |
pravegaservice.zk.connect.security.enable |
false 1 |
pravegaservice.zk.connect.security.tls.trustStore.location |
Unspecified 1 |
pravegaservice.zk.connect.security.tls.trustStore.pwd.location |
Unspecified 1 |
autoScale.controller.connect.security.tls.enable |
true |
autoScale.controller.connect.security.tls.truststore.location |
/etc/secrets/ca-cert.crt |
autoScale.controller.connect.security.auth.enable |
true |
autoScale.security.auth.token.signingKey.basis |
a-secret-value 2 |
autoScale.controller.connect.security.tls.validateHostName.enable |
true |
pravega.client.auth.loadDynamic |
false |
pravega.client.auth.method |
Basic |
pravega.client.auth.token |
Base64-encoded value of 'username:password' string |
[1]: The secret value you use here must match the same value used for other Controller and Segment Store services.
[2]: It is assumed here that Zookeeper TLS is disabled. You may enable it and specify the corresponding client-side TLS configuration properties via these properties.
Configuring TLS and Credentials on Client Side¶
After enabling and configuring TLS and auth on the server-side services, it's time for the clients' setup.
Clients can be made to trust the server's certificates signed by custom CA's using one of the following ways:
-
Configure the client application to use the signing CA's certificate as the truststore. Alternatively, use the servers' certificate as the truststore.
2. Install the CA's certificate in the Java system key store. 3. Create a custom truststore with the CA's certificate and supply it to the Pravega client application, via standard JVM system propertiesClientConfig clientConfig = ClientConfig.builder() .controllerURI("tls://<dns-name-or-ip>:9090") .trustStore("/etc/secrets/ca-cert.crt") ... .build();
javax.net.ssl.trustStore
andjavax.net.ssl.trustStorePassword
.
For auth, client-side configuration depends on the AuthHandler
implementation used. If your server is configured to
use the built-in Password Auth Handler that supports "Basic" authentication, you may supply the credentials as shown below.
ClientConfig clientConfig = ClientConfig.builder() .controllerURI("tls://<dns-name-or-ip>:9090") .trustStore("/etc/secrets/ca-cert.crt") .credentials(new DefaultCredentials("<password>", "<username>")) .build();
Server Hostname Verification¶
For client's server hostname verification to succeed during TLS handshake, the hostname/IP address it uses for accessing the server must match one of the following in the server's certificate:
- Common Name (
CN
) in the certificate'sSubject
field - One of the
Subject Alternative Names
(SAN) field entries
Even if the server listens on the loopback address 127.0.0.1
and its certificate is assigned to localhost
, hostname
verification will fail if the client attempts to access the server via 127.0.0.1
. For the verification to pass,
the client must access the server using the hostname assigned on the certificate localhost
and have a hosts file entry
that maps localhost
to 127.0.0.1
(which is usually already there).
Similarly, if the server certificate is assigned to a non-routable hostname on the network (say, controller01.pravega.io
),
you might need to add an IP address and DNS/host name mapping in the client's operating system hosts file.
10.243.221.34 controller01.pravega.io
If you are reusing preexisting certificate for development/testing on new hosts, you might need to disable hostname
verification. To do so, call validateHostName(false)
of the ClientConfig builder, as shown below. Never disable
hostname verification in production.
ClientConfig clientConfig = ClientConfig.builder() .controllerURI("tls://<dns-name-or-ip>:9090") .trustStore("/etc/secrets/ca-cert.crt") .validateHostName(false) .credentials(...) .build();
Having TLS and Auth Take Effect¶
Any changes to TLS and auth configuration parameters take effect only when the service starts. So, changing those configurations require a restart of the services. The same is true for clients, as well.
Conclusion¶
This document explained about how to enable security in a Pravega cluster running in distributed mode. Specifically, how to perform the following actions were discussed:
- Generating a CA (if needed)
- Generating server certificates and keys for Pravega services
- Signing the generated certificates using the generated CA
- Enabling and configuring TLS and auth on the server Side
- Setting up the
ClientConfig
on the client side for communicating with a Pravega cluster running with TLS and auth enabled - Having TLS and auth take effect