Background
In the previous post, we discussed how with Centrify, MongoDB authentication can be streamlined and we discussed SASL Auth integration. We also discussed how to leverage the authorization capabilities of Centrify to limit access to MongoDB via PAM with SASL.However, SASL is a simple option and can be greatly enhanced by using a different option.
Advantages of using AD Kerberos with Centrify
Centrify automatically creates and maintains the Kerberos environment of a UNIX, Linux or Mac OS X environment, no need to deal with /etc/krb5.conf files, machine keytabs or incompatibilities because Centrify's shared objects are optimized to work with AD regardless of the complexity of the AD environment (one-way trusts, cross-forest trusts, etc).The key benefit here is time to production. When App Developers or DBAs don't have to worry about standing up an environment (such an MIT Kerberos realm), maintaining and understanding Kerberos, it's easier to focus on the tasks around MongoDB. Active Directory is your Kerberos infrastructure and Centrify is the enabler.
From a business perspective consistency is preserved by eliminating duplication of capabilities and processes.
From a security perspective, the access model remains the same and no additional attestation mechanisms need to be created.
From the user's perspective they are more productive because we can eliminate an additional authentication prompt (remember how bad it looked when we saw the plaintext passwords on the screen?)
Another benefit is the utilities like adkeytab that allow for the provisioning and maintenance of service accounts and kerberos key tables in your systems. MongoDB uses the GSSAPI interfaces to provide Kerberos authentication.
Moderation note: This post requires that you understand the basics of Active Directory and Kerberos. If any of these terms: domain controller, kdc, service principal name, user principal name, TGT, TGS, DNS, etc, are foreign to you, please do some background study.
Basics: What is GSSAPI?
Wikipedia: "The Generic Security Service Application Program Interface (GSSAPI, also GSS-API) is an application programming interface for programs to access security services.."
The key here is that MongoDB supports Kerberos via the GSSAPI interfaces, Since Centrify makes Kerberos work effortlessly , the implementation is relatively simple:
Implementation (on CentOS)
Note: You will need the Enterprise Edition of MongoDB to get this going. For instructions of how to set up, go here: http://docs.mongodb.org/manual/tutorial/install-mongodb-enterprise-on-red-hat-or-centos (use CentOS to follow along) - I will be elevating with dzdo:Use adkeytab to create the service account and key table file for MongoDB
Adkeytab has been discussed previously here. Remember that when you use it, the service account's password is randomized; this eliminates the risk of several people knowing the credentials of a shared account, however, makes the burden around protecting the keytab file. Make sure you have protocols around this. If you're using separation of duties, the UNIX admin may not have the rights to create a service account in AD, so you have to work in cooperation with the AD team.
Note: Remember that the Centrify Kerberos tools are in the /usr/share/centrifydc/kerberos/bin directory.
Step 1: Understand the adkeytab parameters:
- this is a new account (the -n option is required)
- credentials are required to create the new account (-u <ad user that can create>)
e.g. jerry.seinfeld (the AD admin in my environment) - a key table file will be created (-K /path/to/file)
e.g. /etc/mongodb.keytab - An OU for service accounts in AD will be used (-c "dn of ou")
e.g. "ou=Service Accounts" - A UPN will be specified (-U service/principal@REALM)
e.g. mongodb/cen3.corp.contoso.com@CORP.CONTOSO.COM - A SPN will be specified (-P service/principal)
e.g. mongodb/cen3.corp.contoso.com - The UserName (samAccountName) will be different than the cn (-S name)
e.g. mongodb.service (note: the limit here is 20 chars) - The final parameter is the cn
e.g. mongodb
Step 2: Run adkeytab in verbose mode (elevated to be able to copy on /etc)
$ dzdo adkeytab -V -n -u jerry.seinfeld -K /etc/mongodb.keytab -U mongodb/cen3.corp.contoso.com@CORP.CONTOSO.COM -P mongodb/cen3.corp.contoso.com -c ou="Service Accounts" -S mongodb mongodb
ADKeyTab version: CentrifyDC 5.2.0-218
Options
-------
use machine ccache: no
domain: corp.contoso.com
server: null
gc: null
user: jerry.seinfeld
container: ou=Service Accounts
account: mongodb
trust: no
des: no
jerry.seinfeld@CORP.CONTOSO.COM's password:
Attempting bind to corp.contoso.com site:CorpHQ server:dc1.corp.contoso.com: ccache:MEMORY:0x5666c0
Bind successful to server dc1.corp.contoso.com
Attempting bind to GC domain:corp.contoso.com site:CorpHQ gcserver:dc1.corp.contoso.com ccache:MEMORY:0x5666c0
Bound to GC server:dc1.corp.contoso.com domain:CORP.CONTOSO.COM
Searching for AD Object: filter = (samAccountName=mongodb.service), root = DC=corp,DC=contoso,DC=com
Searching for AD Object: filter = (samAccountName=mongodb.service$), root = DC=corp,DC=contoso,DC=com
AD Object not found.
Building Container DN from OU=SERVICE ACCOUNTS
Account 'CN=mongodb,OU=SERVICE ACCOUNTS,DC=corp,DC=contoso,DC=com' does not exist
Search for account in GC: filter = (samAccountName=mongodb.service), root = DC=CORP,DC=CONTOSO,DC=COM
SAM name 'mongodb.service' not found in GC
Problem to create account; try again with no password required
Searching for AD Object: filter = (samAccountName=mongodb.service), root = DC=corp,DC=contoso,DC=com
AD Object found: CN=mongodb,OU=Service Accounts,DC=corp,DC=contoso,DC=com
Key Version = 1
Adding managed account keys to configuration file: mongodb
Changing account 'mongodb' password with user 'jerry.seinfeld@CORP.CONTOSO.COM' credentials.
Searching for AD Object: filter = (samAccountName=mongodb.service), root = DC=corp,DC=contoso,DC=com
AD Object found: CN=mongodb,OU=Service Accounts,DC=corp,DC=contoso,DC=com
Key Version = 2
Success: New Account: mongodb
Step 2: Verify the AD user account attributes and make sure you can get a TGT and a TGS with the keytab (elevating to read from /etc)
$ adquery user -PS mongodb
userPrincipalName:mongodb/cen3.corp.contoso.com@CORP.CONTOSO.COM
serverPrincipalName:mongodb/cen3.corp.contoso.com
$ dzdo /usr/share/centrifydc/kerberos/bin/kinit -kt /etc/mongodb.keytab mongodb/cen3.corp.contoso.com@CORP.CONTOSO.COM
[cosmo.kramer@cen3 ~]
$ dzdo /usr/share/centrifydc/kerberos/bin/klist Ticket cache: FILE:/tmp/krb5cc_1149240408
Default principal: mongodb/cen3.corp.contoso.com@CORP.CONTOSO.COM
Valid starting Expires Service principal
10/25/14 14:19:40 10/26/14 00:19:40 krbtgt/CORP.CONTOSO.COM@CORP.CONTOSO.COM
renew until 10/26/14 14:19:40
TGT successful.
$ dzdo /usr/share/centrifydc/kerberos/bin/kinit -kt /etc/mongodb.keytab -S mongodb/cen3.corp.contoso.com@CORP.CONTOSO.COM mongodb
$ dzdo /usr/share/centrifydc/kerberos/bin/klist
Ticket cache: FILE:/tmp/krb5cc_1149240408
Default principal: mongodb@CORP.CONTOSO.COM
Valid starting Expires Service principal
10/25/14 14:20:00 10/26/14 00:20:00 mongodb/cen3.corp.contoso.com@CORP.CONTOSO.COM
renew until 10/26/14 14:20:00
TGS successful
Step 3: Secure the Keytab
Copy the keytab to /var/lib/mongo
$ dzdo mv /etc/mongodb.keytab /var/lib/mongo/mongodb.keytab
Change the owner of the keytab to mongod
$ dzdo chown mongod:mongod /var/lib/mongo/mongodb.keytab
Set up a test user and configure MongoDB for GSSAPI authentication
Note: If you don't know how to properly set up users in Mongo and you're following along from the SASL posting, just disable auth and create the user. We will reenable it later.
Step 4: Make sure that SASL is configured to work with PAM and identify the path for the socket.
$ mongo
> use $external
switched to db $external
> db.createUser({user: "j.peterman@CORP.CONTOSO.COM",roles: [ { role: "read", db: "reporting" }]})
Successfully added user: {
"user" : "j.peterman@CORP.CONTOSO.COM",
"roles" : [
{
"role" : "read",
"db" : "reporting"
}
]
}
The result should be success. Keep in mind that the user's domain has to be in CAPS.
Step 5: Set the KRB5_KTNAME environment variable for the keytab
Step 6: Edit the mongodb.conf file to enable GSSAPI
Re-enable authentication. Note that you can enable both SASL and GSSAPI
Restart MongoDB and make sure there are no errors.
$ dzdo service mongod restart
Test GSSAPI/Kerberos authentication
Step 7: Log in to the system with the externally identified user that was created with the full UPN, inspect the Kerberos TGT.
$ /usr/share/centrifydc/kerberos/bin/klist
Ticket cache: FILE:/tmp/krb5cc_1149240919
Default principal: j.peterman@CORP.CONTOSO.COM
Valid starting Expires Service principal
10/25/14 15:23:35 10/26/14 01:23:35 krbtgt/CORP.CONTOSO.COM@CORP.CONTOSO.COM
renew until 11/01/14 15:23:35
10/25/14 15:25:13 10/26/14 01:23:35 mongodb/cen3.corp.contoso.com@CORP.CONTOSO.COM
renew until 11/01/14 15:23:35
Notice that during login, Centrify will automatically kinit and enable your TGT.
Step 7: Launch mongo with the system name and perform the testing.
mongo cen3.corp.contoso.com
MongoDB shell version: 2.6.5
> db.getSiblingDB("$external").auth({mechanism: "GSSAPI",user:'j.peterman@CORP.CONTOSO.COM',})
1
Output of 1 proves that authentication with Kerberos/GSSAPI was succesful.
> db.getSiblingDB("$external").auth({mechanism: "PLAIN",user:'j.peterman',pwd:'<jp's password>',digestPassword: false})
1
Both GSSAPI and SASL Plain can be used simultaneously. Kerberos is superior due to the fact that the user eliminates one prompt ad a readable password.
> use $external
switched to db $external
> db.createUser({user: "j.peterman@CORP.CONTOSO.COM",roles: [ { role: "read", db: "reporting" }]})
Successfully added user: {
"user" : "j.peterman@CORP.CONTOSO.COM",
"roles" : [
{
"role" : "read",
"db" : "reporting"
}
]
}
The result should be success. Keep in mind that the user's domain has to be in CAPS.
Step 5: Set the KRB5_KTNAME environment variable for the keytab
vi /etc/sysconfig/mongod
and add this line:
export KRB5_KTNAME=/var/lib/mongo/mongodb.keytab
Step 6: Edit the mongodb.conf file to enable GSSAPI
Comment out the bind_ip directive. For Kerberos SSO to
work, you must bind over the network.
Otherwise the appropriate will be localhost versus the
actual hostname of the system
#bind_ip=127.0.0.1
Re-enable authentication. Note that you can enable both SASL and GSSAPI
auth=true
setParameter=saslauthdPath=/var/run/saslauthd/mux
setParameter=authenticationMechanisms=PLAIN,MONGODB-CR,GSSAPI
Restart MongoDB and make sure there are no errors.
$ dzdo service mongod restart
Test GSSAPI/Kerberos authentication
Step 7: Log in to the system with the externally identified user that was created with the full UPN, inspect the Kerberos TGT.
$ /usr/share/centrifydc/kerberos/bin/klist
Ticket cache: FILE:/tmp/krb5cc_1149240919
Default principal: j.peterman@CORP.CONTOSO.COM
Valid starting Expires Service principal
10/25/14 15:23:35 10/26/14 01:23:35 krbtgt/CORP.CONTOSO.COM@CORP.CONTOSO.COM
renew until 11/01/14 15:23:35
10/25/14 15:25:13 10/26/14 01:23:35 mongodb/cen3.corp.contoso.com@CORP.CONTOSO.COM
renew until 11/01/14 15:23:35
Notice that during login, Centrify will automatically kinit and enable your TGT.
Step 7: Launch mongo with the system name and perform the testing.
mongo cen3.corp.contoso.com
MongoDB shell version: 2.6.5
> db.getSiblingDB("$external").auth({mechanism: "GSSAPI",user:'j.peterman@CORP.CONTOSO.COM',})
1
Output of 1 proves that authentication with Kerberos/GSSAPI was succesful.
> db.getSiblingDB("$external").auth({mechanism: "PLAIN",user:'j.peterman',pwd:'<jp's password>',digestPassword: false})
1
Both GSSAPI and SASL Plain can be used simultaneously. Kerberos is superior due to the fact that the user eliminates one prompt ad a readable password.
No comments:
Post a Comment