iconara / cql-rb

Cassandra CQL 3 binary protocol driver for Ruby
106 stars 31 forks source link

Support client/node encryption #110

Closed iconara closed 10 years ago

iconara commented 10 years ago

This is a work in progress for #105. Most of the work is in Ione (see iconara/ione#6), the only thing that is needed in cql-rb is a way to get the OpenSSL::SSL::SSLContext into the connection options.

I've managed to run cql-rb against a node with client encryption enabled like this:

cert_path = '/Users/theo/.ccm/encrypted_206/node1/conf/server.cer'
cert_store = OpenSSL::X509::Store.new
cert_store.set_default_paths
cert_store.add_cert(OpenSSL::X509::Certificate.new(File.read(cert_path)))
ssl_context = OpenSSL::SSL::SSLContext.new
ssl_context.cert_store = cert_store
ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER

client = Cql::Client.connect(ssl: ssl_context)
client.execute("SELECT * FROM system.local")

You also need this in your Gemfile

gem 'ione', github: 'iconara/ione', branch: 'ssl_support'

The API is not final, maybe the option will be called something different.

jasonmk commented 10 years ago

Thanks for working on this. I was able to get it to work great as you described above, however, I think tried to take it step further and turn on client auth on the server. Basically, just doing this before connecting:

ssl_context.key = OpenSSL::PKey::RSA.new(key) ssl_context.cert = OpenSSL::X509::Certificate.new(cert)

Where key and cert are PEM encoded key and cert files. This resulted in a seg fault as shown here: https://gist.github.com/jasonmk/b059127f9a51a69397bf

I'm going to keep investigating, but I thought you might already know what's going on.

Thanks!

iconara commented 10 years ago

That doesn't sound good. I don't want to just point the finger at OpenSSL, but it's very close at hand. I'm scared of that library.

Thanks a lot for testing.

jasonmk commented 10 years ago

Just wanted to give you a heads up. The issue I posted above seems to be isolated to the OpenSSL library on OSX. We were able to get 2 way SSL working on RHEL 6 with no problem. The only catch was that the CA certificate that signed the user's cert had to be in the Java system keystore. Having it in Cassandra's trust store wasn't enough.

If I get some time, I'll probably play around a little more with the OpenSSL versions, but for now, I'm happy to see it working. What do you think the timeframe will be before this gets merged into the baseline?

Thanks!

iconara commented 10 years ago

My main concern is that I don't have any good way of including it in the automatic test suite so I won't know when I break it, and I don't have a good way of testing it myself, it's a bit of a pain to set up the environment for it.

At the same time I wouldn't mind merging it and keeping it as an experimental feature, that can be done soon. It would be nice if there were more people who had tested it.

Would you mind sharing a bit more about the steps necessary to get it working so that I can have something for the readme?

jasonmk commented 10 years ago

Ok, just tested this further using the ssl_support_for_1.2 branch you created. Everything seems to be working well. I'm using certs that are signed by a CA, so it's important to note that the cert that I include in the cert_store is the CA cert, not the server cert. I imagine if you're using a self-signed cert, they would be the same cert. I'm going to try to write some tests for this, but as you mentioned, it's very difficult to automate.

What do you need in order to get enough confidence to merge this into master (and the ione support as well)? Would it be possible to move all of the SSL support into a separate module that isn't included by default, but that someone could require explicitly if they want it?

iconara commented 10 years ago

That's great. I'll merge the necessary code and release it with v1.2 of Ione (there will first be a prerelease), and I'll also try to get a version of cql-rb out. Are the instructions I posted at the top something that I could put into the readme? It would be great if you could share your setup with CA-signed certs too, and how to configure the SSL context when the server authenticates the client too. If you wouldn't mind. Just a chunk of code that shows how to set up and get started.

jasonmk commented 10 years ago

This sums up what I'm doing currectly.

https://gist.github.com/jasonmk/be5257c2b846c2b74c6c

The instructions you posted at the top will definitely work for connecting to a single node. If you are connecting to a cluster, you would have to include all of the certificates for all of your nodes in the certificate store. At that point, I think you end up better off with the process I outlined above using a CA cert to sign everything. The instructions I posted shouldn't change as you move from one node to a cluster. Assuming your running encryption for server-to-server communication across your cluster, you probably already have certificates and keys generated for all of the nodes, so you just have to generate the client ones and import that certificate everywhere.

iconara commented 10 years ago

That's great, thank you so much for the instructions. I will try to wrap this up and release new versions this week.

It's semi-official at this point, but this will probably be the last update for cql-rb, Datastax have taken over the development and will release a more official Ruby driver built on cql-rb soon: https://github.com/datastax/ruby-driver . I can't promise that encryption will be added to the first versions of that driver, but it will get there eventually.

jasonmk commented 10 years ago

Yeah, I was talking with one of the datastax guys about that. Hopefully, this makes it there eventually, but in the mean time we're planning to use the cql-rb for the time being as this encryption support is necessary for a project we're working on.

Thanks!

iconara commented 10 years ago

I've integrated everything into master now, and released Ione v1.2.0.pre2. I'll release cql-rb v2.1.0.pre0 as soon as I weed out a bug I just discovered. There might also be a new Ione release to fix it. It's nothing major, just changed behaviour when you connect to the wrong port.

iconara commented 10 years ago

This is now available in v2.1.0.pre0.

avalanche123 commented 10 years ago

ruby-driver added support for ssl connections here - https://github.com/datastax/ruby-driver/pull/9