JIM LDAP Connector¶
Overview¶
The JIM LDAP Connector enables bi-directional synchronisation with LDAP-compliant directory services. It supports a wide range of directories and provides full lifecycle management of identity objects -- from importing existing data to provisioning new accounts and groups.
Capabilities: Full Import, Delta Import, Export
Supported Directories¶
| Directory | Notes |
|---|---|
| Microsoft Active Directory (AD DS) | Full support including USN-based delta import, userAccountControl, FILETIME dates, and binary attributes (objectGUID, objectSid) |
| Active Directory Lightweight Directory Services (AD LDS) | Full support with AD-specific features |
| OpenLDAP | Full support including parallel import, changelog-based delta import, and RFC 4512 schema discovery |
| Samba AD | Full support with Active Directory compatibility |
| Other RFC 4512-compliant directories (for example 389 Directory Server) | Supported via generic LDAP mode with automatic directory type detection |
JIM automatically detects the directory type during schema discovery by inspecting the Root DSE and adjusts its behaviour accordingly. No manual directory type configuration is required.
Features¶
Import¶
- Full Import
Reads all objects from selected partitions and object types. - Delta Import
Imports only changes since the last import run.- Active Directory
Uses USN (Update Sequence Number) change tracking. USNs are only meaningful when read back against the same domain controller that issued them, so JIM also records the domain controller's identity (its invocationId, falling back to its hostname where an invocationId is not available for comparison) and verifies it on every Delta Import before querying for changes. If the pinned domain controller changed since the last run, or was restored from backup, the Delta Import fails fast with an error naming what changed rather than silently skipping or re-importing changes. See Domain Controller Discovery and Pinning and Delta import fails with a domain controller mismatch error below. - OpenLDAP
Uses the accesslog overlay. - Generic directories
Uses a standard changelog (cn=changelog), where the directory provides one.
- Active Directory
- Parallel imports
Configurable concurrency for OpenLDAP and generic directories, allowing multiple containers and object types to be imported simultaneously. - Paged results
Automatic RFC 2696 Simple Paged Results support for large directories. - Configurable search timeout
Control how long to wait for LDAP search results.
Export¶
- Create, update, and delete
Operations on directory objects. - Configurable delete behaviour
Choose between deleting objects outright or disabling them (e.g. via userAccountControl for Active Directory). - Configurable concurrency
Parallel batch export support with 1-64 concurrent LDAP operations. - Batched multi-valued modifications
Large attribute changes (e.g. group membership) are automatically split into configurable batches to avoid exceeding directory server limits. - Container provisioning
Optionally create organisational units (OUs) on demand when provisioning objects to new locations. - Group placeholder members
Automatic handling of thegroupOfNamesMUST member constraint for OpenLDAP directories.
Schema Discovery¶
- Automatic RFC 4512 schema parsing
Object classes and attributes are discovered directly from the directory's subschema subentry. - Structural and auxiliary class support
Optionally include auxiliary classes in schema discovery. - Internal class classification
Classes the directory keeps for its own configuration or operation are marked internal, and the schema screen puts them out of the way. See Internal object types below. - Partition discovery
Automatically enumerates naming contexts and organisational units. - Hidden partition filtering
Skip Configuration, Schema, and DNS partitions for improved performance.
Security and Connectivity¶
- LDAPS (SSL/TLS)
Encrypted communication over port 636 (or custom port). - Certificate validation
Always on for LDAPS: the certificate chain, its validity period, and its name are all checked. Certificates added in Admin > Certificates are trusted in addition to the operating system's own trust store. - Authentication types
Simple bind or NTLM authentication. - Automatic retry
Configurable retry with exponential backoff for transient failures.
Directory Capabilities Card¶
The Connected System's Details tab shows a Directory Capabilities card with the facts JIM has detected about the target directory:
| Fact | Shown when |
|---|---|
| Directory Type | Always, once detected (Active Directory, Samba AD, OpenLDAP, or Generic) |
| Vendor | The directory reported one |
| DNS Host Name | The directory reported one |
| Paging | Always, once detected (Supported / Not Supported; Samba AD reports Not Supported, see Supported Directories) |
| Pinned Directory Server | A domain controller has been pinned |
| Invocation Id | JIM could read the pinned domain controller's invocationId |
These are read from data JIM already captured during a previous connection; viewing the card never opens a new connection to the directory. Before the first successful connection, the card shows a hint rather than an error. It is read-only: there is nothing here to configure.
Available to automation via GET /connected-systems/{id}/capabilities and Get-JIMConnectedSystemCapability -ConnectedSystemId <id>.
Connection Settings¶
Connectivity¶
| Setting | Description | Default | Example |
|---|---|---|---|
| Host | Hostname or IP address of the directory server. IP address is fastest. | (required) | dc01.corp.local |
| Preferred Domain Controller | Applies to Active Directory and Samba AD. A specific domain controller FQDN to always connect to. Use the Discover... action beside the field to list the forest's domain controllers rather than typing one blind; see Discovering Domain Controllers below. When left blank, JIM automatically discovers and pins the domain controller it reaches via Host; see Domain Controller Discovery and Pinning below. For LDAPS, use a name present in the domain controller's certificate. | (blank; auto-discover) | dc01.corp.local |
| Port | Port for the LDAP connection. Use 389 for LDAP or 636 for LDAPS. | 389 |
636 |
| Use Secure Connection (LDAPS)? | Enable LDAPS (SSL/TLS) for encrypted communication. Certificate validation is always applied; see Certificate validation. | false |
true |
| Connection Timeout | Time in seconds to wait before giving up on a connection attempt. | 10 |
30 |
Discovering Domain Controllers¶
Administrators often do not know which domain controller to enter in Preferred Domain Controller. Rather than typing a hostname blind, use the Discover... action beside the field on the Connected System's settings page: it lists every domain controller in the forest, with the Active Directory Site each belongs to, and clicking one fills the field with your choice.
Discovery only ever informs; it never writes to the setting on its own. Preferred Domain Controller remains ordinary free text throughout, and nothing changes until you click a discovered server (or type a value yourself) and save the Connected System's settings.
The action is enabled once the connectivity settings above (Host, Port, Username, Password) are filled in; you do not need to have saved them first, so a system can be configured and its domain controllers discovered in one sitting. Discovery is only supported for Active Directory and Samba AD; for OpenLDAP or Generic directories, which have no concept of Sites, the dialog reports that discovery is not supported and you can simply type a hostname instead. Discovery works by querying the forest's CN=Sites,CN=Configuration hierarchy, so it uses the same credentials already configured for this Connected System and needs no extra directory permissions or DNS lookups. If the directory cannot be reached, or the credentials are refused, the dialog shows the failure with a Retry action rather than crashing the page.
The same discovery is available beyond the portal:
See Get-JIMConnectedSystemDirectoryServer in the PowerShell reference.
Domain Controller Discovery and Pinning¶
For Active Directory and Samba AD, JIM connects to a single, consistent domain controller rather than reconnecting via whatever the Host setting happens to resolve to each time. This matters for two reasons:
- Replication consistency. If Host is a domain name that DNS round-robins across multiple domain controllers, an export could write to one domain controller while the confirming import reads from another before replication catches up, making confirmed objects appear temporarily missing.
- Delta import correctness. USNs are scoped to the domain controller that issued them, so a Delta Import against a different domain controller than the one that produced the persisted watermark can silently skip or re-import changes. See Delta import fails with a domain controller mismatch error below.
How it works: leave Preferred Domain Controller blank and JIM auto-discovers. On the first connection, JIM connects via Host, reads the domain controller it reached from the directory's rootDSE, and pins every subsequent connection, within a run and across Run Profile executions, to that same domain controller (by FQDN, not IP; this also keeps LDAPS certificate name validation working, since the pinned name is the one the certificate's SAN needs to match). Setting Preferred Domain Controller to a specific FQDN always takes priority over any pin.
If the discovered domain controller cannot be reached by name: JIM does not pin it. Before pinning a domain controller it has just discovered, JIM opens a throwaway connection to that name to prove it works; a directory's advertised name is not guaranteed to resolve from wherever JIM runs, which happens with split-horizon DNS, with a directory reached through an alias or an address, and in DMZ deployments. Where the check fails, the run continues on the connection that already works (Host, or Preferred Domain Controller), nothing is pinned, and the Activity carries a warning naming the domain controller JIM could not reach. Nothing breaks, but Delta Imports do not get the domain controller affinity a pin buys them, so it is worth fixing: either make the name resolve from the JIM host, or set Preferred Domain Controller to a name that does. The check costs one connection, and only when the name being considered is not the one JIM is already connected through, so an established pin re-affirms itself for free on every run.
If the pinned domain controller becomes unavailable: the Run Profile execution fails outright rather than silently failing over mid-run, and the pin is cleared. The next Run Profile execution resolves via Host again, discovers whichever domain controller answers, and re-pins to it. Because that may be a different domain controller than before, a Full Import is needed to re-establish the Delta Import baseline; see Delta import fails with a domain controller mismatch error.
Pinning only applies to Active Directory and Samba AD; OpenLDAP and other generic directories are unaffected.
Multi-domain forests¶
A Connected System manages one domain today. During Partition discovery on Active Directory or Samba AD, JIM lists every domain in the forest, because that is what the directory's crossRef objects expose; it has no way to tell from that list alone which domains the connected domain controller actually holds. A domain controller only ever holds its own domain's naming context and does not chase referrals to serve objects from another domain in the forest.
If you select a Partition for a domain the connected domain controller does not host, the import fails fast with an error naming the Partition and the domain controller, rather than silently returning zero objects. To manage more than one domain, create a separate Connected System per domain, each with its Host setting pointing at that domain's own domain controllers.
Referrals¶
JIM does not follow LDAP referrals. A referral is the directory's way of saying "the objects you asked for live on another server"; JIM ignores it and works only with what the connected server returns directly.
This is deliberate. The platform LDAP client will follow a referral, but it does so on a new connection that carries none of the credentials JIM bound with, making the follow-up read anonymous. Active Directory refuses anonymous reads by default, so a chased referral fails, and it fails against the original search rather than against the referral. The result is an access-denied error on a connection that is authenticated and healthy, which is a considerably worse outcome than not following the referral at all.
In practice this affects Partition discovery on Active Directory and Samba AD, where the search for the forest's domain list can return referrals alongside its results. JIM takes the results and discards the referrals.
What to do instead: connect a Connected System to each directory server whose objects you need, as described under Multi-domain forests above. If a server has no network path from the JIM host and is only reachable by referral from a server that does, JIM cannot manage its objects today; following referrals with JIM's own credentials, so that the follow-up read is authenticated and every server followed is recorded, is planned.
Container Scope¶
Each selected Container carries a scope, set with the two-segment control on its row in the Container tree on the Connected System's Partitions & Containers tab:
| Scope | What is imported | Containers beneath it |
|---|---|---|
| Whole subtree (default) | Objects in the Container and in every Container beneath it. | Covered automatically; they cannot be selected separately, and each says which Container covers it. |
| This level | Objects held directly in the Container. | Not imported. Each can be selected in its own right, with its own scope. |
Whole subtree is the default and is how Container selection has always behaved, so existing Connected Systems are unaffected.
This level is for directories where a branch holds a mixture you do not want wholesale. Selecting OU=Corp with This level, then selecting OU=Sales,OU=Corp with Whole subtree, imports the users sitting directly in OU=Corp and everything under OU=Sales, while leaving the rest of OU=Corp's sub-OUs alone.
Containers are listed by their own name rather than by their full Distinguished Name, which is shown on hover. Use the filter above the tree to find a Container in a large directory; it matches both the name and the Distinguished Name, so a Distinguished Name pasted from elsewhere finds its Container. A hierarchy of more than a couple of dozen Containers opens only as far as its current selections, so what the system imports is visible without scrolling through everything it does not.
Narrowing a Container takes objects out of scope
Changing a Container from Whole subtree to This level stops the objects beneath it being imported. JIM asks you to acknowledge this before saving, because the Connected System Objects already imported from those Containers become obsolete on the next Import Run Profile, and whatever they are joined to is deprovisioned on the next synchronisation. Re-selecting the Containers you still want, before running an import, avoids that.
Scope is also settable from the REST API (PUT /api/v1/synchronisation/connected-systems/{id}/containers/{containerId}) and from PowerShell with Set-JIMConnectedSystemContainer -Scope.
Objects that reference something out of scope
A reference attribute pointing at an object outside the imported Containers cannot be resolved, and JIM reports it as an unresolved reference naming Container Scope as the likely cause. Narrowing a Container is a common way to create these; if a group's members live in a Container you have just excluded, either bring that Container back into scope or expect the membership to import incompletely.
Excluding a Container¶
Service Account, mailbox-archive and staging OUs sitting inside an otherwise wholly-managed branch are the ordinary shape of a production directory. Exclude carves one of those out of a selection made above it: select OU=Corp as a whole subtree, then exclude OU=Service Accounts,OU=Corp, and JIM imports everything in OU=Corp except that branch.
The action appears on a Container's row in the tree wherever a selection above already reaches it, which is exactly where an exclusion means anything. An excluded Container reads Excluded from X, naming the selection it was carved out of, and offers Include to hand it back. Containers beneath it read Excluded by X and are left unimported too.
Whichever statement is nearest to an object decides its fate. That is what makes re-inclusion work: tick a Container inside an excluded branch and it comes back into scope, along with everything beneath it, while the rest of the exclusion stands. Exclusions and re-inclusions nest to any depth.
Excluding is not the same as selecting the siblings you want. Ticking eleven of twelve sibling OUs looks equivalent, and is silently wrong over time: an OU created under the parent afterwards is not in the enumerated set, so its objects are never imported and nothing says so. An exclusion has the opposite and safer failure mode, because the parent is what was selected: a new OU beneath it is imported.
Excluding a Container takes objects out of scope
Objects already imported from an excluded branch become obsolete on the next Import Run Profile, and whatever they are joined to is deprovisioned on the next synchronisation, exactly as narrowing a Container does. Preview the change before saving.
An exclusion is honoured everywhere the selection is: on Full Import, on the delta paths, and on export, where a write into an excluded branch is refused for the same reason it is refused outside the selected Containers entirely.
It is enforced as entries arrive rather than by searching around the branch, so an exclusion inside a selected branch costs a transfer that produces nothing. That cost is reported rather than hidden. An import that discarded entries carries an Entries Discarded by Container Scope panel on its Activity, breaking the figure down per excluded Container, and the same counts are in the run's log. A branch of 500,000 objects carved out of a 510,000-object parent then shows up as a number you can act on, by moving the excluded branch outside the selected one, rather than as an unexplained slow import.
Why not just search around the excluded branch?
JIM could replace one subtree search with a search per sibling and skip the excluded one, and it deliberately does not. The set of siblings comes from the last Retrieve Hierarchy, so a Container created since would be missing from it: its objects would never be searched, never imported, and marked obsolete on the next Full Import. Import scope must not depend on how recently the hierarchy was refreshed, so the transfer cost is accepted and reported instead.
An exclusion survives a rename or a move of the Container, because it is keyed on the directory's own immutable identifier (objectGUID on Active Directory, entryUUID on OpenLDAP) rather than on the Distinguished Name.
A Container can be selected or excluded, never both. An exclusion beneath a This level selection is inert, since such a selection reaches no Container beneath it, and the tree therefore never offers one there.
Exclusions are settable from the REST API (PUT /api/v1/synchronisation/connected-systems/{id}/containers/{containerId} with excluded) and from PowerShell with Set-JIMConnectedSystemContainer -Excluded, and previewable before they are made with excludedContainerIds on the scope-selection preview endpoint or New-JIMConfigurationChangePreview -ExcludedContainerIds.
A whole scope of selections and exclusions can also be stated at once as text, which is how a directory with hundreds of Containers is practically managed:
include OU=Corp,DC=example,DC=com
exclude OU=Service Accounts,OU=Corp,DC=example,DC=com
include OU=App1,OU=Service Accounts,OU=Corp,DC=example,DC=com
See Stating Container Scope as text for the full syntax, the portal's Advanced mode, and the Get- and Set-JIMConnectedSystemContainerScopeText cmdlets.
Credentials¶
| Setting | Description | Example |
|---|---|---|
| Username | Service account username for connecting to the directory. | corp\svc-jim-ldap |
| Password | Service account password (stored encrypted). | (encrypted) |
| Authentication Type | Type of authentication: Simple or NTLM. | Simple |
Import Settings¶
| Setting | Description | Default |
|---|---|---|
| Search Timeout | Maximum time in seconds to wait for LDAP search results. | 300 (5 minutes) |
| Import Concurrency | Number of parallel LDAP connections for OpenLDAP/generic directory imports. Each connection handles one container and object type combination independently. Not used for Active Directory. | 4 |
Retry Settings¶
| Setting | Description | Default |
|---|---|---|
| Maximum Retries | Maximum retry attempts for transient failures. | 3 |
| Retry Delay (ms) | Initial delay between retries in milliseconds. Uses exponential backoff. | 1000 |
Schema Discovery¶
| Setting | Description | Default |
|---|---|---|
| Include Auxiliary Classes | Include auxiliary object classes alongside structural classes during schema discovery. | false |
Internal object types¶
A directory publishes its own machinery in the same schema as the classes you manage. A stock OpenLDAP returns 67 structural classes, of which 27 belong to the server rather than to your directory: the cn=config backend's olc* classes, the accesslog overlay's audit* classes, and the root DSE class.
The Connector marks those Object Types internal, and the Schema tab hides them, telling you how many it is holding back and offering Show internal object types to see them. Nothing is discarded: every class is still discovered, still stored, and still selectable. An Object Type you have already selected is never hidden, whatever its classification.
The judgement is made from the class's OID rather than its name, because an OID arc is assigned to its vendor and does not change. Classes carrying the RFC 4512 OBSOLETE flag are treated the same way, since that is the directory itself declaring them superseded. Classes from the X.500, COSINE and Internet standards arcs, and any schema extensions published under your own organisation's arc, are never marked internal.
Active Directory needs none of this: the Connector already asks the directory to exclude its own hidden and defunct classes when it enumerates them, so what you see is already the classes an administrator manages.
Automation sees the same default. Get-JIMConnectedSystemObjectType omits internal Object Types unless you pass -IncludeInternal. The REST API always returns every Object Type, each carrying the classification tags the Connector reported and an isInternal flag derived from them, so a caller can decide for itself.
Hierarchy¶
| Setting | Description | Default |
|---|---|---|
| Skip Hidden Partitions | Skip Configuration, Schema, and DNS zone partitions when refreshing the hierarchy. Improves performance significantly. | true |
| Create Containers as Needed | Automatically create OUs when provisioning objects to locations that do not yet exist. | false |
Export Settings¶
| Setting | Description | Default |
|---|---|---|
| Delete Behaviour | How to handle object deletions: Delete (remove the object) or Disable (set the disable attribute). | Delete |
| Disable Attribute | Attribute to set when disabling objects. Only shown, and required, when Delete Behaviour is Disable. | userAccountControl |
| Export Concurrency | Maximum number of concurrent LDAP operations during export. Recommended range: 2--8. | 4 |
| Modify Batch Size | Maximum number of values per multi-valued attribute modification in a single LDAP request. Lower values improve compatibility; higher values improve throughput, especially for very large groups. Recommended range: 100--2000. | 1000 |
| Group Placeholder Member DN | Placeholder DN used for group classes that require at least one member (e.g. groupOfNames). Automatically filtered during import. Only applies to non-AD directories. | cn=placeholder |
Directory Tuning for Large Groups (OpenLDAP)¶
When provisioning groups with very large memberships (tens of thousands of members and up) to OpenLDAP, the directory's own write path becomes the bottleneck: each membership modification makes slapd duplicate-check the new values against every existing value with a linear scan, so the cost of appending members grows with the group's current size.
OpenLDAP's sortvals directive addresses this by storing the values of the listed attributes in sorted order, turning the duplicate check into a binary search:
# slapd.conf
sortvals member
# or cn=config (on the frontend database entry)
dn: olcDatabase={-1}frontend,cn=config
changetype: modify
add: olcSortVals
olcSortVals: member
JIM's own large-scale integration testing (up to 500,000 users, with individual groups of up to 495,000 members) runs OpenLDAP with sortvals member enabled, and we recommend it for any deployment where large group memberships are provisioned. Note that sortvals only affects entries written after it is enabled; enable it before loading data, or reload existing data (slapcat/slapadd) afterwards. See the OpenLDAP tuning guide and the slapd.conf(5) man page for details.
Security Considerations¶
Use LDAPS¶
LDAP traffic is unencrypted by default. In production environments, always enable LDAPS (SSL/TLS) to protect credentials and identity data in transit. Set the port to 636 and enable the "Use Secure Connection (LDAPS)?" setting.
Certificate validation¶
When LDAPS is enabled, JIM validates the certificate the directory server presents. Three things are checked, and any one of them failing stops the connection before the service account's credentials are sent:
- Chain
The certificate must chain to an issuer JIM trusts: either one in the operating system's trust store, or one added in Admin > Certificates. - Validity period
An expired or not-yet-valid certificate is rejected, including when its issuer is one you added yourself. - Name
The certificate must have been issued for the value in the Host setting. A certificate fordc01.corp.localis not accepted when JIM connects to10.0.0.5, or todc01.
There is no per Connected System option to relax any of this.
Trusting an internal certificate authority, or a self-signed certificate¶
The quickest route is the certificate JIM already shows you. When an LDAPS connection is refused because JIM does not trust the issuer, the certificate card carries a Trust this certificate action. JIM reads the certificate from the directory server again, checks it is still the one you were shown, and adds it to the Trusted Certificates store. There is nothing to obtain, export or upload.
You are asked to confirm first, because this is a security decision: compare the thumbprint against the one the directory's administrator gives you. Where the server sent the authority that issued its certificate, JIM offers that as well and recommends it, because trusting the authority survives the server's certificate being renewed. A self-signed certificate has no separate authority, so there is only one thing to trust.
Reading the certificate again at the moment you confirm is what makes a change detectable. If the server is presenting something other than what you were shown, JIM trusts nothing and shows you both thumbprints; expected after a renewal, worth investigating otherwise.
Fetch certificate on the Connected System's settings does the same reading before anything has failed, so setting a new system up does not mean saving, failing and coming back. Fetching stores nothing.
You can still upload a certificate by hand via Admin > Certificates, which is the route to take when the directory is not reachable from JIM at the time you are configuring it. Both kinds work:
- An internal certificate authority
Upload the CA (and any intermediates). Every directory server whose certificate it issued is then trusted. - The directory server's own self-signed certificate
Upload the server certificate itself. Only that certificate is then trusted, which is the tighter option where a directory has no certificate authority behind it.
Certificates added this way are trusted in addition to the operating system's trust store, so adding one never stops a publicly-issued or already-trusted certificate from working.
To do the same from a script:
$reading = Get-JIMConnectedSystemServerCertificate -ConnectedSystemId 42
$reading.certificate | Select-Object subject, issuer, thumbprint, issuerThumbprint
Approve-JIMConnectedSystemServerCertificate -ConnectedSystemId 42 `
-Thumbprint $reading.certificate.issuerThumbprint `
-ChangeReason 'Trusting the corporate issuing CA.'
When the certificate name does not match the host you connect to¶
This is the common obstacle: a certificate issued for a fully-qualified name, in an environment where JIM cannot resolve that name, so the Host setting holds an IP address instead. Uploading the certificate does not help, because the name still does not match.
Rather than weakening validation, give JIM's containers a way to resolve the name. In Docker Compose, add a host entry to the jim.web and jim.worker services:
Set the Host setting to dc01.corp.local. The name now resolves inside the container, the certificate matches, and the connection is fully validated. This works when DNS is unavailable or unreliable, because the mapping is static and needs no name server. The alternative is to have the certificate reissued with the name (or IP address) you actually connect to.
Disabling validation entirely
OpenLDAP's own LDAPTLS_REQCERT=never environment variable is honoured by the LDAP client library JIM's containers use, and switches certificate validation off. It applies to the whole container, so it affects every LDAPS Connected System that container serves, and it cannot be scoped to one directory. JIM's development and integration test stacks do not set it: they trust each throw-away directory's own CA through the JIM certificate store instead, so LDAPS validation is exercised for real rather than bypassed. Never set this variable in production: it exposes the service account's credentials to anyone able to intercept the connection.
Setting Passwords¶
Credential attributes such as unicodePwd and userPassword are never imported and can never be used in an Attribute Flow; see Credential attributes are never managed for the full list and the reasoning. The LDAP Connector writes passwords itself, on a separate channel (Passwords covers that channel across all Connectors), with two rules specific to directories.
Use LDAPS. A password set puts the password on the wire, so an unencrypted connection exposes it to anyone on the network path. JIM will not stop you: if "Use Secure Connection (LDAPS)?" is off, passwords are still set and a warning is written to the service log on every run, because some deployments genuinely cannot offer TLS on their directory and locking them out of password management entirely helps nobody. It is your decision, and enabling LDAPS is strongly recommended.
Active Directory decides for itself regardless. It refuses a password write unless the connection is encrypted or the bind is signed and sealed, so in practice LDAPS is required there; JIM reports that refusal with encryption named as the likely fix.
Directories other than Active Directory use the standard extended operation. JIM sets passwords through the LDAP Password Modify extended operation (RFC 3062) and never writes the userPassword attribute directly. Directories apply their configured password hashing to the extended operation, but store a directly written userPassword value exactly as supplied, which would leave the password readable in the directory. If a directory does not advertise support for the extended operation, JIM reports a configuration fault rather than falling back to an unsafe write.
Active Directory and Samba AD use unicodePwd, which the Connector encodes correctly on your behalf.
Check the channel before relying on it. The Connected System's Schema tab carries a Password Channel panel with a read-only preflight covering the things that commonly stop a password set: encryption, the mechanism, whether the service account may actually reset passwords where JIM provisions, and whether the domain password policy could be read. It writes nothing, so it is safe to run against production. See Password policy and the password channel.
There is no way to prove the whole chain without really setting a password somewhere, and JIM does not offer one: every route to it is a password reset against a real account. The preflight covers what surrounds the password, which is where most failures are.
Service Account Permissions¶
The LDAP service account used by JIM should follow the principle of least privilege:
- For import only
Grant read access to the containers and attributes that JIM needs to import. - For export (provisioning)
Grant create, modify, and delete permissions on the target containers. For Active Directory, this typically means delegated control over the relevant OUs. - For container provisioning
If "Create Containers as Needed" is enabled, the service account must have permission to create organisational units. - For delta import
The service account needs read access to the directory's change tracking mechanism (USN attributes for AD, accesslog for OpenLDAP). - For setting passwords
Grant the Reset Password permission on the containers JIM manages. In Active Directory this is a control access right, delegated on the OU (Delegate Control, "Reset user passwords and force password change at next logon"), and it is a separate thing from write access to attributes: an account with full write permission on an OU still cannot set a password without it. The service account does not need to be a Domain Admin, and should not be. - For checking reset rights
To answer the reset-rights preflight rather than reporting that it could not tell, the service account also needs read access to thenTSecurityDescriptorattribute of accounts in those containers. Reading an object's permissions is normally covered by ordinary read access; where it is not, the check reports an unknown rather than a denial. - For discovering Fine-Grained Password Policies
Detecting whether any exist requires read access to the domain's Password Settings Container (CN=Password Settings Container,CN=System,<domain DN>), which by default is restricted to Domain Admins. Without it JIM reports that it could not tell, and treats the domain policy it read as a floor. Granting read on that container is optional; it buys a definite answer in the Password Channel panel and nothing else.
Dedicated service account
Always use a dedicated service account for JIM rather than sharing credentials with other applications or using a personal account. This simplifies auditing and ensures that permission changes do not inadvertently affect JIM's operations.
Network Considerations¶
- Ensure firewall rules allow traffic from the JIM container to the directory server on the configured port (389 or 636).
- If JIM is running in a container, the directory server must be reachable from the container network. When using Docker Compose, this may require configuring the network mode or adding the directory server to the container's DNS resolution.
- For Active Directory environments, JIM connects to a single domain controller. Consider using a domain controller in the same network segment as JIM to minimise latency.
Troubleshooting¶
Connection failures¶
If JIM cannot connect to the directory server:
- Verify the hostname or IP address is correct and reachable from the JIM container (
pingornslookupfrom within the container). - Check that the port is correct (389 for LDAP, 636 for LDAPS) and not blocked by a firewall.
- Increase the Connection Timeout if the directory server is slow to respond.
LDAPS failures show you the certificate
The LDAP client library reports a rejected certificate the same way it reports an unreachable server, so its own message ("The LDAP server is unavailable") tells you nothing. JIM therefore looks at the certificate itself when an LDAPS connection fails, and shows it to you: its subject, the names it was issued for, its issuer, its validity dates and its thumbprint, alongside which check it failed and what to do about it.
You will see it in two places: on the Connected System's settings when you test the connection, and on the failed Activity when a Run Profile could not connect. The same detail is available to automation on the Activity's errorDetail field in the REST API. If the connection failed for a reason that is nothing to do with the certificate, the original error stands unchanged.
Authentication failures¶
If authentication fails with "invalid credentials":
- Verify the username format matches the authentication type. For Simple bind, use a full DN (e.g.
CN=svc-jim,OU=Service Accounts,DC=corp,DC=local) or UPN (e.g.svc-jim@corp.local). For NTLM, useDOMAIN\usernameformat. - Check that the service account password is correct and has not expired.
- Ensure the service account is not locked out or disabled.
Delta import not detecting changes¶
If delta imports return no changes when changes are expected:
- Active Directory: verify that the service account has read access to the
uSNChangedattribute. - OpenLDAP: verify that the accesslog overlay is configured and the changelog database is accessible.
- Run a full import to re-baseline, then test delta import again.
Delta import fails with a domain controller mismatch error¶
Active Directory and Samba AD Delta Imports check that they are still talking to the same domain controller that produced the persisted USN watermark, and fail fast with an error naming the previous and current domain controller (or their invocationId) if not. This is expected, protective behaviour, not a bug: a USN watermark from one domain controller is meaningless against another, and continuing regardless risks silently skipping or re-importing changes.
With domain controller discovery and pinning in place, the most common cause is the previously pinned domain controller having become unreachable: JIM already cleared the pin and failed that run outright, and the following run resolved via Host, discovered a different domain controller, and re-pinned to it. The other cause is the domain controller having been restored from backup, which is issued a new invocationId even though its hostname is unchanged.
- No action is usually needed beyond running a Full Import: JIM has already re-pinned automatically.
- If you need consistent affinity to one specific domain controller regardless of availability, set Preferred Domain Controller rather than relying on auto-discovery.
- Run a Full Import to re-establish the delta baseline against whichever domain controller JIM connects to next; subsequent Delta Imports then succeed as long as that domain controller keeps answering.
Export failures¶
If exports fail with LDAP errors:
- Check the activity log for the specific LDAP error code and message.
- For "insufficient access rights" errors, verify the service account has write permissions on the target container.
- For "constraint violation" errors on multi-valued attributes, try reducing the Modify Batch Size setting.
- For group membership operations, ensure the Group Placeholder Member DN setting is appropriate for your directory.