Skip to content

Instantly share code, notes, and snippets.

@wavedocs
Forked from leommoore/mongodb_3.2.x_security.md
Created January 25, 2017 10:37
Show Gist options
  • Save wavedocs/7fb45d10f3feeccfdaa1baae41f7b024 to your computer and use it in GitHub Desktop.
Save wavedocs/7fb45d10f3feeccfdaa1baae41f7b024 to your computer and use it in GitHub Desktop.
MongoDB 3.2.x Security

#MongoDB 3.2.x Security

##Network Ports The standard ports used by mongo are:

ProcessRoleDefault Port
mongodStand-alone27017
--shardsvr27018
--configsvr27019
mongosn/a27017
Status page (off)+1000

You should limit access to the mongo servers using firewall rules to specify the ip addresses that can connect to the database. You can change the default ports but this will not stop an automated script.

You can also limit which specific interfaces are connected to mongo using the bindIp: 10.23.22.11 in the mongod.conf.

Remember that replica/shards sets listen on 27018 and the config server listens on 27019.

##Mongo with SSL You can enable SSL on your Mongo server by setting it in your mongod.conf.

net:
  ssl:
     mode: requireSSL
     PEMKeyFile: /certs/example_cert.pem
     PEMKeyPassword: myPassword
     CAFile:     /certs/cacert.pem

You can have four different modes:

  • requireSSL - Client must use SSL
  • allowSSL - Clients may or may not use SSL. Servers do not use SSL to talk to other servers.
  • preferSSL - Clients may or may not use SSL. Servers will use SSL to talk to other servers.
  • disabled - Do not use SSL. This is the default.

The PEMKeyFile is the certificate. It should be the fully qualified server name ie mongo0.example.com. Your certificates location should also be protected using file security.

##Connecting to a Mongo using SSL To connect to a mongo instance using the shell you need to do:

mongo --ssl -sslCAFile /certs/cacert.pem --host mongo0.example.com --sslPEMKeyFile /certs/example_cert.pem --sslPEMKeyPassword myPassword

##Check the Server Security Status

db.serverStatus().security
{
    "SSLServerSubjectName": "[email protected],CN=mongo0.example.com,OU=HQ,O=Plus N,ST=CA,C=US",
    "SSLServerHasCertificateAuthority": true,
    "SSLServerCertificateExpirationDate": ISODate("2020-12-31T23:00:00Z")
}

##Users & Roles There are a number of predefined roles:

  • root - All powerful. Use with caution
  • userAdminAnyDatabase - Can create users and assign roles on any database. Use with caution
  • userAdmin - Can only create users and assign roles in a specific database
  • read - Read collections in a specific database.
  • readWrite - Read and Write to a specific database

###Enabling Authentication To enable authentication you need to ensure that the following line is added to the mongod.conf:

security:
    authorization: enabled

Then restart mongo. You can connect to a local mongo with the shell and there are no users defined. This is called the localhost exception. It allows you to gain access so that you can start setting up the users. Once the first user is created the localhost exception no longer applies.

###First User The first user should be an admin user that can manage the database.

use admin

var adminUser = {
              "user": "adminUser",
              "pwd": "mypassword",
              "readOnly" : false,
              "roles": [
                     {
                         "role": "userAdminAnyDatabase",
                         "db": "admin"
                     }
              ]
          }

 db.createUser(adminUser) 

The readOnly: false option give the adminUser readWrite access to all databases.

####Reporting User Change the database to the applicationDB unless you want to have a central authentication using the admin database.

user applicationDB
var rptUser = {user: 'rptUser', pwd: '1234', roles: [{role: 'read', db: 'mydatabase'}]}
db.createUser(rptUser) 

####Application

use applicationDB
var appUser = {user: 'appUser', pwd: '1234', roles: [{role: 'readWrite', db: 'mydatabase'}]}
db.createUser(appUser) 

###Deleting a user:

db.dropUser("fred")

###Add Roles to Users If we want to add the ability for the adminUser to be able to read and write to the database then we can grant this role to the user. The admin user can manage users and roles.

db.grantRolesToUser("adminUser",["readWrite"])

When the role is expressed as a string ie "readWrite" then it is assumed to mean the current database.

To give access to specific database

db.grantRolesToUser("fred",[{db: "mydatabase", role: "read"])

To remove a role from a user:

db.revokeRolesFromUser("fred", ["read"])

###Viewing user Details There are two ways to view the user details:

show users

or, if you can read the system.users table, you can just find it.

##Authentication Database If it quite possible to authenticate with a different database from the one you are using. For example you may have a number of databases but only one central user database. The user will still only have the rights on the database that have been assigned to it, regardless of the authentication right on the user database. To log on using a specific authentication database:

mongo --username fred --password mypassword --authenticationDatabase userdatabase

##Logging in and out from the mongo Shell

db.logout("fred") db.auth("fred","mypassword")

##Intra Cluster Authentication To ensure that all members of a cluster (replica set or shards or both) are real you can give each one a key file containing a shared secret. The Key File has the following properties:

  • Arbitrary content
  • 6-1024 characters
  • Base64 characters only
  • User-only file read properties

You need to specify the Key File in the mongod.conf.

###Server1

storage:
    dbPath: /data
    
replication:
    replSetName: rs1

security:
    keyFile: /certs/clusterKeyFile.txt
    clusterAuthMode: sendKeyFile

net:
    port: 27017
    ssl:
        mode: requireSSL
        PEMKeyFile: /certs/clusterHost1_complete.pem
        PEMKeyPassword: mypassword
        CAFile: /certs/cacert.pem

###Server2

storage:
    dbPath: /data
    
replication:
    replSetName: rs1

security:
    keyFile: /certs/clusterKeyFile.txt
    clusterAuthMode: sendKeyFile

net:
    port: 27017
    ssl:
        mode: requireSSL
        PEMKeyFile: /certs/clusterHost2_complete.pem
        PEMKeyPassword: mypassword
        CAFile: /certs/cacert.pem

###Initiating a replica set using SSL Certs
When you intitialize a set which are using certs you ned to specify the exact name as per the certs:

    var cfg = { _id: "rs1", members: [{_id: 0, "host1.example.com:27017"}, {_id: 1, "host2.example.com:27017"}] }
    rs.initiate(cfg)
    
You then need to create the ```superUser``` so that you can vire the ```rs.status()``` or ```rs.config()```.

    use admin
    db.createUser({ "user": "root", "pwd": "mypassword", "roles": ["root"]})
    
Then log in as this user:

   db.auth("root","mypassword")
   rs.config()

That means the replica set is running with SSL and Authentication is enabled and it is uing a Key File to authenticate the members of the cluster.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment