Skip to main content

Ldap Security

Overview

In the context of security, LDAP servers serve as global storage for user credentials. They allow you to log in to all your services using a single set of credentials, eliminating the need to create separate internal users for each service.

Ilum can be easily integrated with an LDAP server. To do this, you simply need to provide the necessary Helm configuration to connect to your LDAP server, query users, verify their credentials, and define how user attributes should be mapped to Ilum's internal users.

For example, you can configure Ilum to map LDAP roles, groups, and relationships such as user-role, user-group, and group-role associations. Additionally, you can map attributes like email, description, and full name to Ilum users.

Once configured, you can log in to Ilum using an LDAP user, and all relevant data will be mapped from LDAP to Ilum according to your Helm configuration.

Quick start

Let's set up a test LDAP server, configure Ilum to use it, map users from it, and let's observe how Ilum handles the integration.

Create a test LDAP server

We will use OpenLDAP docker image to set up LDAP server on kubernetes.

First of all, let's prepare the ldif file, which is a list of entries (users, groups and roles) for our LDAP server, and put it into configmap.yaml file:

apiVersion: v1
kind: ConfigMap
metadata:
name: openldap-init
data:
custom.ldif: |
dn: dc=springframework,dc=org
objectclass: top
objectclass: domain
objectclass: extensibleObject
dc: springframework

dn: ou=subgroups,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: subgroups

dn: ou=people,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: people

dn: cn=dataengineer,ou=subgroups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfNames
cn: dataengineer
member: uid=ben
businessCategory: "sales data"

dn: cn=datascientist,ou=subgroups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfNames
cn: datascientist
member: uid=alice
member: uid=bob
member: uid=george
businessCategory: "overall data analysis"

dn: uid=ben,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Ben Alex
mail: [email protected]
description: dataengineer
uid: ben
userPassword: secret

dn: uid=alice,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Alice Smith
mail: [email protected]
description: datascientist in marketing
uid: alice
userPassword: password

dn: uid=bob,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Bob Martinez
mail: [email protected]
description: datascientist in sales
uid: bob
userPassword: key

dn: uid=george,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: George Ardenson
mail: [email protected]
description: datascientist in fraud detection
uid: george
userPassword: pass

The file includes:

  • LDAP base
  • 2 categories of objects: people and subgroups
  • 2 subgroup entries: dataengineer and datascientist
  • 4 users: 1 dataengineer and 3 datascientists

To create kubernetes config map run command:

kubectl apply -f configmap.yaml

After that create openldap deployment using this yaml file deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
name: openldap
spec:
replicas: 1
selector:
matchLabels:
app: openldap
template:
metadata:
labels:
app: openldap
spec:
containers:
- name: openldap
image: bitnami/openldap:latest
env:
- name: LDAP_ROOT
value: "dc=springframework,dc=org"
- name: BITNAMI_DEBUG
value: "true"
volumeMounts:
- name: openldap-init
mountPath: /ldifs/custom.ldif
subPath: custom.ldif
- name: data
mountPath: /bitnami/openldap
volumes:
- name: openldap-init
configMap:
name: openldap-init
- name: data
emptyDir: {}

And running command:

kubectl apply -f deployment.yaml

Finally add kubernetes service with service.yaml file:

apiVersion: v1
kind: Service
metadata:
name: openldap
spec:
ports:
- protocol: TCP
port: 1389
targetPort: 1389
selector:
app: openldap
type: ClusterIP

and command:

kubectl apply -f service.yaml

In the end you should have openldap up and running in your namespace.

Ilum Helm configuration

In order to configure Ilum Core to make use of LDAP server for authentication and authorization use values.yaml file:

ilum-core:
security:
type: ldap
ldap:
base: dc=springframework,dc=org
urls:
- ldap://openldap:1389
passwordEncoder: adaptive
adminUsers:
- "ben"
groupMapping:
base: ou=subgroups
filter: "(member={0})"
memberAttribute: "uid"
name: "cn"
description: "businessCategory"
userMapping:
base: "ou=people"
filter: "uid={0}"
password: userPassword
username: uid
email: mail
description: description
fullname: cn

and command:

helm upgrade ilum -f values.yaml --reuse-values

What exactly is happening in the configuration above?

  1. We set Ilum's security type to ldap.
  2. We connect Ilum Core to the LDAP server by providing the URL and base DN.
  3. In user mapping, we set base DN, filter, and password to query LDAP users during authentication and verify their credentials.
  4. In group mapping, we set base DN, filter, and memberAttribute to query LDAP groups based on the specified memberAttribute of an LDAP user.
  • For example, if we log in with uid=bob, Ilum will query groups using the filter (member={bob}), since memberAttribute is set to uid.
  1. We define how LDAP fields map to Ilum objects.
  • For example, if an LDAP group has businessCategory set to datascientist in sales, this value will be written into the corresponding Ilum group's description according to the configuration.
  1. Admin users: By default, all LDAP users have only read permissions. We must specify which LDAP users should have admin permissions. In this case, we designate Ben as an admin because he is a data engineer responsible for Ilum's setup.

Workflow

Let's log in to Ilum Core using ben:secret as credentials.

After logging in, we will notice a new user, Ben, created in the security section. This user will have all the values mapped from the LDAP server, including email, description, and fullname.

Ilum

Moreover bob will have a newly created group dataengineer, which was also mapped from LDAP server:

Ilum

By default, all roles will have only read permissions. However, since we have set Bob as an admin user in the Helm configuration, he will possess the ADMIN role from the start.

Now, let's log in with alice:password. Similarly, we will see the newly created user Alice.

Ilum

and newly created group datascientist:

Ilum

However, this time, Alice will only have read permissions because she is not an admin user, and the mapped group will be empty. Therefore, we need to manually assign permissions to the group.

For example, here we assign the default DATA_SCIENTIST role along with permissions for Ilum services and Ilum jobs management.

Ilum

Now, let's log in with bob:key. Similarly, a new user will be created. However, this time, since Bob is a member of the datascientist group in the LDAP server, he will have the same permissions as Alice because the datascientist group will be mapped to him.

Ilum

Moreover, if we want to assign specific permissions to a separate user, we can do so by editing their permissions directly.

Full Configuration

Here is the whole configuration:

ilum-core:
security:
type: ldap
ldap:
base: "<your_base_dn>"
urls:
- ldap://<domain>:<port>
username: "<your_admin_username>"
password: "<your_admin_password>"
passwordEncoder: <chosen_password_encoder>
adminUsers:
- <admin-user>
userMapping:
base: "<your_user_base>"
filter: "<your_filter>"
password: "<your_password>"
username: "<your_username>"
fullname: "<your_fullname>"
description: "<your_description>"
department: "<your_department>"
email: "<your_email>"
enabled: "<your_enabled>"
enabledValue: "<your_enabled_value>"
groupMapping:
base: "<your_group_base>"
filter: "<your_filter>"
memberAttribute: "<your_member_attribute>"
roleFilterAttribute: "<your_role_filter_attribute>"
name: "<your_name>"
description: "<your_description>"
roles: "<your_roles>"
enabled: "<your_enabled>"
enabledTrue: "<your_enabled_true>"
roleMapping:
base: "<your_role_base>"
filter: "<your_filter>"
memberAttribute: "<your_member_attribute>"
name: "<your_name>"
description: "<your_description>"
enabled: "<your_enabled>"
enabledTrue: "<your_enabled_true>"

1. enabled, enabledTrue

Used to map the state ENABLED/DISABLED from LDAP to Ilum. enabled should have name of the ldap attribute, which contains the state, enabledTrue (or enabledValue for users) should have the value which stands for ENABLED.

For example to map state of this user:

dn: uid=george,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: George Ardenson
mail: [email protected]
description: datascientist in fraud detection
uid: george
userPassword: pass
status: on

we should set

userMapping:
enabled: "status"
enabledValue: "on"

Similarly you can map state in roles and groups.

Note: by default true and enabled is perceived as ENABLED state

2. roles and roleFilterAttribute

Used to map group-to-roles relationship from LDAP to Ilum.

roles stands for group attribute which contains roles of the group. By default these are names of roles. Optionally you can set roleFilterAttribute to bound values from roles to value of attribute in LDAP role.

For exapmle to map this group and its subgroup to Ilum group and role:

dn: cn=datascientist,ou=subgroups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfNames
cn: datascientist
member: uid=george
businessCategory: "overall data analysis"
ident: "kq320"

dn: cn=users,ou=subgroups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfNames
cn: datascientist
member: uid=alice
member: uid=bob
member: uid=george
businessCategory: "overall data analysis"
roles: kq320
roles: br200
roles: ll100

You should set configuraiton like this:

groupMapping:
roles: subgroups
roleFilterAttribute: ident

Note: if roleFilterAttribute is not set, Ilum won't map LDAP role to Ilum, but instead it will bound an existing role with the same name or create a new one.

3. passwordEncoder

This can have the following values:

  • adaptive
  • bcrypt
  • md5
  • sha256

They represent the password encoder used to encode passwords on the LDAP server.

By default, Ilum uses the adaptive encoder, which reads the prefix (e.g., {bcrypt} or {noop}) and selects the appropriate encoder to verify credentials based on that prefix. If no prefix is present, Ilum will not use any encoder.

4. LDAP with TLS To configure Ilum to connect LDAP with TLS visit this page