> For the complete documentation index, see [llms.txt](https://docs.elimity.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.elimity.com/gateways-ldap/v2.2.5/step-by-step-deployment-guide.md).

# Step-by-step deployment guide

{% hint style="info" %}
This version of the gateway is currently compatible with Elimity Insights server versions matching `>=3.42.0`.
{% endhint %}

## 1. Setting up an LDAP proxy

Each deployment of the Elimity Insights gateway for LDAP should communicate with an instance of the Elimity Insights LDAP proxy, as depicted in the diagram below:

<figure><img src="/files/U60TvkBd628I972Ddajy" alt=""><figcaption></figcaption></figure>

The proxy simply relays connections to your LDAP server, the actual connection parameters (e.g. hostname, user, password) reside in gateway configuration. Refer to [the documentation about our LDAP proxy](/other-components-ldap-proxy/step-by-step-deployment-guide.md) for detailed setup instructions.

{% hint style="info" %}
This version of the gateway is currently compatible with proxy versions matching `>=2.0.0`.
{% endhint %}

Note down your proxy's URL.

## 2. Configuring the gateway

The first step in setting up automatic imports via an LDAP gateway is configuring the gateway itself. As usual, please make sure your instance of Elimity Insights can reach the gateway and that the gateway can reach your LDAP proxy.

To configure your gateway, mount an HJSON configuration file at `/app/config/config.hjson` with the properties listed below. The following snippet provides a good starting point:

```hjson
{
  "jwtValidationBaseUrl": "https://example.elimity.com",
  "jwtValidationGatewayUrl": "https://gateway.example.com",
  "jwtValidationSourceId": "42",
  "ldapPassword": "example-ldap-password",
  "ldapProxyUrl": "https://proxy.example.com",
  "ldapServer": "example-ldap-server",
  "ldapUser": "example-ldap-user"
}
```

Edit the following properties in this file to configure the gateway to your needs:

<table data-full-width="true"><thead><tr><th>Property</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>jwtValidationAudiences</code></td><td><code>option[list[string]]</code></td><td>Audiences for JWT validation, defaults to <code>["gateway"]</code></td></tr><tr><td><code>jwtValidationBaseUrl</code></td><td><code>string</code></td><td>Expected Elimity Insights base URL for JWT validation, e.g. <code>"https://example.elimity.com"</code></td></tr><tr><td><code>jwtValidationGatewayUrl</code></td><td><code>string</code></td><td>Expected gateway URL for JWT validation, e.g. <code>"https://gateway.example.com"</code></td></tr><tr><td><code>jwtValidationIssuer</code></td><td><code>option[string]</code></td><td>Issuer for JWT validation, defaults to <code>"https://auth.elimity.com/"</code></td></tr><tr><td><code>jwtValidationExpr</code></td><td><code>option[string]</code></td><td><a href="https://expr-lang.org/">Expr</a> program implementing JWT custom claim validation, defaults to <code>"claims.base_url == baseURL &#x26;&#x26; claims.gateway_url == gatewayURL &#x26;&#x26; claims.source_id == sourceID"</code></td></tr><tr><td><code>jwtValidationOptional</code></td><td><code>option[boolean]</code></td><td>Flag indicating whether JWT validation is optional, defaults to <code>false</code></td></tr><tr><td><code>jwtValidationSourceId</code></td><td><code>string</code></td><td>Expected source id for JWT validation, e.g. <code>"42"</code></td></tr><tr><td><code>ldapCaCertsData</code></td><td><code>option[string]</code></td><td>Optional PEM-encoded SSL certificates to override the LDAP proxy's trust store</td></tr><tr><td><code>ldapPassword</code></td><td><code>string</code></td><td>Password for LDAP simple bind</td></tr><tr><td><code>ldapProxyUrl</code></td><td><code>string</code></td><td>HTTP(S) URL of the proxy you set up in step 1</td></tr><tr><td><code>ldapServer</code></td><td><code>string</code></td><td>Hostname, IP or URL of the LDAP server you want to import from</td></tr><tr><td><code>ldapUser</code></td><td><code>string</code></td><td>User for LDAP simple bind</td></tr></tbody></table>

### JWT validation

We highly recommend requiring JWT validation to secure your gateway. Please read our official documentation about the following topics to understand how Elimity Insights authenticates to gateways via OAuth2:

* [Gateway-based imports](/reference-manual/advanced-topics/gateway-based-imports.md)
* [OAuth2 endpoint parameters for gateway authentication](/reference-manual/server-configuration/oauth2-endpoint-parameters-for-gateway-authentication.md)

Our SaaS customers can simply set the `jwtValidationBaseUrl`, `jwtValidationGatewayUrl` and `jwtValidationSourceId` configuration options, which provides the following security guarantees:

* Only requests coming from the configured Elimity Insights are allowed
* Only requests targeting the configured gateway URL are allowed
* Only requests for importing the configured source are allowed

On-premise customers should additionally set the `jwtValidationAudiences`, `jwtValidationIssuer` and `jwtValidationExpr` configuration options. Alternatively you can also set `jwtValidationOptional` to `true` and perform authentication in a proxy instead.

## 3. Deploying the gateway

Since we distribute the gateway as a Docker image, our recommendation for deployment is to use a CaaS solution like Google Cloud Run or Azure Container Apps. If that's not an option, you can also manually deploy the image on e.g. Windows Server. Refer to [our documentation about gateways and import agents](/technical-guides/gateways-and-import-agents.md) for additional details.

## 4. Creating a custom source in Elimity Insights

To set up automatic imports via the LDAP gateway we need to create a custom source in Elimity Insights itself first. If you're unsure about the data model then we recommend to start with just a single entity type. You can simply extend the data model later on.

## 5. Enabling automatic imports

Having created the new custom source, you can now navigate to its detail page in Elimity Insights and open the 'CONFIG' tab. Click the 'EDIT' button and enter your gateway's URL and the desired CRON schedule. For Elimity Insights server versions matching `>=3.46.0`, set the SDK version to `1`. Also add the following configuration values:

<table data-full-width="true"><thead><tr><th>Key</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>entityTypes</code></td><td>JSON</td><td>JSON array describing how to import entities from your LDAP server; refer to <a href="#entity-types">the dedicated section below</a> for more information</td></tr><tr><td><code>ignoreSearchResultReferences</code></td><td>JSON</td><td>JSON boolean indicating whether to ignore search result references instead of failing the import when receiving them from the LDAP server, defaults to <code>false</code></td></tr><tr><td><code>relationshipTypes</code></td><td>JSON</td><td>JSON array describing how to import relationships from your LDAP server; refer to <a href="#relationship-types">the dedicated section below</a> for more information</td></tr></tbody></table>

### Entity types

For each item in the `entityTypes` configuration value, the gateway will perform searches in your LDAP server, convert the results into entities and send those to Elimity Insights. Refer to the snippet below as a starting point:

```json
[
  {
    "attributes": [
      {
        "assignedExpr": "'accountExpires' in attributes",
        "id": "accountExpires",
        "type": "dateTime",
        "valueExpr": "int(attributes.accountExpires.Unix())"
      },
      {
        "assignedExpr": "'badPwdCount' in attributes",
        "id": "badPwdCount",
        "type": "number",
        "valueExpr": "float(attributes.badPwdCount)"
      },
      {
        "assignedExpr": "'c' in attributes",
        "id": "country",
        "type": "string",
        "valueExpr": "string(attributes.c)"
      },
      {
        "assignedExpr": "'userAccountControl' in attributes",
        "id": "disabled",
        "type": "boolean",
        "valueExpr": "bitand(attributes.userAccountControl, 2) != 0"
      }
    ],
    "extraSearchBases": ["ou=domain controllers,dc=samdom,dc=example,dc=com"],
    "id": "user",
    "nameExpr": "string(attributes.cn)",
    "searchBase": "cn=users,dc=samdom,dc=example,dc=com",
    "searchFilter": "(objectClass=user)"
  },
  {
    "attributes": [],
    "id": "group",
    "nameExpr": "string(attributes.cn)",
    "searchBase": "cn=users,dc=samdom,dc=example,dc=com",
    "searchFilter": "(objectClass=group)"
  }
]
```

More specifically, the `entityTypes` configuration value should be a JSON array of objects, where each object should have the following properties:

<table data-full-width="true"><thead><tr><th>Property</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>attributes</code></td><td><code>list[object]</code></td><td>Describes how to import attributes of the entity type's entities</td></tr><tr><td><code>attributes[].assignedExpr</code></td><td><code>option[string]</code></td><td><a href="https://expr-lang.org/">Expr</a> program to determine whether the attribute is assigned, defaults to <code>"true"</code>; refer to <a href="#expr-programs">the dedicated section below</a> for more information</td></tr><tr><td><code>attributes[].id</code></td><td><code>string</code></td><td>Unique identifier of the attribute type for which the gateway should import assignments</td></tr><tr><td><code>attributes[].type</code></td><td><code>string</code></td><td>Data type of the attribute type, one of <code>"boolean"</code>, <code>"date"</code>, <code>"dateTime"</code>, <code>"number"</code>, <code>"string"</code> or <code>"time"</code></td></tr><tr><td><code>attributes[].valueExpr</code></td><td><code>string</code></td><td><a href="https://expr-lang.org/">Expr</a> program to determine the attribute assignment's value; refer to <a href="#expr-programs">the dedicated section below</a> for more information</td></tr><tr><td><code>extraSearchBases</code></td><td><code>option[list[string]]</code></td><td>Optional additional base DNs for LDAP search requests; defaults to <code>[]</code></td></tr><tr><td><code>id</code></td><td><code>string</code></td><td>Unique identifier of the entity type for which the gateway should import entities</td></tr><tr><td><code>nameExpr</code></td><td><code>string</code></td><td><a href="https://expr-lang.org/">Expr</a> program to extract the entity name from an LDAP search result; refer to <a href="#expr-programs">the dedicated section below</a> for more information</td></tr><tr><td><code>searchBase</code></td><td><code>string</code></td><td>Base DN for the LDAP search request</td></tr><tr><td><code>searchFilter</code></td><td><code>string</code></td><td>Filter for the LDAP search request</td></tr></tbody></table>

### Relationship types

For each item in the `relationshipTypes` configuration value, the gateway will iterate over all possible combinations of entities, creating relationships for those that match the configured predicate. Refer to the snippet below as a starting point:

```json
[
  {
    "fromEntityTypeId": "user",
    "expr": "to.dn in from.attributes.memberOf",
    "toEntityTypeId": "group"
  },
  {
    "fromEntityTypeId": "group",
    "expr": "to.dn in from.attributes.memberOf",
    "toEntityTypeId": "group"
  }
]
```

More specifically, the `relationshipTypes` configuration value should be a JSON array of objects, where each object should have the following properties:

<table data-full-width="true"><thead><tr><th>Property</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>fromEntityTypeId</code></td><td><code>string</code></td><td>Unique identifier of the entity type from which the relationships start</td></tr><tr><td><code>expr</code></td><td><code>string</code></td><td><a href="https://expr-lang.org/">Expr</a> program to determine whether the gateway should create a relationship for a given combination of entities; refer to <a href="#expr-programs">the dedicated section below</a> for more information</td></tr><tr><td><code>toEntityTypeId</code></td><td><code>string</code></td><td>Unique identifier of the entity type where the relationships end</td></tr></tbody></table>

### Expr programs

Each of the `attributes[].assignedExpr`, `attributes[].valueExpr` and `nameExpr` properties in the `entityTypes` items must represent a valid [Expr](https://expr-lang.org/) program for which Elimity Insights injects the following variables:

<table data-full-width="true"><thead><tr><th>Variable</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>attributes</code></td><td><code>map[string]any</code></td><td>Map containing all attributes of the LDAP search result</td></tr><tr><td><code>dn</code></td><td><code>string</code></td><td>DN of the LDAP search result</td></tr></tbody></table>

For the `expr` property in `relationshipTypes` items we inject `from` and `to` variables instead, these have their own `attributes` and `dn` fields as described above.

The programs for `attributes[].assignedExpr` and `nameExpr` in `entityTypes` items should have result types `bool` and `string` respectively. For `attributes[].valueExpr`, the expected result type depends on `attributes[].type`:

| Attribute type                   | Expected result type |
| -------------------------------- | -------------------- |
| `"boolean"`                      | `bool`               |
| `"date"`, `"dateTime"`, `"time"` | `int64` (Unix time)  |
| `"number"`                       | `float64`            |
| `"string"`                       | `string`             |

Programs for `expr` in `relationshipTypes` items should have result type `bool`.

The value type for entries in the `attributes` map depends on the LDAP attribute's syntax, the table below lists some examples:

| LDAP attribute syntax | Value type  |
| --------------------- | ----------- |
| Boolean               | `bool`      |
| Integer               | `int64`     |
| Directory String      | `string`    |
| Generalized Time      | `time.Time` |

Additionally, if the LDAP attribute type is multi-valued, then Elimity Insights injects an array of values instead of a single one.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.elimity.com/gateways-ldap/v2.2.5/step-by-step-deployment-guide.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
