Guide to Sync Configuration
What is LDAP Sync?
LDAP (Lightweight Directory Access Protocol) is the standard way to read and synchronise information from Active Directory (AD).
In Zluri’s setup, the LDAP Agent connects to your AD and fetches details like users, groups, and organizational units (OUs) — all based on the YAML configuration.
How the Configuration Works
Your configuration file controls what data to sync, how often to sync, and what access permissions to apply.
It’s structured in three main sections:
Configuration
├── General Settings (connection, timing, logging)
├── Global Settings (default sync rules)
└── Search Bases (specific OU rules and exceptions) (Optional)
Section 1: General Settings
These settings control timing, retries, and LDAP connection behaviour.
general:
polling_frequency_minutes: 5 # How often the agent checks for tasks in Zluri for AD
sync_frequency_minutes: 60 # How often to perform a full sync
max_page_size: 1000 # Number of records fetched per request
daily_sync_hour: 23 # Local hour (0–23) when a full sync will automatically run daily
Understanding Key Terms
- polling_frequency_minutes : How often the agent checks for tasks in Zluri for AD
- sync_frequency_minutes: How often to perform a full sync
- daily_sync_hour: It’s a local hour (0–23) when a full sync will automatically run daily. Follows 24 hour format. 23 in the above example = 11 PM.
- max_page_size: Number of records fetched per request
Section 2: Global Settings
These are the default rules that apply to all AD objects unless overridden by a specific search base rule(Section 3).
globalSettings:
defaultSearchBase:
enabled: true
baseDN: "DC=ZLURI,DC=DEV" # Root of your domain
scope: sub # Search the full directory tree
accessModeDefault: R # Default: read-only access
entities:
users:
attributes:
- dn
- cn
- mail
- memberOf
objectClasses:
search:
- user
create:
- user
filters:
dn:
include: []
exclude:
- ^CN=Guest.*
ldapCustomFilter: "(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"
# If your AD stores built‑in Users container and you want those users included
includeUsersContainer: true
Understanding Key Terms
-
enabled: true or false - Enable/disable synchronisation for this entity
-
baseDN: The root location in AD where synchronisation starts.
Example:
DC=company,DC=com
means your entire domain. -
scope:
base
- Indicates that only the entry specified as the search base should be considered. None of its subordinates will be considered.one
- Indicates that only the immediate children of the entry specified as the search base should be considered. The base entry itself should not be considered, nor any descendants of the immediate children of the base entry.sub
- Indicates that the entry specified as the search base, and all of its subordinates to any depth, should be considered.children
- Indicates that the entry specified by the search base should not be considered, but all of its subordinates to any depth should be considered.
-
accessModeDefault:
R
: Data is visible and synced, but not changedRW
: Full sync and update permissions
-
includeUsersContainer: If your AD stores built‑in Users container and you want those users included, use true
true
: If your AD stores built‑in Users container and you want those users included, value = true (DEFAULT)false
: If your AD stores built‑in Users container and you want those users included, value = false
-
attributes: List of data fields to pull (name, username, email, etc.).
Understanding Filters
-
ldapCustomFilter
: Define which records to include/exclude.Example:
ldapCustomFilter: "(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"
The
ldapCustomFilter
above ensures disabled user accounts are skipped. -
Understanding
include
andexclude
filters:include
andexclude
filters use regex (regular expressions) to decide which directory objects are synced based on their Distinguished Name (DN) — the object’s full AD path (e.g.,CN=John Doe,OU=Corporate,DC=company,DC=com
).-
include
→ Defines which objects to sync.Empty list
[]
means include all.Example:
include: - "^CN=ADM_.*"
→ Syncs only objects whose names start with
ADM_
. -
exclude
→ Defines which objects not to sync. Empty list[]
means no exclusions.Example:
exclude: - "^CN=Guest,.*"
→ Skips all users whose names start with “Guest”.
Exclude takes precedence — if something matches both include and exclude, it’s excluded.
You can use regex symbols like:
^
= starts with$
= ends with.*
= any characters|
= OR condition
-
Section 3: Search Bases (Specific Rules)
Each “search base” represents a folder (OU) in your AD where specific sync rules apply.
This allows fine-grained control. For example, you can give full access to IT, but read-only access to HR.
Example:
searchBases:
- baseDN: "OU=Corporate,DC=ZLURI,DC=DEV"
ruleId: "corporate-rule"
enabled: true
scope: sub
traversal:
users:
accessModeDefault: RW # Can read and modify user data
filters:
dn:
exclude:
- ".*,OU=HR,OU=Corporate,.*" # Skip HR users
Understanding Key Terms
-
baseDN: Where in AD this rule starts applying
-
ruleId: Each search base must include a short, unique
ruleId
. This ID helps Zluri identify which rule governs a specific LDAP object or action.- When Zluri performs an operation (e.g., sync, modify, or access validation) and it fails due to permission restrictions, the error message will clearly reference the ruleId — allowing admins to quickly identify which rule caused the restriction.
Example: “Action denied: privileged-access rule restricts modification of this user.”
- In short,
ruleId
provides traceability between LDAP sync behavior, configuration logic, and any permission-based enforcement within Zluri.
-
scope: Whether to include sub-OUs (folders) under this one
-
accessModeDefault: Default permission for the entity type (R, RW)
-
filters: Define what to include/exclude by name or condition(explained here)
Example Configuration File with all three sections
-
Basic / Quick Start Configuration:
This version contains only General and Global Settings — no
searchBases
.It’s perfect for first-time setups or small domains that just need full-directory sync with minimal filtering.
# ===============================
# 1) GENERAL SETTINGS
# ===============================
general:
# Timers (minutes)
polling_frequency_minutes: 5 # How often the agent checks for AD changes
sync_frequency_minutes: 600 # How often to run a full sync
daily_sync_hour: 23 # Local hour (0–23) when a full sync will automatically run daily
# Reliability & performance
max_page_size: 500
# Page size for LDAP queries (tune for your AD)
# ===============================
# 2) GLOBAL DEFAULTS
# ===============================
globalSettings:
# Where the agent starts if no specific rule matches
defaultSearchBase:
enabled: true
baseDN: "DC=COMPANY,DC=LOCAL" # Root of your AD domain
scope: sub # sub = include all child OUs, explained above in section 2
accessModeDefault: R # R=read, RW=read/write
# Entity‑level defaults that apply everywhere unless a searchBase overrides them
entities:
users:
# Optional: add attributes includes the immutable defaults
attributes:
- mail
- memberOf
- whenChanged
objectClasses:
search:
- user
create:
- user
filters:
dn:
include: []
exclude:
- ^CN=Guest,.* # Skip Guest accounts globally
# Only enabled users (standard AD disabled bit check)
ldapCustomFilter: "(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"
groups:
attributes:
- member
- groupType
- description
objectClasses:
search:
- group
create:
- group
filters:
dn:
include: []
exclude: []
ldapCustomFilter: "(objectClass=group)"
ous:
attributes:
- description # `dn`,`ou`,`objectClass` are auto‑added
objectClasses:
search:
- organizationalUnit
create:
- organizationalUnit
filters:
dn:
include: []
exclude: []
ldapCustomFilter: "(objectClass=organizationalUnit)"
# If your AD stores built‑in Users container and you want those users included
includeUsersContainer: true
-
Advanced / Granular Configuration (with Search Bases)
This version includes
searchBases
with per-OU controls, filters, overrides, and ruleIds. It’s meant for large or complex environments where different departments or OUs need different sync or access rules.
# ===============================
# 1) GENERAL SETTINGS
# ===============================
general:
# Timers (minutes)
polling_frequency_minutes: 5 # How often the agent checks for AD changes
sync_frequency_minutes: 600 # How often to run a full sync
daily_sync_hour: 23 # Local Timezone in hour when the full sync will run
# Reliability & performance
max_page_size: 500
# Page size for LDAP queries (tune for your AD)
# ===============================
# 2) GLOBAL DEFAULTS
# ===============================
globalSettings:
# Where the agent starts if no specific rule matches
defaultSearchBase:
enabled: true
baseDN: "DC=COMPANY,DC=LOCAL" # Root of your AD domain
scope: sub # sub = include all child OUs, explained above in section 2
accessModeDefault: R # R=read, RW=read/write
# Entity‑level defaults that apply everywhere unless a searchBase overrides them
entities:
users:
# Optional: add attributes includes the immutable defaults mentioned in the Defaults Section
attributes:
- mail
- memberOf
- whenChanged
objectClasses:
search:
- user
create:
- user
filters:
dn:
include: []
exclude:
- ^CN=Guest,.* # Skip Guest accounts globally
# Only enabled users (standard AD disabled bit check)
ldapCustomFilter: "(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"
groups:
attributes:
- member
- groupType
- description
objectClasses:
search:
- group
create:
- group
filters:
dn:
include: []
exclude: []
ldapCustomFilter: "(objectClass=group)"
ous:
attributes:
- description # `dn`,`ou`,`objectClass` are auto‑added
objectClasses:
search:
- organizationalUnit
create:
- organizationalUnit
filters:
dn:
include: []
exclude: []
ldapCustomFilter: "(objectClass=organizationalUnit)"
# If your AD stores built‑in Users container and you want those users included
includeUsersContainer: true
# ===============================
# 3) SEARCH BASES (specific OU rules)
# ===============================
searchBases:
# --- Corporate OU: Standard RW access ---
- baseDN: "OU=Corporate,DC=COMPANY,DC=LOCAL"
ruleId: "corporate-rule"
enabled: true
scope: sub
traversal:
users:
accessModeDefault: RW
filters:
dn:
include: []
exclude:
- .*,OU=HR,OU=Corporate,.* # Exclude HR users from Corporate
ldapCustomFilter: "" # No extra filter beyond globals
groups:
accessModeDefault: RW
filters:
dn:
include:
- ^CN=(TEAM|APP)_.* # Only TEAM_* or APP_* groups
exclude: []
ldapCustomFilter: ""
ous:
accessModeDefault: RW
filters:
dn:
include: []
exclude:
- ^OU=BreakGlass,.* # Don’t traverse BreakGlass OU
ldapCustomFilter: ""
# --- HR OU: Read‑only & scoped ---
- baseDN: "OU=HR,OU=Corporate,DC=COMPANY,DC=LOCAL"
ruleId: "hr-restrictions"
enabled: true
scope: sub
traversal:
users:
accessModeDefault: R
filters:
dn:
include: []
exclude: []
ldapCustomFilter: "(department=Human Resources)" # Only HR users
groups:
accessModeDefault: R # Hide HR groups
filters:
dn:
include: []
exclude: []
ldapCustomFilter: ""
ous:
accessModeDefault: R
filters:
dn:
include: []
exclude: []
ldapCustomFilter: ""
# --- Privileged Accounts: High security ---
- baseDN: "OU=Privileged Accounts,DC=COMPANY,DC=LOCAL"
ruleId: "privileged-access"
enabled: true
scope: sub
traversal:
users:
accessModeDefault: R
filters:
dn:
include:
- ^CN=ADM_.* # Admin‑prefixed accounts only
exclude: []
ldapCustomFilter: ""
ous:
accessModeDefault: R
filters:
dn:
include: []
exclude:
- ^OU=Disabled,.*
ldapCustomFilter: ""
# --- Service Accounts: Audit‑only ---
- baseDN: "OU=Service Accounts,DC=COMPANY,DC=LOCAL"
ruleId: "service-audit"
enabled: true
scope: sub
traversal:
users:
accessModeDefault: R
filters:
dn:
include: []
exclude: []
# Only actual service principals
ldapCustomFilter: "(&(objectClass=user)(servicePrincipalName=*))"
# Minimal audit fields; agent auto‑adds immutable defaults
attributes:
- sAMAccountName
- servicePrincipalName
- pwdLastSet
- lastLogonTimestamp
Defaults (always fetched)
General Settings:
- Sync frequency minutes -
sync_frequency_minutes
- min you can set is - 120(2 hours)
- max you can set it - 1440(24 hours)
- default - 360(6 hours)
- Polling frequency minutes -
polling_frequency_minutes
- min you can set is - 5
- max you can set it - 30
- default - 5
- Maximum Page Size -
max_page_size
- min you can set is - 500
- max you can set it - 2500
- default - 500
Attributes:
Even if you remove attributes in your config, the agent always fetches a minimal, non‑removable set so objects can be identified and joined correctly. These are enforced by the agent at runtime (your YAML doesn’t need to include them).
Immutable default attributes for entities:
- Users:
dn
,cn
,userPrincipalName
,mail
,userAccountControl
,sAMAccountName
,objectClass
- Groups:
dn
,member
,groupType
,objectClass
,cn
- OUs:
dn
,cn
If you list attributes, the agent uses your list + these defaults (no duplicates). You cannot opt out of defaults.
Scope:
Scope is defaulted to sub which searches the full directory tree for the specified baseDN.
User Container:
If your AD stores built‑in Users container by default, the value = true.
🧾 Example: Privileged Accounts Rule
- baseDN: "OU=Privileged Accounts,DC=ZLURI,DC=DEV"
ruleId: "privileged-access"
enabled: true
traversal:
users:
accessModeDefault: R # Read-only for all privileged accounts
filters:
dn:
include: ["^CN=ADM_.*"] # Include only accounts starting with ADM_
✅Explanation:
This means:
“Fetch all admin (ADM_) accounts under the Privileged Accounts OU, but never sync the BreakGlass account.”
🧮 Filter Logic (How Inclusion & Exclusion Works)
Zluri combines global and searchbases rule-specific filters like this:
Effective Filter = (Global Filter) AND (Rule Filter)
If both define rules, only users matching both conditions will sync.
Evaluation order:
- Include patterns → Objects must match these (if defined)
- Exclude patterns → Objects matching are skipped
- LDAP custom filter → Additional logic (AD-side filtering)
🧩 Real-World Scenarios
✅ Scenario 1: Exclude Disabled Users
ldapCustomFilter: "(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"
Means: Only syncs users who are enabled in AD.
✅ Scenario 2: HR Read-Only Access
- baseDN: "OU=HR,OU=Corporate,DC=company,DC=com"
traversal:
users:
accessModeDefault: "R"
ldapCustomFilter: "(department=Human Resources)"
Means: HR users can be seen but not modified.
⚙️ Best Practices
Tip | Why It Matters |
---|---|
Start with read-only mode | Avoid accidental changes |
Use clear rule names | Easier debugging |
Test regex filters | Prevent unwanted exclusions |
Limit sync scope | Improves performance |
Document overrides | Keeps your setup auditable |
🚨 Troubleshooting
Troubleshooting Doc
Updated about 4 hours ago