Configuring users with LDAP

The Deephaven authentication server allows the use of Lightweight Directory Access Protocol (LDAP) to validate usernames and passwords. The LDAP authentication provider can be a Microsoft Active Directory installation or an OpenLDAP installation.

To log on with LDAP authentication, either the system must be set up to use a single default domain (see authentication.server.ldap.domain below), or the user name must be entered in the form of user@AD.domain.name. WIndows NT style logins (domain\user) cannot be used.

To configure Deephaven to authenticate users with LDAP, set the following properties in the configuration for the authentication server. In a typical installation, authentication server properties are set in the iris-environment.prop file, which must be exported from etcd using dhconfig, and reimported after editing.

Once the properties are defined in the service.name=authentication_server stanza of the iris-environment.prop file, set iris.enableManagedUserAuthentication to false, save the file, reimport, and restart the authentication server and the Client Update Service for changes to take effect.

LDAP properties

LDAP properties can be defined in the service.name=authentication_server stanza of iris-environment.prop.

PropertiesDescription
authentication.server.ldap.enabledSet to true to configure the authentication server to validate usernames and passwords against an LDAP server. (The default is false.)
authentication.server.ldap.hostsA comma-separated list of LDAP server hostnames.
authentication.server.ldap.portThe port number the LDAP service is listening to. This must be the same for all LDAP hosts.
authentication.server.ldap.servicesA comma-separated list of DNS SRV records to identify the hosts to use. The priority of the SRV records is respected. Within a given priority level, weights are ignored and hosts are selected randomly. If multiple SRV records are listed, all hosts from the first SRV record take priority over the hosts from the second SRV record. Because SRV records include a port number, the authentication.server.ldap.port is not used when this property is set. Note: If both authentication.server.ldap.services and authentication.server.ldap.hosts are specified, the services will be used and the hosts will be ignored.
authentication.server.ldap.tlsflags(Optional) A flag that determines how the authentication server will attempt to establish a secure connection to the LDAP server. There are three possible values:
  • LDAPS — Connect using a URL beginning with ldaps://
  • STARTTLS — Connect to the server, then use the STARTTLS extension before proceeding. (This is the default.)
  • TRYSTARTTLS — Use the STARTTLS extension after connecting, but continue with an insecure connection if STARTTLS fails. This mode should never be used in production.
authentication.server.ldap.rouserA username with read access to the LDAP directory.
authentication.server.ldap.ropassThe base64-encoded password for the rouser. This property is deprecated for security reasons. It is strongly recommended that all new installations use the authentication.server.ldap.ropassFile property instead.
authentication.server.ldap.ropassFileThe path to the file containing the base64-encoded password for the rouser. It is recommended to use an absolute path (e.g., /db/TempFiles/irisadmin/authentication_server/ldap_ropass), but it is also possible to use a path relative to the authentication server's working directory (e.g., just ldap_ropass). Note: To encode a password with base64 and store it in a file called "iris_ropass", you can run the following command: echo -n '[password]' &#124 base64 > /db/TempFiles/irisadmin/authentication_server/ldap_ropass
authentication.server.ldap.searchDomainThe LDAP domain to search for users.
authentication.server.ldap.validDomainsA list of valid user domain names. This option is used when there are multiple domain names serviced by the LDAP server. For example, if the LDAP server contains the users "John@company1.net", "Mike@groupA.company1.net", and "Harry@company2.com", then all three domains — "company1.net", "groupA.company1.net", and "company2.com" — would be listed under the property. If "company1.net" and "groupA.company1.net" are listed but "company2.com" is not, users "John" and "Mike" will be able to log in, and "Harry" will not.
authentication.server.ldap.requireDomainDetermines whether users are required to include their domain name as part of their username when logging in. This is required when multiple validDomains are configured. (The default value is true if and only if multiple validDomains are configured.) If false, a value of authentication.server.ldap.domain is required.
authentication.server.ldap.domainDomain name to use in conjunction with user names that do not include a domain. This value is only used when authentication.server.ldap.requireDomain is false.
authentication.server.ldap.searchAttributeDetermines the attribute that is searched for. For example, this can be set to sAMAccountName rather than the default userPrincipalName when searching for user objects.
authentication.server.ldap.followReferralsA boolean controlling whether authentication will follow LDAP referrals, which may be useful to set as true such as when sAMAccountName is set as the searchAttribute. Defaults to false.
authentication.server.ldap.objectClassDetermines the object to search for. Defaults to user, which is appropriate for the login integration.
authentication.server.ldap.dnFormatPrefix and authentication.server.ldap.dnFormatSufffixIf used, these two properties must both be set. They are used to match distinguished name formats that are different from the default ActiveDirectory formats for users. These are required when configuring LDAP integration with an OpenLDAP provider.

Adding custom trust stores

Typically, when a client wants to add custom CA trust chains, they are added to Java's default trust store. This can be inconvenient because certificates added to the global trust store will affect all Java applications, which may not be desired. To avoid this situation, Deephaven's LDAP integration can be configured to use other trust stores in addition to the global java trust store.

Clients should first create a new trust store using the keytool utility and add any necessary trusted certificates to it. The following command will create a new trust store in the current directory named "ExampleStore" and add the certificate "MyCompanyCA" to it, aliased to the name "myCA":

keytool -import -file <path to Cert>/MyCompanyCA.cert -alias myCA -keystore ExampleStore

Repeat the same command for any other certificates required in order to add them all to the "ExampleStore" keystore.

The following properties are used to configure each additional trust store.

PropertiesDescription
authentication.server.ldap.truststore.<StoreName>.pathThe absolute path to the trust store file.
authentication.server.ldap.truststore.<StoreName>.passwordThe password Deephaven should use to open the trust store. Note: the password must be base64-encoded.
authentication.server.ldap.truststore.<StoreName>.passwordFileIf the password is not provided through the password property, it must be stored in a password file that is specified with this property. It must be base64-encoded within this file.
authentication.server.ldap.truststore.<StoreName>.type(optional) The trust store file's type. There are two possible values:
  • jks (default) — The standard Java Keystore file type for Java version 8 and below.
  • pkcs12 — Public-Key Cryptography Standard, another common storage format for keys and certificates.

Testing LDAP access

The ldapsearch command can be used to verify that the configured properties can be used to successfully bind to the LDAP directory. It is part of the openldap package and can be added to a Deephaven server using a package manager such as yum or apt. The following is a template for using ldapsearch.

ldapsearch -ZZ -h [hostname] -b "dc=mycompany,dc=net" -D "[rouser]" -s sub -W  "(& (userPrincipalName=[user-name-to-test]) (objectClass=user))"
  • The -W option will cause ldapsearch to prompt for a password.
  • The -ZZ option is to require use of STARTTLS and a successful upgrade to TLS on the session.

To test a configuration with LDAPS, a full LDAPS URI can be specified by using the -H flag instead of -h:

ldapsearch -H ldaps://[hostname]:[port] -b "dc=mycompany,dc=net" -D "[rouser]" -s sub -W  "(& (userPrincipalName=[user-name-to-test]) (objectClass=user))"

When testing with the -ZZ option, ldapsearch will fail if TLS cannot be established, while the -Z option instead will report the TLS error but still continue to try to authenticate the user. These two options are comparable to the STARTTLS and TRYSTARTTLS options for Deephaven tlsflags.

Running ldapsearch without any of -H, -Z, or -ZZ will attempt connect without TLS and also without requiring SSL. While ldapsearch and TRYSTARTTLS can connect without requiring SSL, Deephaven should always be used with SSL connections for LDAP in production environments. One way to verify whether an SSL session can be established is by using openssl.

For example, the following will attempt to connect to the LDAP server and validate its connection. The Verify return code at the end of its output should indicate 0 (okay). If it reports a problem verifying the certificate chain, it will probably be necessary to import the server's certificate (see Adding custom trust stores above).

openssl s_client -connect [hostname]:636

Verification of the SSL connection with a certificate to be imported can be done by specifying the certificate as an argument to the openssl utility:

openssl s_client -connect [hostname]:636 -CAfile [full path to certificate]

Example configurations and test commands

Below are several example LDAP configurations and corresponding ldapsearch commands that can be used to test them. These examples assume the password for the read-only user is example-pass, which is represented by the base64 string ZXhhbXBsZS1wYXNz.

One Domain, STARTTLS with Active Directory provider

This example configuration uses one domain and will connect securely using STARTTLS.

authentication.server.ldap.enabled=true
authentication.server.ldap.hosts=ldap1.mycompany.net
authentication.server.ldap.domain=mycompany.net
authentication.server.ldap.rouser=readuser
authentication.server.ldap.ropass=ZXhhbXBsZS1wYXNz

The following command could be used to test this configuration:

ldapsearch -ZZ -h  ldap1.mycompany.net -b "dc=mycompany,dc=net" -D "readuser@mycompany.net" -s sub -W  "(& (userPrincipalName=[user-name-to-test]) (objectClass=user))"

One Domain, STARTTLS with OpenLDAP provider

This example configuration uses one domain and will connect securely using STARTTLS.

authentication.server.ldap.enabled=true
authentication.server.ldap.hosts=ldap1.mycompany.net
authentication.server.ldap.domain=mycompany.net
authentication.server.ldap.port=389
authentication.server.ldap.tlsflags=STARTTLS
authentication.server.ldap.rouser=uid=readuser,ou=People,dc=mycompany,dc=net
authentication.server.ldap.ropass=ZXhhbXBsZS1wYXNz
authentication.server.ldap.searchAttribute=cn
authentication.server.ldap.objectClass=account
authentication.server.ldap.dnFormatPrefix=uid=
authentication.server.ldap.dnFormatSuffix=,ou=People,

Note the dnFormatPrefix matches the portion of the DN before the user name and the dnFormatSuffix matches the portion after the user name; and that the rouser user name is presented as a full DN.

The following command could be used to test this configuration (where testuser1 is the user account being checked):

LDAPTLS_REQCERT=never ldapsearch -ZZ -h ldap1.mycompany.net -b "dc=mycompany,dc=net" -D "uid=testUser1,ou=People,dc=mycompany,dc=net" -s sub -W  "(& (cn=testUser1) (objectClass=account))"

One Domain, STARTTLS, full LDAP DN used as the rouser

This example configuration is similar to the previous one, but uses a complete LDAP DN as the read-only user, instead of a simple user name:

authentication.server.ldap.enabled=true
authentication.server.ldap.hosts=ldap1.mycompany.net
authentication.server.ldap.rouser=CN=readuser,OU=Users,DC=mycompany,DC=net
authentication.server.ldap.ropass=ZXhhbXBsZS1wYXNz

The following command could be used to test this configuration:

ldapsearch -ZZ -h ldap1.mycompany.net -b "dc=mycompany,dc=net" -D "CN=readuser,OU=Users,DC=mycompany,DC=net" -s sub -W  "(& (userPrincipalName=example@mycompany.net) (objectClass=user))"

One Domain, STARTTLS, with LDAP Servers Defined by SRV Records

This example configuration uses one domain, STARTTLS to connect securely, and retrieves the appropriate LDAP server names using a DNS service record.

authentication.server.ldap.enabled=true
authentication.server.ldap.services=_ldap._tcp.mycompany.net
authentication.server.ldap.domain=mycompany.net
authentication.server.ldap.rouser=readuser
authentication.server.ldap.ropass=ZXhhbXBsZS1wYXNz

On most systems, the dig command can be used to verify the SRV record:

dig -t SRV _ldap._tcp.mycompany.net

The of dig output will specify the hostnames that provide the LDAP service:

;; ANSWER SECTION:
_ldap._tcp.mycompany.net. 60 INSRV0 100 636 ldap1.mycompany.net.
_ldap._tcp.mycompany.net. 60 INSRV0 100 636 ldap2.mycompany.net.

The hostnames returned can be tested using the same ldapsearch command as the previous example.

One Domain, LDAPS

This example configuration uses one domain and will connect securely using LDAPS.

authentication.server.ldap.enabled=true
authentication.server.ldap.hosts=ldap1.mycompany.net
authentication.server.ldap.port=636
authentication.server.ldap.tlsflags=LDAPS
authentication.server.ldap.rouser=readuser
authentication.server.ldap.ropass=ZXhhbXBsZS1wYXNz

The following command could be used to test this configuration:

ldapsearch -H ldaps://ldap1.mycompany.net:636 -b "dc=mycompany,dc=net" -D "readuser@mycompany.net" -s sub -W  "(& (userPrincipalName=[user-name-to-test]) (objectClass=user))"

Multiple Domains, LDAPS

This example configuration supports authenticating users in multiple domains and will connect securely using LDAPS.

authentication.server.ldap.enabled=true
authentication.server.ldap.hosts=ldap1.mycompany.net,ldap2.mycompany.net
authentication.server.ldap.port=636
authentication.server.ldap.tlsflags=LDAPS
authentication.server.ldap.searchDomain=mycompany.net
authentication.server.ldap.validDomains=mycompany.net,altcompany.com
authentication.server.ldap.rouser=readuser@mycompany.net
authentication.server.ldap.ropass=ZXhhbXBsZS1wYXNz

The following command could be used to test this configuration:

ldapsearch -H ldaps://ldap1.mycompany.net:636 -b "dc=mycompany,dc=net" -D "readuser@mycompany.net" -s sub -W  "(& (userPrincipalName=[user-name-to-test]@altcompany.net) (objectClass=user))"