Active Directory Authentication

A secure Elasticsearch cluster can authenticate users from a Active Directory using the LDAP protocol. With the Active Directory Realm Authentication, you can assign roles to Active Directory groups. When a user authenticates with Active Directory, the privileges for that user are the union of all privileges defined by the roles assigned to the set of groups that the user belongs to.

Active Directory and LDAP

The Active Directory Realm uses LDAP to communicate with Active Directory. The Active Directory Realm is similar to the LDAP realm but takes advantage of extra features and streamlines configuration.

A general overview of LDAP will help with the configuration. LDAP databases, like Active Directory, store users and groups hierarchically, similar to the way folders are grouped in a file system. The path to any entry is a Distinguished Name, or DN. A DN uniquely identifies a user or group. User and group names typically use attributes such as common name (cn) or unique ID (uid). An LDAP directory’s hierarchy is built from containers such as the organizational unit (ou), organization (o), or domain controller (dc).

LDAP ignores white space in a DN definition. The following two DNs are equivalent:

"cn=admin,dc=example,dc=com"
"cn =admin ,dc= example , dc = com"

Although optional, connections to the Active Directory server should use the Secure Sockets Layer (SSL/TLS) protocol to protect passwords. Clients and nodes that connect via SSL/TLS to the LDAP server require the certificate or the root CA for the server. These certificates should be put into each node’s keystore/truststore.

Active Directory Realm Configuration

Like all realms, the active_directory realm is configured under the shield.authc.realms settings namespace in the elasticsearch.yml file. The following snippet shows an example of such configuration:

Example Active Directory Configuration. 

shield:
  authc:
    realms:
      active_directory:
        type: active_directory
        order: 0
        domain_name: example.com
        unmapped_groups_as_roles: true
      ...

Table 5. Active Directory Realm Settings

Setting

Required

Description

type

yes

Indicates the realm type and must be set to active_directory

order

no

Indicates the priority of this realm within the realm chain. Realms with lower order will be consulted first. Although not required, it is highly recommended to explicitly set this value when multiple realms are configured. Defaults to Integer.MAX_VALUE.

enabled

no

Indicates whether this realm is enabled/disabled. Provides an easy way to disable realms in the chain without removing their configuration. Defaults to true.

domain_name

yes

Specifies the domain name of the Active Directory. The cluster can derive the LDAP URL and user_search_dn fields from values in this element if those fields are not otherwise specified.

url

no

Specifies a LDAP URL in the form of ldap[s]://<server>:<port>. Shield attempts to authenticate against this URL. If not specified, the URL will be derived from the domain_name, assuming clear-text ldap and port 389 (e.g. ldap://<domain_name>:389).

user_search.base_dn

no

Specifies the context to search for the user. The default value for this element is the root of the Active Directory domain.

user_search.scope

no

Specifies whether the user search should be sub_tree (default), one_level or base. one_level only searches users directly contained within the base_dn. sub_tree searches all objects contained under base_dn. base specifies that the base_dn is a user object, and that it is the only user considered.

user_search.filter

no

Specifies a filter to use to lookup a user given a username. The default filter looks up user objects with either sAMAccountName or userPrincipalName

group_search.base_dn

no

Specifies the context to search for groups in which the user has membership. The default value for this element is the root of the Active Directory domain.

group_search.scope

no

Specifies whether the group search should be sub_tree (default), one_level or base. one_level searches for groups directly contained within the base_dn. sub_tree searches all objects contained under base_dn. base specifies that the base_dn is a group object, and that it is the only group considered.

unmapped_groups_as_roles

no

When set to true, the names of any unmapped LDAP groups are used as role names and assigned to the user. The default value is false.

files.role_mapping

no

Specifies the path and file name for the YAML role mapping configuration file. The default file name is role_mapping.yml in the Shield config directory.

hostname_verification

no

When set to true, hostname verification will be performed when connecting to a LDAP server. The hostname or IP address used in the url must match one of the names in the certificate or the connection will not be allowed. Defaults to true.

cache.ttl

no

Specified the time-to-live for cached user entries (a user and its credentials will be cached for this configured period of time). Defaults to 20m (use the standard elasticsearch time units)

cache.max_users

no

Specified the maximum number of user entries that can live in the cache at a given time. Defaults to 100,000.

cache.hash_algo

no

(Expert Setting) Specifies the hashing algorithm that will be used for the in-memory cached user credentials (see here for possible values).

Active Directory authentication expects the username entered to be the same name as the sAMAccountName or userPrincipalName and not the CommonName (CN). The URL is optional, but allows the use of custom ports.

Note

Binding to Active Directory fails when the domain name is not mapped in DNS. If DNS is not being provided by a Windows DNS server, add a mapping for the domain in the local /etc/hosts file.

Mapping Groups to Roles

By default, the mapping file that connects groups and roles is config/shield/role_mapping.yml. You can configure the path and name of the mapping file by setting the appropriate value for the shield.authc.active_directory.files.role_mapping configuration parameter. When you map roles to groups, the roles of a user in that group are the combination of the roles assigned to that group and the roles assigned to that user.

The role_mapping.yml file uses the YAML format. Within a mapping file, Elasticsearch roles are keys and Active Directory groups are values. Groups and roles can have a many-to-many mapping.

Example Group and Role Mapping File. 

# Example LDAP group mapping configuration:
# roleA   this is an elasticsearch role
#  - groupA-DN  this is any group distinguished name
#  - groupB-DN
monitoring:
  - "cn=admins,dc=example,dc=com"
user:
  - "cn=users,dc=example,dc=com"
  - "cn=admins,dc=example,dc=com"

After setting up group-to-role mappings, copy this file to each node node. Tools like Puppet or Chef can help with this.

Adding a Server Certificate

To use SSL/TLS to access your Active Directory server over an URL with the ldaps protocol, make sure the client used by Shield can access the certificate of the CA that signed the LDAP server’s certificate. This will enable Shield’s client to authenticate the Active Directory server before sending any passwords to it.

To do this, first obtain a certificate for the Active Directory servers or a CA certificate that has signed the certificate.

You can use the openssl command to fetch the certificate and add the certificate to the ldap.crt file, as in the following Unix example:

echo | openssl s_client -connect ldap.example.com:636 2>/dev/null | openssl x509 > ldap.crt

This certificate needs to be stored in the node keystore/truststore. Import the certificate into the truststore with the following command, providing the password for the keystore when prompted.

keytool -import -keystore node01.jks -file ldap.crt

If not already configured, add the path of the keystore/truststore to elasticsearch.yml as described in Securing Nodes. By default, Shield will attempt to verify the hostname or IP address used in the url with the values in the certificate. If the values in the certificate do not match, Shield will not allow a connection to the Active Directory server. This behavior can be disabled by setting the hostname_verification property.

Finally, restart Elasticsearch to pick up the changes to elasticsearch.yml.

User Cache

To avoid connecting to the Active Directory server for every incoming request, the users and their credentials are cached locally on each node. This is a common practice when authenticating against remote servers and as can be seen in the table above, the characteristics of this cache are configurable.

The cached user credentials are hashed in memory, and there are several hash algorithms to choose from:

Table 6. Cache hash algorithms

Algorithm

Description

bcrypt

Uses bcrypt algorithm with salt generated in 10 rounds.

bcrypt4

Uses bcrypt algorithm with salt generated in 4 rounds (default).

bcrypt5

Uses bcrypt algorithm with salt generated in 5 rounds.

bcrypt6

Uses bcrypt algorithm with salt generated in 6 rounds.

bcrypt7

Uses bcrypt algorithm with salt generated in 7 rounds.

bcrypt8

Uses bcrypt algorithm with salt generated in 8 rounds.

bcrypt9

Uses bcrypt algorithm with salt generated in 9 rounds.

sha1

Uses SHA1 algorithm.

sha2

Uses SHA2 algorithm.

md5

Uses MD5 algorithm.

noop,clear_text

Doesn’t hash the credentials and keeps it in clear text in memory. CAUTION: keeping clear text is considered insecure and can be compromised at the OS level (e.g. memory dumps and ptrace).

Cache Eviction API

Shield exposes an API to force cached user eviction. The following example, evicts all users from the ad1 realm:

$ curl -XPOST 'http://localhost:9200/_shield/realm/ad1/_cache/clear'

It is also possible to evict specific users:

$ curl -XPOST 'http://localhost:9200/_shield/realm/ad1/_cache/clear?usernames=rdeniro,alpacino'

Multiple realms can also be specified using comma-delimited list:

$ curl -XPOST 'http://localhost:9200/_shield/realm/ad1,ad2/_cache/clear'