LDAP


For this mode, Lenses relies on the LDAP server to handle the user authentication. The groups that a user belongs to (authorization) may come either from LDAP (automatic mapping), or via manually mapping an LDAP user to a set of Lenses groups.

Since the authentication is deferred, this means users are stored by LDAP and not Lenses. Once the authentication is successful, the next step involves querying LDAP for the user’s groups. All the user’s groups are then matched by name (case sensitive) with the groups stored in Lenses. All the matching groups' permissions are combined. If a user has been assigned manually a set of Lenses groups, then the groups coming from LDAP are ignored.

Active Directory (AD) and OpenLDAP (with the memberOf overlay if LDAP group mapping is required) servers are tested and supported in general. Due to the LDAP standard ambiguity, it is impossible to support all the configurations in the wild. The most usual pain point is LDAP group mapping. If the default class that extracts and maps LDAP groups to Lenses groups does not work, it is possible to implement your own.

Before setting up an LDAP connection, we advise to familiarize with LDAP and/or have access to your LDAP and/or Active Directory administrators.

An LDAP setup example with LDAP group mapping is shown below:

# LDAP connection details

lenses.security.ldap.url="ldaps://example.com:636"
## For the LDAP user please use the distinguished name (DN).
## The LDAP user must be able to list users and their groups.
lenses.security.ldap.user="cn=lenses,ou=Services,dc=example,dc=com"
lenses.security.ldap.password="[PASSWORD]"
## When set to true, it uses the lenses.security.ldap.user to read the user's groups
## lenses.security.ldap.use.service.user.search=false

# LDAP user search settings

lenses.security.ldap.base="ou=Users,dc=example,dc=com"
lenses.security.ldap.filter="(&(objectClass=person)(sAMAccountName=<user>))"

# LDAP group search and mapping settings

lenses.security.ldap.plugin.class="io.lenses.security.ldap.LdapMemberOfUserGroupPlugin"
lenses.security.ldap.plugin.group.extract.regex="(?i)CN=(\\w+),ou=Groups.*"
lenses.security.ldap.plugin.memberof.key="memberOf"
lenses.security.ldap.plugin.person.name.key = "sn"

In the example above you can distinguish three key sections for LDAP:

  • the connection settings,
  • the user search settings,
  • and the group search settings.

Lenses uses the connection settings to connect to your LDAP server. The provided account should be able to list users under the base path and their groups. The default group plugin only needs access to the memberOf attributes for each user, but your custom implementation may need different permissions.

When a user tries to login, a query is sent to the LDAP server for all accounts that are under the lenses.security.ldap.base and match the lenses.security.ldap.filter. The result needs to be unique; a distinguished name (DN) —the user that will login to Lenses.

In the example, the application would query the LDAP server for all entities under ou=Users,dc=example,dc=com that satisfy the LDAP filter (&(objectClass=person)(sAMAccountName=)) where would be replaced by the username that tries to login to Lenses. A more simple filter could be cn=, which for user Mark would return the DN cn=Mark,ou=Users,dc=example,dc=com.

Once the user has been verified, Lenses queries the user groups and maps them to Lenses groups. For every LDAP group that matches a Lenses group, the user is granted the selected permissions.

Depending on the LDAP setup, only one of the user or the Lenses service user may be able to retrieve the group memberships. This can be controlled by the option lenses.security.ldap.use.service.user.search.

The default value (false) uses the user itself to query for groups. Groups be can created in the admin section of the web interface, or in the command line via the lenses-cli application.

LDAP user group mapping 

If mapping LDAP groups to Lenses groups is not desired. Manually map LDAP users to Lenses groups, using the web interface, or the lenses-cli.

  • Create a user of type LDAP inside Lenses and assign them groups.

LDAP still provides the authentication, but all LDAP groups for this user are ignored.

When you create an LDAP user in Lenses, the username will be used in the search expression set in lenses.security.ldap.filter to authenticate them. If no user should be allowed to use the groups coming from LDAP, then this functionality should be disabled.

Additionaly you can set lenses.security.ldap.plugin.memberof.key or lenses.security.ldap.plugin.group.extract.regex to a bogus entry, rendering it unusable.

An example would be:

lenses.security.ldap.plugin.memberof.key = "notaKey"

Group extract plugin 

The group extract plugin is a class that implements an LDAP query that retrieves a user’s groups and makes any necessary transformation to match the LDAP group to a Lenses group name.

The default class implementation that comes with Lenses is io.lenses.security.ldap.LdapMemberOfUserGroupPlugin.

If your LDAP server supports the memberOf functionality, where each user has his/her group memberships added as attributes to his/her entity, you can use it by setting the lenses.security.ldap.plugin.class option to this class:

lenses.security.ldap.plugin.class=io.lenses.security.ldap.LdapMemberOfUserGroupPlugin

Below you will see a brief example of its setup.

# Set the full classpath that implements the group extraction
lenses.security.ldap.plugin.class="io.lenses.security.ldap.LdapMemberOfUserGroupPlugin"

# The plugin uses the 'memberOf' attribute. If this attribute has a different
# name in your LDAP set it here.
lenses.security.ldap.plugin.memberof.key="memberOf"

# This regular expression should return the group common name. If it matches
# a Lenses group name, the user is granted its permissions.
# As an example if there is a 'memberOf' attribute with value:
#   cn=LensesAdmins,ou=Groups,dn=example,dn=com
# The regular expression will return 'LensesAdmins'.
# Group names are case sensitive.
lenses.security.ldap.plugin.group.extract.regex="(?i)cn=(\\w+),ou=Groups.*"

# This is the LDAP attribute that holds the user's full name. It's optional.
lenses.security.ldap.plugin.person.name.key = "sn"

As an example, the memberOf search may return two attributes for user Mark:

attribute  value
---------  ------------------------------------------
memberOf   cn=LensesAdmin,ou=Groups,dc=example,dc=com
memberOf   cn=RandomGroup,ou=Groups,dc=example,dc=com

The regular expression (?i)cn=(\w+),ou=Groups.* will return these two regex group matches:

LensesAdmin
RandomGroup

If any of these groups exist in Lenses, Mark will be granted the permissions of the matching groups.

The lenses.security.ldap.plugin.group.extract.regex should contain exactly one regular expression capturing group.

If you need to apply more groups for your matching purposes, you should use non-capturing groups (e.g (?:groupRegex).

As an example, the regular expression (?i)cn=((?:Kafka|Apps)Admin),ou=Groups,dc=example,dc=com applied to memberOf attributes:

attribute  value
---------  ------------------------------------------
memberOf   cn=KafkaAdmin,ou=Groups,dc=example,dc=com
memberOf   cn=AppsAdmin,ou=Groups,dc=example,dc=com
memberOf   cn=BizAdmin,ou=Groups,dc=example,dc=com

will return these two regex group matches:

AppsAdmin
KafkaAdmin

Custom LDAP plugin 

If your LDAP does not offer the memberOf functionality, or uses a complex setup, you can provide your own implementation. Start with the code on GitHub, create a JAR, add it to the plugins/ folder and set your implementation’s full classpath:

# Set the full classpath that implements the group extraction
lenses.security.ldap.plugin.class="io.lenses.security.ldap.LdapMemberOfUserGroupPlugin"

Do not forget to grant to the account any permissions it may need for your plugin to work.

Manage permissions 

To learn how to use data centric permissions for users and service accounts see access management permsissions.

LDAP Configuration Options

See configuration settings.

Notes

The following configuration entries are specific to the default group plugin. A custom LDAP plugin might require different entries under lenses.security.ldap.plugin:

lenses.security.ldap.plugin.memberof.key
lenses.security.ldap.plugin.person.name.key
lenses.security.ldap.plugin.group.extract.regex
lenses.security.ldap.plugin.person.name.key