10

Authenticate Percona Server for MongoDB Users via Native LDAP

 3 years ago
source link: https://www.percona.com/blog/2021/07/08/authenticate-percona-server-for-mongodb-users-via-native-ldap/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

supports two different ways of authenticating against an LDAP service:

  • operating system libraries (aka Native LDAP)
  • saslauthd (aka LDAP proxy)

We’ve talked about the LDAP proxy option many times already. In this post, I am going to discuss the Native LDAP approach.

Note: for the purposes of the examples, I am considering a RHEL-based distribution.

Prerequisites

First of all, the following packages are needed at the operating system level:

Shell
yum install cyrus-sasl-devel cyrus-sasl-md5 cyrus-sasl-plain cyrus-sasl-gssapi cyrus-sasl-lib

If any of these are missing, you most likely will encounter some cryptic errors. For example, something like the following could appear in your mongod.log:

Shell
2021-07-22T14:29:14.905-0500 E QUERY [js] Error: SASL(-4): no mechanism available: No worthy mechs found :

By default, MongoDB creates a TLS connection when binding to the LDAP server. The next step is to make the certificate for the company’s internal Certificate Authority (CA) available to our MongoDB server. We can do this by placing the certificate file in /etc/openldap/certs/ directory:

Shell
cp my_CA.crt /etc/openldap/certs/

Next, we need to point our server to the CA certificate we copied, by adding the following line to /etc/openldap/ldap.conf:

Shell
tee -a /etc/openldap/ldap.conf <<EOF
TLS_CACERT /etc/openldap/certs/my_CA.crt

MongoDB Configuration

Once the prerequisites are fulfilled, we need to adjust our mongod.conf to authenticate against LDAP. We need:

  • a read-only user that allows MongoDB to query LDAP
  • an LDAP queryTemplate to authorize users based on LDAP group membership

If you don’t know what this query string will be, you should work together with the LDAP server administrators to figure it out. The following example is for an Active Directory deployment:

Shell
ldap:
  servers: "ldap.example.com"
  authz:
    queryTemplate: "DC=example,DC=com??sub?(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={USER}))"
  userToDNMapping:
      match : "(.+)",
      ldapQuery: "DC=example,DC=com??sub?(userPrincipalName={0})"
  bind:
    queryUser: "ldapreadonly@example"
    queryPassword: "mypwd"
  setParameter:
    authenticationMechanisms: "PLAIN,SCRAM-SHA-1,SCRAM-SHA-256"

We can also use transformation expressions in order to avoid specifying the complete DN of the authenticating users. In the example above, the {0} is replaced with the first token of the user as specified. If you are logging in as [email protected] that would be the string “myuser”, so the query becomes:

Shell
ldapQuery: "DC=example,DC=com??sub?(userPrincipalName=myuser)"

This returns the following LDAP result:

Shell
"cn=myuser,dc=example,dc=com"

The queryTemplate specified in the config file is the standard AD-specific way to query a user’s groups recursively. The {USER} above is replaced with the transformed username and becomes:

Shell
queryTemplate: "DC=example,DC=com??sub?(&(objectClass=group)(member:1.2.840.113556.1.4.1941:="cn=myuser,dc=example,dc=com"))"

The authenticationMechanisms as specified allows MongoDB to authenticate both LDAP and built-in users. The PLAIN word might raise some eyebrows but remember the connection is still encrypted unless you specify the transportSecurity: none.

Creating Roles for LDAP Groups

We need to create roles in the MongoDB admin database for each of the LDAP groups we are going to be using.

For example, we can create groups for users that require read-only or read-write privileges respectively:

Shell
db.getSiblingDB("admin").createRole(
     role: "CN=myapp_rw,CN=Users,DC=example,DC=com",
     privileges: [],
     roles: [
       { role: "readWrite", db: "myapp" }
db.getSiblingDB("admin").createRole(
     role: "CN=myapp_ro,CN=Users,DC=example,DC=com",
     privileges: [],
     roles: [
       { role: "read", db: "myapp" }

In this case, any authenticating users that are members of the myapp_ro group in LDAP will automatically get read-only permissions against the myapp database.

Testing Access

To authenticate using LDAP, the following form can be used:

Shell
mongo --username [email protected] --password mypwd --authenticationMechanism=PLAIN --authenticationDatabase='$external' --host 127.0.0.1

Since we left the SCRAM-SHA options in the config file, we are still able to authenticate using MongoDB built-in users as well:

Shell
mongo --username root --password mypwd --authenticationDatabase admin --authenticationMechanism=SCRAM-SHA1 --host 127.0.0.1

Final Words

We’ve seen how to use the native method to configure LDAP integration. The main benefit of this method is that it requires fewer moving parts than the proxy-based approach.

Keep in mind that Percona Server for MongoDB offers LDAP authentication (and authorization) free of charge in all versions. These features are not available in the MongoDB Community Edition.

You might also want to check the official documentation on this topic, as there are some additional options to deal with things like LDAP-referrals, connection pool sizes, etc.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK