# Single Sign-On with LDAP

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

LDAP (Lightweight Directory Access Protocol) is a standardized protocol for accessing directory services. In Connectware, LDAP can be used to authenticate users at login and assign permissions based on information from your directory service, such as Microsoft Active Directory or OpenLDAP.

This guide shows how to enable LDAP login in Connectware, choose an authorization model, and configure your directory so users receive the correct roles.

## Prerequisites

* Connectware Enterprise license required. For more information, see [cybus.io](https://www.cybus.io/en/product/licenses/).
* Active Directory or OpenLDAP server reachable from Connectware.
* LDAP user and group structure prepared according to the configuration steps in this guide.

## How LDAP Works in Connectware

Connectware uses LDAP in two steps:

1. **Authentication**: When a user signs in, Connectware verifies the username and password against your LDAP directory.
2. **Authorization**: After successful authentication, Connectware assigns Connectware roles to the user based on your LDAP configuration.

On the first successful login, Connectware creates a corresponding user in its internal user database. On each subsequent successful login, role assignments are synchronized from LDAP.

You can choose between the following authorization modes:

* **Group mode**: Roles are assigned based on LDAP group membership.
* **Attribute mode**: Roles are assigned based on LDAP user attributes.

In both cases, role management happens in LDAP, not in Connectware.

## Choose Your LDAP Authentication Method

Decide how Connectware authenticates users against your LDAP directory. This choice depends on how your directory is structured and how users are organized within it.

Connectware provides the following methods for LDAP authentication:

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

A bind user is common in LDAP setups with complex directory structures. It is a limited user that you create in your LDAP directory. This user is usually read-only and has permission to search the LDAP directory tree.

You use it when users do not share a single LDAP base DN (i.e., when they are not in the same group). If your users are spread throughout the directory tree, you will likely want to use a bind user.

### Direct Authentication Without a 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 `ou=users,dc=corp,dc=com` and the DN of all users follows the pattern `<RDN_OF_USER>,ou=users,dc=corp,dc=com`
* Groups are not nested
  * Example of unsupported nesting: A user is a member of `group A`, `group A` is a member of `group B`, and `group B` is the group linked with a Connectware role.

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

### Authentication Using a 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,ou=production,dc=corp,dc=com`
    * User 2: `cn=user2,ou=operations,dc=corp,dc=com`
  * In this case, Connectware needs to search from a common base DN (`dc=corp,dc=com`) to locate user entries
* Your setup uses nested groups
  * The search base must be the common DN shared by all groups and users

If your directory needs additional constraints (e.g., multiple branches), configure a custom LDAP search filter. See [LDAP Search Filters](#ldap-search-filter).

## Choose Your LDAP Authorization Mode

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 are assigned to the Connectware user automatically. This way, permissions can be easily managed 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=corp,dc=com`. Users in this group automatically receive the role when logging in.

For more information, see [Example Setup for Group Mode](#example-setup-for-group-mode).

### Attribute Mode

When an 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.

For more information, see [Example Setup for Attribute Mode](#example-setup-for-attribute-mode).

## Enable LDAP Authentication

{% tabs %}
{% tab title="Kubernetes" %}

#### Enabling LDAP Authentication (Kubernetes)

1. To enable the LDAP feature in Connectware, set the `global.authentication.ldap.enabled` Helm value to `true`.
2. Additionally, provide the following Helm values within the `global.authentication.ldap` context:

| Value    | Example                    | Description                                                                                                                      |
| -------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `bindDn` | `ou=users,dc=corp,dc=com`  | Base DN for direct authentication **or** full DN of a dedicated bind user. See [parameter table](#helm-values-ldap) for details. |
| `url`    | `ldap://ldap.corp.com:389` | URL of the LDAP server in format `scheme://hostname:port`.                                                                       |

**Example**

{% code lineNumbers="true" %}

```yaml
global:
  authentication:
    ldap:
      enabled: true
      bindDn: ou=users,dc=corp,dc=com
      url: ldap://ldap.corp.com:389
```

{% endcode %}

If you are using a bind user to search through the directory tree, you must specify the full DN of the bind user as `bindDn` and provide the following additional values:

| Value          | Example           | Description                                                   |
| -------------- | ----------------- | ------------------------------------------------------------- |
| `bindPassword` | `ANc97WCO"!xcC=(` | Password for the bind user as defined in your LDAP server.    |
| `searchBase`   | `dc=corp,dc=com`  | Base DN for searching users when using a dedicated bind user. |

**Example**

{% code lineNumbers="true" %}

```yaml
global:
  authentication:
    ldap:
      enabled: true
      bindDn: cn=binduser,ou=users,dc=corp,dc=com
      bindPassword: <password of binduser>
      url: ldap://ldap.corp.com:389
      searchBase: dc=corp,dc=com
```

{% endcode %}

If you do not want to provide the bind user and its password through Helm values (for example, when following a GitOps approach), you can reference an existing Kubernetes secret via `existingBindSecret`. For more information, see [Bind User Credentials via Existing Kubernetes Secret](#bind-user-credentials-via-existing-kubernetes-secret).

3. After enabling LDAP authentication, you must configure how Connectware derives user roles from LDAP. This is controlled through the `mode` setting in the `global.authentication.ldap` context. Connectware supports `group` mode and `attribute` mode.

For more information, see [Choose Your LDAP Authorization Mode](#choose-your-ldap-authorization-mode).
{% endtab %}

{% tab title="Docker Compose" %}

#### Enabling LDAP Authentication (Docker Compose)

For a list of all environment variables for Docker, see [Docker Compose](https://docs.cybus.io/2-0-6/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 look like this:

{% code lineNumbers="true" %}

```bash
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.
5. To set up a configuration with direct authentication (no dedicated bind user), do the following:

Example configuration for LDAP mode `attribute`:

{% code lineNumbers="true" %}

```bash
CYBUS_LDAP_ENABLED=true
CYBUS_LDAP_MODE=attribute
CYBUS_LDAP_BIND_DN=ou=users,dc=corp,dc=com
CYBUS_LDAP_URL=ldap://ldap.corp.com:389
CYBUS_LDAP_USER_RDN=cn
CYBUS_LDAP_ROLES_ATTRIBUTE=employeeType
```

{% endcode %}

Example configuration for LDAP mode `group`:

{% code lineNumbers="true" %}

```bash
CYBUS_LDAP_ENABLED=true
CYBUS_LDAP_MODE=group
CYBUS_LDAP_BIND_DN=ou=users,dc=corp,dc=com
CYBUS_LDAP_URL=ldap://ldap.corp.com:389
CYBUS_LDAP_USER_RDN=cn
CYBUS_LDAP_MEMBER_ATTRIBUTE=memberOf
```

{% endcode %}

This configuration would look for users matching the LDAP query `cn=username,ou=users,dc=corp,dc=com`.

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

6. To set up a configuration with a dedicated bind user, do the following:

Example configuration for LDAP mode `attribute`:

{% code lineNumbers="true" %}

```bash
CYBUS_LDAP_ENABLED=true
CYBUS_LDAP_MODE=attribute
CYBUS_LDAP_BIND_DN=cn=binduser,ou=users,dc=corp,dc=com
CYBUS_LDAP_BIND_PASSWORD=<password of binduser>
CYBUS_LDAP_SEARCH_BASE=dc=corp,dc=com
CYBUS_LDAP_URL=ldap://ldap.corp.com:389
CYBUS_LDAP_USER_RDN=cn
CYBUS_LDAP_ROLES_ATTRIBUTE=employeeType
```

{% endcode %}

Example configuration for LDAP mode `group`:

{% code lineNumbers="true" %}

```bash
CYBUS_LDAP_ENABLED=true
CYBUS_LDAP_MODE=group
CYBUS_LDAP_BIND_DN=cn=binduser,ou=users,dc=corp,dc=com
CYBUS_LDAP_BIND_PASSWORD=<password of binduser>
CYBUS_LDAP_SEARCH_BASE=dc=corp,dc=com
CYBUS_LDAP_URL=ldap://ldap.corp.com:389
CYBUS_LDAP_USER_RDN=cn
CYBUS_LDAP_MEMBER_ATTRIBUTE=memberOf
```

{% endcode %}

Make sure to change the RDN prefix (`cn`) if needed for `CYBUS_LDAP_BIND_DN=cn=binduser,ou=users,dc=corp,dc=com`.

7. After saving the new configuration, do one of the following:

* If your Connectware instance is running as a system service, run `systemctl restart connectware` to restart it.
* Otherwise, run `docker compose up -d` from within the installation folder to restart it.

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`).
{% endtab %}
{% endtabs %}

## Configure LDAP Parameters

Once the authentication method and authorization model are defined, configure the LDAP parameters required by Connectware. The available parameters depend on the deployment type and the chosen configuration path.

The following tables list all supported LDAP parameters for Kubernetes and Docker Compose deployments.

{% tabs %}
{% tab title="Helm Values" %}

#### Helm Values (LDAP)

| Helm value                                                                                                                                           | Description                                                                                                                                                                                                                                                                                                                                                                   |
| ---------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `global.authentication.ldap.enabled`                                                                                                                 | `true/false`. Enables LDAP integration.                                                                                                                                                                                                                                                                                                                                       |
| `global.authentication.ldap.bindDn`                                                                                                                  | <p><strong>Without <code>bindPassword</code>:</strong> Base DN where all user entries are located (e.g., <code>ou=users,dc=corp,dc=com</code>).<br><strong>With <code>bindPassword</code>:</strong> Full DN of a dedicated bind user (e.g., <code>cn=binduser,ou=users,dc=corp,dc=com</code>).</p>                                                                            |
| <p><code>global.authentication.ldap.bindPassword</code><br><strong>or</strong> <code>global.authentication.ldap.existingBindSecret</code></p>        | <p>Password for the dedicated bind user <strong>or</strong> reference a Secret with keys <code>bindDn</code> and <code>bindPassword</code>. When provided, <code>bindDn</code> must contain the full DN of the bind user, and <code>searchBase</code> becomes required.<br><strong>Note:</strong> If both are provided, <code>existingBindSecret</code> takes precedence.</p> |
| `global.authentication.ldap.searchBase`                                                                                                              | Base DN for searching users. **Required only when using a dedicated bind user** (i.e., when `bindPassword` is set).                                                                                                                                                                                                                                                           |
| `global.authentication.ldap.searchFilter`                                                                                                            | Optional custom user search filter; overrides default username-based lookup. See [LDAP Search Filters](#ldap-search-filter).                                                                                                                                                                                                                                                  |
| `global.authentication.ldap.url`                                                                                                                     | LDAP/AD server URL, e.g., `ldap://host:389` or `ldaps://host:636`.                                                                                                                                                                                                                                                                                                            |
| `global.authentication.ldap.mode`                                                                                                                    | `group` or `attribute`.                                                                                                                                                                                                                                                                                                                                                       |
| `global.authentication.ldap.rolesAttribute`                                                                                                          | LDAP attribute containing Connectware roles. Used only with `mode: attribute`.                                                                                                                                                                                                                                                                                                |
| `global.authentication.ldap.memberAttribute`                                                                                                         | LDAP attribute indicating group memberships (often `memberOf`). Used only with `mode: group`.                                                                                                                                                                                                                                                                                 |
| `global.authentication.ldap.userRdn`                                                                                                                 | LDAP user property (e.g., `cn`) used as the username at login.                                                                                                                                                                                                                                                                                                                |
| `global.authentication.ldap.caChain.trustAllCertificates`                                                                                            | `true` accepts all certificates (not recommended). Default is `false`.                                                                                                                                                                                                                                                                                                        |
| <p><code>global.authentication.ldap.caChain.cert</code><br><strong>or</strong> <code>global.authentication.ldap.caChain.existingConfigMap</code></p> | <p>Provide full CA chain in PEM via <code>cert:</code> <strong>or</strong> reference a ConfigMap (file must be <code>ca.crt</code>). No file path option.<br><strong>Note:</strong> If both are provided, <code>existingConfigMap</code> takes precedence.</p>                                                                                                                |
| `global.authentication.ldap.autoEnforceMfa`                                                                                                          | Enforce MFA for LDAP users after first login. Requires `global.authentication.mfa.enabled: true` and keys configured.                                                                                                                                                                                                                                                         |
| {% endtab %}                                                                                                                                         |                                                                                                                                                                                                                                                                                                                                                                               |

{% tab title="Environment Variables" %}

#### Environment Variables (LDAP)

| 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`          | <p><strong>Without <code>CYBUS\_LDAP\_BIND\_PASSWORD</code>:</strong> Base DN where all user entries are located (e.g., <code>ou=users,dc=corp,dc=com</code>).<br><strong>With <code>CYBUS\_LDAP\_BIND\_PASSWORD</code>:</strong> Full DN of a dedicated bind user (e.g., <code>cn=binduser,ou=users,dc=corp,dc=com</code>).</p> |
| `CYBUS_LDAP_BIND_PASSWORD`    | Password for the dedicated bind user. When provided, `CYBUS_LDAP_BIND_DN` must contain the full DN of the bind user, and `CYBUS_LDAP_SEARCH_BASE` becomes required.                                                                                                                                                              |
| `CYBUS_LDAP_SEARCH_BASE`      | Base DN for searching users. **Required only when using a dedicated bind user** (i.e., when `CYBUS_LDAP_BIND_PASSWORD` is set). Example: `dc=corp,dc=com`.                                                                                                                                                                       |
| `CYBUS_LDAP_SEARCH_FILTER`    | Optional custom filter for user search requests. Only valid with a dedicated bind user. See [LDAP Search Filters](#ldap-search-filter).                                                                                                                                                                                          |
| `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 verification for Secure LDAP. Default is `false`.                                                                                                                                                                                                                           |
| `CYBUS_LDAPS_CA_FILE`         | <p>Path to CA file for LDAP server validation. Used with Secure LDAP when <code>CYBUS\_LDAPS\_TRUST\_ALL\_CERTS</code> is <code>false</code>.<br><strong>Note:</strong> The CA file must be mounted into the container for this path to be accessible.</p>                                                                       |
| `CYBUS_LDAP_AUTO_ENFORCE_MFA` | When `true`, enforces MFA for LDAP users after their first login.                                                                                                                                                                                                                                                                |
| {% endtab %}                  |                                                                                                                                                                                                                                                                                                                                  |
| {% endtabs %}                 |                                                                                                                                                                                                                                                                                                                                  |

## Example LDAP Setups

This section shows a complete Docker example setup for both authorization models.

Each example follows the same structure: LDAP preparation, Connectware configuration, and role assignment behavior. You can use these examples as a reference and adapt them to your own directory structure.

### Example Setup for Group Mode

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.
2. Configure Connectware with LDAP parameters.
3. Link LDAP groups with Connectware roles.
4. Assign LDAP users to these LDAP groups.

{% stepper %}
{% step %}
**Define 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 structure:

{% code lineNumbers="true" %}

```
dc=corp,dc=com
├ ou=users
│  ├ cn=user1
│  ├ cn=user2
│  └ cn=user3
└ ou=connectware
```

{% endcode %}

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

{% code lineNumbers="true" %}

```
dc=corp,dc=com
├ ou=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 actual password of `user1`.

{% code lineNumbers="true" %}

```bash
ldapsearch -LLL -b "cn=user1,ou=users,dc=corp,dc=com" -D "cn=user1,ou=users,dc=corp,dc=com" -w PASSWORD
```

{% endcode %}

Result of the command:

{% code lineNumbers="true" %}

```
dn: cn=user1,ou=users,dc=corp,dc=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: user1
...
memberOf: cn=cw-minimal,ou=connectware,dc=corp,dc=com
...
```

{% endcode %}

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

{% code lineNumbers="true" %}

```bash
ldapsearch -LLL -b "cn=user1,ou=users,dc=corp,dc=com" -D "cn=user1,ou=users,dc=corp,dc=com" -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 %}
**Configure Connectware with LDAP Parameters**

* Edit the `.env` file as follows:

{% code lineNumbers="true" %}

```bash
CYBUS_LDAP_ENABLED=true
CYBUS_LDAP_MODE=group
CYBUS_LDAP_BIND_DN=ou=users,dc=corp,dc=com
CYBUS_LDAP_URL=ldap://ldap.corp.com:389
CYBUS_LDAP_MEMBER_ATTRIBUTE=memberOf
CYBUS_LDAP_USER_RDN=cn
```

{% endcode %}

Make sure to adjust the LDAP URL to match your environment.
{% endstep %}

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

1. Log 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-admin`, 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=corp,dc=com`.

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>The field is labeled "DN of AD Group" in the UI, but it accepts the DN of any LDAP group, whether from Active Directory or OpenLDAP.</p></div>

   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=corp,dc=com`).
   3. In the **Copy Permissions** field, select **minimum-access** and click **Add**.
   4. Click **Create** to add your new role.

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

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

1. You can assign different Connectware roles to your users `user1`, `user2`, and `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 log into Connectware, `user1` will be created (if it is the first login) and the role `LDAP-Admin` will be assigned automatically.
3. Log out from Connectware, remove `user1` from group `cw-admin`, and add it to `cw-minimal`.
4. Log into Connectware with `user1` again. `user1` has limited access and you cannot navigate to the user section. Permissions of `user1` changed according to the LDAP group membership.

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

### Example Setup for Attribute Mode

1. LDAP setup.
2. Configure Connectware with LDAP parameters.
3. Assign roles to the LDAP user entry.

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

The following examples assume that you have an LDAP DIT structure like the following:

{% code lineNumbers="true" %}

```
dc=corp,dc=com
└ ou=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" %}

```bash
CYBUS_LDAP_ENABLED=true
CYBUS_LDAP_MODE=attribute
CYBUS_LDAP_BIND_DN=ou=users,dc=corp,dc=com
CYBUS_LDAP_URL=ldap://ldap.corp.com: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 user's **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 the roles attribute in the `.env` file) with the value `connectware-admin` to the LDAP user `user1`.
3. Add the Connectware role `minimum-access` to `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" %}

```bash
ldapsearch -LLL -b "cn=user1,ou=users,dc=corp,dc=com" -D "cn=user1,ou=users,dc=corp,dc=com" -w PASSWORD
```

{% endcode %}

Result of the command:

{% code lineNumbers="true" %}

```
dn: cn=user1,ou=users,dc=corp,dc=com
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 user `user1`.
6. To revoke access to Connectware for a certain user, the Connectware roles just have to be removed from the LDAP user 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

When LDAP authentication is enabled, user management in Connectware differs from local user accounts. These differences are important to understand when operating and troubleshooting an LDAP-based setup.

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

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://639096190-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfDpOJO2upcq5EpoSahvK%2Fuploads%2Fgit-blob-6a57caacd55a8bdeb8b8a140fbb0155260dc3b7f%2Fldap_user_details.png?alt=media" alt=""><figcaption></figcaption></figure>

### Roles

You cannot 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 synchronized to the Connectware user on each successful login.

### Grant Types

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

### LDAP User Password

You cannot 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 this local user information will not prevent 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.

## Advanced LDAP Configuration

### Customizing the User RDN

The user RDN (relative distinguished name) defines which LDAP attribute is used to identify a user during authentication.

By default, Connectware uses the `cn` attribute as the user identifier during login. This means the username entered at the Connectware login screen is mapped to an LDAP distinguished name constructed with `cn=<username>`.

You may need to change the user RDN if your directory uses a different attribute to identify users, for example, `uid`, `sn`, or `sAMAccountName`. In such cases, you must configure Connectware to use the appropriate LDAP attribute as the user RDN.

* The configured user RDN must match the directory schema used for user entries.
* When using direct authentication without a dedicated bind user, the user RDN is combined with the base DN to form the bind DN.
* When using a dedicated bind user, the user RDN is used during the search operation to locate the user entry.

Make sure the chosen attribute uniquely identifies users within the configured search scope.

Configuration examples for Kubernetes and Docker Compose are provided in the following sections.

{% tabs %}
{% tab title="Kubernetes Configuration" %}
**Customizing the User RDN (Kubernetes)**

1. In the `values.yaml` file, configure the `global.authentication.ldap.userRdn` Helm value.

**Example**

{% code lineNumbers="true" %}

```yaml
global:
  authentication:
    ldap:
      enabled: true
      bindDn: ou=users,dc=corp,dc=com
      url: ldap://ldap.corp.com:389
      userRdn: uid
```

{% endcode %}

With this configuration, Connectware uses `uid=<username>` instead of `cn=<username>` when authenticating users.

2. Apply the configuration changes via the `helm upgrade` command.

**Example**

```bash
helm upgrade -n ${NAMESPACE} ${INSTALLATION_NAME} -f values.yaml
```

For more information, see [Applying Helm Configuration Changes](https://docs.cybus.io/2-0-6/connectware-on-kubernetes/connectware-helm-chart#applying-helm-configuration-changes).
{% endtab %}

{% tab title="Docker Compose Configuration" %}
**Customizing the User RDN (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 and configure the `CYBUS_LDAP_USER_RDN` environment variable.

**Example**

{% code lineNumbers="true" %}

```bash
CYBUS_LDAP_ENABLED=true
CYBUS_LDAP_URL=ldap://ldap.corp.com:389
CYBUS_LDAP_BIND_DN=ou=users,dc=corp,dc=com
CYBUS_LDAP_USER_RDN=uid
```

{% endcode %}

With this configuration, Connectware constructs user DNs using `uid=<username>`.
{% endtab %}
{% endtabs %}

### TLS for LDAP Authentication

You can secure LDAP communication by using LDAPS. When TLS is enabled, Connectware validates the certificate presented by the LDAP server.

You can choose from the following options:

* Use a certificate signed by a trusted root CA.
* Provide a custom CA certificate chain to Connectware.
* Disable certificate validation for non-production environments.

{% tabs %}
{% tab title="Kubernetes" %}
**Enabling TLS for LDAP Authentication (Kubernetes)**

1. To enable TLS for LDAP, set a valid `ldaps://` URL for the Helm value `url` in the `global.authentication.ldap` context.
2. Adjust the TCP port number. By default, LDAPS uses port 636.
   {% endtab %}

{% tab title="Docker Compose" %}
**Enabling TLS for LDAP Authentication (Docker Compose)**

1. To enable TLS for LDAP, set a valid `ldaps://` URL for `CYBUS_LDAP_URL`.
2. Adjust the TCP port number. By default, LDAPS uses port 636.
   {% endtab %}
   {% endtabs %}

#### Providing the CA Certificate

{% tabs %}
{% tab title="Kubernetes" %}
**Providing the CA Certificate through Helm Values**

* To provide the CA certificate, set the Helm value `caChain.cert` in the `global.authentication.ldap` context. Provide the complete certificate chain necessary to validate the LDAP server's certificate.

**Example**

{% code lineNumbers="true" %}

```yaml
global:
  authentication:
    ldap:
      enabled: true
      bindDn: ou=users,dc=corp,dc=com
      url: ldaps://ldap.corp.com:636
      caChain:
        cert: |
          -----BEGIN CERTIFICATE-----
          MIIFpTCCA40CFGFL86145m7JIg2RaKkAVCOV1H71MA0GCSqGSIb3DQEBCwUAMIGN
          [skipped for brevity - include whole certificate]
          SKnBS1Y1Dn2e
          -----END CERTIFICATE-----
```

{% endcode %}

As an alternative, you can provide the CA certificate through a manually created [Kubernetes ConfigMap](#providing-the-ca-certificate-through-a-kubernetes-configmap).

**Providing the CA Certificate through a Kubernetes ConfigMap**

To provide the CA certificate necessary to validate the certificate used by your LDAP server, you can manually create a Kubernetes ConfigMap that contains the certificate as a file named ca.crt. You will then provide the name of this ConfigMap in the Helm value `caChain.existingConfigMap` in the `global.authentication.ldap` context.

**Example**

* Create the Kubernetes ConfigMap from a file named ca.crt in your current directory:

{% code lineNumbers="true" %}

```bash
kubectl -n ${NAMESPACE} create cm cw-ldap-ca-cert --from-file=ca.crt
```

{% endcode %}

* Specify the name of the ConfigMap:

{% code lineNumbers="true" %}

```yaml
global:
  authentication:
    ldap:
      enabled: true
      bindDn: ou=users,dc=corp,dc=com
      url: ldaps://ldap.corp.com:636
      caChain:
        existingConfigMap: cw-ldap-ca-cert
```

{% endcode %}
{% endtab %}

{% tab title="Docker Compose" %}
**Providing the CA Certificate through Environment Variables**

* To provide the CA certificate, set `CYBUS_LDAPS_CA_FILE` to the path where the certificate will be available inside the container. Provide the complete certificate chain necessary to validate the LDAP server's certificate.
* The CA certificate file must be mounted into the Connectware container.
  {% endtab %}
  {% endtabs %}

#### Disabling Certificate Validation

While we do not recommend skipping certificate validation for production use, it is possible to tell Connectware to accept any certificate the LDAP server presents.

{% tabs %}
{% tab title="Kubernetes" %}
**Disabling Certificate Validation (Kubernetes)**

* To disable certificate validation, set the Helm value `caChain.trustAllCertificates` in the `global.authentication.ldap` context to `true`.

**Example**

{% code lineNumbers="true" %}

```yaml
global:
  authentication:
    ldap:
      enabled: true
      bindDn: ou=users,dc=corp,dc=com
      url: ldaps://ldap.corp.com:636
      caChain:
        trustAllCertificates: true
```

{% endcode %}
{% endtab %}

{% tab title="Docker Compose" %}
**Disabling Certificate Validation (Docker Compose)**

* To disable certificate validation, set `CYBUS_LDAPS_TRUST_ALL_CERTS` to `true`.
  {% endtab %}
  {% endtabs %}

### LDAP Search Filter

Connectware uses an LDAP search filter to locate a user entry during authentication. The filter is constructed dynamically based on the configured user RDN, the username entered during login, and an optional custom filter extension.

#### Filter Format and Construction

By default, Connectware constructs the LDAP search filter as:

{% code lineNumbers="true" %}

```txt
(<userRdn>=<username>)
```

{% endcode %}

Where:

* `CYBUS_LDAP_USER_RDN` (Docker Compose) or `userRdn` (Kubernetes) is configured in Connectware.
* `username` is the value entered by the user during login.

If you configure an additional search filter extension, Connectware combines both parts using an AND condition. The resulting filter has the following structure:

{% code lineNumbers="true" %}

```txt
(&(<userRdn>=<username>)(<searchFilter>))
```

{% endcode %}

#### RFC 4515 Encoding Requirements

LDAP search filters must follow RFC 4515. Certain special characters in filter values must be escaped using hexadecimal notation.

See the official RFC for full details: <https://datatracker.ietf.org/doc/rfc4515/>

**Characters Requiring Escaping**

The following characters must be escaped when used in LDAP filter values:

| Character | Hex Escape | Description       |
| --------- | ---------- | ----------------- |
| `*`       | `\2a`      | Asterisk          |
| `(`       | `\28`      | Left parenthesis  |
| `)`       | `\29`      | Right parenthesis |
| `\`       | `\5c`      | Backslash         |
| NUL       | `\00`      | Null character    |

**Non-ASCII Characters**

Non-ASCII characters (such as international characters) should be encoded as hex-escaped UTF-8 bytes. Each byte of the UTF-8 representation must be escaped individually.

**Example**: The German character `ü` is represented in UTF-8 as bytes `0xC3 0xBC`, which must be escaped as `\c3\bc` in an LDAP filter.

**Encoding Example**

{% code lineNumbers="true" %}

```txt
Clear text search filter: (cn=*)
Escaped search filter: (cn=\2a)
```

{% endcode %}

When used as an extension, only the escaped expression is added.

#### When to Use a Custom Search Filter

Extending the search filter is useful in scenarios such as:

* Users are not uniquely identifiable by their username alone.
* Multiple entries share the same RDN within a large search base.
* You want to restrict authentication to a specific subtree or object type.

#### Example Scenario

Given the following directory structure, we have two entries with the same RDN `cn=a.smith`:

{% code lineNumbers="true" %}

```txt
dc=corp,dc=com
├── ou=customers
│   └── cn=a.smith
└── ou=employees
    └── cn=a.smith
```

{% endcode %}

If the search base is set to `dc=corp,dc=com`, the username alone is not sufficient to uniquely identify the entry.

To restrict authentication to employees only, you can extend the filter to match entries whose DN contains `ou=employees`.

**Testing the Custom Search Filter**

You can validate the filter using `ldapsearch` before applying it to Connectware:

{% code lineNumbers="true" %}

```bash
ldapsearch -L \
  -b "dc=corp,dc=com" \
  -D "cn=admin,dc=corp,dc=com" \
  -w admin_pass \
  "(&(cn=a.smith)(ou:dn:=employees))"
```

{% endcode %}

#### Configuring the Filter Extension

{% tabs %}
{% tab title="Kubernetes Configuration" %}
**Configuring the Filter Extension (Kubernetes)**

* In the `values.yaml` file, configure the `global.authentication.ldap.searchFilter` Helm value.

**Example**

{% code lineNumbers="true" %}

```yaml
global:
  authentication:
    ldap:
      enabled: true
      bindDn: cn=binduser,ou=users,dc=corp,dc=com
      bindPassword: <password of binduser>
      searchBase: dc=corp,dc=com
      userRdn: cn
      searchFilter: ou:dn:=employees
      url: ldap://ldap.corp.com:389
```

{% endcode %}

{% hint style="info" %}
Be aware that no surrounding brackets are used for the additional expression. Brackets within your expression can be used, e.g., `&(objectClass=iNetOrgPerson)(ou:dn:=employees)`.
{% endhint %}
{% endtab %}

{% tab title="Docker Compose Configuration" %}
**Configuring the Filter Extension (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 and configure the `CYBUS_LDAP_SEARCH_FILTER` environment variable.
   {% endtab %}
   {% endtabs %}

### Bind User Credentials via Existing Kubernetes Secret

If you do not want to provide the bind user for LDAP authentication through the Helm values `bindDn` and `bindPassword` within the `global.authentication.ldap` context, you can also manually create a Kubernetes secret in Connectware's namespace through your preferred method of managing secrets in Kubernetes. You will then need to provide the name of this secret in the Helm value `existingBindSecret`.

This secret needs to contain two keys, `bindDn` and `bindPassword`, containing the parameters that you did not specify directly as Helm values. If you want to use different keys, you can customize these as shown below.

**Example**

1. Create your Kubernetes secret:

{% code lineNumbers="true" %}

```bash
kubectl -n ${NAMESPACE} create secret generic my-ldap-user --from-literal=bindDn="cn=binduser,ou=users,dc=corp,dc=com" --from-literal=bindPassword="S3cretPassword"
```

{% endcode %}

2. Specify the name of the secret in your `values.yaml` file:

{% code lineNumbers="true" %}

```yaml
global:
  authentication:
    ldap:
      enabled: true
      existingBindSecret: my-ldap-user
      searchBase: dc=corp,dc=com
      url: ldap://ldap.corp.com:389
```

{% endcode %}

#### Customizing Kubernetes Secret Keys

If you want to customize the keys used in the Kubernetes secret, you can do so and specify the keys you want to use instead in the Helm value `existingBindSecretDnKey` and `existingBindSecretPasswordKey` within the `global.authentication.ldap` context.

**Example**

1. Create your Kubernetes secret:

{% code lineNumbers="true" %}

```bash
kubectl -n ${NAMESPACE} create secret generic custom-ldap-user --from-literal=username="cn=binduser,ou=users,dc=corp,dc=com" --from-literal=password="S3cretPassword"
```

{% endcode %}

2. Specify the name of the secret in your `values.yaml` file:

{% code lineNumbers="true" %}

```yaml
global:
  authentication:
    ldap:
      enabled: true
      existingBindSecret: custom-ldap-user
      existingBindSecretDnKey: username
      existingBindSecretPasswordKey: password
      searchBase: dc=corp,dc=com
      url: ldap://ldap.corp.com:389
```

{% endcode %}
