If you have an LDAP server that supports sync repl (rfc4533 content synchronisation) then you are able to synchronise from it to Kanidm for the purposes of coexistence or migration.

If there is a specific Kanidm sync tool for your LDAP server, you should use that instead of the generic LDAP server sync.

Installing the LDAP Sync Tool

See installing the client tools.

Configure the LDAP Sync Tool

The sync tool is a bridge between LDAP and Kanidm, meaning that the tool must be configured to communicate to both sides.

Like other components of Kanidm, the LDAP sync tool will read your /etc/kanidm/config if present to understand how to connect to Kanidm.

The sync tool specific components are configured in it's own configuration file.

# The sync account token as generated by "system sync generate-token".
sync_token = "eyJhb..."

# A cron-like expression of when to run when in scheduled mode. The format is:
#   sec  min   hour   day of month   month   day of week   year
# The default of this value is "0 */5 * * * * *" which means "run every 5 minutes".
# schedule = ""

# If you want to monitor the status of the scheduled sync tool (you should)
# then you can set a bind address here.
# If not set, defaults to no status listener.
# status_bind = ""

# The LDAP URI to the server. This MUST be LDAPS. You should connect to a unique single
# server in the LDAP topology rather than via a load balancer or dns srv records. This
# is to prevent replication conflicts and issues due to how 389-ds and openldap sync works.
ldap_uri = "ldaps://specific-server.ldap.kanidm.com"
# Path to the LDAP CA certificate in PEM format.
ldap_ca = "/path/to/kanidm-ldap-ca.pem"
# The DN of an account with content sync rights. On 389-ds, by default cn=Directory Manager has
# this access. On OpenLDAP you must grant this access.
ldap_sync_dn = "cn=Directory Manager"
ldap_sync_pw = "directory manager password"

# The basedn to search
ldap_sync_base_dn = "dc=ldap,dc=dev,dc=kanidm,dc=com"
# Filter the entries that are synchronised with this filter
# NOTE: attribute-value-assertions with spaces require quoting!
ldap_filter = "(|(objectclass=person)(objectclass=posixgroup))"
# ldap_filter = "(cn=\"my value\")"

# By default Kanidm seperates the primary account password and credentials from
# the unix credential. This allows the unix password to be isolated from the
# account password so that compromise of one doesn't compromise the other. However
# this can be surprising for new users during a migration. This boolean allows the
# user password to be set as the unix password during the migration for consistency
# and then after the migration they are "unlinked".
# sync_password_as_unix_password = false

# The objectclass used to identify persons to import to Kanidm.
# If not set, defaults to "person"
# person_objectclass = ""

# Attribute mappings. These allow you to bind values from your directory server
# to the values that Kanidm will import.
# person_attr_user_name = "uid"
# person_attr_display_name = "cn"
# person_attr_gidnumber = = "uidnumber"
# person_attr_login_shell = "loginshell"
# person_attr_password = "userpassword"

# If the password value requires a prefix for Kanidm to import it, this can be optionally
# provided here.
# person_password_prefix = ""

# The objectclass used to identify groups to import to Kanidm.
# If not set, defaults to "groupofnames"
# group_objectclass = ""

# Attribute mappings. These allow you to bind values from your directory server
# to the values that Kanidm will import.
# group_attr_name = "cn"
# group_attr_description = "description"
# group_attr_member = "member"
# group_attr_gidnumber = "gidnumber"

# The sync tool can alter or exclude entries. These are mapped by their syncuuid
# The syncuuid is derived from nsUniqueId in 389-ds. It is the entryUUID for OpenLDAP
# This is chosen oven DN because DN's can change with modrdn where nsUniqueId/entryUUID is
# immutable and requires an entry to be deleted and recreated.

# my-problematic-entry
exclude = true

# Remap the uuid of this entry to a new uuid on Kanidm
# map_uuid = <uuid>

# Remap the name of this entry to a new name on Kanidm
# map_name = <name>

# Remap the gidnumber for groups, and uidnumber for users
# map_gidnumber = <number>

This example is located in examples/kanidm-ldap-sync.

In addition to this, you may be required to make some configuration changes to your LDAP server to enable synchronisation.


You must enable the syncprov overlay in slapd.conf

moduleload syncprov.la
overlay syncprov

In addition you must grant an account full read access and raise its search limits.

access to *
    by dn.base="cn=sync,dc=example,dc=com" read
    by * break

limits dn.exact="cn=sync,dc=example,dc=com" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited

For more details see the openldap administration guide.

389 Directory Server

You can find the name of your 389 Directory Server instance with:

dsconf --list

Using this you can show the current status of the retro changelog plugin to see if you need to change its configuration.

dsconf <instance name> plugin retro-changelog show
dsconf slapd-DEV-KANIDM-COM plugin retro-changelog show

You must modify the retro changelog plugin to include the full scope of the database suffix so that the sync tool can view the changes to the database. Currently dsconf can not modify the include-suffix so you must do this manually.

You need to change the nsslapd-include-suffix to match your LDAP baseDN here. You can access the basedn with:

ldapsearch -H ldaps://<SERVER HOSTNAME/IP> -x -b '' -s base namingContexts
# namingContexts: dc=ldap,dc=dev,dc=kanidm,dc=com

You should ignore cn=changelog as this is a system internal namingContext. You can then create an ldapmodify like the following.

fn main() {
dn: cn=Retro Changelog Plugin,cn=plugins,cn=config
changetype: modify
replace: nsslapd-include-suffix
nsslapd-include-suffix: dc=ipa,dc=dev,dc=kanidm,dc=com

And apply it with:

ldapmodify -f change.ldif -H ldaps://<SERVER HOSTNAME/IP> -x -D 'cn=Directory Manager' -W
# Enter LDAP Password:

You must then reboot your 389 Directory Server.

Running the Sync Tool Manually

You can perform a dry run with the sync tool manually to check your configurations are correct and that the tool can synchronise from LDAP.

kanidm-ldap-sync [-c /path/to/kanidm/config] -i /path/to/kanidm-ldap-sync -n
kanidm-ldap-sync -i /etc/kanidm/ldap-sync -n

Running the Sync Tool Automatically

The sync tool can be run on a schedule if you configure the schedule parameter, and provide the option "--schedule" on the cli

kanidm-ldap-sync [-c /path/to/kanidm/config] -i /path/to/kanidm-ldap-sync --schedule
kanidm-ldap-sync -i /etc/kanidm/ldap-sync --schedule

As the sync tool is part of the tools container, you can run this with:

docker create --name kanidm-ldap-sync \
  --user uid:gid \
  -p 12345:12345 \
  -v /etc/kanidm/config:/etc/kanidm/config:ro \
  -v /path/to/ldap-sync:/etc/kanidm/ldap-sync:ro \
  kanidm-ldap-sync -i /etc/kanidm/ldap-sync --schedule

Monitoring the Sync Tool

When running in schedule mode, you may wish to monitor the sync tool for failures. Since failures block the sync process, this is important for a smooth and reliable synchronisation process.

You can configure a status listener that can be monitored via tcp with the parameter status_bind.

An example of monitoring this with netcat is:

# status_bind = "[::1]:12345"
# nc ::1 12345

It's important to note no details are revealed via the status socket, and is purely for Ok or Err status of the last sync. This status socket is suitable for monitoring from tools such as Nagios.