4.3
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=
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 check the help center .
LDAP Configuration Options
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