Configuring Syracuse for MongoDB X509 Authentication

Enabling X509 authentication

To enable X509 authentication for MongoDB, you need:

  • a client certificate,
  • a client private key file,
  • a CA certificate.

Make sure you add the Certificate entity instance (including the client certificate and the client private key file), as well as the
CA Certificate entity instance (including the CA certificate) to the MongoDB database before switching to X509 authentication.

Example: Assuming these instances are named "mongoclient" and "mongoca", you have to make the following adjustments to the collaboration section of nodelocal.js.

exports.config = {
  // ...
  collaboration: {
    // ..
    mongoX509Cert: ["mongoclient", "mongoca"],
  }
  // ..
}

In this example, you should find the following files on the certificate path of the Syracuse instance:

  • ./mongoclient.crt
  • ./mongoclient.key
  • ./mongoca.cacrt

Alternatively, you can also enable X509 authentification with mongoX509Cert:true, which allows you to use the raw certificate in mongoOtps.server.cert or mongoOtps.server.replSet.

Setting up MongoDB with X509 authentication

Source from the Internet:
Configure X509 client authentication

Generating a CA certificate

The first step is to generate a CA certificate, if necessary. It is used to generate all MongoDB related certificates.

To do so, enter the following command in OpenSSL:

openssl req -x509 -days 365 -newkey rsa:2048 -out [CA_CERTIFICATE] -keyout [CA_KEY]

Generating a server certificate

The MongoDB server requires a server certificate with the following characteristics:

  • The subject common name must match the server name.
  • The server name cannot be an IP address.
  • The distinguished name for the subject of the server certificate must not be identical to the distinguished name for the subject of the CA certificate.

Enter the following command in OpenSSL to generate the certificate request and sign the certificate:

openssl req -newkey rsa:2048 -keyout server-key.pem -out server-req.csr
openssl x509 -req -days 360 -in server-req.csr -CA [CA_CERTIFICATE] -CAkey [CA_KEY] -CAcreateserial -out server-cert.crt

Stripping the passphrase

  1. Enter the following command:
    openssl rsa -in server-key.pem > server-key-no.pem
  2. Copy server-cert.crt and server-key-no.pem into a single file using the command below:
    copy server-cert.crt+server-key-no.pem [SERVER_CERT_KEY]

Generating the MongoDB client certificate

Note: The subject must contain "O", "OU" or "C", as well as extra fields "keyUsage" and "extendedKeyUsage". The "O", "OU" and "C" values must not be identical to the corresponding values of the server certificate.

Caution: Do not use special characters (including blank spaces) in the subject as they might cause the authentication to fail.

To generate the MongoDB client certificate:

  1. Create a .cnf config file containing the text below:
    [mongoClient]
    keyUsage         = digitalSignature
    extendedKeyUsage = clientAuth
  2. Generate the certificate signing request, and then the certificate itself by entering the following command in OpenSSL:
    openssl req -newkey rsa:2048 -keyout [CLIENT_KEY] -out client-req.csr
    openssl x509 -req -days 360 -in client-req.csr -extensions mongoClient -extfile [CLIENT_SSL_CONFIG] -CA [CA_CERTIFICATE] -CAkey [CA_KEY] -CAcreateserial -out [CLIENT_CERTIFICATE]
  3. To test the connection:
    1. Strip the passphrase from [CLIENT_KEY].
    2. Copy [CLIENT_CERTIFICATE] and the client key with the stripped passphrase into a single file [CLIENT_CERT_KEY].
      This is done the same way as for the server key and the server certificate.
    3. Run the "mongo" executable.

Invoking the MongoDB server without SSL

For the first invocation of the MongoDB server without SSL, enter the following command:

mongod --port [PORT] [--logpath [LOGFILE]] [--smallfiles] [--dbpath [PATH_FOR_MONGODB]]

Creating a MongoDB user

  1. Retrieve the user name from the certificate by entering the following command:
    openssl x509 -in [CLIENT_CERTIFICATE] -inform PEM -subject -nameopt RFC2253 -noout

    The output will be similar to the following:
    Subject= CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry
  2. Start the mongo client with the following command:
    mongo [--port [PORT]]  [--host [HOSTNAME]]
  3. Enter the following code in the MongoDB client:
    db.getSiblingDB("$external").runCommand(
      {
        createUser: "CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry",
        roles: [
                 { role: 'readWrite', db: 'syracuse' },
                 { role: 'userAdminAnyDatabase', db: 'admin' }
               ],
        writeConcern: { w: "majority" , wtimeout: 5000 }
      }
    )

    Note: Make sure you adjust the roles to your needs.

Invoking the MongoDB server with the X509 authentication

For the invocation of the MongoDB server with the X509 authentication, enter the following command:

mongod [--clusterAuthMode x509] --sslMode requireSSL --sslPEMKeyFile [SERVER_CERT_KEY] --sslCAFile [CA_CERTIFICATE] --port [PORT] [--logpath [LOGFILE]] [--smallfiles] [--dbpath [PATH_FOR_MONGODB]]

Note:

  • The --clusterAuthMode option is only necessary for replica sets or shared clusters, not for standalone MongoDB servers.
  • [CA_CERTIFICATE]: file system path of the CA certificate.
  • [SERVER_CERT_KEY]: file system path of the file containing the server certificate and the server private key.

Testing the configuration with the MongoDB client

Run the following command to test the configuration:

mongo --ssl --sslPEMKeyFile [CLIENT_CERT_KEY] --sslCAFile [CA_CERTIFICATE] --host [HOSTNAME] --port [PORT] -u [DN] --authenticationMechanism=MONGODB-X509 --authenticationDatabase='$external'

Note:

  • [CLIENT_CERT_KEY]: file system path of the file containing the client certificate and the client private key.
  • [DN]: Distinguished name of the user specified before.

Appendix

Below is a simple Javascript client to test the connection (Source: mongodb.github.io/tutorial):

var MongoClient = require('mongodb').MongoClient,
  fs = require('fs');
// Read the cert and key
var cert = fs.readFileSync([CLIENT_CERTIFICATE]);
var key = fs.readFileSync([CLIENT_KEY]);
var ca = fs.readFileSync([CA_CERTIFICATE]);
// User name (obtained from cert - please adjust it)
var userName = "CN=client,OU=kerneluser,O=10Gen,L=New York City,ST=New York,C=US";
// Connect using the MONGODB-X509 authentication mechanism
MongoClient.connect('mongodb://'+encodeURIComponent(userName)+'@[HOSTNAME]:[PORT]/syracuse?authMechanism=MONGODB-X509&ssl=true', {
server:{
  sslKey:key,
  sslValidate: true,
  checkServerIdentity:false, // optional
  sslCert:cert,
sslCA:[ca]},
  sslKey:key,
  sslCert:cert,
}, function(err, db) {
if (err) console.log("Error", err);
  if(db) { console.log("Closing"); db.close();}
});