> This page is for Tools.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.moveworks.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.moveworks.com/_mcp/server.

# Configure an LDAP SSL certificate for the On-Prem Agent

> Get, convert, verify, and install the PEM certificate the Moveworks On-Prem Agent needs to connect to LDAP or Active Directory over SSL or StartTLS.

Set up the PEM certificate the Moveworks On-Prem Agent uses to verify your LDAP or Active Directory server over SSL (LDAPS, usually port 636) or StartTLS (usually port 389), for a first setup or a replacement. This page is for administrators of the agent host. To rotate other credentials, see [Rotate On-Prem Agent credentials and certificates](/tool-studio/moveworks-agent/moveworks-agent-configuration-guides/rotating-credentials-and-certificates).

## Before you begin

* You know the LDAP server's fully qualified domain name (FQDN) and its SSL or StartTLS port.
* You can SSH to the agent host, the server or VM that runs the agent's container, and it has OpenSSL 1.1.1 or later. Run commands from the folder that contains `setup_agent.sh`. Certificates go in its `moveworks/certs/` subfolder, which the container sees as `/home/moveworks/agent/certs/`.
* You need a certificate file only if your organization's own certificate authority (CA) signed the LDAP server's certificate, as is typical for Active Directory domain controllers. The agent already trusts public CAs; for those, leave out `path_to_cert`.

Wildcard certificates aren't accepted for LDAP over SSL. See [Microsoft's guidance on enabling LDAP over SSL](https://docs.microsoft.com/en-US/troubleshoot/windows-server/identity/enable-ldap-over-ssl-3rd-certification-authority).

## Get the certificate

When you set `path_to_cert`, the agent trusts only the certificates in that file for the LDAP connection. Your best option is a file with the CA certificates that issued the server's certificate: the root and any intermediates. Ask your PKI or Active Directory administrator for them, or pull the chain the server presents:

#### LDAPS (port 636)

```shell
openssl s_client -connect <ldap-host>:636 -showcerts </dev/null 2>/dev/null \
  | sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' > ldap_cert.pem
```

#### StartTLS (port 389)

```shell
openssl s_client -connect <ldap-host>:389 -starttls ldap -showcerts </dev/null 2>/dev/null \
  | sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' > ldap_cert.pem
```

Replace `<ldap-host>` with the server's FQDN. The command saves every certificate the server sends, usually its own certificate and the intermediates. That's enough: the agent trusts every certificate in the file.

> **Warning**
>
> Don't pipe `s_client` output through `openssl x509 -outform PEM`. That saves only the server's own certificate. It works until the server renews its certificate, and then the agent fails with `x509: certificate signed by unknown authority`.

The file should hold one or more blocks like this:

```text
-----BEGIN CERTIFICATE-----
content of the server or intermediate CA certificate
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
content of the next CA certificate
-----END CERTIFICATE-----
```

## Convert the certificate to PEM

The agent reads only PEM-encoded certificates. If the first line of your file isn't `-----BEGIN CERTIFICATE-----`, convert it:

| You have                        | Command                                                        |
| ------------------------------- | -------------------------------------------------------------- |
| A `.p7b` bundle                 | `openssl pkcs7 -print_certs -in certnew.p7b -out ca_chain.pem` |
| A binary (DER) `.cer` or `.crt` | `openssl x509 -inform der -in cert.cer -out cert.pem`          |

A `.cer` or `.crt` file can already be PEM-encoded. Check its first line before you convert it.

## Verify the certificate

1. Show the first certificate in the file, which is the server's own certificate if you pulled it from the server:
   ```shell
   openssl x509 -in ldap_cert.pem -noout -subject -issuer -enddate -ext subjectAltName
   ```
   For every field, run `openssl x509 -in ldap_cert.pem -text -noout`.
2. Confirm the **Subject Alternative Name** (SAN) lists a `DNS:` entry that matches the `host` you'll put in `agent_config.yml`. The agent checks the SAN only. A certificate with the name only in the subject's CN fails with `x509: certificate relies on legacy Common Name field`.
3. Confirm `notAfter` is in the future.

## Install the certificate on the agent host

The agent runs as the `moveworks` user in group `17540` inside the container, so that group needs read access. The host needs no group of that name. Copy the file to the host (`scp ldap_cert.pem <user>@<agent-host>:~`), then, from the folder that contains `setup_agent.sh`, run:

```shell
sudo cp ~/ldap_cert.pem moveworks/certs/ldap_cert.pem
sudo chgrp 17540 moveworks/certs/ldap_cert.pem
sudo chmod 640 moveworks/certs/ldap_cert.pem
```

`setup_agent.sh` mounts `moveworks/certs/` for you. A custom `docker run` or `podman run` command must mount the same folders, or the agent fails with `no such file or directory`:

```shell
-v "<install-folder>/moveworks/conf":/home/moveworks/agent/conf \
-v "<install-folder>/moveworks/certs":/home/moveworks/agent/certs \
-v "<install-folder>/moveworks/logs":/var/log/moveworks \
```

Mount the existing `certs` folder, not a new one: its `agent_key.pem` decrypts the secrets in `agent_config.yml`.

## Point the agent at the certificate

Set `path_to_cert` to the file's path inside the container. Use the configurator, or edit the file with the agent stopped:

* **Configurator:** run `sudo ./setup_agent.sh --reconfigure`, select **\[3] LDAP Configs**, and edit `path_to_cert`. This requires agent 2.10.4 or later. See [Reconfiguring an Existing Agent](/tool-studio/moveworks-agent/moveworks-agent-configuration-guides/reconfiguring-an-existing-agent).
* **File:** edit `moveworks/conf/agent_config.yml`. Use the LDAP host name, not its IP address.

#### Single domain (LDAPS)

```yaml
ldap_config:
  host: ldaps.company.com
  port: 636
  service_user: COMPANY\svc_moveworks
  ldap_service_password:
    encrypted_value: <encrypted>
  use_ssl: true
  path_to_cert: /home/moveworks/agent/certs/ldap_cert.pem
```

#### Single domain (StartTLS)

```yaml
ldap_config:
  host: ldap.company.com
  port: 389
  service_user: COMPANY\svc_moveworks
  ldap_service_password:
    encrypted_value: <encrypted>
  use_start_tls: true
  path_to_cert: /home/moveworks/agent/certs/ldap_cert.pem
```

#### LDAP forest

Each domain has its own `path_to_cert`. Domains can share one file if the same CA signed their certificates.

```yaml
ldap_forest_config:
  primary.company.com:
    domain: primary.company.com
    host: dc-primary.company.com
    port: 636
    service_user: PRIMARY\svc_moveworks
    ldap_service_password:
      encrypted_value: <encrypted>
    use_ssl: true
    path_to_cert: /home/moveworks/agent/certs/primary-cert.pem
```

#### Public CA (no file)

```yaml
ldap_config:
  host: ldaps.company.com
  port: 636
  service_user: COMPANY\svc_moveworks
  ldap_service_password:
    encrypted_value: <encrypted>
  use_ssl: true
```

Then [restart the agent and check folder permissions](/tool-studio/moveworks-agent/moveworks-agent-configuration-guides/rotating-credentials-and-certificates#restart-the-agent-and-check-folder-permissions).

## Confirm it works

1. Check the logs: `sudo grep -hE 'x509|LDAP Result|cert path' moveworks/logs/*.INFO.log | tail -20`. No output means no certificate errors.
2. Test the service account against the server. See [Validating the LDAP Service Account](/tool-studio/moveworks-agent/moveworks-agent-troubleshooting#validating-the-ldap-service-account).

## Troubleshoot LDAP SSL certificate errors

A failed connection is usually logged as `LDAP Result Code 200 "Network Error"` followed by the underlying error:

| Error in the log                                              | Cause                                                                                                       | Fix                                                                                                                      |
| ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `x509: certificate signed by unknown authority`               | The file lacks a CA certificate in the chain, or isn't PEM.                                                 | Pull the full chain, and convert the file to PEM.                                                                        |
| `x509: certificate is valid for NMH-DC01.domain.com, not ...` | `host` isn't in the certificate's SAN, such as a load-balanced name on one domain controller's certificate. | Set `host` to a SAN name (see [Verify the certificate](#verify-the-certificate)), or get a certificate that includes it. |
| `x509: certificate has expired or is not yet valid`           | A certificate is outside its validity dates, or the host clock is wrong.                                    | Check with `openssl x509 -enddate -noout -in ldap_cert.pem` and `date -u`, then renew or replace.                        |
| `x509: certificate relies on legacy Common Name field`        | The server's certificate has no SAN.                                                                        | Request a certificate with a SAN.                                                                                        |
| `TLS cert path: open ...: no such file or directory`          | `path_to_cert` doesn't match a file in `moveworks/certs/`, or the folder isn't mounted.                     | Compare `sudo grep -n path_to_cert moveworks/conf/agent_config.yml` with `sudo ls moveworks/certs/`.                     |
| `TLS cert path: open ...: permission denied`                  | The agent can't read the file.                                                                              | `sudo chgrp 17540 <file> && sudo chmod 640 <file>`, then restart.                                                        |

> **Warning**
>
> `tls_skip_verify: true` under `ldap_config` hides these errors by turning off certificate verification. Don't use it in production.

For other certificate errors, see [Troubleshooting](/tool-studio/moveworks-agent/moveworks-agent-troubleshooting).