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?
- We set Ilum's security type to ldap.
- We connect Ilum Core to the LDAP server by providing the URL and base DN.
- In user mapping, we set base DN, filter, and password to query LDAP users during authentication and verify their credentials.
- 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.
- 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.
- 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.
Moreover bob will have a newly created group dataengineer
, which was also mapped from LDAP server:
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.
and newly created group datascientist:
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.
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.
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