Skip to content

Instantly share code, notes, and snippets.

@trentjeff
Last active October 2, 2023 14:44
Show Gist options
  • Save trentjeff/85a66a0ca61349c26af1e0426573e1b3 to your computer and use it in GitHub Desktop.
Save trentjeff/85a66a0ca61349c26af1e0426573e1b3 to your computer and use it in GitHub Desktop.
TlsManager for WebClient

Currently, the TlsManager was introduced in 3.x & 4.x to support TLS/SSLContext configuration. The motivator of this was primarily to support OCI Certificates Service integration, including automatic detection and rotation of keys and certificates.

The existing design goal for TlsManager was centered around server/listener side support. However, we do have to also consider the client-side integration for TLS configuration as well. The important thing to note here is that the manager was designed to abstract and hide the details of "management and lifecycle" behind its implementation. The manager just needs to be sure that it can deliver a SSLContext at startup, and optionally be able to manage its lifecycle post-startup (i.e., checking for updated certificates, etc).

Fortunately in 4.x, the Tls and TlsConfig are shared between server and client-side. This is not the case for 3.x though.

The OCI implemetation for TlsManager will (a) download the certificate(s) and key(s) at startup, and then (b) update Tls when we poll and detect changes made by the OCI Certificate Service endpoint response. All of this, though, happens in memory and is non-persistent in nature - nothing is stored to the file system locally in this exchange.

In order to support all of OCI's use cases, however, we will also need to support WebClient w/ TLS in 3.x as well - where these certificates are again being managed behind an OCI service. In the vein of supporting client side for 3.x, I have identified these approaches to address this gap:

Approach (1)

Extend TlsManager's configuration to optionally provide a file location to store the remote certificates and keys locally on the file system; This optional configuration will be made mandatory if/when client-side TLS is required to use these remote certificates/keys. The assumption here is that the WebClient is used in the same JVM as the server, and starting the server is a prerequisite to using the WebClient TLS configuration.

The pro to this approach is that it allows WebClient to be used basically as-is, based upon the physical location for the pem files. It also centralizes the feature to simply ConfiguredTlsManager for both 3.x and 4.x.

The con to this approach is that it... (a) requires the server to be run 1st as a pre-requisite, (b) requires security-sensitive material (keys and certificates) to be stored on the file system.

Approach (2)

Have TlsManager be integrated as-is currently designed for WebClient integration (i.e., WebClientTls) into 3.x.

The pro to this approach is that we have symmetry between client and server. The con to this approach is efficiency and performance - ideally on the same VM we should have only one TlsManager instance running. Without lots of effort, we run the risk of many TlsManager instances running on the same VM doing the same exact thing across the server and clients. This topology is aniticpated for OCI Pegasus based applications where the service will be communicating to may backing services using WebClient as well - many of which would probably be sharing the same tls configuration. One way to mitigate this work is to ensure that the TlsManager remains a singleton instance on the same JVM for the exact same configuration inputs. Note that having the "same TlsManager instance for the same Tls configuration" should be something we also put into 4.x.

Another consideration/con here is that most of our customers seem to be using microprofile's rest-client instead of WebClient - especially for MP which is what customers will be using initially for Pegasus. TBD on all of this relative to this module.. See https://helidon.io/docs/latest/#/mp/restclient#_configuration.

Approach (3)

Provide a tool and/or API extension to the OCI TlsManager Integration module that will allow a customer to independently download the certificate(s) from the OCI, but then use either WebClient or RestClient as-is designed today. This is a variation to approach #1, but instead of relying on configuration we rely on an API or CLI to perform the local persistence of the certificates.

The pro to this approach is simplicitly and modularity, and it should just work for WebClient and RestClient use cases. The con to this approach is that there is no rotation feature made available for client-side use cases, not automatically at least.

Recommendation

I am recommending going with approach (3) and additionally enhancing 4.x to "ensure that the TlsManager remains a singleton instance on the same JVM for the exact same configuration inputs".

@danielkec
Copy link

danielkec commented Sep 26, 2023

I like the most option #2. We can think of some kind of a keystore type to propagate the configuration for rest-client, something like:

myClient/mp-rest/trustStore=tlsManager://HelidonTlsManager
myClient/mp-rest/trustStoreType=tlsManager

@Verdent can provide expertise on that

@trentjeff
Copy link
Author

trentjeff commented Sep 26, 2023

I like the most option #2. We can think of some kind of a keystore type to propagate the configuration for rest-client, something like:

myClient/mp-rest/trustStore=tlsManager://HelidonTlsManager
myClient/mp-rest/trustStoreType=HelidonTlsManager

@Verdent can provide expertise on that

tlsManager is only referenceable by a Config key (e.g., "web-server.tls.manager.my-tls-manager"). So I guess that is what you intend in "tlsManager://HelidonTlsManager" here @danielkec ?

@danielkec
Copy link

Singleton tls manager, or named bean/service, whatever works better for option #2

@trentjeff
Copy link
Author

Discussed with Tomas. He prefers option #2 as well, with additional code to ensure there is a single TlsManager per unique configuration to avoid proliferation of TlsManager instances on the same JVM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment