# LDAP Configuration

{% hint style="info" %}
LDAP integration requires a Connectware Enterprise license.
{% endhint %}

LDAP (Lightweight Directory Access Protocol) is a standardized protocol for accessing and managing directory information services. It serves as a centralized authentication and authorization system, commonly used for:

* User authentication (Single Sign-On)
* Directory services
* Access control management

Cybus Connectware supports user authentication and authorization through LDAP based on your existing local directory service like Active Directory or OpenLDAP.

This guide explains how to set up a connection and configure your LDAP users to access Connectware.

## Prerequisites

* Connectware Enterprise license required. For more information, see [cybus.io](https://www.cybus.io/en/product/licenses/).
* Active Directory or OpenLDAP server
* LDAP configuration according to this guide

## Connectware LDAP Modes

Connectware supports the following LDAP authorization modes:

* **Group mode**: Sets permissions based on LDAP group membership
* **Attribute mode**: Sets permissions based on LDAP user attributes

### Group Mode

Connectware roles can be associated with LDAP groups. When an LDAP user successfully logs in for the first time, a Connectware user is created. Depending on the LDAP group memberships of the LDAP user, corresponding roles will be assigned to the Connectware user automatically. In this way, permissions can be easily handled by adding or removing LDAP users to or from the related LDAP groups.

**Example:** You can link the Connectware role `LDAP-Admin` to an LDAP group `cn=cw-admin,ou=connectware,dc=example,dc=org`. Users in this group automatically get the role when logging in.

### Attribute Mode

When the LDAP user successfully logs in for the first time, a Connectware user is created. A custom attribute in the LDAP user entry specifies which roles should be automatically assigned to the Connectware user. Authorization is controlled by adding or removing Connectware role names in the LDAP user's attributes.

**Example:** If the custom attribute `employeeType` contains the value `connectware-admin`, the admin role is assigned to the user.

## LDAP Authentication Methods

Connectware provides the following methods for LDAP authentication:

* Authentication with a dedicated bind user
* Authentication without a dedicated bind user (direct user authentication)

### Direct Authentication (No Dedicated Bind User)

You can authenticate without a dedicated bind user when your LDAP structure meets the following requirements:

* All user entries are located in the same branch of the LDAP Directory Information Tree (DIT)
* All users share the same base DN
  * Example: The base DN is `cn=users,dc=example,dc=org` and the DN of all users follow the pattern `<RDN_OF_USER>,cn=users,dc=example,dc=org`
* Groups are not nested
  * Example of unsupported nesting: A user is member of `group A`, `group A` is member of `group B`, and `group B` is the group that is linked with a Connectware role.

When no dedicated bind user is used, Connectware takes the given `bind DN`, adds the `user RDN`, and binds with the user credentials to the LDAP server. Binding with user credentials is the actual authentication step with an LDAP server.

### Authentication with Dedicated Bind User

A dedicated bind user is required when your LDAP structure requires searches or involves complex group relationships. Configure this by setting the `CYBUS_LDAP_BIND_PASSWORD` environment variable.

You need this authentication method when:

* User entries are distributed across different DIT locations
  * Example:
    * User 1: `cn=user1,cn=foo,dc=example,dc=org`
    * User 2: `cn=user2,cn=bar,dc=example,dc=org`
  * In this case, Connectware needs to search from a common base DN (`dc=example,dc=org`) to locate user entries
* Your setup uses nested groups
  * The search base must be the common DN shared by all groups and users

## Connectware LDAP Parameters

In order to enable the LDAP feature, the following [Environment Variables](https://docs.cybus.io/1-9-0/documentation/configuration/environment-variables) must be configured:

| Parameter                     | Description                                                                                                                              |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `CYBUS_LDAP_ENABLED`          | Enables LDAP integration when set to `true`. If `false`, LDAP is disabled and all other LDAP parameters are ignored.                     |
| `CYBUS_LDAP_BIND_DN`          | Specifies the bind DN for LDAP authentication.                                                                                           |
| `CYBUS_LDAP_BIND_PASSWORD`    | Required for dedicated bind user. If not set, `CYBUS_LDAP_BIND_DN` is used as base DN to generate a bind DN with user login credentials. |
| `CYBUS_LDAP_SEARCH_BASE`      | Starting point for LDAP searches. Only used with dedicated bind user. Example: `ou=tech,dc=cybus,dc=io`.                                 |
| `CYBUS_LDAP_SEARCH_FILTER`    | Optional custom filter for user search requests. Only valid with dedicated user.                                                         |
| `CYBUS_LDAP_URL`              | The URL of the LDAP/AD server.                                                                                                           |
| `CYBUS_LDAP_MODE`             | Specifies the LDAP mode: Either `group` or `attribute`.                                                                                  |
| `CYBUS_LDAP_ROLES_ATTRIBUTE`  | LDAP attribute containing user roles. Only valid with `CYBUS_LDAP_MODE=attribute`.                                                       |
| `CYBUS_LDAP_MEMBER_ATTRIBUTE` | LDAP attribute for group memberships. Only valid with `CYBUS_LDAP_MODE=group`. Usually set to `memberOf`.                                |
| `CYBUS_LDAP_USER_RDN`         | LDAP user property (e.g., `cn`) containing the username used for Connectware login.                                                      |
| `CYBUS_LDAPS_TRUST_ALL_CERTS` | When `true`, accepts all servers without certificate check for Secure LDAP. Default is `false`.                                          |
| `CYBUS_LDAPS_CA_FILE`         | Path to CA file for LDAP server validation. Used with Secure LDAP when `CYBUS_LDAPS_TRUST_ALL_CERTS` is `false`.                         |
| `CYBUS_LDAP_AUTO_ENFORCE_MFA` | When `true`, enforces MFA for LDAP users after their first login.                                                                        |

## Configuring LDAP Settings

These instructions are specific to Docker Compose deployments. For Kubernetes deployments, refer to the Kubernetes documentation on [Cybus Learn](https://www.cybus.io/learn/kubernetes/configuring-core-services/configuring-connectware-to-use-ldap-authentication/).

For a list of all environment variables for Docker Compose, see [Docker Compose](https://docs.cybus.io/1-9-0/documentation/environment-variables#docker-compose).

1. Navigate to your Connectware installation directory. If you have used the default values during installation, this is the installation folder: `/opt/connectware`.
2. The directory contains an `.env` file that is loaded when starting Connectware. Open the `.env` file in a text editor of your choice.
3. Locate the LDAP settings section in the `.env` file. By default, the settings looks like this:

{% code lineNumbers="true" %}

```yaml
CYBUS_LDAP_ENABLED=false
CYBUS_LDAP_URL=
CYBUS_LDAP_MODE=
CYBUS_LDAP_BIND_DN=
CYBUS_LDAP_BIND_PASSWORD=
CYBUS_LDAP_SEARCH_BASE=
CYBUS_LDAP_ROLES_ATTRIBUTE=
CYBUS_LDAP_MEMBER_ATTRIBUTE=
CYBUS_LDAP_USER_RDN=
```

{% endcode %}

4. Set the individual parameters according to your local directory service configuration.

{% stepper %}
{% step %}
**Configuration with Direct Authentication (No Dedicated Bind User)**

Example configuration for LDAP mode `attribute`:

{% code lineNumbers="true" %}

```yaml
CYBUS_LDAP_ENABLED=true
CYBUS_LDAP_MODE=attribute
CYBUS_LDAP_BIND_DN=ou=tech,dc=example,dc=org
CYBUS_LDAP_URL=ldap://<LDAPSERVERURL>
CYBUS_LDAP_USER_RDN=cn
CYBUS_LDAP_ROLES_ATTRIBUTE=employeeType
```

{% endcode %}

Example configuration for LDAP mode `group`:

{% code lineNumbers="true" %}

```yaml
CYBUS_LDAP_ENABLED=true
CYBUS_LDAP_MODE=group
CYBUS_LDAP_BIND_DN=ou=tech,dc=example,dc=org
CYBUS_LDAP_URL=ldap://<LDAPSERVERURL>
CYBUS_LDAP_USER_RDN=cn
CYBUS_LDAP_MEMBER_ATTRIBUTE=memberOf
```

{% endcode %}

This configuration would look for users applicable to the LDAP query `cn=username,ou=tech,dc=example,dc=org`.

{% hint style="warning" %}
Do not use quotation marks to encapsule the variable values.
{% endhint %}
{% endstep %}

{% step %}
**Configuration with Dedicated Bind User**

Example configuration for LDAP mode `attribute`:

{% code lineNumbers="true" %}

```yaml
CYBUS_LDAP_ENABLED=true
CYBUS_LDAP_MODE=attribute
CYBUS_LDAP_BIND_DN=cn=<binduser>,ou=tech,dc=example,dc=org
CYBUS_LDAP_BIND_PASSWORD=<password of binduser>
CYBUS_LDAP_SEARCH_BASE=dc=example,dc=org
CYBUS_LDAP_URL=ldap://<LDAPSERVERURL>
CYBUS_LDAP_USER_RDN=cn
CYBUS_LDAP_ROLES_ATTRIBUTE=employeeType
```

{% endcode %}

Example configuration for LDAP mode `group`:

{% code lineNumbers="true" %}

```yaml
CYBUS_LDAP_ENABLED=true
CYBUS_LDAP_MODE=group
CYBUS_LDAP_BIND_DN=cn=<binduser>,ou=tech,dc=example,dc=org
CYBUS_LDAP_BIND_PASSWORD=<password of binduser>
CYBUS_LDAP_SEARCH_BASE=dc=example,dc=org
CYBUS_LDAP_URL=ldap://<LDAPSERVERURL>
CYBUS_LDAP_USER_RDN=cn
CYBUS_LDAP_MEMBER_ATTRIBUTE=memberOf
```

{% endcode %}

Be aware to change the RDN prefix (`cn`) if needed for `CYBUS_LDAP_BIND_DN=cn=<binduser>,ou=tech,dc=example,dc=org`.
{% endstep %}
{% endstepper %}

5. After saving the new configuration it has to be loaded by running the Connectware instance by executing `docker compose up -d` from within the installation folder. If the Connectware instance is running as system service, restart by executing `systemctl restart connectware` instead.
6. The new configuration is now loaded. The next step is to supply your directory service users with Connectware roles (LDAP mode `attribute`) or link LDAP groups with Connectware roles (LDAP mode `group`).

## Example Setup for LDAP Mode Group

In order to assign permissions to Connectware users by grouping their LDAP user entries with LDAP groups, you need to perform the following steps:

1. [Define LDAP groups according to Connectware roles that you want to use.](#defining-ldap-groups-according-to-connectware-roles)
2. [Configure Connectware with LDAP parameters.](#configuring-connectware-with-ldap-parameters)
3. [Link LDAP groups with Connectware roles.](#linking-ldap-groups-with-connectware-roles)
4. [Assign LDAP users to these LDAP groups.](#assigning-ldap-users-to-ldap-groups)

{% stepper %}
{% step %}
**Defining LDAP Groups According to Connectware Roles**

In this example, additional groups are created and associated with Connectware roles. This is not a mandatory practice, but is intended to demonstrate the concept.

We assume that we have the following DIT:

{% code lineNumbers="true" %}

```yaml
dc=example,dc=org
├ cn=users
│  ├ cn=user1
│  ├ cn=user2
│  └ cn=user3
└ ou=connectware
```

{% endcode %}

1. Create the groups `cw-admin` and `cw-minimal` as follows:

{% code lineNumbers="true" %}

```yaml
dc=example,dc=org
├ cn=users
│  ├ cn=user1
│  ├ cn=user2
│  └ cn=user3
└ ou=connectware
├ cn=cw-minimal
└ cn=cw-admin
```

{% endcode %}

2. Now add `user1` to `cw-minimal`.
3. Run the following command to retrieve and display all attributes for `user1`. Make sure to change `PASSWORD` to the password of `user1`.

{% code lineNumbers="true" %}

```yaml
ldapsearch -LLL  -b "cn=user1,cn=users,DC=example,DC=org" -D "CN=user1,cn=users,DC=example,DC=org" -w PASSWORD
```

{% endcode %}

Result of the command:

{% code lineNumbers="true" %}

```yaml
dn: CN=user1,CN=users,DC=example,DC=org
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: user1
...
memberOf: CN=cw-minimal,OU=connectware,DC=example,DC=org
...
```

{% endcode %}

4. If you are using OpenLDAP and you do not see the attribute `memberOf`, run the following command:

{% code lineNumbers="true" %}

```yaml
ldapsearch -LLL  -b "cn=user1,cn=users,DC=example,DC=org" -D "CN=user1,cn=users,DC=example,DC=org" -w PASSWORD +
```

{% endcode %}

* If you can see the `memberOf` attribute, your LDAP is correctly configured for group operations. You can proceed with the next configuration steps.
* If the `memberOf` attribute is not visible, your OpenLDAP installation lacks the required `memberOf module`. In this case, your OpenLDAP instance needs additional configuration.
  {% endstep %}

{% step %}
**Configuring Connectware with LDAP Parameters**

* Edit the `.env` file as follows:

{% code lineNumbers="true" %}

```yaml
CYBUS_LDAP_ENABLED=true
CYBUS_LDAP_MODE=group
CYBUS_LDAP_BIND_DN=ou=users,dc=example,dc=org
CYBUS_LDAP_URL=ldap://127.0.0.1:389
CYBUS_LDAP_MEMBER_ATTRIBUTE=memberOf
CYBUS_LDAP_USER_RDN=cn
```

{% endcode %}

Be aware of adjusting the LDAP url, the given example uses an Active Directory service that runs on the local machine.
{% endstep %}

{% step %}
**Linking LDAP Groups with Connectware Roles**

1. Login into Connectware as administrator and select **User** > **User Management**. Select the **Roles** tab and click **Add Role**.
2. In the **Create Role dialog**, do the following:
   1. In the **Name** field, enter `LDAP-Admin`.
   2. To associate this role with the LDAP group `cw-minimal`, you have to copy the DN of that LDAP group to the field **DN of AD Group**. In this example, this will be `CN=cw-admin,OU=connectware,DC=example,DC=org`.
   3. In the **Copy Permissions** field, select **connectware-admin** and click **Add**.
   4. Click **Create** to add your new role.
3. Click **Add Role** again to add another role with the following configuration:
   1. In the **Name** field, enter `LDAP-Minimal`.
   2. In the **DN of AD Group** field, add the DN of the related LDAP group (`CN=cw-minimal,OU=connectware,DC=example,DC=org`).
   3. In the **Copy Permissions** field, select **minimum-access** and click **Add**.
   4. Click **Create** to add your new role.

<img src="https://2317229820-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLPAf7nVSLAm6jvBxu1bg%2Fuploads%2Fgit-blob-cf6968b9bef74cb75234af6035964fdada6d7c17%2Fldap_create_role_group.png?alt=media" alt="" data-size="original">
{% endstep %}

{% step %}
**Assigning LDAP Users to LDAP Groups**

1. Now you could assign different Connectware roles to your users `user1` `user2` `user3` by adding them to, or removing them from the groups `cw-minimal` or `cw-admin`.
2. When you add `user1` to the group `cw-admin` and login at Connectware, the `user1` will be created (if it is the first login) and the role `LDAP-Admin` will be assigned automatically.
3. Now logout from Connectware, remove `user1` from group `cw-admin` and add it to `cw-minimal`.
4. Login at Connectware with `user1` again. You’ll realize, that `user1` has limited access and you can’t navigate to the user section. Permissions of `user1` changed according to the LDAP group membership.

If you login as `user2` and `user2` is not assigned to any LDAP group yet, the `user2` will be created but you’ll see an error dialog saying that no permission was added and thus you will be forced to logout again.
{% endstep %}
{% endstepper %}

## Example Setup for LDAP Mode Attribute

1. [LDAP setup](#ldap-setup)
2. [Configure Connectware with LDAP parameters](#configuring-connectware-with-ldap-parameters-1)
3. [Assign roles to LDAP user entry](#assigning-roles-to-ldap-user-entry)

{% stepper %}
{% step %}
**LDAP Setup**

The following examples assume to have an LDAP DIT like the following:

{% code lineNumbers="true" %}

```yaml
dc=example,dc=org
└ cn=users
├ cn=user1
└ cn=user2
```

{% endcode %}

This structure is not mandatory but be aware to adjust the following examples according to your LDAP setup in the next steps.
{% endstep %}

{% step %}
**Configuring Connectware with LDAP Parameters**

* Edit your `.env` file as follows:

{% code lineNumbers="true" %}

```yaml
CYBUS_LDAP_ENABLED=true
CYBUS_LDAP_MODE=attribute
CYBUS_LDAP_BIND_DN=ou=users,dc=example,dc=org
CYBUS_LDAP_URL=ldap://127.0.0.1:389
CYBUS_LDAP_ROLES_ATTRIBUTE=employeeType
CYBUS_LDAP_USER_RDN=cn
```

{% endcode %}

Make sure to replace the `CYBUS_LDAP_URL` with your actual LDAP server address and port.
{% endstep %}

{% step %}
**Assigning Roles to LDAP User Entry**

1. To assign roles to LDAP users you have to add the Connectware role names as values to the users **CYBUS\_LDAP\_ROLES\_ATTRIBUTE** that you defined in the `.env` file. In our example, we will use the attribute name `employeeType`.
2. To add the Connectware role `connectware-admin` to the LDAP user `user1`, add the attribute `employeeType` (defined as roles attribute in the `.env` file) with the value `connectware-admin` to the LDAP user `user1`
3. Add the Connectware role `minimum-access` to the `user2` by adding the attribute `employeeType` with the value `minimum-access` to the LDAP user `user2`.
4. Check if the attributes have been set correctly by running the following command:

{% code lineNumbers="true" %}

```yaml
ldapsearch -LLL  -b "cn=user1,cn=users,DC=example,DC=org" -D "CN=user1,cn=users,DC=example,DC=org" -w PASSWORD
```

{% endcode %}

Result of the command:

{% code lineNumbers="true" %}

```yaml
dn: CN=user1,CN=users,DC=example,DC=org
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: user1
...
employeeType: connectware-admin
...
```

{% endcode %}

5. If you now log into Connectware as `user1`, the Connectware role `connectware-admin` will be assigned to the user `user1`.
6. To revoke access to Connectware for a certain user, the Connectware roles just have to be removed from the LDAP user again by deleting the corresponding attribute `employeeType`.

Connectware comes with predefined user roles like `connectware-admin` and `minimum-access` but additional roles can be created and assigned to users in the same way.
{% endstep %}
{% endstepper %}

## User Management for LDAP Users in Connectware

<figure><img src="https://2317229820-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLPAf7nVSLAm6jvBxu1bg%2Fuploads%2Fgit-blob-f90060b63a08cbef1c2fe9cb0dc2b65fe53f00ef%2Fldap_user_list.png?alt=media" alt=""><figcaption></figcaption></figure>

You can use LDAP to connect to your local user directory service to authenticate and authorize Connectware users during login to verify credentials and synchronize with assigned roles.

When using LDAP authentication, Connectware user management differs from regular local user accounts in several aspects. The following sections detail these differences and explain how LDAP users are handled within Connectware.

<figure><img src="https://2317229820-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLPAf7nVSLAm6jvBxu1bg%2Fuploads%2Fgit-blob-6a57caacd55a8bdeb8b8a140fbb0155260dc3b7f%2Fldap_user_details.png?alt=media" alt=""><figcaption></figcaption></figure>

### Roles

You can not add or remove roles from within Connectware. All roles have to be assigned in the user details of the directory user. Modified user roles are synched to the Connectware user on each successful login.

### GrantTypes

Every LDAP user is defaulting to token authentication. This property is not modifiable.

### LDAP User Password

You can not change the password from within Connectware as it uses the LDAP directory service for authentication.

### Deleting LDAP Users

You can still remove LDAP users from the Connectware user database. Note that this only deletes the Connectware internal user information. Deleting these local user information will not restrict the user from logging into Connectware again.

To fully revoke access, you must either remove their Connectware roles in LDAP or remove them from LDAP groups associated with Connectware roles, depending on your integration mode.

## LDAP Filters

The LDAP search filter values must follow RFC4515 standards, requiring hex notation encoding for special characters. All non-basic UTF-8 characters used as filter values need proper encoding according to the RFC4515 specifications. See the [RFC4515 documentation](https://datatracker.ietf.org/doc/rfc4515/) for detailed encoding requirements.

### RFC4515 Excerpt

{% code lineNumbers="true" %}

```yaml
EXCLAMATION    = %x21 ; exclamation mark ("!")
AMPERSAND      = %x26 ; ampersand (or AND symbol) ("&")
ASTERISK       = %x2A ; asterisk ("*")
COLON          = %x3A ; colon (":")
VERTBAR        = %x7C ; vertical bar (or pipe) ("|")
TILDE          = %x7E ; tilde ("~")
```

{% endcode %}

### Example

{% code lineNumbers="true" %}

```yaml
Clear text search filter: '(cn=*)'

Escaped search filter: '(cn=*\2a*)'
```

{% endcode %}

For a list of valid UTF-8 characters and their respective hex value, see [UTF-8](https://www.utf8-chartable.de/unicode-utf8-table.pl) .
