Faq - ldap

FAQ on LDAP

With Aerospike 4.1, the ability to use external authentication systems is supported. That release supports LDAP authentication. An updated client will send not only the hashed version of the password (in case the user is internal), but also the actual password, which will be sent to the external system. The external auth capabilities can be disabled on the client login call, which will not send the password but only the hashed password.

What is the LDAP Authentication Flow in Aerospike?

An Aerospike client API allows the specification of a username and password from the application.

  • If the client detects a server with external authentication enabled, it will first determine whether it has a stored access token. If it has no access token, it sends the username, the bcrypt() version of the password, and the password. The inclusion of both systems allows transparent hybrid access.

  • The server will then check the local database, and if the user exists and has a bcrypt() version of the password set, the bcrypt() version of the password is checked. If the password check succeeds, an access token is generated by the server. If the bcrypt() password does not match, the authentication fails. If there is no bcrypt() version of the password, then authentication passes to the external phase.

  • The configured LDAP server is contacted, and a BIND login request is initiated. If configured, the username may be remapped or translated. Both a standard password and an SASL authentication will be supported, using OpenLDAP libraries.

  • If the LDAP login succeeds, the server generates an access token and passes it to the client.

  • The cluster then makes a request to the LDAP server using the appropriate wildcard query to determine the list of groups available for this user. Once this is done, the result is stored locally and distributed to other members of the cluster.

  • The client then opens each successive TCP connection using the access token, which is validated by verifying the timestamp and the HMAC. This is done on every TCP connection.

  • If the client needs a new TCP connection and the access token is no longer valid, the server will reject the access token and the client will request a new access token from the server through the same interaction as specified above.

How do I do an in-place upgrade from a local authenticated enabled cluster to an external authenticated enabled cluster?

When upgrading from Aerospike local authentication to external authentication, each server is separately authenticated, but maintenance of groups is done by one elected server within the cluster.

An in-place upgrade can be supported as long as the following operational procedure is followed:

  • Update all clients to a version which supports external authentication (and thus the sensing of whether a server supports the old or new authentication mechanisms),
  • Update the server configuration to include LDAP external auth information and restart.

Note - If you have TLS enabled you must add your certs on the client machine and either an ldap.conf file must be created or environment variables must be set.

Note - A TCP connection attempt with an expired token will fail, and the client must log in again to get a fresh token.

Does turning on security for user access (local or LDAP) present any noticeable overhead in latency?

We would recommend benchmarking this based on your traffic pattern.

In general, we do not expect a noticeable performance degradation with simple access control (TLS or LDAP would likely have a more noticeable impact on performance). The client(s) would authenticate (would need credentials) for each new connection being created.

I enabled LDAP but it is not working as expected and I see the following warning getting printed in the server logs. I confirmed that LDAPSEARCH works as expected.

WARNING (security): (ldap_ee.c:548) couldn't start tls: ldaps://ldap.dev.aerospike err 1 (Operations error)

LDAP support of the current Aerospike server uses StartTLS rather than ldaps:// which is deprecated. Support for ldaps has nevertheless been included in Aerospike EE server versions 4.6 and above.

How to configure ldap in aerospike.conf?

Modify the aerospike.conf configuration file by adding a security stanza and enable ldap. Remember to include the query-user-dn (setting for an ldap privileged user with permission to query ldap) and query-user-password-file (clear text password file to that ldap privileged user)

See sample configuration below for a tls enabled ldap server over port 389:

security {
    enable-security true
    enable-ldap true
    ldap {
        query-base-dn dc=field,dc=aerospike,dc=com
        query-user-dn cn=admin,dc=field,dc=aerospike,dc=com
        query-user-password-file /etc/aerospike/passwordldap.txt
        server ldap://127.0.0.1:389
        disable-tls false
        tls-ca-file /etc/openldap/certs/myldap.field.aerospike.com.cert
        user-dn-pattern uid=${un},ou=People,dc=field,dc=aerospike,dc=com
        role-query-search-ou false
        role-query-pattern (&(objectClass=posixGroup)(memberUid=${un}))
        polling-period 10
    }
    log {
        report-violation true
    }
} 

In the above sample, the aerospike server will contact the ldap server over tls and authenticate using the user specified in query-user-dn.

More details on the aerospike ldap configuration can be found here:

https://www.aerospike.com/docs/operations/configure/security/ldap/

How to test the ldap configuration with aql?

All our aerospike clients will require an authentication mode be set when trying to connect using ldap credentials. In aql, that option is set through the –auth option. This would set the authentication mode when user/password is defined.

Modes are:

  • INTERNAL
  • EXTERNAL
  • EXTERNAL_INSECURE

The default is INTERNAL. This mode must be set to EXTERNAL or EXTERNAL_INSECURE when using LDAP. If TLS is not configured on the Aerospike server, then you can use EXTERNAL_INSECURE mode (not recommended, of course).

sample outputs:

EXTERNAL with no tls configured will give an error:

aql --auth EXTERNAL -Uaerospike -P aerospike
Seed:         127.0.0.1
User:         aerospike
Config File:  /etc/aerospike/astools.conf /root/.aerospike/astools.conf 
Error -1: TLS is required for external authentication

EXTERNAL_INSECURE mode should succeed in the above case:

aql --auth EXTERNAL_INSECURE -Uaerospike -P aerospike
Seed:         127.0.0.1
User:         aerospike
Config File:  /etc/aerospike/astools.conf /root/.aerospike/astools.conf 
Aerospike Query Client
Version 3.23.0
C Client Version 4.6.9
Copyright 2012-2019 Aerospike. All rights reserved.
aql> 

If TLS is enabled on the sever , the EXTERNAL authentication mode should succeed:

aql --auth EXTERNAL -Ubadwan -P aerospike --tls-enable --tls-cafile /root/certs/ca.crt -p 4333 -h 127.0.0.1:server:4333
Seed:         127.0.0.1:server:4333
User:         aerospike
Config File:  /etc/aerospike/astools.conf /root/.aerospike/astools.conf 
Aerospike Query Client
Version 3.23.0
C Client Version 4.6.9
Copyright 2012-2019 Aerospike. All rights reserved.

How can I troubleshoot LDAP authentication and binding errors while testing with aql?

If the configuration in aerospike.conf for the privileged user with permission to query ldap is incorrect, you will see errors like the ones below in the Aerospike logs:

WARNING (security): (ldap_ee.c:650) error binding to ldap for user CN=aerospike,OU=People: 49 (Invalid credentials)
WARNING (security): (ldap_ee.c:605) couldn't authenticate trusted aerospike user

Confirm the correct values for the parameters noted below with your LDAP admin and then test the authentication with ldapsearch. The necessary parameters from the Aerospike config file can be mapped to an ldapsearch query as follows:

  • query-base-dn: -b (ex: dc=field,dc=aerospike,dc=com)
  • query-user-dn: -D (ex: cn=admin,dc=field,dc=aerospike,dc=com)
  • query-user-password-file: -y (ex: /etc/aerospike/passwordldap.txt)
  • server: -H (ex: ldap://127.0.0.1:389)

Example ldapsearch query:

ldapsearch -y /etc/aerospike/passwordldap.txt -D "cn=admin,dc=field,dc=aerospike,dc=com" -b "dc=field,dc=aerospike,dc=com" -H ldap://127.0.0.1:389

Note that the values for query-user-dn and query-base-dn should be put inside quotes in the ldapsearch query (the -D and -b parameters, respectively) but not in aerospike.conf.

Also note that ldapsearch will allow spaces inside these values, but spaces must be escaped in aerospike.conf, for example:

query-user-dn uid=aerospike,ou=Trusted/20User,dc=field,dc=aerospike,dc=com

Once you have verified the correct values with ldapsearch and confirmed they are formatted correctly for the corresponding parameters in your Aerospike config file, retest with aql.

How to create an LDAP user (ie: aerospike)?

a) Write info to an .ldif file:

cat aerospike.ldif

dn: uid=aerospike,ou=People,dc=field,dc=aerospike,dc=com
objectClass: top
objectClass: account
objectClass: posixAccount
objectClass: shadowAccount
cn: aerospike
uid: aerospike 
uidNumber: 1001
gidNumber: 1001
homeDirectory: /home/aerospike
loginShell: /bin/bash
gecos: aerospike 
userPassword: aerospike
shadowLastChange: 0
shadowMax: 0
shadowWarning: 0

b) Use ldapadd command to create the user:

# ldapadd -x -w admin -D "cn=admin,dc=field,dc=aerospike,dc=com" -f /tmp/aerospike.ldif 
adding new entry "uid=aerospike,ou=People,dc=field,dc=aerospike,dc=com"

How to associate an Aerospike Role to a CN?

This is required to map an LDAP group to an Aerospike role (details available on the Access Control Guide page).

a) create a CN group file with for the aerospike role name:

This file would create a group on the ldap server with the name of an Aerospike role (in this example, read-write-udf). Same procedure could be used to create CN groups for any custom Aerospike roles.

cat read-write-udf.ldif

dn: cn=read-write-udf,dc=field,dc=aerospike,dc=com
objectClass: top
objectClass: posixGroup
gidNumber: 680

b) Use ldapadd command to create the group:

ldapadd -x -w admin -D "cn=admin,dc=field,dc=aerospike,dc=com" -f read-write-udf.ldif

c) create a file to map username(s) to the CN group:

cat modify.ldif

dn: cn=read-write-udf,dc=field,dc=aerospike,dc=com
changetype: modify
add: memberuid
memberuid: aerospike 

d) Modify the LDAP group and associate a username:

ldapmodify -x -w admin -D "cn=admin,dc=field,dc=aerospike,dc=com" -f modify.ldif 

How to list ldap users and groups using ldapsearch?

a) List all group and users:

ldapsearch -x -b dc=field,dc=aerospike,dc=com -D "cn=admin,dc=field,dc=aerospike,dc=com" -w admin

b) List a specific user identified by uid:

ldapsearch -x -b dc=field,dc=aerospike,dc=com -D "cn=admin,dc=field,dc=aerospike,dc=com" -w admin '(uid=aerospike)'

output:

# extended LDIF
#
# LDAPv3
# base <dc=field,dc=aerospike,dc=com> with scope subtree
# filter: (uid=aerospike)
# requesting: ALL
#

# aerospike, People, field.aerospike.com
dn: uid=aerospike,ou=People,dc=field,dc=aerospike,dc=com
objectClass: top
objectClass: account
objectClass: posixAccount
objectClass: shadowAccount
cn: aerospike
uid:: YmFkd2FuIA==
uidNumber: 1001
gidNumber: 1001
homeDirectory: /home/aerospike
loginShell: /bin/bash
gecos:: YmFkd2FuIA==
userPassword:: YWVyb3NwaWtl
shadowLastChange: 0
shadowMax: 0
shadowWarning: 0

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

c) List a specific role/group identify by memberUid:

ldapsearch -x -b dc=field,dc=aerospike,dc=com -D "cn=admin,dc=field,dc=aerospike,dc=com" -w admin '(memberUid=aerospike)'

output:

ldapsearch -x -b dc=field,dc=aerospike,dc=com -D "cn=admin,dc=field,dc=aerospike,dc=com" -w admin '(memberUid=aerospike)'
# extended LDIF
#
# LDAPv3
# base <dc=field,dc=aerospike,dc=com> with scope subtree
# filter: (memberUid=aerospike)
# requesting: ALL
#

# read-write-udf, field.aerospike.com
dn: cn=read-write-udf,dc=field,dc=aerospike,dc=com
objectClass: top
objectClass: posixGroup
gidNumber: 680
cn: read-write-udf
memberUid:: YmFkd2FuIA==

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

How to test LDAP with an LDAP server with tls enabled?

a) Using the -ZZ or -Z options to force StartTLS over port 389:

ldapsearch -ZZ -h 127.0.0.1 -p 389 -b dc=field,dc=aerospike,dc=com -D "cn=admin,dc=field,dc=aerospike,dc=com" -w admin

b) Enabling ldapsearch debug with -d -1 option:

ldapsearch -ZZ -h 127.0.0.1 -p 389 -b dc=field,dc=aerospike,dc=com -D "cn=admin,dc=field,dc=aerospike,dc=com" -w admin -d -1

Any LDAP server and LDAP client config client examples?

a) Sample LDAP daemon config:

cat /etc/sysconfig/slapd
# OpenLDAP server configuration
# see 'man slapd' for additional information

# Where the server will run (-h option)
# - ldapi:/// is required for on-the-fly configuration using client tools
#   (use SASL with EXTERNAL mechanism for authentication)
# - default: ldapi:/// ldap:///
# - example: ldapi:/// ldap://127.0.0.1/ ldap://10.0.0.1:1389/ ldaps:///
SLAPD_URLS="ldapi:/// ldap:/// ldaps:///"

# Any custom options
#SLAPD_OPTIONS=""

# Keytab location for GSSAPI Kerberos authentication
#KRB5_KTNAME="FILE:/etc/openldap/ldap.keytab"

TLSCACertificateFile="/etc/openldap/certs/myldap.field.aerospike.com.cert"
TLSCertificateFile="/etc/openldap/certs/myldap.field.aerospike.com.cert"
TLSCertificateKeyFile="/etc/openldap/certs/myldap.field.aerospike.com.key"

b) LDAP client config:

cat /etc/openldap/ldap.conf 
#
# LDAP Defaults
#

# See ldap.conf(5) for details
# This file should be world readable but not world writable.

#BASE	dc=example,dc=com
#URI	ldap://ldap.example.com ldap://ldap-master.example.com:666

#SIZELIMIT	12
#TIMELIMIT	15
#DEREF		never

#TLS_CACERTDIR	/etc/openldap/certs
TLS_CACERT /etc/openldap/certs/myldap.field.aerospike.com.cert 
TLS_REQCERT allow
# Turning this off breaks GSSAPI used with krb5 when rdns = false
SASL_NOCANON	on

What is the definition of an ldap DN?

DN is the LDAP Distinguished Name. It is a string that uniquely identifies an entry in the LDAP directory.

For example:

dn: uid=aerospike,ou=People,dc=field,dc=aerospike,dc=com

Info about DN definition can be found on this LDAP WIKI page.

It consists of a uid, an OU Organizational Unit and a DC Domain Components.

Note that in the Aerospike config file, any spaces in the DN must be escaped.

For example:

query-user-dn uid=aerospike,ou=Trusted/20User,dc=field,dc=aerospike,dc=com

Reference

Timestamp

July 2019

© 2015 Copyright Aerospike, Inc. | All rights reserved. Creators of the Aerospike Database.