-
Notifications
You must be signed in to change notification settings - Fork 426
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add connection properties for specifying custom TrustManager #70
Conversation
Adds two new connection properties that can be used to specify a custom TrustManager implementation: trustManagerClass - Class name of the custom TrustManager trustManagerConstructorArg - Optional argument to pass to the constructor of the custom TrustManager. If encryption is enabled and the trustManagerClass property is specified, it will be retrieved via Class.forName(...). If the optional property trustManagerConstructorArg is specified, then a constructor will be retrieved via getDeclaredConstructors(String.class). The TrustManager will then be instantiated by specified the optional argument as a parameter. If the optional property trustManagerConstructorArg is not specfied, then the default no argument constructor of the class will be retrieved and instantiated.
@sehrope I like your implementation. As per my understanding you are adding ability to configure 3rd party / Custom TrustManager's. Do you have any specific scenario where you need this kind of requiement? |
Yes the specific scenario is a dynamic environment where connections to disparate databases are created on the fly (check out our product JackDB 😄). Using the standard keystore based approach isn't feasible as you'd be constantly adding / removing to the same shared keystore file. That also has the disadvantage of requiring a file on the local filesystem which preferably avoided in PaaS style deployments. With this patch, we can customize each connection with a custom TrustManager that validates the specific remote server certificate that we're expecting. Below is an example of a TrustManager that takes a single certificate as an argument and validates againt it. Note that the remote certificate does not have to byte-for-byte match the constructor argument. The chain is what's being validated so you can specify a parent certificate as the constructor argument and all child certificates signed by that parent will be trusted as well. This works particularly well in DBaaS environments (ex: like SQL Azure) where each server would have a unique certificate but they'd all be signed by a common parent.
|
@sehrope I got crux of requirement. You want a way to validate direct certificate without passing key-store. I appreciate your solution & approach. Right now your suggestion is in review process. Mean while can you open this Pull Request for dev branch? |
Done. I've created #74 targeting the dev branch. |
is there any plans to merge this soon? |
@josecollazzi, #74 was created against the dev branch. Please follow updates there. |
This PR adds two new connection properties:
trustManagerClass
- The fully qualified class name of a custom javax.net.ssl.TrustManagertrustManagerConstructorArg
- An optional argument to pass to the constructor of the TrustManager.If
trustManagerClass
is specified and an encrypted connection is requested, the custom TrustManager will be used rather than the default system JVM keystore based TrustManager.The primary use case for this is to dynamically specify the specific set of certificates that are trusted on a per connection basis without modifying the global settings for the JVM environment (i.e. no need to use a shared / global JKS).
For the error message localization code on line 1803, I've added handling for the case where the caught exception does not provide a localized message. That situation can arise when a custom TrustManager implementation is used as the Driver has no control over that code (it's use specified).
The new code tries to get a localized message, if one is not available then it tries the non-localized message, and if that is not available it defaults to an empty string. The final empty string default is required as subsequent code assumes that all caught exceptions will have a localized error message and would otherwise throw a NullPointerException from within the error handling code.
There's no additional tests for it in the test suite but I've tested it externally using both the specific custom TrustManager we'll be using as well as custom implementation of PermissiveX509TrustManager (which effectively mimics the behavior of
trustServerCertificate=true
).