[[active-directory]]
=== Configuring an Active Directory Realm

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:

[source,shell]
---------------------------------
"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
[source, yaml]
------------------------------------------------------------
shield:
  authc:
    realms:
      active_directory:
        type: active_directory
        order: 0
        domain_name: example.com
        unmapped_groups_as_roles: true
      ...
------------------------------------------------------------

[[ad-settings]]

.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 <<ref-shield-files-location,location>> for the <<ad-role-mapping, YAML role  mapping configuration file>>. By default it is `CONFIG_DIR/shield/users/role_mapping.yml`.
| `follow_referrals`         | no        | Boolean value that specifies whether Shield should follow referrals returned by the LDAP server. Referrals are URLs returned by the server that are to be used to continue the LDAP operation (e.g. search). Default is `true`.
| `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 {ref}/common-options.html#time-units[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 <<ad-cache-hash-algo,here>> for possible values).
|=======================

NOTE:   `hostname_verification` is considered to be a senstivie setting and therefore is not exposed via
        {ref}/cluster-nodes-info.html#cluster-nodes-info[nodes info API].


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.


==== 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:

[source, shell]
----------------------------------------------------------------------------------------------
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.

[source,shell]
----------------------------------------------------------------------------------------------------
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-communications, Securing Communications with Encryption and IP Filtering>>.
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 <<ad-settings, 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:

[[ad-cache-hash-algo]]

.Cache hash algorithms
|=======================
| Algorithm                       | Description
| `ssha256`                       | Uses a salted `sha-256` algorithm (default).
| `md5`                           | Uses `MD5` algorithm.
| `sha1`                          | Uses `SHA1` algorithm.
| `bcrypt`                        | Uses `bcrypt` algorithm with salt generated in 10 rounds.
| `bcrypt4`                       | Uses `bcrypt` algorithm with salt generated in 4 rounds.
| `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.
| `sha2`                          | Uses `SHA2` algorithm.
| `apr1`                          | Uses `apr1` algorithm (md5 crypt).
| `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:

[source, java]
------------------------------------------------------------
$ curl -XPOST 'http://localhost:9200/_shield/realm/ad1/_cache/clear'
------------------------------------------------------------

It is also possible to evict specific users:

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

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

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