Skip to content
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

Open
wants to merge 5 commits into
base: v2.4.x
Choose a base branch
from

Conversation

atomicules
Copy link

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:

    conn = r.connect(:host =>'rethink.domain.com',
        :port => 11111,
        :auth_key => '<auth_key>',
        :ssl => {}
    )

Python

For Python you'd do the same as for Ruby:

    conn = r.connect(host='rethink.domain.com',
        port=11111,
        auth_key='<auth_key>',
        ssl=>{})

Java

For Java you have to use the sslContext option and initiate it using nulls (which means it uses the system trust manager):

    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();

Also need to look at making corresponding changes to the rethinkdb client itself, i.e. for rethinkdb dump and rethinkdb restore, but I thought this would be a good place to start.

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
@AtnNn
Copy link
Member

AtnNn commented Dec 22, 2016

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.

@gabor-boros
Copy link
Member

@adriantodt what do you think about this PR for the Java driver?

@srh srh changed the base branch from next to v2.4.x April 17, 2022 01:35
@srh
Copy link
Contributor

srh commented Apr 17, 2022

Pointing towards v2.4.x. This is so we can make v2.4.x the main branch of the repository. What I should do is close this PR and make a separate issue in each of the driver repositories (because they've been split out from the main repo) but... pointing to v2.4.x works for now and is slightly less work. I intend to revisit this after v2.4.2 gets released.

@atomicules
Copy link
Author

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?

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

Successfully merging this pull request may close these issues.

None yet

4 participants