|
| 1 | +package mgo |
| 2 | + |
| 3 | +import ( |
| 4 | + "crypto/tls" |
| 5 | + "crypto/x509" |
| 6 | + "io/ioutil" |
| 7 | + "net" |
| 8 | +) |
| 9 | + |
| 10 | +func ExampleCredential_x509Authentication() { |
| 11 | + // MongoDB follows RFC2253 for the ordering of the DN - if the order is |
| 12 | + // incorrect when creating the user in Mongo, the client will not be able to |
| 13 | + // connect. |
| 14 | + // |
| 15 | + // The best way to generate the DN with the correct ordering is with |
| 16 | + // openssl: |
| 17 | + // |
| 18 | + // openssl x509 -in client.crt -inform PEM -noout -subject -nameopt RFC2253 |
| 19 | + // subject= CN=Example App,OU=MongoDB Client Authentication,O=GlobalSign,C=GB |
| 20 | + // |
| 21 | + // |
| 22 | + // And then create the user in MongoDB with the above DN: |
| 23 | + // |
| 24 | + // db.getSiblingDB("$external").runCommand({ |
| 25 | + // createUser: "CN=Example App,OU=MongoDB Client Authentication,O=GlobalSign,C=GB", |
| 26 | + // roles: [ |
| 27 | + // { role: 'readWrite', db: 'bananas' }, |
| 28 | + // { role: 'userAdminAnyDatabase', db: 'admin' } |
| 29 | + // ], |
| 30 | + // writeConcern: { w: "majority" , wtimeout: 5000 } |
| 31 | + // }) |
| 32 | + // |
| 33 | + // |
| 34 | + // References: |
| 35 | + // - https://docs.mongodb.com/manual/tutorial/configure-x509-client-authentication/ |
| 36 | + // - https://docs.mongodb.com/manual/core/security-x.509/ |
| 37 | + // |
| 38 | + |
| 39 | + // Read in the PEM encoded X509 certificate. |
| 40 | + // |
| 41 | + // See the client.pem file at the path below. |
| 42 | + clientCertPEM, err := ioutil.ReadFile("harness/certs/client.pem") |
| 43 | + |
| 44 | + // Read in the PEM encoded private key. |
| 45 | + clientKeyPEM, err := ioutil.ReadFile("harness/certs/client.key") |
| 46 | + |
| 47 | + // Parse the private key, and the public key contained within the |
| 48 | + // certificate. |
| 49 | + clientCert, err := tls.X509KeyPair(clientCertPEM, clientKeyPEM) |
| 50 | + |
| 51 | + // Parse the actual certificate data |
| 52 | + clientCert.Leaf, err = x509.ParseCertificate(clientCert.Certificate[0]) |
| 53 | + |
| 54 | + // Use the cert to set up a TLS connection to Mongo |
| 55 | + tlsConfig := &tls.Config{ |
| 56 | + Certificates: []tls.Certificate{clientCert}, |
| 57 | + |
| 58 | + // This is set to true so the example works within the test |
| 59 | + // environment. |
| 60 | + // |
| 61 | + // DO NOT set InsecureSkipVerify to true in a production |
| 62 | + // environment - if you use an untrusted CA/have your own, load |
| 63 | + // its certificate into the RootCAs value instead. |
| 64 | + // |
| 65 | + // RootCAs: myCAChain, |
| 66 | + InsecureSkipVerify: true, |
| 67 | + } |
| 68 | + |
| 69 | + // Connect to Mongo using TLS |
| 70 | + host := "localhost:40003" |
| 71 | + session, err := DialWithInfo(&DialInfo{ |
| 72 | + Addrs: []string{host}, |
| 73 | + DialServer: func(addr *ServerAddr) (net.Conn, error) { |
| 74 | + return tls.Dial("tcp", host, tlsConfig) |
| 75 | + }, |
| 76 | + }) |
| 77 | + |
| 78 | + // Authenticate using the certificate |
| 79 | + cred := &Credential{Certificate: tlsConfig.Certificates[0].Leaf} |
| 80 | + if err := session.Login(cred); err != nil { |
| 81 | + panic(err) |
| 82 | + } |
| 83 | + |
| 84 | + // Done! Use mgo as normal from here. |
| 85 | + // |
| 86 | + // You should actually check the error code at each step. |
| 87 | + _ = err |
| 88 | +} |
0 commit comments