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 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 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 Realm Settings for all of the options you can set for an LDAP realm.

Configuring an LDAP Realm with User Search [1.1.0] Added in 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:

  1. 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 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:

    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
  2. 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:

  1. 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 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:

    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 Realm Settings

Table 1. 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.

user_group_attribute

no

Specifies the attribute to examine on the user for group membership. The default is memberOf. This setting will be ignored if any group_search settings are specified.

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 the attribute specified by user_group_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.

timeout.tcp_connect

no

Specifies the TCP connect timeout period for establishing an LDAP connection. An s at the end indicates seconds, or ms indicates milliseconds. Defaults to 5s (5 seconds).

timeout.tcp_read

no

Specifies the TCP read timeout period after establishing an LDAP connection. An s at the end indicates seconds, or ms indicates milliseconds. Defaults to 5s (5 seconds).

timeout.ldap_search

no

Specifies the LDAP Server enforced timeout period for an LDAP search. An s at the end indicates seconds, or ms indicates milliseconds. Defaults to 5s (5 seconds).

files.role_mapping

no

Specifies the path and file name for the 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 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 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 algorithms for the possible values. (Expert Setting)


Table 2. 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.


Table 3. User Search LDAP Realm Settings [1.1.0] Added in 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 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 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 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.

monitoring: 
  - "cn=admins,dc=example,dc=com" 
user:
  - "cn=users,dc=example,dc=com" 
  - "cn=admins,dc=example,dc=com"

The name of a role defined in roles.yml.

The distinguished name of the admins group.

The distinguished name of the users group.

For more information, see 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:

  1. 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 Configuring a Separate Truststore.)

    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.

    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.

  2. 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:

    shield.ssl.keystore.path:          /home/es/config/shield/node01.jks 
    shield.ssl.keystore.password:      myPass 
    shield.ssl.keystore.key_password:  myKeyPass 

    The full path to the node keystore file. This must be a location within the Elasticsearch configuration directory.

    The password used to access the keystore.

    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 Enabling SSL/TLS in the Node Configuration.

  3. 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.
  4. 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 hostname_verification property to false. hostname_verification is considered to be a sensitive setting and is not exposed via nodes info API.