[[ldap]]
=== Using LDAP to Authenticate Users

You can configure Shield to communicate with a Lightweight Directory Access Protocol 
(LDAP) directory to authenticate users. To integrate with LDAP, you configure an LDAP realm and 
assign LDAP groups to Shield roles in the <<mapping-roles, role mapping file>>. 

To protect passwords, communications between Shield and the LDAP server should be encrypted 
using SSL/TLS. Clients and nodes that connect via SSL/TLS to the LDAP server need to have the
LDAP server's certificate or the server's root CA certificate installed in their keystore or 
truststore. For more information about installing certificates, see <<ssl-tls, Setting Up SSL>>.

==== Configuring an LDAP Realm

LDAP stores users and groups hierarchically, similar to the way folders are grouped in a file 
system. An LDAP directory's hierarchy is built from containers such as the
 _organizational unit_ (`ou`), _organization_ (`o`), and _domain controller_ (`dc`).

The path to a entry is a _Distinguished Name_ (DN) that uniquely identifies a user or group. 
User and group  names typically have attributes such as a _common name_ (`cn`) or _unique ID_ (`uid`). 
A DN is specified as a string, for example  `"cn=admin,dc=example,dc=com"`. White space is ignored. 

The LDAP realm supports two modes of operation, a user search mode 
and a mode with specific templates for user DNs. See <<ldap-settings, LDAP Realm Settings>>
for all of the options you can set for an LDAP realm.

[[ldap-user-search]]
===== Configuring an LDAP Realm with User Search added[1.1.0]
LDAP user search is the most common mode of operation. In this mode, a specific user with 
permission to search the LDAP directory is used to search for the user DN based on the username 
and an LDAP attribute. 

To configure an LDAP Realm with User Search:

. Add a realm configuration of type `ldap` to `elasticsearch.yml` in the 
`shield.authc.realms` namespace. At a minimum, you must set the realm 
`type` to `ldap`, specify the `url` of the LDAP server, and specify the container DN to search for 
users with the `user_search.base_dn` option. If you are configuring multiple realms, you 
should also explicitly set the `order` attribute to control the order in which the realms are 
consulted during authentication. See <<ldap-settings, LDAP Realm Settings>>
for all of the options you can set for an LDAP realm.
+
For example, the following snippet shows an LDAP realm configured with a user search:
+
[source, yaml]
------------------------------------------------------------
shield:
  authc:
    realms:
      ldap1:
        type: ldap
        order: 0
        url: "ldaps://ldap.example.com:636"
        bind_dn: "cn=ldapuser, ou=users, o=services, dc=example, dc=com"
        bind_password: changeme
        user_search:
          base_dn: "dc=example,dc=com"
          attribute: cn
        group_search:
          base_dn: "dc=example,dc=com"
        files:
          role_mapping: "/mnt/elasticsearch/group_to_role_mapping.yml"
        unmapped_groups_as_roles: false
------------------------------------------------------------

. Restart Elasticsearch 

===== Configuring an LDAP Realm with User DN Templates
If your LDAP environment uses a few specific standard naming conditions for users, you can use  
User DN templates to configure the realm. The advantage of this method is that a search does not 
have to be performed to find the user DN. However, multiple bind operations might be needed to find 
the correct user DN.  

To configure an LDAP Realm with User Search:

. Add a realm configuration of type `ldap` to `elasticsearch.yml` in the 
`shield.authc.realms` namespace. At a minimum, you must set the realm 
`type` to `ldap`, specify the `url` of the LDAP server, and specify at least one template with
the  `user_dn_templates` option. If you are configuring multiple realms, you 
should also explicitly set the `order` attribute to control the order in which the realms are 
consulted during authentication. See <<ldap-settings, LDAP Realm Settings>>
for all of the options you can set for an LDAP realm.
+
For example, the following snippet shows an LDAP realm configured with User DN templates:
+
[source, yaml]
------------------------------------------------------------
shield:
  authc:
    realms:
      ldap1:
        type: ldap
        order: 0
        url: "ldaps://ldap.example.com:636"
        user_dn_templates:
          - "cn={0}, ou=users, o=marketing, dc=example, dc=com"
          - "cn={0}, ou=users, o=engineering, dc=example, dc=com"
        group_search:
          base_dn: "dc=example,dc=com"
        files:
          role_mapping: "/mnt/elasticsearch/group_to_role_mapping.yml"
        unmapped_groups_as_roles: false
------------------------------------------------------------

[[ldap-settings]]
===== LDAP Realm Settings

.Common LDAP Realm Settings
|=======================
| Setting                        | Required | Description
| `type`                         | yes      | Indicates the realm type. Must be set to `ldap`.
| `order`                        | no       | Indicates the priority of this realm within the realm 
                                              chain. Realms with a lower order are consulted first. 
                                              Although not required, we recommend explicitly
                                              setting this value when you configure multiple realms. 
                                              Defaults to `Integer.MAX_VALUE`.
| `enabled`                      | no       | Indicates whether this realm is enabled or disabled. 
                                              Enables you to disable a realm without removing its 
                                              configuration. Defaults to `true`.
| `url`                          | yes      | Specifies an LDAP URL of the form of 
                                              `ldap[s]://<server>:<port>`. Shield attempts to 
                                              authenticate against this URL.
| `group_search.base_dn`         | no       | Specifies a container DN to search for groups in which 
                                              the user has membership. When this element is absent, 
                                              Shield searches for a `memberOf` attribute set on the 
                                              user to determine group membership.
| `group_search.scope`           | no       | Specifies whether the group search should be 
                                              `sub_tree`, `one_level` or `base`.  `one_level` only 
                                              searches objects directly contained within the 
                                              `base_dn`. The default `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.
| `group_search.filter`          | no       | Specifies a filter to use to lookup a group. If not 
                                              set, the realm searches for `group`, 
                                              `groupOfNames`, or `groupOfUniqueNames`, with the 
                                              attributes `member` or `memberOf`.  Any instance of 
                                              `{0}` in the filter is replaced by the user 
                                              attribute defined in `group_search.user_attribute`
| `group_search.user_attribute`  | no       | Specifies the user attribute that is fetched and 
                                              provided as a parameter to the filter.  If not set, 
                                              the user DN is passed to the filter.
| `unmapped_groups_as_roles`     | no       | Specifies whether the names of any unmapped LDAP groups 
                                              should be used as role names and assigned to the user. 
                                              Defaults to `false`.
| `connect_timeout`              | no       | Specifies the timeout period for establishing an 
                                              LDAP connection. An `s` at the end indicates seconds, 
                                              `ms` indicates milliseconds. Defaults to `5s` (5 seconds).
| `read_timeout`                 | no       | The timeout period for an LDAP operation.  An `s` at 
                                              the end indicates seconds, `ms` indicates 
                                              milliseconds. Defaults to `5s` (5 seconds).
| `files.role_mapping`           | no       | Specifies the path and file name for the 
                                              <<ldap-role-mapping, YAML role mapping configuration 
                                              file>>. Defaults to
                                              `ES_HOME/config/shield/role_mapping.yml`.
| `follow_referrals`             | no       | 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). Defaults to 
                                              `true`.
| `hostname_verification`        | no       | Specifies whether hostname verification is performed when 
                                              connecting to an LDAP server. When `true`, 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. Due to its potential security impact, 
                                              `hostname_verification` is not exposed via the
                                              {ref}/cluster-nodes-info.html#cluster-nodes-info[nodes 
                                              info API]. Defaults to `true`.
| `cache.ttl`                | no           | Specifies the time-to-live for cached user entries. A 
                                              user's credentials are cached for this period of time. 
                                              Specify the time period using the standard Elasticsearch 
                                              {ref}/common-options.html#time-units[time units]. 
                                              Defaults to `20m`.
| `cache.max_users`          | no           | Specifies the maximum number of user entries that can be 
                                              stored in the cache at one time. Defaults to 100,000.
| `cache.hash_algo`          | no           | Specifies the hashing algorithm that is used for the 
                                              cached user credentials. See <<cache-hash-algo, 
                                              Cache hash algorithms>> for the possible values.
                                              (Expert Setting) 
|=======================

.User Template LDAP Realm Settings
|=======================
| Setting                        | Required | Description
| `user_dn_templates`            | yes      | Specifies the DN template that replaces the user name 
                                              with the string `{0}`. This element is multivalued, 
                                              allowing for multiple user contexts.
|=======================

.User Search LDAP Realm Settings added[1.1.0]
|=======================
| Setting                                  | Required | Description
| `bind_dn`                                | no       | The DN of the user that is used to 
                                                        bind to the LDAP and perform searches. If 
                                                        not specified, an anonymous bind 
                                                        is attempted. Due to its potential security 
                                                        impact, `hostname_verification` is not 
                                                        exposed via the
                                                        {ref}/cluster-nodes-info.html#cluster-nodes-info[
                                                        nodes info API]. 
| `bind_password`                          | no       | The password for the user that is used 
                                                        to bind to the LDAP. Due to its potential 
                                                        security impact, `hostname_verification` is 
                                                        not exposed via the
                                                        {ref}/cluster-nodes-info.html#cluster-nodes-info[
                                                        nodes info API]. 
| `user_search.base_dn`                    | yes      | Specifies a container DN to search for users.
| `user_search.scope`                      | no       | The scope of the user search. Valid values 
                                                        are `sub_tree`, `one_level` or `base`. 
                                                        `one_level` only searches objects directly 
                                                        contained within the `base_dn`. 
                                                        `sub_tree` searches all objects contained 
                                                        under `base_dn`. `base` specifies that the 
                                                        `base_dn` is the user object, and that it is 
                                                        the only user considered. Defaults to 
                                                        `sub_tree`.
| `user_search.attribute`                  | no       | Specifies the attribute to match with the 
                                                        username presented to Shield. Defaults to 
                                                        `uid`.
| `user_search.pool.size`                  | no       | Specifies the maximum number of connections 
                                                        to the LDAP server to allow in the connection 
                                                        pool. Defaults to `20`.
| `user_search.pool.initial_size`          | no       | The initial number of connections to create 
                                                        to the LDAP server on startup. Defaults to `5`.
| `user_search.pool.health_check.enabled`  | no       | Enables or disables a health check on 
                                                        LDAP connections in the connection pool. 
                                                        Connections are checked in the background at 
                                                        the specified interval. Defaults to `true`.
| `user_search.pool.health_check.dn`       | no       | Specifies the distinguished name to retrieve  
                                                        as part of the health check. Defaults to the 
                                                        value of `bind_dn`. If `bind_dn` is not 
                                                        configured, you must specify a value.
| `user_search.pool.health_check.interval` | no       | How often to perform background checks 
                                                        of connections in the pool. Defaults to 
                                                        `60s`.
|=======================

NOTE:   If any settings starting with `user_search` are specified, the `user_dn_templates` 
        the settings are ignored.

[[assigning-roles-ldap]]
==== Assigning LDAP Groups to Roles

To configure privileges for LDAP users, you assign LDAP groups to roles in 
the role mapping file stored on each node. When a user authenticates with LDAP, 
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. 

You specify groups using their distinguished names. For example, the following mapping 
configuration assigns the LDAP `admins` group both the `monitoring` and `user` roles, and 
assigns the  `user` role to the `users` group. 

[source, yaml]
------------------------------------------------------------
monitoring: <1>
  - "cn=admins,dc=example,dc=com" <2>
user:
  - "cn=users,dc=example,dc=com" <3>
  - "cn=admins,dc=example,dc=com"
------------------------------------------------------------
<1> The name of a role defined in <<defining-roles, `roles.yml`>>.
<2> The distinguished name of the `admins` group.
<3> The distinguished name of the `users` group.

For more information, see <<mapping-roles, Mapping Users and Groups to Roles>>.

==== Encrypting Communications Between Shield and LDAP with SSL/TLS

You should encrypt communications between Shield and your LDAP server to protect the user 
credentials that are sent to for authentication. Connecting via SSL/TLS 
ensures that the identity of the LDAP server is authenticated before Shield 
transmits the user credentials, and the user names and passwords are encrypted in transit.

To encrypt communications between Shield and your LDAP server:

. Configure each node to trust certificates signed by the CA that signed your LDAP server
certificates. For example, the following command imports `cacert.pem` 
into node01's keystore.  (For information about using truststores, see <<create-truststore, 
Configuring a Separate Truststore>>.)
+
[source,shell]
--------------------------------------------------
cd CONFIG_DIR/shield
keytool -importcert -keystore node01.jks -file cacert.pem -alias ldap_ca
--------------------------------------------------
+
The CA cert must be a PEM encoded certificate. 
+
[NOTE]
===============================
You can also import the individual server certificates rather than the CA certificate, but
this is only recommended if you have a single LDAP server.
You can fetch the LDAP server certificate with `openssl`. 
For example, the following command gets the certificate for `ldap.example.com` and stores it locally 
in `ldap.crt`.

[source, shell]
----------------------------------------------------------------------------------------------
echo | openssl s_client -connect ldap.example.com:636 2>/dev/null | openssl x509 > ldap.crt
----------------------------------------------------------------------------------------------

If you are using an older version of openssl you might need to use use the `-host` and 
`-port` options rather than the `-connect` option.
===============================

. If you haven't already configured the path to the node's keystore or truststore  in 
`elasticsearch.yml`, set the `shield.ssl.keystore.path` or `shield.ssl.truststore.path` 
attributes. For example:
+
[source, yaml]
--------------------------------------------------
shield.ssl.keystore.path:          /home/es/config/shield/node01.jks <1>
shield.ssl.keystore.password:      myPass <2>
shield.ssl.keystore.key_password:  myKeyPass <3>
--------------------------------------------------
<1> The full path to the node keystore file. This must be a location within the Elasticsearch
configuration directory.
<2> The password used to access the keystore.
<3> The password used to access the certificate. This is only required if you specified a separate 
certificate password when generating the certificate.
+
For more information, see <<ssl-tls, Enabling SSL/TLS in the Node Configuration>>. 

. Set the `url` attribute in the realm configuration to specify the LDAPS protocol and 
the secure port number. For example, `url: ldaps://ldap.example.com:636`. 

. Restart Elasticsearch to pick up the changes to `elasticsearch.yml`.


NOTE: By default, when you configure Shield to connect to an LDAP server using SSL/TLS, 
      Shield attempts to verify the hostname or IP address specified with the `url` attribute in 
      the realm configuration with the values in the certificate. If the values in the certificate 
      and realm configuration do not match, Shield does not allow a connection to the LDAP server. 
      This is done to protect against man in the middle attacks. If necessary, 
      you can disable this behavior by setting the <<ref-ssl-tls-settings, `hostname_verification`>> 
      property to `false`. `hostname_verification` is considered to be a sensitive setting and 
      is not exposed via {ref}/cluster-nodes-info.html#cluster-nodes-info[nodes info API].