LDAP / Active Directory
One connector class serves two shapes of directory over LDAPv3: Active Directory, and generic LDAP — OpenLDAP, 389-DS, ApacheDS, eDirectory. They share the transport and diverge on schema; the AD-only parts below are marked.
It is the connector partners implement first, and the one that touches accounts most destructively — it creates them, moves them between containers, and at the end of a leaver's grace window deletes them outright. So this page is less a feature list than an account of what it does to your directory, and where it deliberately stops.
Two templates, one engine
The catalogue ships the directory twice; the choice seeds a different schema and a different default posture:
| Active Directory | Generic LDAP | |
|---|---|---|
| Vendor key | active_directory |
ldap |
| Engine template | active_directory |
openldap |
| Default role | Target | Bidirectional |
| User class | user (person objects) |
inetOrgPerson |
| Group class | group |
groupOfNames |
| Login attribute | sAMAccountName |
uid |
| Stable object id | objectGUID |
DN |
| Account status | userAccountControl bit 0x2 |
no standard attribute |
| Account types shipped | three (below) | none |
AD defaults to Target because identities are normally HR-authoritative and the directory holds accounts that correlate to them; a small LDAP directory is as often the source of record, so the generic template defaults to bidirectional. Both are overridable. The last three rows matter most: generic LDAP has no standard status attribute, so enable and disable are unavailable there, and no rename-stable identifier, so a rename presents to reconciliation as a new object.
Authentication, and where the connector runs
Simple bind with a bind DN and password, over LDAPS. That is the whole list; both templates advertise exactly one method. An earlier version of this page offered "simple-bind or GSSAPI", which was wrong rather than out of date: SASL/GSSAPI binding — Kerberos, NTLM — is not implemented, and a directory requiring it cannot be bound to today. Plain LDAP on port 389 works and is for lab use only. The per-connector TLS options documented elsewhere (a tenant trusted-CA store, a skip-verify flag) apply to the HTTP engines, not to this one: LDAP certificate trust is whatever the machine running the connector already trusts.
That machine is normally the agent. An on-premises directory is by definition unreachable from a SaaS control plane, so agent mode is the normal posture — the connector runs inside your network on the tier-3 agent, and the bind credential is resolved from the agent's own encrypted store rather than travelling from the control plane.
Tunnel mode is impossible for LDAP, and the platform refuses it rather than degrading. Tunnelling bridges HTTP calls through the agent; LDAP is raw TCP with no HTTP layer to intercept, so there is nothing to bridge. Configuring it fails loudly when the engine is built, instead of falling back to a control-plane socket that would never reach the directory. The same refusal covers the other raw-socket engines (SQL, SFTP, SMB). In-process execution remains available for a lab directory the control plane can reach; the write primitives, the wizard's per-object test and the connectivity probe all travel over the agent protocol, so agent mode is not a reduced feature set.
Finding your domain: rootDSE base-DN detection
A directory template must ship some search base, and the placeholder is
inevitably wrong — CN=Users,DC=corp,DC=local is nobody's actual domain. A new
connector's first act is then to return zero records, which reads as breakage
rather than as an unedited default.
So the connectivity probe asks the server where it lives. Every LDAP server
publishes its naming contexts in the rootDSE, readable with a base-scope
search on the empty DN, and defaultNamingContext is the domain root. The wizard
re-homes each search base onto that domain while preserving the leaf container:
CN=Users,DC=corp,DC=local against a discovered root of DC=rapidvalue,DC=demo
becomes CN=Users,DC=rapidvalue,DC=demo.
Three properties make this safe to have on by default:
It rides the existing probe rather than being a separate call. The read happens on the connection the health check already opened and bound, and the naming contexts return on the existing connectivity result — no new connector method, no second round trip, and the agent path stays symmetrical with the in-process one.
It is best-effort and never downgrades a healthy bind. If the read fails — an unusual server, a bind too restricted to perform it — the failure is swallowed and the successful bind stands: connectivity reports healthy with no naming contexts, and the bases stay as they were. A discovery convenience is not allowed to make a working directory look broken.
It only rewrites a base still equal to the pristine template default. The
wizard rebuilds the vendor template, collects the base DNs it would have
produced, and rewrites only those; a base an administrator has edited is never
touched, and a one-shot flag stops a re-entered step rewriting twice. A DN with no
DC= components — ou=people,o=acme, a directory that was never AD-shaped — is
returned unchanged, because there is no domain suffix to swap.
Referrals are never chased
A subtree search against a real AD naming context routinely returns referrals — pointers to other domain controllers holding subordinate parts of the tree. Most LDAP client libraries, including this one's, follow them by default. From this position that is almost always wrong: the referral target is typically a host the agent cannot resolve or reach, so the follow-up connection fails and takes the whole search down with it.
The resulting failure is why this is called out rather than quietly configured.
Referral chasing fails with an invalid server address socket error — and it
fails only on searches. The health check binds and reads the rootDSE without a
subtree search, so it stays green. You get a connector reporting a healthy
connection, valid credentials and a reachable server, while every user and group
read fails with what looks like a network problem on a server you can plainly see
is up.
So referral chasing is disabled unconditionally: the connector only reads entries beneath the search bases it was given, and following a referral is never wanted.
Binary attributes must leave the connector JSON-safe
AD returns objectGUID and objectSid — and any schema extension declared binary
— as raw bytes. Two things break on that.
The first is transport: in agent mode the read result is posted to the control
plane as JSON, and raw bytes are not serialisable. The task dies mid-transfer, so
the sync sits at 0 read instead of reporting a clear failure.
The second makes this a correctness concern rather than a formatting one. On
Active Directory objectGUID is the account's external id — the rename-stable
anchor tying a directory object to the account row that governs it. Stringifying
raw bytes with a language default yields a representation of the byte buffer, not
the identifier: unstable, and nothing like what an administrator sees in a
directory tool. Every sync would mint new accounts and orphan the previous ones.
So values are normalised at the search boundary — objectGUID to a canonical GUID
string (decoded little-endian, as AD stores it), objectSid to a canonical
S-1-5-… string, any other binary value to base64. This covers the raw attribute
dictionary as well as the derived identifier, so no byte value reaches the control
plane by any route, in either execution mode.
One limit, because the format invites the assumption: objectSid is formatted,
not resolved. The connector renders the SID; it does not look up the principal it
names. A SID in a read is a SID, not an account name.
Reading the directory
Each object can carry several search bases with their own filters, so a directory whose users live under three OUs does not need three connectors; results are unioned, de-duplicated and paged. A failure on any one path aborts the whole read, naming the offending base DN — a partial union is never presented as success, because a mistyped OU that silently returned nothing would look like a population that had simply shrunk, and reconciliation treats a missing account as a removed one.
⚠ Nested groups are not expanded
Membership is read from the direct
memberattribute. The connector performs no transitive membership search, and contributes no group-in-group relationships to the platform's transitive-access model — that path is implemented for Entra ID, not for LDAP. A group nested inside another is read as a member of it, not as a route to that group's members.The in-product object description mentions a
nested_groupstoggle for the AD in-chain matching rule. That option is not implemented; setting it has no effect. It is named here rather than removed quietly, because finding it in a configuration file and expecting it to work is precisely the discovery this portal exists to prevent.
What the connector writes
| Operation | Active Directory | Generic LDAP |
|---|---|---|
| Create account | ADD under the account type's write-home OU | ADD under the write-home OU |
| Update attributes | MODIFY (replace) | MODIFY (replace) |
| Enable / disable | userAccountControl bit flip |
not available |
| Grant group membership | add member | add member |
| Revoke group membership | remove member | remove member |
| Move to another OU | MODRDN | MODRDN |
| Delete account | DELETE | DELETE |
Enable and disable are AD-only, and the connector says so rather than pretending:
on a generic directory both return an explicit failure naming the missing
userAccountControl attribute.
On create, the connector owns the structural attributes — object classes, the CN
that forms the DN, the initial userAccountControl — while your provisioning
mappings supply everything else and win over the connector's own defaults for the
same attribute. The division stops a mapping fighting the DN placement or the
status bit-math. See Provisioning Mappings, and
Read/Write Parity for what happens when the write path
and the correlation rules drift apart.
Each account type gets its own creation OU
Directories separate account kinds by container: ordinary users in one place, administrative accounts in another, service accounts in a third. A connector with a single creation base would drop every new account into the same OU regardless of what it is. So the creation OU belongs to the account type, not to the connector: when provisioning routes a new account onto a type — a decision the access model has already made — that type's write-home is handed to the connector, which creates the object beneath it. A type with no write-home falls back to the connector's first users search base, so directories that never set one are unaffected.
Three account types ship for Active Directory:
| Type | Purpose class | Created under | Identified by |
|---|---|---|---|
| Personal accounts | personal | CN=Users |
everything not matched below |
| Privileged admin accounts | administrative | OU=Admins |
login-name prefixes adm-, adm_, a-, admin-, da- |
| Service accounts (NHI) | service | OU=ServiceAccounts |
login-name prefixes svc-, svc_, service-, sa-, srv- |
All three are enabled by default, and each OU leaf is combined with your real
domain suffix at onboarding, so OU=Admins becomes
OU=Admins,DC=yourdomain,DC=example. The prefixes are conventions, not standards,
and every rule here is editable per system.
Personal is deliberately the catch-all — no filter of its own, taking whatever
the admin and service rules do not claim. A directory naming its admin accounts
ops.jdoe therefore classifies them as personal until you say otherwise, which is
visible and correctable, where a personal type with its own restrictive filter
would leave them matching nothing at all. Service accounts are typed as non-human
identities, which puts them on a different lifecycle: a longer dormancy threshold
and NHI ownership review rather than a manager. Admin and service ship without
an ownership rule, because such an account shares its human owner but not that
human's email address — the email correlation that works for personal accounts
would silently fail, and a blank to configure beats a rule that cannot match. See
Account Types and Account Rules. The
generic template ships no account types; conventions outside AD are too varied
to guess.
The leaver sequence
1. Move. When a terminated identity's account is being disabled, the connector first re-parents it into that account type's configured leaver OU — an MODRDN keeping the relative name and changing only the parent, so the account keeps its name and moves house. Every part is gated: only when the owning identity is terminated, only when the engine can move accounts, only when a leaver OU is configured for the type. It is idempotent, and best-effort — a failed move is logged and the flow continues to the disable. A successful move is audited.
The terminated-only guard matters more than it looks. An emergency lockout also disables accounts, but a lockout is a reversible security override; moving that account would leave it in the wrong container when the lockout is lifted. Only the permanent leaver path moves anything.
2. Disable. The userAccountControl disable bit is set. On a generic directory
this step is unavailable and the account stays enabled in place until the delete
window elapses — a real gap, and a reason to prefer AD for the full leaver flow.
3. Delete — only after a grace window, and only if you asked for one. A daily sweep looks at accounts that are disabled, whose owning identity is terminated, and which record when they were disabled. It resolves a retention window from the account type, falling back to the tenant lifecycle default. If no window is configured, nothing is deleted — the account stays disabled indefinitely, which is the default posture. Where a window is configured and has elapsed, the account is deleted in the directory and the platform's own account row moves to pending delete: the row is kept, so the audit trail survives the removal of the object it describes.
⚠ A deliberate, narrow exception to a platform-wide rule
RapidValue does not hard-delete governed objects. Dormant-access remediation soft-revokes; identity erasure pseudonymises; audit rows are immutable at the database level. Directory account deletion is the one place that rule is broken, and it is broken because a directory accumulating every leaver's account forever is itself a governance failure.
So it is fenced. It applies only to accounts whose identity is terminated. It requires a retention window to be configured — off unless set. It runs only once that window has elapsed, measured from the disable timestamp. It is audited. And it applies only to connectors that declare the capability: an engine with no real delete primitive marks the account pending-delete and removes nothing, rather than reporting a deletion that never occurred. If the directory refuses the delete, the account stays disabled and the sweep retries next window rather than escalating.
Known edges
Stated inline above and collected here: no SASL/GSSAPI; no LDAP-specific TLS
configuration; nested groups are not expanded and the nested_groups option does
nothing; objectSid is formatted, not resolved; enable and disable are AD-only;
generic LDAP has no rename-stable identifier; tunnel mode is refused rather than
degraded; and the shipped classification prefixes are conventions that will miss a
directory naming things differently — which is why the onboarding wizard runs them
against real sampled accounts, so coverage is visible before activation rather
than after.
Which buttons to click in your directory, which rights to delegate on which OU, and what each error code means are deliberately not on this page: those live in the connector's setup checklist inside the product, beside the wizard step that needs them. That list is worth reading before enabling writes — a least-privilege bind account needs separate, explicit rights to create, modify, move and delete objects, each on a different container.
Further reading: