3

I'm trying to setup mongo locally to test the setup described in

https://www.compose.com/articles/connect-to-mongo-3-2-on-compose-from-golang/ "A Little Harder" section

Mongo

I have a working set of self signed credentials, and mongo setup. I've included keys, as those will only be used during dev to make sure mongo ssl code is working.

mongo ssl config

When using this, running via

mongod --config config/location

The config is

net:
  port: 27017
  ssl:
    mode: requireSSL
    CAFile: /data/mongo/ca.crt
    PEMKeyFile: /data/mongo/server.pem
    allowInvalidHostnames: true
    allowConnectionsWithoutCertificates: true

I can then connect to the db with

mongo --ssl --sslCAFile /data/mongo/ca.crt

Golang

func NewSession(url string, ca string) (m *mgo.Session, err error) {
    roots := x509.NewCertPool()
    roots.AppendCertsFromPEM([]byte(ca))

    tlsConfig := &tls.Config{}
    tlsConfig.RootCAs = roots

    url = strings.TrimSuffix(url, "?ssl=true")
    dialInfo, err := mgo.ParseURL(url)
    dialInfo.DialServer = func(addr *mgo.ServerAddr) (net.Conn, error) {
        conn, err := tls.Dial("tcp", addr.String(), tlsConfig)
        return conn, err
    }

    //Here it is the session. Up to you from here ;)
    session, err := mgo.DialWithInfo(dialInfo)
    if err != nil {
        return m, err
    }

    session.SetMode(mgo.Monotonic, true)

    return session, nil
}

Result

The golang stuff tries to connect and hits the 10s timeout. A fmt at the top of session shows the correct file is making it into the ca var.

Mongo logs show

utumongo_1         | 2017-07-27T08:09:14.964+0000 I NETWORK  [initandlisten] connection accepted from 172.19.0.4:57474 #30 (1 connection now open)
utumongo_1         | 2017-07-27T08:09:14.966+0000 E NETWORK  [conn30] SSL: error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate
utumongo_1         | 2017-07-27T08:09:14.967+0000 I NETWORK  [conn30] end connection 172.19.0.4:57474 (0 connections now open)

Edit Updated mongo config

jimmiebtlr
  • 438
  • 4
  • 14

1 Answers1

3

What are you passing into NewSession as the ca parameter? This needs to be the PEM encoded CA certificate bytes, not the file name of the CA certificate. AppendCertsFromPEM will return true if it managed to add any certificates to the pool.

The article already shows code to do this:

if ca, err := ioutil.ReadFile("myPEM"); err == nil { 
    roots.AppendCertsFromPEM(ca)
}

The SSL error means that the client is rejecting the server certificate. I suspect it is because your self-signed certificate was not added to the pool correctly.

EDIT

I ran a copy of mongo locally with your config. Using docker, this was:

docker run --rm -ti -v $(pwd):/data/mongo --net=host mongo -f /data/mongo/mongo.yaml

When ran from where your configuration was extracted

Using your NewSession func inside Go showed that the tls.Dial was returning an error due to the lack of any Subject Access Name (SAN) extensions as per my comment below.

You will need to correct your server certificate to have the appropriate host name (or IP address) SAN entries required.

You can debug this and any other TLS connection errors that occur with:

dialInfo.DialServer = func(addr *mgo.ServerAddr) (net.Conn, error) {
    conn, err := tls.Dial("tcp", addr.String(), tlsConfig)
    if err != nil {
        fmt.Println(err)
    }
    return conn, err
}
Martin Campbell
  • 1,728
  • 10
  • 11
  • I'm specifically passing in something of the format -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- – jimmiebtlr Jul 27 '17 at 09:48
  • Avoided passing a filename around, rather just a string that is the ca set via env or such – jimmiebtlr Jul 27 '17 at 09:49
  • It appears to be getting the correct value to the function at least. – jimmiebtlr Jul 27 '17 at 09:49
  • Did you verify `AppendCertsFromPEM` was returning `true`. Also, re-reading your post, your mongo connection is using a client certificate. Are you wanting to only accept authenticated clients? If so, need to add the client certificate to the `tlsConfig` – Martin Campbell Jul 27 '17 at 09:55
  • AppendCertsFromPEM is returning true, just updated the mongo config a bit, had removed the client cert verification. Had it originally trying to verify client certs, but have since removed that (no way to configure in compose to my knowledge). – jimmiebtlr Jul 27 '17 at 10:05
  • Had a look at your certificates. Your self-signed CA is OK but your server certificate is not. You are issuing with a CN of 127.0.01 which I assume won't match the server hostname and there are no SANs present. You may need to set `ServerName` in the TLS config. Additionally, you don't have any server certificate extensions so the certificate could be getting rejected for this reason. Does `err` contain any error after dialing within your `DialServer` func? – Martin Campbell Jul 27 '17 at 11:27