Skip to main content

Documentation Index

Fetch the complete documentation index at: https://conductorone-ian-account-to-user-pipeline.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Availability

The Active Directory connector is self-hosted and supports Windows and Linux.

Capabilities

ResourceSyncProvision
Accounts
Groups
Group Managed Service Accounts (gMSAs)
The Active Directory connector supports automatic account provisioning and deprovisioning. When a new account is created by C1, the account’s password is sent to a vault. Highlights:
  • Primary group memberships sync automatically via primaryGroupID; AD’s memberOf doesn’t include them.
  • Multi-domain and cross-forest sync in a single run via additional-domains config — see Multi-domain and cross-forest sync.
  • gMSA sync is opt-in via enable-gmsa-sync; provisioning modifies the msDS-GroupMSAMembership security descriptor ACL.
  • Two connection modes: LDAP (default on Linux) and WinLDAP (default on Windows; uses wldap32.dll for Kerberos/GSSAPI).
  • Account provisioning (create/delete) requires LDAPS (ldaps: true).
User profiles include UAC-derived state booleans, FILETIME timestamps, and configurable extension attributes — see User profile attributes under Reference.

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):
Action nameAdditional fieldsDescription
enable_userresource_id (resource ID, required)Enable a disabled AD account (clears ACCOUNTDISABLE flag)
disable_userresource_id (resource ID, required)Disable an active AD account (sets ACCOUNTDISABLE flag)
lock_accountresource_id (resource ID, required)Lock an AD account — alias for disable_user, sets the ACCOUNTDISABLE UAC flag. AD has no separate lock state.
unlock_accountresource_id (resource ID, required)Unlock an AD account — alias for enable_user, clears the ACCOUNTDISABLE UAC flag.
update_user_attrsresource_type (string, required), resource_id (string, required), attrs (map, required), attrs_update_mask (string list, required)Update user attributes. Known names (for example, first_name) are mapped to AD attributes; unknown names are passed through as raw AD attribute names. Empty values clear the attribute.
lookup_userAt least one of: upn (string), sam_account_name (string), employee_id (string)Look up a user by UPN, SAM Account Name, or Employee ID and return their DN, SAM Account Name, UPN, display name, employee ID, and objectGUID
set_managerresource_id (resource ID, required), plus exactly one of: manager_resource_id (resource ID) or clear_manager (bool)Set or clear the manager attribute on a user. The handler returns the resulting manager_dn as an output for observability; manager_dn is not an input.
Resource actions (on user resources):
Action nameAdditional fieldsDescription
update_profileuser_id (resource ID, required), plus optional string fields (see Push attributes under User profile attributes), and custom_attributes (map of raw AD attribute names to values)Update a user’s profile attributes. Empty values clear the attribute in AD.
move_ouuser_id (resource ID, required), target_ou (string, required)Move a user to a different Organizational Unit. Automatically handles CN collisions by appending a numeric suffix.
Resource actions (on group resources):
Action nameAdditional fieldsDescription
createname (string, required), organizationalUnit (string, required), plus optional: sAMAccountName, description, groupScope (global/domain_local/universal), groupType (security/distribution), managedByUser (resource ID), managedByGroup (resource ID), mailEnabled (bool), primaryEmailAddress, emailAliases (string list), hideFromGAL (bool), gidNumber (int), userMembers (resource ID list), groupMembers (resource ID list)Create a new AD group with optional initial members, mail settings, and POSIX attributes
Custom PowerShell actions: You can define additional actions backed by PowerShell scripts in the config file. See Custom PowerShell actions below.

Resources

Gather Active Directory credentials

To configure the Active Directory connector, you need an Active Directory service account with appropriate permissions. The specific permissions depend on your intended use:
  • Sync only: Read access to AD objects
  • Entitlement provisioning: Delegated rights to modify group membership
  • Account provisioning: Delegated rights to create, delete, and manage user accounts, plus LDAPS enabled
  • gMSA provisioning: Permission to modify msDS-GroupMSAMembership on gMSA objects
The service account also needs Log on as a service permission and Modify access to C:\ProgramData\ConductorOne.

Create a service account

1
Create a dedicated AD service account for the connector (for example, svc-baton). A standard domain user account with read access is sufficient for sync-only operation.
2
Grant the service account Log on as a service permission via local or domain Group Policy, depending on your environment.

Entitlement provisioning permissions

For entitlement provisioning support, the service account needs delegated rights to manage group membership.
1
Open Active Directory Users and Computers (ADUC) or run dsa.msc from the command line.
2
Right-click on your forest root (or a specific OU if you only want to provision into groups in that OU) and select Delegate Control.
3
Add the service account running the baton-active-directory service.
4
From the tasks to delegate, check the box for Modify the membership of a group.
5
Click Next, then Finish.
This delegation grants the service account the ability to provision and deprovision access from Active Directory groups, but it excludes special built-in groups like Administrators, Domain Admins, Enterprise Admins, and Schema Admins. To manage those protected groups, you must grant explicit Write Members permission on each group and update AdminSDHolder to prevent the permission from being removed:
1
For each protected group: right-click the group, click the Security tab, click Advanced, click Add, select the service account as the principal, and grant Write Members permission.
2
Run the following PowerShell script from a domain controller with domain admin credentials to ensure AdminSDHolder does not remove the permission after 60 minutes:
$domain = "REPLACE_WITH_YOUR_DOMAIN"
$samAccountName = "REPLACE_WITH_YOUR_SERVICE_ACCOUNT"
$adminSDHolderPath = "CN=AdminSDHolder,CN=System," + (Get-ADDomain).DistinguishedName

$acl = Get-Acl "AD:\$adminSDHolderPath"
$identity = New-Object System.Security.Principal.NTAccount("$domain\$samAccountName")

$rule = New-Object System.DirectoryServices.ActiveDirectoryAccessRule(
    $identity,
    [System.DirectoryServices.ActiveDirectoryRights]::WriteProperty,
    [System.Security.AccessControl.AccessControlType]::Allow,
    [Guid]"bf967a9c-0de6-11d0-a285-00aa003049e2",  # GUID for 'member' attribute
    [System.DirectoryServices.ActiveDirectorySecurityInheritance]::None
)

$acl.AddAccessRule($rule)
Set-Acl -Path "AD:\$adminSDHolderPath" -AclObject $acl

Account provisioning permissions

User account provisioning requires ldaps: true in your config.
1
Open ADUC or run dsa.msc from the command line.
2
Right-click on your forest root (or a specific OU) and select Delegate Control.
3
Add the service account running the baton-active-directory service.
4
From the tasks to delegate, check the box for Create, delete, and manage user accounts.
5
Click Next, then Finish.
Your service account is now ready. Continue to the connector configuration.

Configure the Active Directory connector

To complete this task, you’ll need:
  • The Connector Administrator or Super Administrator role in C1
  • An Active Directory service account with the appropriate permissions (see above)
The Active Directory connector is self-hosted — it runs on a Windows or Linux server in your environment with direct network access to your domain controllers. Once installed and configured, Baton runs as a Windows service (or Linux daemon). The service maintains contact with C1, syncs and uploads data at regular intervals, and passes that data to the C1 UI for access reviews and access requests.

Requirements

Host server (Windows Server or Linux):
  • 2-4 vCPU
  • 4-8 GB RAM
  • Minimum OS disk space for the binary (~60 MB) plus room for logs and the local sync database
  • The connector runs as a Windows service or Linux daemon — a dedicated host is not required
Network:
  • Outbound TCP/443 to your C1 tenant
  • Outbound LDAP (TCP/UDP 389), LDAPS (TCP 636), and Kerberos (TCP/UDP 88) to each domain controller the connector talks to. Global Catalog adds TCP 3268 / 3269. For the full multi-domain port list, see Multi-domain and cross-forest sync.
Identity:
  • An Active Directory service account with appropriate permissions (see Gather Active Directory credentials above)
  • The Connector Administrator or Super Administrator role in C1

File locations

Windows (the default install path; %PROGRAMDATA% is typically C:\ProgramData):
  • Binary: C:\Program Files\ConductorOne\baton-active-directory.exe
  • Config: %PROGRAMDATA%\ConductorOne\baton-active-directory\config.yaml — auto-discovered at startup if BATON_CONFIG_PATH is not set
  • Log: %PROGRAMDATA%\ConductorOne\baton-active-directory\baton.log
The service account must have Modify access to %PROGRAMDATA%\ConductorOne so the connector can write to the log file. If the connector can’t write to this directory, the service will fail to start. Linux: there is no default config location — set BATON_CONFIG_PATH (or pass --config-file) to wherever you deploy config.yaml. A common pattern is /etc/baton-active-directory/config.yaml with the log redirected via systemd journal or --file.

Step 1: Set up a new Active Directory connector in C1

1
In C1, navigate to Integrations > Connectors and click Add connector.
2
Search for Baton and click Add.
3
Choose how to set up the new Active Directory connector:
  • Add the connector to a currently unmanaged app (select from the list of apps that were discovered in your identity, SSO, or federation provider that aren’t yet managed with C1)
  • Add the connector to a managed app (select from the list of existing managed apps)
  • Create a new managed app
4
Set the owner for this connector. You can manage the connector yourself, or choose someone else from the list of C1 users. Setting multiple owners is allowed.If you choose someone else, C1 will notify the new connector owner by email that their help is needed to complete the setup process.
5
Click Next.
6
In the Settings area of the page, click Edit.
7
Click Rotate to generate a new Client ID and Secret.Carefully copy and save these credentials. You will need them when configuring the connector.
8
Next to the Not Connected label, click on the word Baton to navigate to the application page. Click the pencil icon at the top of the page and rename the application to Active Directory. This updates the application name, connector name, and icon.

Step 2: Install and configure baton-active-directory

1
Download the latest Windows MSI from the C1 download center.
2
Run the MSI on the host designated to run the connector. The installer prompts for your AD domain, C1 credentials, and connection settings, then writes the YAML config (with DPAPI-encrypted secrets by default) and registers the Windows service with auto-restart recovery.
3
After install, a Configuration Editor shortcut is available from the Start Menu if you need to change settings later. See GUI Configuration Editor below.

Option 2: CLI setup command

1
On the host designated to run the connector, create a folder: C:\Program Files\ConductorOne.
2
Copy baton-active-directory.exe to the ConductorOne folder.
3
From an elevated Command Prompt (cmd.exe), run:
baton-active-directory.exe setup
The setup command must be run from cmd.exe. PowerShell is not supported — the command’s interactive prompts and stdin handling rely on cmd.exe semantics, and running from PowerShell will fail or hang.
The setup command checks for a config file, offers to copy the binary to Program Files, optionally configures a service account, and registers the Windows service with auto-start and recovery.First-run behavior: if no config exists, setup launches the GUI Configuration Editor in a separate window. Fill in your domain, base DN, and C1 credentials, click Save, and close the editor — setup resumes in cmd.exe and finishes registering the service.For non-interactive setup (no prompts, LocalSystem account, no editor), use: baton-active-directory.exe setup -y
4
Grant the service account Modify folder permissions to C:\ProgramData\ConductorOne so it can write to the log file.
baton-active-directory setup and the Windows installer now apply this grant automatically when you specify a non-LocalSystem service account. This step is only required if you change the service account later via services.msc or sc config.
Failing to grant this permission results in a silent service start error (SCM code 1053). The underlying open sink ".../baton.log": Access is denied message is recorded in the Application event log under the baton-active-directory source.
5
Launch the Services console, locate the service named baton-active-directory, and configure it:
  1. Double-click to open properties
  2. Change the Startup type to Automatic
  3. Navigate to the Log On tab and click This account
  4. Click Browse, enter your service account name, and click Check Names
  5. Enter the service account password and confirm it
  6. Click Apply
  7. Navigate back to the General tab and click Start

Step 3: Manage the Windows service

1
Use the following commands to manage the service (all require administrator privileges):
  • To start the service: baton-active-directory.exe start
  • To stop the service: baton-active-directory.exe stop
  • To check the status: baton-active-directory.exe status
  • To remove the service: baton-active-directory.exe remove (config and binary are preserved)
2
The connector syncs current data, uploads it to C1, and prints a Task complete! message when finished.
3
Check that the connector data uploaded correctly. In C1, click Apps. On the Managed apps tab, locate and click the name of the application you added the Active Directory connector to. Active Directory data should be found on the Entitlements and Accounts tabs.
Done. Your Active Directory connector is now pulling access data into C1.

Reference

The sections below cover advanced configuration, troubleshooting, and customization. Skim them only when you need to tune the connector beyond defaults.

Configuration reference

All fields below can be set in the YAML config file. Unless noted, each field also maps to an equivalent CLI flag (--field-name) and environment variable (BATON_FIELD_NAME). Example minimal config:
base-dn: DC=example,DC=com
domain: example.com
mode: winldap
ldaps: true
client-id: <C1 client ID>
client-secret: <C1 client secret>
# Include this line to enable provisioning
provisioning: true
If you make changes to the config file, a service restart is required for the changes to take effect.
Connection:
FieldTypeDefaultDescription
domainstring(required)Fully-qualified Windows domain. Example: baton.example.com
base-dnstring(required)Base DN for LDAP searches. Example: DC=baton,DC=example,DC=com
sitenamestring(any reachable DC)AD site name. When set, scopes DC discovery to an available DC in that site. Example: US-DC-01
modestringwinldap (Windows) / ldap (Linux)Connection mode: ldap (Go library) or winldap (Windows wldap32.dll system calls)
ldapsboolfalseEnable LDAPS (TLS). Required for account provisioning.
ldaps-portint636LDAPS port. Use 3269 for Global Catalog over LDAPS.
ldaps-skip-verifybooltrueSkip LDAPS certificate validation (go-ldap mode only; ignored in WinLDAP).
sync-scopestringStandaloneStandalone or GlobalCatalog. GlobalCatalog is sync-only — provisioning is not supported and some profile fields are unavailable.
Authentication:
FieldTypeDefaultDescription
bind-typestringexternalexternal (Kerberos/GSSAPI, uses the service account running the Windows service — no bind-user or bind-password needed) or simple (username/password)
bind-userstringFull DN of the bind user (required for simple)
bind-passwordstring (secret)Password for the bind user (required for simple). On Windows, can be stored as dpapi:… for DPAPI encryption.
Simple-bind example:
bind-type: simple
bind-user: "CN=svc-baton,OU=ServiceAccounts,DC=example,DC=com"
bind-password: "secret"
Search scope:
FieldTypeDefaultDescription
user-search-dnstringbase-dnDN to search for users
user-search-filterstring(&(objectCategory=person)(objectClass=user))LDAP filter for users
group-search-dnstringbase-dnDN to search for groups
group-search-filterstring(objectCategory=group)LDAP filter for groups
skip-ouslist of DNsOUs to exclude. Mutually exclusive with only-ous.
only-ouslist of DNsOUs to include. Mutually exclusive with skip-ous.
custom-user-attributeslist of stringsExtra LDAP attributes to include in the user profile (for example, githubUserName)
sync-extension-attributesboolfalseSync extensionAttribute1extensionAttribute15 on every user profile. Equivalent to listing all 15 names in custom-user-attributes.
use-display-nameboolfalseUse the LDAP displayName attribute as the C1 resource label instead of cn. Falls back to cn when displayName is empty. Applies to user and gMSA resources.
gMSA:
FieldTypeDefaultDescription
enable-gmsa-syncboolfalseEnable syncing of Group Managed Service Accounts
gmsa-search-dnstringbase-dnDN to search for gMSAs. Example: CN=Managed Service Accounts,DC=example,DC=com
gmsa-search-filterstring(objectClass=msDS-GroupManagedServiceAccount)LDAP filter for gMSAs
Actions & provisioning:
FieldTypeDefaultDescription
provisioningboolfalseEnable Grant/Revoke and account provisioning. Required for any write operation.
powershell-actionsmapCustom PowerShell-backed actions. See Custom PowerShell actions.
C1 credentials:
FieldTypeDefaultDescription
client-idstring(required)C1 client ID. On Windows, can be stored as dpapi:….
client-secretstring (secret)(required)C1 client secret. On Windows, can be stored as dpapi:….
Multi-domain:
FieldTypeDefaultDescription
additional-domainslist of mapsAdditional trusted domains to sync. YAML-only — not exposed as a CLI flag or environment variable. See Multi-domain and cross-forest sync.
Run baton-active-directory --help to see every flag with its current default.

Multi-domain and cross-forest sync

The connector can sync across multiple AD domains and forests in a single run. Add additional trusted domains to your config using native YAML syntax:
additional-domains:
  - domain: remote-forest.example.com
    base-dn: DC=remote-forest,DC=example,DC=com
  - domain: child.example.com
    base-dn: DC=child,DC=example,DC=com
    bind-type: simple
    bind-user: "CN=svc-baton,OU=ServiceAccounts,DC=child,DC=example,DC=com"
    bind-password: "secret"
    ldaps: true
Each additional domain supports independent connection settings (bind type, credentials, LDAPS, search filters, OU restrictions, read-only mode). Cross-domain group memberships are resolved automatically via Foreign Security Principals.
The additional-domains field is YAML-only — it cannot be set via CLI flags or environment variables.
Supported trust types
  • 1-way outbound trust (primary trusts remote, or remote trusts primary)
  • 2-way trust
  • Cross-forest trust
  • External (non-transitive) trust
Prerequisites
1. Active Directory trust. A trust relationship must exist between the domains. For Kerberos (bind-type: external), the connector’s domain must be trusted by the remote domain. For simple bind, any network connectivity is sufficient. Verify with:
Get-ADTrust -Filter * | Select-Object Name, Direction, TrustType, ForestTransitive
2. DNS resolution. The connector machine must resolve the remote domain’s SRV records, DC hostnames, and A records. The recommended approach is a conditional forwarder on your primary DNS server:
Add-DnsServerConditionalForwarderZone `
    -Name "remote-forest.example.com" `
    -MasterServers "192.0.2.10" `
    -ReplicationScope "Forest"
Verify with:
Resolve-DnsName -Name "_ldap._tcp.dc._msdcs.remote-forest.example.com" -Type SRV
Resolve-DnsName -Name "DC01.remote-forest.example.com"
3. Network connectivity. The connector must reach the remote domain’s DCs on the ports you use:
PortProtocolPurpose
389TCP/UDPLDAP (plaintext with signing)
636TCPLDAPS (TLS)
88TCP/UDPKerberos KDC (external/Kerberos auth)
3268TCPGlobal Catalog (optional)
3269TCPGlobal Catalog over SSL (optional)
4. LDAPS certificate trust (if using LDAPS). The remote forest’s root CA certificate must be trusted on the connector machine:
  • Option A — Automatic cross-forest trust: With a 2-way trust and Enterprise CAs in both forests, the remote root CA is typically published to AD automatically.
  • Option B — Manual import: Export the remote CA and import it into the connector machine’s Trusted Root CAs (machine store):
    Import-Certificate -FilePath "remote-root-ca.cer" `
        -CertStoreLocation "Cert:\LocalMachine\Root"
    
  • Option C — Skip validation (go-ldap mode only, lab/testing): Set ldaps-skip-verify: true. This has no effect in WinLDAP mode, which always validates against the Windows certificate store.
  • Option D — Plain LDAP with signing: Omit ldaps: true for the additional domain and connect over TCP/389 with LDAP signing.
5. Kerberos configuration (for bind-type: external). On Windows domain-joined hosts, cross-realm Kerberos is typically automatic when a forest or external trust exists. The connector targets the remote DC’s hostname (for example, DC01.remote-forest.example.com) rather than the domain FQDN, because the SPN (ldap/DC01…) is registered under the DC’s machine account. On Linux, add the remote realm to /etc/krb5.conf:
[realms]
REMOTE-FOREST.EXAMPLE.COM = {
    kdc = DC01.remote-forest.example.com
    admin_server = DC01.remote-forest.example.com
}

[domain_realm]
.remote-forest.example.com = REMOTE-FOREST.EXAMPLE.COM
remote-forest.example.com = REMOTE-FOREST.EXAMPLE.COM

[capaths]
PRIMARY.EXAMPLE.COM = {
    REMOTE-FOREST.EXAMPLE.COM = .
}
6. Permissions. Authenticated Users has read access to most AD objects by default, which is usually sufficient. For gMSA provisioning in an additional domain, set read-only: false on the domain entry and grant the bind account write access to msDS-GroupMSAMembership.
Additional domain fields
Each entry under additional-domains supports the following fields:
FieldTypeDefaultDescription
domainstring(required)FQDN of the remote domain
base-dnstringauto-discovered via rootDSEBase DN for LDAP searches
bind-typestringexternalexternal (Kerberos) or simple
bind-userstringBind DN (required for simple)
bind-passwordstringBind password (required for simple)
ldapsboolinherits primaryOmit to inherit from the primary domain; set true or false to override
ldaps-portint636LDAPS port
read-onlyboolsee belowPrevent write operations (Grant/Revoke) to this domain
user-search-dnstringbase-dnOverride user search base
user-search-filterstringprimary filterOverride user search filter
group-search-dnstringbase-dnOverride group search base
group-search-filterstringprimary filterOverride group search filter
skip-ouslistOUs to exclude
only-ouslistOUs to include (mutually exclusive with skip-ous)
gmsa-search-dnstringbase-dnOverride gMSA search base
gmsa-search-filterstringprimary filterOverride gMSA search filter
read-only default: When omitted, read-only defaults to true unless bind-type is explicitly set (in which case it defaults to false). Providing domain-specific bind credentials signals that writes are intended. Set read-only explicitly to override.
How it works
  • Resource enumeration: the connector paginates across all configured domains — the primary completes first, then each additional domain. All resources land in a single unified sync.
  • Cross-domain DN lookups (group members, managers, Foreign Security Principals): the DN’s domain suffix is matched against your configured domains to route the lookup.
  • Cross-domain SID lookups (gMSA ACLs, primary group SIDs): the SID is resolved against each configured domain in order until a match is found.
  • NetBIOS names (needed for down-level logon display): each forest’s configurationNamingContext is queried for crossRef entries. On Windows, the primary domain also uses the native DsCrackNamesW API; additional domains always fall back to LDAP crossRef.
Diagnosing issues
Run the built-in test harness to check DC resolution, TLS handshake, certificate validation, and LDAP bind for every configured domain:
baton-active-directory.exe test-ldaps
Common failures:
  • LDAP error 81 (“Server Down”) on the remote domain — TLS handshake failure, almost always a missing CA trust. Import the remote root CA (Option B above) or use plain LDAP with signing.
  • LDAP result code 32 (“No Such Object”) during the grants phase — the connector hit a DN or SID on a remote domain that isn’t configured. Add the missing domain to additional-domains.
  • “baseDN auto-discovery failed” — can’t reach the remote rootDSE. Check DNS and network, or set base-dn explicitly.
  • “SASL bind failed” / “Cannot obtain Kerberos ticket” — cross-realm Kerberos isn’t working. Verify the trust, DNS SRV records, and that you’re targeting the DC hostname rather than the domain FQDN. As a fallback, switch that domain to bind-type: simple.
  • “netbios domain is empty” warnings — the NetBIOS cache couldn’t load crossRef entries. Confirm read access to the remote configurationNamingContext.
Performance
Each additional domain adds to the sync cycle. The connector completes one domain fully before moving on; LDAP pagination (1000 entries per page) is used throughout; total sync time scales linearly with the number of domains and objects.

gMSA sync

To sync Group Managed Service Accounts, enable the flag in your config:
enable-gmsa-sync: true
# Optional: restrict gMSA search scope
gmsa-search-dn: "OU=gMSA,DC=example,DC=com"
Each gMSA exposes a password_retrieval entitlement representing which principals are authorized to retrieve the managed password. Grant and Revoke operations modify the gMSA’s msDS-GroupMSAMembership security descriptor ACL.

OU filtering

You can restrict which Organizational Units the connector syncs by using skip-ous or only-ous (mutually exclusive):
# Exclude specific OUs
skip-ous:
  - "OU=Test,DC=example,DC=com"
  - "OU=Disabled,DC=example,DC=com"

# Or include only specific OUs
only-ous:
  - "OU=Engineering,DC=example,DC=com"
  - "OU=Sales,DC=example,DC=com"

Custom user attributes

By default, the connector syncs a standard set of AD user attributes. Use custom-user-attributes to include additional AD attributes in the user profile for account correlation:
custom-user-attributes:
  - githubUserName
  - extensionAttribute1
  - whenCreated
  - pwdLastSet
Once synced, the specified attributes appear as profile fields on the user in C1 and can be configured as additional usernames for account correlation.
Casing: LDAP attribute names are case-insensitive (RFC 4512 §2.5), so configuring mail, Mail, or MAIL all reference the same AD attribute. The connector matches the operator’s configured casing case-insensitively against the entry’s returned attribute names. The profile-map key preserves the operator’s configured casing — so a config of Mail produces profile["Mail"], not profile["mail"] — predictable for downstream consumers reading the C1 profile JSON.
For the common case of surfacing the full Exchange-schema extension attribute range, use the convenience flag sync-extension-attributes: true instead of listing all 15 names manually:
sync-extension-attributes: true

Resource label (cn vs displayName)

By default, the connector uses the LDAP cn attribute as the C1 resource label. AD often stores cn in Last, First order while displayName carries the operator-curated First Last form. To use displayName as the C1 Identity Name, set:
use-display-name: true
Falls back to cn when displayName is empty or whitespace. Applies to both user and gMSA resources. This setting is off by default to preserve existing Identity Names on upgrade — flipping it changes resource labels across access reviews and audit history.

Custom PowerShell actions

You can define additional connector actions backed by PowerShell scripts:
powershell-actions:
  reset-password:
    path: "C:\\Scripts\\Reset-Password.ps1"
    args:
      resource_id:
        type: string
        is_required: true
      new_password:
        type: string
        is_required: true
Each custom action appears alongside the built-in connector actions and can be used in C1 automations. Argument types can be string, int, or bool.

User profile attributes

Synced user profiles carry the standard AD attributes (display name, email, manager, department, etc.) plus three groups of extra fields the connector populates from AD: read-only state booleans, FILETIME timestamps, and any custom attributes you list in custom-user-attributes.

Read-only state attributes

Four booleans are surfaced on every user profile:
FieldSourceMeaning
password_never_expiresstored userAccountControlStatic admin config (DONT_EXPIRE_PASSWD bit)
password_not_requiredstored userAccountControlStatic admin config (PASSWD_NOTREQD bit)
account_lockedcomputed msDS-User-Account-Control-ComputedLive state — matches what ADUC and Get-ADUser show, accounting for lockoutDuration
password_expiredcomputed msDS-User-Account-Control-ComputedLive state — accounts for max-password-age policy
The two static flags come from the stored UAC bits set by an admin. The two live-state flags come from AD’s server-computed UAC attribute, which is re-evaluated each time the connector reads the user. By default, locked-out accounts also map to STATUS_DISABLED in C1 (backwards-compatible). To keep locked accounts as STATUS_ENABLED and report lockout state solely via the account_locked field above, set:
locked-account-is-disabled: false
This is recommended when locked users should remain visible in access reviews.

Timestamp attributes

The connector parses every well-known AD time attribute to an RFC3339 (UTC) timestamp and surfaces it under a canonical *At profile key. The canonical naming convention is raw AD attribute name + At.
Canonical profile keySource AD attribute(s)Source format
pwdLastSetAtpwdLastSetFILETIME
accountExpiresAtaccountExpiresFILETIME
lockoutTimeAtlockoutTimeFILETIME
badPasswordTimeAtbadPasswordTimeFILETIME
lastLoginAtlastLogon or lastLogonTimestampFILETIME
whenChangedAtwhenChangedgeneralizedTime
whenCreatedAtwhenCreatedgeneralizedTime
Sentinel handling: values that AD encodes as “never” (0) or “never expires” (0x7FFFFFFFFFFFFFFF for FILETIME) cause the parsed *At key to be omitted — no year-1601 or year-30828 dates leak into a profile view. Raw values for operator-configured attributes: if you include one of the source AD attribute names above in custom-user-attributes, the raw value is also surfaced under the operator-requested key (preserving the YAML contract for downstream tooling that reads by attribute name) — except when the value is a sentinel, in which case the raw is also suppressed (the meaningless 19-digit integer would only confuse reviewers).
Operator configRaw value typeProfile contains
custom-user-attributes: [pwdLastSet]valid FILETIMEpwdLastSet (raw) + pwdLastSetAt (parsed) + passwordLastSet (legacy alias)
custom-user-attributes: [accountExpires]sentinel 9223372036854775807neither key (both suppressed)
custom-user-attributes: [lastLogon]sentinel 0neither key (both suppressed)
custom-user-attributes: [whenChanged]valid generalizedTimewhenChanged (raw) + whenChangedAt (parsed)
(default — not listed in custom-user-attributes)any non-sentinelparsed *At only
pwdLastSet and lockoutTime are not replicated to the Global Catalog, so they may be missing under sync-scope: GlobalCatalog. badPasswordTime is local to each domain controller and not replicated at all — its value reflects the DC the connector talked to during the sync. lastLogon is also per-DC and not replicated; the connector prefers lastLogonTimestamp (replicated) when both are present.
Backwards-compat aliases (v0.5.5 transition): for one release, the connector also emits each renamed FILETIME canonical key under its pre-v0.5.5 name — passwordLastSet (alongside pwdLastSetAt), lockedOutAt (alongside lockoutTimeAt), and lastBadPasswordAt (alongside badPasswordTimeAt) — so downstream automations reading the older keys continue to work. The new generalizedTime keys (whenChangedAt, whenCreatedAt, lastLoginAt) have no legacy aliases since they’re introduced in this release. Legacy aliases will be dropped in a future release; new consumers should target the canonical *At form.

Push attributes

The update_profile resource action accepts 23 named string fields, each named after the canonical AD attribute it targets. The platform’s push-rule UI shows the AD attribute name in its “App attribute” column, so the value you map to in C1 corresponds directly to the attribute AD will receive. Attributes outside this list (including extensionAttribute1 through extensionAttribute15) must be set via the custom_attributes map field on update_profile, or via the update_user_attrs global action.
AD attributeCategoryNotes
givenNameIdentityFirst name
middleNameIdentityMiddle name
snIdentityLast name / surname
displayNameIdentityOperator-curated full name
sAMAccountNameIdentityPre-Windows-2000 login
userPrincipalNameIdentityUPN login, e.g. user@domain.com
mailContactEmail address
telephoneNumberContactPrimary phone
mobileContactMobile phone
titleOrganizationJob title
departmentOrganizationDepartment
divisionOrganizationDivision
companyOrganizationCompany
descriptionOrganizationFree-form description
employeeIDOrganizationEmployee ID (string)
employeeNumberOrganizationEmployee number
employeeTypeOrganizationEmployment type
lAddressCity / locality
stAddressState or province
streetAddressAddressStreet address
postalCodeAddressPostal / ZIP code
cAddressCountry code, ISO 3166 alpha-2
physicalDeliveryOfficeNameAddressOffice location
Pre-v0.5.5 push rules used snake_case field names (first_name, display_name, email, etc.). Those rules continue to work — the connector resolves both the canonical AD names listed above and the legacy snake_case aliases to the same target attribute. New push rules should prefer the AD-canonical names so the C1 UI’s “App attribute” column matches what AD actually expects.
AD enforces schema constraints on attribute values. For example, the c (country) attribute has a maximum length of 3 characters and expects ISO 3166-1 alpha-2 codes (for example, US, not United States). Constraint violations are logged with each attribute name and value length to aid debugging.
The update_user_attrs global action recognizes the 23 fields above (plus their legacy snake_case aliases for backwards compatibility), plus 15 extension attribute names (extensionAttribute1 through extensionAttribute15 — also accepted as extension_attribute_1extension_attribute_15). Any attribute name not in the combined list is passed through as a raw AD attribute name, allowing direct access to any writable AD attribute.

Troubleshooting “search returned 0 entries”

When the connector logs winldap_ldap_search: search returned 0 entries at INFO level, it means a configured search base (typically user-search-dn or group-search-dn) produced no entries. The log line includes base, filter, and scope so you can correlate which search returned empty. There are three common causes:
  1. The search filter is too narrow — verify with an ldapsearch or Get-ADUser -LDAPFilter from the same DC the connector is bound to. If they also return zero, the filter or the DN is wrong.
  2. The DN doesn’t exist as written — the connector logs the exact base string sent to AD. Copy it verbatim into dsquery * "<base>" -limit 1 on the DC to confirm.
  3. The bound DC isn’t authoritative for the search base — when you narrow user-search-dn or group-search-dn into a delegated OU, a child-domain OU, or a Read-Only DC subtree, the bound DC may answer with LDAP_REFERRAL (result code 10) or LDAP_PARTIAL_RESULTS (9) instead of entries. The connector surfaces this case explicitly: alongside the zero-entries INFO, look for a WARN log of the form ldap_ext_search: non-success result code_name=LDAP_REFERRAL r1=10. The same condition surfaces in the C1 sync-failure panel as LDAP error: LDAP_REFERRAL, so it’s identifiable from the platform side too without needing log access. The connector does not chase referrals. WinLDAP’s referral-chasing option (LDAP_OPT_REFERRALS) is explicitly disabled — it has to be, to work around an AD pagination bug where chased subordinate referrals confuse the paging control and corrupt the page cookie. Re-enabling chasing would also introduce an authentication-security risk (chased referrals can authenticate against arbitrary servers). The remediation is to adjust the search configuration so the bound DC is authoritative for the subtree:
    • Widen the search base (e.g. move from OU=Sub,OU=Parent,DC=corp,DC=example,DC=com up to OU=Parent,... or to the partition root DC=corp,DC=example,DC=com).
    • Configure a different bind DC that is authoritative for the OU — pass --sitename to scope discovery to a site that includes an authoritative DC, or set up additional-domains if the subtree belongs to a different partition.
    • For multi-domain forests, use additional-domains so the connector binds separately against each partition’s authoritative DC instead of chasing referrals from one DC.

LDAPS troubleshooting

LDAPS settings (ldaps, ldaps-port, ldaps-skip-verify) live in the Configuration reference. This section covers the parts that don’t fit in a flag table: how the two connection modes treat certificate trust differently, and how to diagnose handshake failures.

Certificate trust depends on connection mode

The ldaps-skip-verify flag behaves differently depending on mode:
  • WinLDAP mode (default on Windows): TLS validation is delegated to the Windows certificate store. ldaps-skip-verify has no effect — the OS always validates against Cert:\LocalMachine\Root. To trust a CA, import its root certificate into the Windows machine store:
    certutil -addstore Root <path-to-ca.cer>
    
  • LDAP mode (Go library, default on Linux): TLS validation uses Go’s TLS stack. ldaps-skip-verify: true (the default) disables hostname and chain validation, which lets self-signed AD certs work in lab environments. For production, set ldaps-skip-verify: false and either trust the CA at the OS level or import it into the connector machine.
If mode: ldap doesn’t connect on a Windows host (typical when the AD server requires channel binding or LDAP signing), switch to mode: winldap.

Diagnose with test-ldaps

The connector ships a diagnostic command that exercises every configured domain end-to-end:
baton-active-directory.exe test-ldaps
It runs four checks per domain — DC resolution, TCP connect, TLS handshake (with cert subject/issuer/expiry reported even on validation failure), and LDAP bind — and prints per-step PASS/FAIL with the actionable fix when something breaks. Common LDAPS failure signatures and what they mean:
  • x509: certificate signed by unknown authority (go-ldap mode) — the connector machine doesn’t trust the CA that issued the DC certificate. Import the CA root or set ldaps-skip-verify: true for testing only.
  • tls: failed to verify certificate: x509: certificate is valid for X, not Y — certificate Subject/SAN doesn’t include the hostname the connector is connecting to. Verify you’re targeting a DC hostname that matches the cert (DCs typically have multiple SAN entries).
  • LDAP Result Code 81 "Server is unavailable" in WinLDAP mode — usually a TLS handshake failure where Schannel rejected the cert. Check the Windows event log under LDAP-Client and Schannel sources for the rejection reason.
  • Connection times out on port 636 — port not open between the connector host and the DC, or LDAPS isn’t enabled on the DC. Confirm the DC has a Server Authentication EKU certificate in its Personal store.
For multi-domain setups, test-ldaps checks every entry in additional-domains plus the primary, so a single run covers your whole topology.

DPAPI secrets encryption

On Windows, the connector can encrypt sensitive config values (client-id, client-secret, and bind-password) using Windows DPAPI machine-scoped encryption. Encrypted values are prefixed dpapi: in the YAML config and are decrypted transparently at startup. The installer encrypts by default; you can also encrypt an existing config manually:
baton-active-directory.exe encrypt-config

GUI Configuration Editor

The connector includes a native Windows GUI for managing configuration without editing YAML files manually. It’s the same window that setup launches automatically on first run when no config exists (Option 2, Step 3) — you can also open it standalone at any time:
baton-active-directory.exe config-editor
If installed via the MSI installer, a Configuration Editor shortcut is also available in the Start Menu. The editor exposes every YAML config field across a tabbed layout (Connection, Authentication, Sync Scope, Multi-Domain, gMSA, Advanced). Notable toggles on the Advanced tab include Lockout Status Behavior (locked-account-is-disabled), Sync Extension Attributes (sync-extension-attributes), and Use displayName as Resource Label (use-display-name). Secret fields (bind passwords, client secret) are write-only — entering a new value encrypts it via DPAPI on save; leaving a field blank preserves the existing encrypted value.

What’s next?

Once your Active Directory connector is synced, you can use C1 to run user access reviews on AD group memberships, enable just-in-time access requests for AD groups and gMSAs, and automate provisioning workflows using connector actions.