LDAP Module
Introduction
This module synchronizes users from LDAP sources into ApiOmat LDAPUsers and LDAPGroups. LDAPUser is a subclass of User and can be used to authenticate within an application or via REST. For authorization purposes, these users may be members of LDAPGroups, a subclass of Role. The authentication is done directly against the LDAP directory.
Configuration
Server Hostname(s) |
Hostname(s) or IP(s) of the LDAP server(s), comma separated
|
Server Port(s) |
Port(s) of the LDAP server(s), comma separated, default value is 636 if LDAPS is enabled or 389 if not. |
Bind DN |
User for bind operation, leave empty for anonymous access |
Bind DN password |
User password for bind operation |
Base DN |
Root node of LDAP Directory |
User filter |
Filter to get all Users |
User ID |
LDAP attribute name which contains a user ID, this field will be used for the "userName" field in ApiOmat, default is sAMAccountName |
Module of User class (optional) |
If you want to use your own subclass of LDAPUser, insert your subclasse's module's name here so you can sync users to it. |
User class name (optional) |
If you want to use your own subclass of LDAPUser, insert your subclasse's name here so you can sync users to it. |
Activate sync LDAP groups |
If set to true (default), the synchronization will include LDAP groups |
Group filter |
Filter to get all groups |
Group name attribute |
The attribute that identifies a group's name. Default is "cn". |
Attributes holding member information |
Attributes holding distinguished names of group members, separated by comma |
Module of Role class (optional) |
If you want to use your own subclass of LDAPGroup, insert your subclass's module's name here so you can sync groups to it. |
The user's group attribute name |
The attribute of an LDAPUser that identifies group memberships of this user. Default is "distinguishedname". |
Role class name (optional) |
If you want to use your own subclass of LDAPGroup, insert your subclass's name here so you can sync groups to it. |
Write user attributes map |
If set to true (default), all attributes will be written to the "userAttributes" map of the LDAP user (in addition to the fields that match the attribute names) |
Disable auth for the sync |
If set to true (default), no auth checks will be done during user synchronization. This increases the synchronization speed. |
Log all messages async |
If set to true (default), all messages of the synchronization process will be logged asynchronously. |
Overwrite missing attributes |
If set to true (defaults to false), each field of the class will be set to null if the respective attribute does not exist (or is empty) in LDAP. |
Use LDAPS |
If set to true (defaults to false), all connections to your LDAP server(s) will be encrypted. |
Certificate for LDAPS |
The SSL public certificate of your LDAP server. Required when using LDAPS - upload the certificate file in this field. |
Module setup
Fill in the values fitting to your directory. An example would be:
Server Hostname |
|
Server Port |
389 |
Bind DN |
uid=admin,ou=system |
Bind DN password |
123456 |
Base DN |
OU=com,DC=mycompany,DC=local |
User filter |
(objectCategory=Person) |
User ID |
uid |
Group filter |
(objectClass=group) |
Group name attribute |
cn |
Attributes holding member information |
uniquemember,member |
Custom user class
You can define a custom user class which the LDAP users will get synced to. To do so, you have to create a class that inherits from the LDAPUser class in the LDAP module and then set your class's name and module name in the module configuration, in the fields User class name and Module of User class respectively.
You can add additional attributes that match the attribute names for your entities on the LDAP server. The values of these attributes will be automatically mapped on the synchronized objects. If you only need the attributes that exist on your class and don't want to have all attributes stored in the userAttributes attribute of the LDAPUser, you can set the Write user attributes map flag to false in your module configuration. This may speed up the synchronization process a bit and saves bandwidth when retrieving the users within a frontend.
Custom role class
You can define a custom class for LDAP groups in the same way as for LDAP users - create a class that inherits from LDAPGroup and set it's name and module name in the module configuration, in the fields Role class name and Module of Role class respectively.
The name attribute of the respective objects will be populated with the value of the attribute whose name can be configured with the property Group name attribute.
LDAPS
To use LDAP with encryption (LDAPS), first enable it on your server and generate an SSL certificate for said server.
Upload this certificate in the module configuration field "Certificate for LDAPS", and set the flag "Use LDAPS" to true. You will also have to set the port if you are not using the default of 636.
Now all connections to your server will be completely encrypted with TLS.
Synchronization
The synchronization process consists of four tasks.
-
Import all users that exist on the LDAP server as instances of LDAPUser (or whichever class you've set in your configuration). Users that already exist will be updated if there are changes on the LDAP user.
-
Check every existing ApiOmat user of the configured class to see if they still exist on the LDAP server. If they don't exist anymore, they will be deleted from ApiOmat.
-
If the module configuration property Activate sync LDAP groups is set to true, groups from the LDAP server are imported as instances of LDAPGroup (or whichever class you've set in your configuration) in the same manner as users. Also, names of users imported in the previous part are added to the members list of the respective LDAPGroup, using the module configuration property Attributes holding member information.
-
If the module configuration property Activate sync LDAP groups is set to true, check every existing ApiOmat group of the configured class to see if it still exists on the LDAP server. If it doesn't exist anymore, it will be deleted from ApiOmat.
If your LDAP server is not available when the process is executed, it will be aborted and the data on ApiOmat will remain unchanged. If there is an error during the creation, update or deletion of a single user (e.g. through an already existing user with the same user name in another class) the error will be logged and the synchronization will proceed with the next user.
If more than one LDAP server is configured, the module tries to connect to each server until it finds a working connection. The first working connection is then used for synchronization. The list of ports are related to the hostnames. If no ports are given, the default port will be used - 636 if LDAPS is enabled, 389 if not.
Otherwise, you have to write the ports in the corresponding order of the hostnames. For instance, if you have one ldap server on ldap1.yourcompany.com listening on port 489 and another server ldap2.yourcompany.com on port 589, you have to enter "ldap1.yourcompany.com,ldap2.yourcompany.com" in the Server hostname configuration field and "489,589" in the ports configuration field.
Use
All you have to do is configure the directory and wait until the next synchronization, which is done every hour. You can also manually start the synchronization via the MyModule page in dashboard or via REST:
curl -v $HOST/yambas/rest/modules/LDAP/v/$MODULEVERSION/$APPNAME/spec/sync/$APPNAME -u $USER:$PASSWORD
After a successful synchronization, you have to set the LDAPUser class (or whichever class you've set in your configuration) as the Authentication class in your backend configuration to authenticate to your LDAP server. We will then check the credentials against your LDAP server. Please note that it has to be done this way as we cannot synchronize the passwords of the users.
Your imported LDAPGroup's names may then be used in ApiOmat's access control lists of any class.
User Authentication via OAuth2 Tokens
The synchronized users are objects of the class LDAPUser, which inherits from the User class in the Basics module. So you can make use of the existing OAuth2 functionality and e.g. send a request to "YOURHOST/yambas/oauth/token" to get an access token for the user. For more info about how this works in ApiOmat, see here: ApiOmat and OAuth2.
In the case of LDAP, you might want to force the user to authenticate against the LDAP server as soon as the access token is expired, instead of allowing them to use the previously received refresh token. To do this, just change the value yambas.oAuth2TokenValiditySeconds.standard.refresh in your apiomat.yaml file to 0, or if you want refresh tokens to work except for LDAP, you can manually set the refresh token expiry in every request when fetching a token.
Healthcheck
The LDAP module provides a healthcheck, for more general info about how they work in ApiOmat, see Health checks. This healthcheck returns 0 (which means it's healthy), when the module is able to establish a functional connection to or more of the given hosts, otherwise 1.
Additionally, we have a custom healthcheck, which is reachable at:
curl $HOST/yambas/rest/modules/$MODULENAME/v/$MODULEVERSION/$APPNAME/spec/healtheck/ -u $USER:$PASSWORD
Note: in this case, the user has to be an ApiOmat customer.
This will return a JSON, which will look like this when it's healthy:
{
"<URL-OF-LDAP>:<PORT-OF-LDAP>"
:
{
"isReachable"
:
true
,
"isCredentialsValid"
:
true
,
"isUserLocked"
:
false
,
"isHealthy"
:
true
}
}