Security Configuration

Lenses allows you to easily secure access to the Lenses API and UI. You can password protect the UI and API as well as allow service accounts. More advanced features include LDAP and Kerberos authentication, role and group based access control, topic whitelisting/blacklisting. This section describes how to configure the security setup.

Lenses security options start with lenses.security.*** and should be stored in a separate file, named security.conf. You can set the path to the security configuration file in the main configuration file lenses.conf via the key lenses.secret.file. This way security.conf can be managed only by the administration team and have more tight access control than the rest of the configuration.

Lenses has support for the following login modes: BASIC, LDAP and KERBEROS. The security mode is configured through the lenses.security.mode option. The permission matrix contains additional details on roles and access levels.

BASIC

If BASIC mode is set, then user accounts and groups are stored in the configuration file itself. Users are assigned one or more groups and this determines which roles they are granted. Users and groups are set via the lenses.security.users and lenses.security.groups options respectively. For example:

# Security by default to is set to BASIC, alternatively LDAP.
lenses.security.mode=BASIC

# Define the user groups and their roles. At least one user group needs to be set
lenses.security.groups=[
     {"name": "adminGroup", "roles": ["admin", "write", "read"]},
     {"name": "writeGroup", "roles": ["read", "write"], topic: { blacklist: ["payment.*"] },
     {"name": "readGroup",  "roles": ["read"], topic: { whitelist: [ "users.*" ] },
     {"name": "nodataGroup",  "roles": ["nodata"]}
]

#Define the users and link each one to the group(-s) it belongs
lenses.security.users=[
  {"username": "admin", "password": "admin999", "displayname": "Lenses Admin", "groups": ["adminGroup"]},
  {"username": "write", "password": "write1", "displayname": "Write User", "groups": ["writeGroup"]},
  {"username": "read", "password": "read1", "displayname": "Read Only", "groups": ["readGroup"]},
  {"username": "nodata", "password": "nodata1", "displayname": "No Data", "groups": ["nodataGroup"]}
]

The admin role inherits automatically the read and write privileges. The write role inherits read privilege.

Security modes require lenses.security.groups to be specified. In addition to specifying the roles for each group, you can optionally specify which topics can be accessed through a whitelist/blacklist approach. In the example above, the writeGroup will get to access all topics apart from the ones starting with payment. The readGroup has been set using the whitelisting approach, and will only allow access to topics with names starting with users. The entries for the topic.whitelist and topic.blacklist are expected to be regular expressions.

The permission matrix contains additional details on roles and access levels.

Note

Lenses offers topic centric security; you can control which topics a user group can access. A simple white/black list configuration enables you to handle multi-tenancy over Kafka. Leaving out the setting means the group will be able to access all topics.

LDAP

It is common for enterprises to use an LDAP server for user management and Lenses can integrate with your LDAP environment for user authentication and group assignment.

If you want to use LDAP support then the lenses.security.mode option must be set to LDAP and the ldap configuration section must be completed to provide the settings.

Each individual LDAP setup will assign membership to groups using a different hierarchy, therefore there is a plugin to allow custom implementations for retrieving the user group list.

The project template for a custom implementation can be found on Github. With the implementation ready, all that is required is to drop the jar file into Lenses lib folder and set the configuration entry lenses.security.ldap.plugin to point to the implementation full classpath.

Lenses provides out-of-the-box a default implementation via com.landoop.lenses.security.ldap.LdapMemberOfUserGroupPlugin class. Here is the template for the LDAP configuration section:

lenses.security.mode=LDAP
lenses.security.ldap.url="ldaps://mycompany.com:636"
lenses.security.ldap.base="OU=Users,DC=mycompany,DC=com"
lenses.security.ldap.user="$LDAP_USER"
lenses.security.ldap.password="$LDAP_USER_PASSWORD"
lenses.security.ldap.filter="(&(objectClass=person)(sAMAccountName=<user>))"

//LDAP roles retriever settings
lenses.security.ldap.plugin.class="com.landoop.lenses.security.ldap.LdapMemberOfUserGroupPlugin"
lenses.security.ldap.plugin.group.extract.regex="(?i)CN=(\\w+),ou=ServiceGroups.*"
lenses.security.ldap.plugin.memberof.key="memberOf"
lenses.security.ldap.plugin.person.name.key = "sn"
Key Description Optional Type Default
url
The LDAP server url.
For example: ldap://mycompany.com:10389
No String N/A
base
Your LDAP base.
For example: dc=jboss,dc=org
No String N/A
user
Your LDAP user.
For example: uid=admin,ou=system
No String N/A
password Your LDAP user password. No String N/A
filter
The LDAP search filter - must result in
a unique result. See default value. <user>
is required since is replaced
at runtime with the current
user id.
Yes String (&(objectClass=person)(sAMAccountName=<user>))
plugin.class
Contains the full classpath for
the LDAP roles retriever implementation
Yes string N/A
plugin.memberof.key
Your LDAP member of key entry.
This is the key for which a
role is attached to the user entry.
For example,
memberOf: cn=AdminR,ou=Groups,dc=jboss,dc=org
- links the AdminR role to the
current user entry.
Yes String memberOf
plugin.person.name.key
Your LDAP person entry attribute
containing the user full name.
The default value if the configuration is
not provided is sn.
yes string sn
plugin.group.extract.regex
The regular expression syntax to extra
the role for each memberof entry.
The default value matches the
earlier example for memberof.
Yes String (?i)CN=(\\w+),ou=Groups.*

Note

The configuration entries lenses.security.ldap.plugin.memberof.key, lenses.security.ldap.plugin.person.name.key and lenses.security.ldap.plugin.group.extract.regex are specific to the implementation Lenses provides out of the box. Any custom implementation may require different entries under lenses.security.ldap.plugin

Here is a sample configuration LDAP enabled Lenses:

lenses.security.mode=LDAP
lenses.security.ldap.url="ldaps://landoop.ldap.url:636"
lenses.security.ldap.base="DC=landoop,DC=com"
lenses.security.ldap.password=*****
lenses.security.ldap.user="UID=smiths,OU=Services,DC=landoop,DC=com"
lenses.security.ldap.filter="(&((objectclass=person)(CN=<user>)))"

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

Kerberos

A popular solution for single sign on is Kerberos, which is often used in corporate environments. Clients obtain tickets from the Kerberos Key Distribution Centre (KDC) for a particular service and then that ticket is sent to the service when the client needs to authenticate against it.

If you want to enable Kerberos support then the lenses.security.mode option must be set to KERBEROS and the kerberos configuration section must be completed to provide the specific kerberos settings. The following table enumerates the kerberos config settings.

Key Description Optional Type Default
servicePrincipal The Lenses service principal. For example, HTTP/hostname No String N/A
keytab The path to the location of the service keytab No String N/A
debug Set to true to output Java’s JAAS debugging information Yes Boolean false

Here is a sample configuration for Kerberos enabled Lenses:

lenses.security.mode=KERBEROS
lenses.security.kerberos.service.principal="HTTP/lenses.host"
lenses.security.kerberos.keytab=/tmp/lenses.keytab
lenses.security.kerberos.debug=true

One of the limitations of Kerberos is that it is purely an authentication system for user principals without support for group membership. Therefore, in order to combine authentication with authorization it is necessary to map users to groups in a similar manner to the BASIC mode.

This is simply a mapping from username to group(s) specified in the security config, as in the following example:

#Define the users and link each one to the group(-s) it belongs
lenses.security.mappings = [
  { "username": "sam@LANDOOP.COM", "groups": ["adminGroup", "userGroup"] },
  { "username": "tom@LANDOOP.COM", "groups": ["userGroup"] }
]

Once Kerberos is enabled you should be implicitly logged in whenever you visit the lenses UI or directly to one of the REST API’s such as /api/auth. If you are using Kerberos on a windows system, then logging into your windows domain is usually sufficient to issue your Kerberos credentials. On a Linux environment, you will typically need to login manually using kinit at the command line before visiting any Kerberos enabled service.

Service Accounts

Service accounts allow easier integration with Lenses API. A typical use case is enabling your CI/CD tools to interact with Lenses. Via the lenses.security.service.accounts specific users and their authorization token can be defined. Here is how two service accounts can be created:

lenses.security.groups=[
      {"name": "group1", "roles": ["admin", "write", "read"]},
      {"name": "group2", "roles": ["read", "write"], topic: { blacklist: ["payment.*"] },
      {"name": "group3",  "roles": ["read"], topic: { whitelist: [ "users.*" ] },
]

lenses.security.service.accounts=[
  {
    "username": "jenkins",
    "token": "1231543kn!!1",
    "groups": ["group1", "group2"]
  },
  {
    "username": "goCli",
    "token": "12345678",
    "groups": ["group3"]
  }
]

Your CI system (like Jenkins) and the Lenses Go CLI tool can call into the API without having to first login. All that is required is for every HTTP request to contain the HTTP header: X-Kafka-Lenses-Token:$TOKEN.

Each service account is of course linked to a user group in order to restrict the actions it can execute.