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
Server Name Indication (Let's Encrypt / Server only certificate) support for Ruby, Python and Java drivers #6204
base: v2.4.x
Are you sure you want to change the base?
Conversation
This way a connection can be made to a Let's Encrypt enabled server. It is, however, still necessary to reference ca_certs, but instead of self-signed pairs a proper ca_cert bundle should be used (Mozilla, Curl, etc): conn = r.connect(:host =>'rethink.domain.com', :port => 11111, :auth_key => '<auth_key>', :ssl => { :ca_certs => "/opt/pkg/share/mozilla-rootcerts/cacert.pem" } )
This way you only have to do: conn = r.connect(:host =>'rethink.domain.com', :port => 11111, :auth_key => '<auth_key>', :ssl => { :ssl => true } ) This looks a bit silly (and the second :ssl can actually be anything), but :ssl is used for ssl_opts. Could change it so :ssl is just a boolean and add a separate :ssl_opts, but this would break compatibility so seems a bad idea. There is no other way to detect a ssl connection so something has to be set somewhere to flag it's a ssl connection. Can't use an empty :ssl as the code assumes that is no ssl (although suppose could change that). I'm also not sure if OpenSSL::X509::DEFAULT_CERT_FILE is the correct way. Almost seems as if we should be using a default context instead of creating a new one, although don't know if that is possible. Note: this is just thinking out load at the moment.
For a Let's Encrypt / non-self signed certificate connection we'd now do the following: conn = r.connect(:host =>'rethink.domain.com', :port => 11111, :auth_key => '<auth_key>', :ssl => {} ) Self-signed certs work as before
Similar to the changes made to the Ruby driver this allows SSL connections to be made where there is only a server certificate i.e. not self-signed certs. To connect you'd do: conn = r.connect(host='rethink.domain.com', port=11111, auth_key='<auth_key>', ssl=>{})
Enabling SNI itself is easy, the tricky bit for me was modifying a test app to work with it. For that I [applied these changes][1] on a different branch based off the 2.3.3 driver since I had connection code that would work with that - the recent [Jackson changes][2] here broke my connection example. You have to use the SSLContext option similar to [here][3]: private static final String DEFAULT_SSL_PROTOCOL = "TLSv1.2"; ... Connection conn = null; Connection.Builder builder = r.connection(). hostname(host). port(port). authKey(authKey); final SSLContext sslContext = SSLContext.getInstance(DEFAULT_SSL_PROTOCOL); sslContext.init(null, null, null); conn = builder.sslContext(sslContext).connect(); Init with all null options here is valid. It will use the default/system trust manager for verification. [1]: 771f34d [2]: rethinkdb#6157 [3]: https://github.com/pires/rethinkdb-ssl-test/blob/master/src/main/java/com/github/pires/App.java#L70
Thanks! This looks like a good feature to have. It might take a while before we can review and merge your code, we're working on #6137. Eventually your nice examples above will have to be added to the docs and test suite. |
@adriantodt what do you think about this PR for the Java driver? |
Pointing towards |
I am still around. I seem to have a lot less time available for open-source than I used to, but may be able to find time to re-work this PR if needed (i.e. across different driver repos). I'm also wondering if we get some of this supported for free now with updates to underlying languages? |
Description
Enable Server Name Indication / Let's Encrypt / Server only certificate support in the Ruby, Python and Java drivers; The Node/Javascript driver already works with server only certificates using the
servername
property.The changes are minimal and non-breaking to existing usage. These commits can be cleaned up, squashed, etc, but for now providing it as is to provide as much information and context as possible.
Ruby
For Ruby you'd specify an empty ssl hash to indicate SNI:
Python
For Python you'd do the same as for Ruby:
Java
For Java you have to use the sslContext option and initiate it using nulls (which means it uses the system trust manager):
Also need to look at making corresponding changes to the rethinkdb client itself, i.e. for
rethinkdb dump
andrethinkdb restore
, but I thought this would be a good place to start.