Skip to main content

Capabilities

The LDAP connector supports automatic account provisioning and deprovisioning.

Group membership provisioning

A group’s membership lives in member (a DN), uniqueMember (a DN) or memberUid (a login name), and which one it is cannot be derived from the entry’s object classes: posixGroup is STRUCTURAL under RFC 2307 and AUXILIARY under rfc2307bis, and a client such as SSSD chooses the attribute it reads through its own ldap_schema setting. The connector therefore learns it per entry instead of assuming it:
  • Grant writes the attribute the group entry already uses, or, when the entry holds no membership yet, the one its object classes suggest (groupOfUniqueNames alone: uniqueMember; posixGroup with no DN group class: memberUid; otherwise member). If the server rejects an attribute as not permitted by the entry, the next candidate is tried. A group whose membership has diverged across attributes is written to each of them. memberUid is written as the principal’s uid or cn, whichever form the group’s own values already use.
  • Every write is confirmed by re-reading the entry on the connection that accepted it, and asking the same question sync asks — is this principal a member? A write the server accepted but that cannot be confirmed is a retryable failure, and is never followed by a write to a second attribute.
  • Revoke removes the membership from wherever it actually is, deleting the exact stored values from every attribute that holds the principal in one request. A revoke never acts on a guess or on a configured pin.
  • A revoke acts on the group’s own attributes and on nothing else, so a membership held only through a nested group is not revoked here: it answers GrantAlreadyRevoked, changes nothing in the directory, and reappears on the next sync — revoke it at the source group instead. The one membership the connector does report and cannot remove with a write to the group is the user’s primary group, minted from the user entry’s own gidNumber; that one is reported as an error naming it, whether or not this call also removed a direct membership. Otherwise the result is a plain success (a direct membership was removed) or GrantAlreadyRevoked (there was none).
  • Set --group-member-attribute to member, uniqueMember or memberUid (default auto) to pin the attribute a grant writes, for directories the connector cannot learn from — notably one with schema checking disabled, so that no attribute is ever rejected. The pin governs grants only; revokes still act on where the membership actually is. See the connector README for the full behavior and its limits.

POSIX account provisioning

The LDAP connector supports provisioning posixAccount entries with automatic UID number assignment. When creating a new POSIX account, the connector can look up the highest uidNumber currently in use across all existing posixAccount entries in your directory and automatically assign the next available value. To use this feature, configure the following account provisioning mappings:
Automatic UID number calculation assigns uidNumber only. You must provide gidNumber manually in the Additional Attributes mapping. If you set Calculate the next valid UID Number to true, any uidNumber value provided in Additional Attributes is ignored.
A mapping that resolves to an empty value is omitted from the LDAP add. A zero-length value is not portable across attribute types — a directory rejects the whole add with result 21 (Invalid Attribute Syntax) on most of them — so an optional field the account leaves unset cannot break account creation, and it is not stored as an empty value either. A list keeps its non-empty entries and is omitted only when none remain. Values such as false and 0 are real values and are still sent.objectClass is the exception: a mapping that resolves to no object class at all is rejected before the add, because an account cannot be created without one.This is the opposite of update_profile, where an empty custom_attributes value clears the attribute. See the update_profile rules under Connector actions.

Connector actions

Connector actions are custom capabilities that extend C1 automations with app-specific operations. You can use connector actions in the Perform connector action automation step. Global actions (connector-level):
To use create_ou, the connector’s bind account must have permission to add child entries under the target parent DN (by default, the configured base DN). For OpenLDAP and similar servers, this is write/add access on the parent container; for Active Directory, delegate the Create Organizational Unit objects right on the parent OU.

User enable/disable attributes

Some directories do not use the standard userAccountControl (Active Directory) or nsAccountLock (FreeIPA) flags to mark an account’s lifecycle state, but their own attribute — IDMWorks, for example, uses revoke, where Y means disabled and N means enabled. enable-user-attributes and disable-user-attributes map LDAP attribute names to the values that mean enabled and disabled:
Both maps are unset by default. When configured:
  • Sync reports an account as disabled when any configured attribute holds its disabled value, as enabled when any holds its enabled value, and otherwise falls back to userAccountControl then nsAccountLock. Values are compared case-insensitively and whitespace-trimmed; any value of a multi-valued attribute counts.
  • disable_user writes exactly the attributes named in disable-user-attributes, and enable_user writes exactly those in enable-user-attributes. Neither action touches an attribute named only in the other direction.
  • Because of that isolation, a configuration that sets both maps must name the same attributes in each — otherwise enable_user would leave an attribute at its disabled value while the synced status kept reporting the account as disabled. Asymmetric key sets are rejected at startup. To clear an attribute when enabling, give it an explicit empty value (enable-user-attributes: {"revoke": ""}), which keeps the attribute name present.
  • The same attribute cannot be given the same value in both directions; attribute names must not be empty; objectClass and password attributes cannot be used as the marker; and the disable side cannot use an empty value. Each is rejected at startup. An absent attribute reads as enabled, so “disable by clearing the marker” would clear it, report success, and leave sync reporting the account enabled — an empty value stays legal only on the enable side, where it means clear-on-enable.
  • Each action returns success, status ("enabled" / "disabled"), applied (the number of attributes changed; 0 means the account was already in the requested state), and updated_user (encoded from the entry the write was verified against; absent only if encoding it failed, since a failed re-read fails the action). The connector re-reads the entry and verifies the configured attributes now hold their configured values — or are absent, for a configured clear — before reporting success. An attribute it cannot write (the entry’s RDN attribute, for example) fails the action rather than being reported as skipped, on the first call and on every retry alike.
  • Unlike update_profile, these actions are global, not resource-scoped. user_id still takes the C1 account identifier rather than the LDAP DN, for the same reason.
  • Quote the values. The configuration loader stringifies map values before the connector sees them, so an unquoted TRUE/FALSE arrives as the string "true" and is written that way; LDAP’s Boolean syntax (RFC 4517) requires uppercase, so the modify is rejected instead of setting the attribute. The connector cannot tell a quoted "true" from an unquoted one by then, so this is not caught at startup. Y and N are not YAML booleans and are safe unquoted.
  • As an environment variable the value must be JSON: BATON_DISABLE_USER_ATTRIBUTES='{"revoke":"Y"}' works, BATON_DISABLE_USER_ATTRIBUTES='revoke=Y' is rejected at startup rather than silently configuring nothing. A nested YAML map and repeated --disable-user-attributes key=value flags both work as written.
With a “clear on enable” definition (revoke: "Y" / revoke: "") the enabled state is reached by fall-through rather than by matching a positive value: no configured attribute matches its disabled value, so the built-in rules apply and an unspecified status defaults to enabled. “Enabled” therefore means “the disabled marker is absent”.
Resource-scoped actions (user): The update_profile action returns success (bool), updated_user (the modified user resource, re-fetched after the write; absent if the read-back failed, though the write itself still succeeded), applied (the number of attributes changed), and skipped (named fields or custom_attributes entries that were not written). updated_user carries the resource identity, displayName, and the user trait — not the entry’s full attribute set. A value the action just wrote appears there only when it also feeds one of those: display_name through displayName, email through the trait’s email list, and a custom_attributes key only when it maps to a trait field (mail, displayName, sAMAccountName, userPrincipalName, a non-RDN uid or cn, lastLogonTimestamp, authTimestamp). first_name, last_name, and every other custom_attributes key reach the directory but do not appear in updated_user. Use applied to confirm those. Two requirements come from the C1 side rather than from LDAP:
  • user_id takes the C1 account identifier, not the LDAP DN. C1 resolves the account to the connector’s resource before dispatching the action. A DN fails inside C1 with resource <dn> with type user was not found and never reaches the connector, so it produces no connector log line and leaves the directory untouched.
  • An attribute push rule must map from a single-valued attribute. The connector’s user profile carries only attributes that hold exactly one value on the entry, so a multi-valued source resolves to nothing: the rule saves and enables, and each push reports zero attributes applied.
update_profile is intended for generic LDAP directories (Active Directory and FreeIPA have their own connectors). It applies the following rules:
  • Named fields: first_name → givenName, last_name → sn, display_name → displayName, email → mail. A named field is applied only when present and non-empty; a present-but-empty named field cannot clear the attribute and is instead reported in skipped.
  • inetOrgPerson requirement: only last_name (sn) is universal — it’s a MUST attribute of the base person object class. first_name (givenName, defined in RFC 4519), display_name (displayName, RFC 2798), and email (mail, RFC 4524) are permitted on an entry only by RFC 2798’s inetOrgPerson object class, so writing one of them to an entry that doesn’t carry inetOrgPerson fails loudly with LDAP result code 65 (“Object Class Violation”) — an atomic, clearly-signaled failure with no partial write, not a silent no-op.
  • Custom attributes: custom_attributes maps arbitrary raw LDAP attribute names to values; an empty value clears the attribute (unlike the named fields above, where empty just means “not supplied”). Keys are used verbatim as attribute names — the named-field mapping above applies only to the named arguments, never to custom_attributes. {"user_id": "x"} therefore writes an attribute literally named user_id; it does not write uid. A name the directory does not define is refused by the server, and the result code depends on the implementation: OpenLDAP returns 17 (“Undefined Attribute Type”), ApacheDS returns 16 (“No Such Attribute”). The same goes for baton profile field names such as login and path: they are attempted as literal attribute names rather than skipped.
  • Collisions: a custom_attributes key is dropped (never merged with, or overwriting, a named field’s slot) and reported once in skipped when it case-insensitively matches either one of the four named field names, or the LDAP attribute a supplied named field is writing (givenName, sn, displayName, mail). The latter only applies when that named field was actually supplied and non-empty; otherwise {"givenName": "Jane"} is an ordinary raw write.
  • Not modifiable: password attributes (userPassword, or any name containing password — use credential rotation instead) and objectClass are rejected; the user’s RDN attribute (for example cn when the DN is cn=jdoe,...) is skipped, since renaming requires a different operation.
  • Multi-valued attributes: setting (not clearing) a value on an attribute that currently holds more than one value returns an error instead of silently discarding the extra values; clearing (an empty value) still removes all values.
  • Value types: custom_attributes carries one string per attribute, so binary attributes (jpegPhoto, userCertificate;binary) and option-tagged attributes (;lang-xx) cannot be set through this action.
  • Scope: only entries within the configured user search scope (user-search-dn, falling back to base-dn) can be modified; out-of-scope or non-user DNs are rejected.
The connector’s bind account must have permission to modify the target entry.

Gather LDAP credentials

Configuring the connector requires you to pass in credentials for LDAP. Gather these credentials before you move on. Here’s the set of credentials you’ll need when setting up the connector:
  • The username and password of an LDAP account
  • URL of the LDAP server, which can use either ldap: or ldaps: schemes, and optionally includes a port number
Done. Next, move on to the connector configuration instructions.

Configure the LDAP connector

To complete this task, you’ll need:
  • The Connector Administrator or Super Administrator role in C1
  • Access to the set of LDAP credentials generated by following the instructions above
Follow these instructions to use a built-in, no-code connector hosted by C1.Cloud-hosted connector not currently available.