Wednesday, July 22, 2020

TLS

In this section, we talk about securing Pravega controller service with TLS. Pravega is a stream store that enables data to be appended continuously to a stream and TLS stands for Transport Layer Security which stands for a protocol that encrypts data in transit between the controller and the client.  The documentation for Pravega talks about using keys, certificates, keystores and truststores to secure the controller. It also provides these samples as out of box that can be tried with in-memory standalone mode of deployment for Pravega.
The controller.auth.tlsEnabled=true and controller.auth.tlsCertFile=/etc/secrets/cert.pem  are the settings required to secure the controller service. They can also be passed in via environment variables or JVM system properties.
The certificate that the client uses to connect with the server needs to be imported into the truststore on the server side. The keytool command can be used for this purpose as follows.
 
Care must be taken to ensure that the certificate used meets the following criteria: 1) the client sends a certificate and the server accepts the certificate based on a known certificate authority. It does not have to be signed certificates to share the same certificate authority but it signed certificates are universally accepted. 2)  The certificates are properly deployed on the hosts and runtime for the client and the server. and 3) the certificates are not expired.

When the certificates and deployment are proper, the controller uri is available as tls://ip:port instead of tcp://ip:port which can then be used programmatically to make connections such as with:
ClientConfig clientConfig = ClientConfig.builder()
              .controllerURI("tls://A.B.C.D:9090")
              .trustStore("/etc/ssl")
              .credentials(new DefaultCredentials("password", "username"))
              .build();

This mode of deployment will be different if the controller is behind a service such as when deployed on a container orchestration framework. For example, in the case of Kubernetes, it is not necessary to configure the controller with tls if the corresponding K8s service is also provisioned with load balancing and TLS. In such a case, the TLS encryption stops at the K8s service and the communication between the service and the controller will remain internal.
 
With the suitable controllerUri established for the clients to connect, the reading and writing of events to the stream should work the same. Commonly encountered exceptions include the following:
Caused by: java.security.cert.CertificateException: No subject alternative names matching IP address 10.10.10.10 found        at sun.security.util.HostnameChecker.matchIP(HostnameChecker.java:168)        at sun.security.util.HostnameChecker.match(HostnameChecker.java:94)        at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455)        at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:436)        at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:252)        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:136)        at io.netty.handler.ssl.ReferenceCountedOpenSslClientContext$ExtendedTrustManagerVerifyCallback.verify(ReferenceCountedOpenSslClientContext.java:237)        at io.netty.handler.ssl.ReferenceCountedOpenSslContext$AbstractCertificateVerifier.verify(ReferenceCountedOpenSslContext.java:625)        ... 26 more
which indicates that the certificates do not have the same alternate domain names specified as that of the host from which the client connects.  The usual mitigation for this is to disable the hostname verification or to have the alternate name specified in the certificate imported into the server's truststore.

No comments:

Post a Comment