bobthecow / genghis

The single-file MongoDB admin app
http://genghisapp.com
MIT License
1.45k stars 166 forks source link

Connecting to a replicaset w/ SSL? #195

Closed taxilian closed 9 years ago

taxilian commented 9 years ago

Hey,

we've been using Genghis as our primary UI for mongodb for several years, but now find ourselves unable to use it. We're now using SSL w/ an internal CA in order to secure connections between replicaset members at remote locations, and we can't find a way to make genghis connect.

We use the following to connect via command-line:

mongo --ssl --sslPEMKeyFile /etc/mongodb_cert.pem --sslCAFile /etc/gradecam_ca.crt :

Any suggestions? We don't mind adding something hacky in the code for a single instance if it'll give us a workaround =]

Thanks for your hard work on this, Justin.

bobthecow commented 9 years ago

There is a way, but it's definitely hacky :)

Are you using the PHP backend? If so, check out the connecting over SSL page. The spot you'd add those config options would be here:

https://github.com/bobthecow/genghis/blob/master/src/php/Genghis/Models/Server.php#L71

If you're using the Ruby backend, let me know :)

taxilian commented 9 years ago

I've sworn off PHP (with Genghis and in general =]); the PHP version has a tendency to rewrite objects to be arrays and vise versa because it doesn't know the difference...

If I were using PHP I could maybe figure it out. I don't really know anything about Ruby, though. I'm sure I could still track it down if I tried hard enough, but I'm hoping you already know the answer =]

bobthecow commented 9 years ago

I don't blame you, that's caused no end of problems :)

I'll take a look at the Ruby backend in a minute and see if I can sort it out for you.

bobthecow commented 9 years ago

Here's the equivalent line for genghis.rb:

https://github.com/bobthecow/genghis/blob/master/src/rb/genghis/models/server.rb#L134

You'll want to add various :ssl_* options to the @opts hash there. See the MongoClient constructor docs for more on what those are. It'll prolly look something like this:

opts = {
  :connect_timeout => 1,
  :w               => 1,
  :ssl_key         => 'foo'
  :ssl_ca_cert     => 'bar',
}

@client ||= Mongo::MongoClient.from_uri(@dsn, opts.merge(@opts))
taxilian commented 9 years ago

Awesome. This will basically make this copy of genghis so it will only work w/ SSL, correct?

As a thought, it would be cool if you had an "ssl options" dropdown when adding a connection; give it default options of "None" and "SSL Enabled" for basic stuff, but then allow an optional file to be placed somewhere / specified somehow that defines additional SSL configurations where you can indicate the key, CA Cert, etc. Maybe you have better ideas / plans for the future; I'm just brainstorming on minimalist ways to provide the functionality without hacks, in the spirit of genghis =]

Thanks again, I'll try this out.

taxilian commented 9 years ago

Hmm. so far no luck; I'll have to keep playing.

  def client
    opts = {
      :connect_timeout => 1,
      :w => 1,
      :ssl => true,
      :ssl_ca_cert => 'CRT TEXT HERE',
      :ssl_key => 'KEY TXT HERE'
    }
    @client ||= Mongo::MongoReplicaSetClient.from_uri(@dsn, opts.merge(@opts))
  rescue OpenSSL::SSL::SSLError => e

This is what I'm currently using, in case you have any ideas. I've already tried both MongoClient and MongoReplicaSetClient; doesn't seem to make any difference. The attempts to connect to mongos all say "Failed to connect to a master node" and the replicaset attempt says "Cannot connect to a replicaset using seeds .."

Is there a way to get more verbose logging?

taxilian commented 9 years ago

I realized after posting that that I need the :ssl_cert as well, but adding it didn't help.

taxilian commented 9 years ago

Ahh, found it! I was making erroneous assumptions. In the node.js driver you have to specify the certificates as a string passed into the parameter, but the ruby driver wants the filename. Final working block of code:

  def client
    opts = {
      :connect_timeout => 1,
      :w => 1,
      :ssl => true,
      :ssl_ca_cert => '/path/to/ca.crt',
      :ssl_key => '/path/to/private.key',
      :ssl_cert => '/path/to/private.crt'
    }
    @client ||= Mongo::MongoClient.from_uri(@dsn, opts.merge(@opts))
  rescue OpenSSL::SSL::SSLError => e
    raise Mongo::ConnectionFailure.new('SSL connection error')
  rescue StandardError => e
    raise Mongo::ConnectionFailure.new(e.message)
  end
bobthecow commented 9 years ago

Awesome!

Yeah, it'd be nice to provide an option for this sort of thing. I'll see if I can come up with something simple that makes sense.

taxilian commented 9 years ago

Let me know if you need someone to test it =] We'll be using ssl exclusively at GradeCam for production databases from here on out, so we'll be using the hack until then.