Active Directory With LDAP Connector

Last modified 06 Oct 2025 14:27 +02:00

This describes how to configure and use the Active Directory Connector (LDAP), including required permissions, limitations, and best practices.

Status

Both provisioning and synchronization work well.

Recommended connector

Active Directory Connector (LDAP)

Resource configuration

No remote connector server is needed for this connector.

Administrative account for provisioning and synchronization

To support provisioning and synchronization of users:

  1. In the Active Directory domain "Delegate Control" mechanism, assign the following privileges to the midPoint administrative account:

    • Create, delete and manage user accounts

    • Reset user passwords and force password change at next logon

    • Read all user information

    • Create, delete and manage groups

    • Modify the membership of a group

    • Create, delete and manage managed service accounts (MSA)

      If you are using a newer version of Windows where the Create, delete and manage groups option is not available, make the midPoint account that accesses AD a member of the Domain admin group.
  2. Add the midPoint account to the Domain admin group using the following Powershell command:

    Add-ADGroupMember -Identity 'CN=Domain Admins,CN=Users,DC=ad2019,DC=lab,DC=evolveum,DC=com' -Members 'CN=MidPoint,CN=Users,DC=ad2019,DC=lab,DC=evolveum,DC=com'
  3. For LiveSync, make sure you have the "Replicating Directory Changes" (DS-Replication-Get-Changes) permission. Assign it by using the following Powershell command:

    #############
    # Module ActiveDirectory is needed to be loaded just once.
    # In case of AD: "prefix" the module is not loaded automatically.
    #############
    Import-Module ActiveDirectory
    
    $path = "AD:DC=ad2019,DC=lab,DC=evolveum,DC=com"
    $acl = Get-Acl -Path $path
    $ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule(
    	[System.Security.Principal.IdentityReference] (get-aduser -identity midpoint).SID,
    	[System.DirectoryServices.ActiveDirectoryRights] 'ExtendedRight',
    	[System.Security.AccessControl.AccessControlType] 'Allow',
    	(new-object Guid '1131f6aa-9c07-11d1-f79f-00c04fc2dcd2')
    )
    $acl.AddAccessRule($ace)
    Set-Acl -Path $path -AclObject $acl
    Each permission in AD has its own GUID. This unique ID is used for assignments. In case of the DS-Replication-Get-Changes permission, it is 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2 (https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/1522b774-6464-41a3-87a5-1e5633c3fbbb).

Framework: ConnId
Bundle: com.evolveum.polygon.connector-ldap
Version: most recent stable version
Connector: com.evolveum.polygon.connector.ldap.ad.AdLdapConnector

Connector configuration

Currently, there is no published documentation.

Active Directory LDAP strangeness

Active Directory in the default configuration is not really an LDAPv3-compliant server. It has many quirks, extensions, modifications, and it twists the LDAP standard almost beyond recognition. The LDAP connector was modified to survive this brutal "interpretation" of the LDAP specifications. However, there are many things that needs to be taken into account when configuring an AD resource:

  • instanceType, nTSecurityDescriptor and objectCategory are formally defined as mandatory attributes in the top object class. This means they are (formally) mandatory for all objects accessed using an LDAP connection.
    However, the reality is different. It seems to be OK to create an object without these attributes. Therefore, for a proper operation of midPoint, we recommend to modify the schema using the limitations mechanism in the midPoint Resource Schema Handling by setting minOccurs=0. (This is already done in the sample referenced below.)

  • Objects can easily have attributes that are not defined in any object classes that they have. E.g., a normal user (the user object class) may have an info attribute. If such extra attributes are used in your AD instance, then the best way is to configure them as operational attributes in the connector configuration and define them explicitly in the Resource Schema Handling (see MID-3379).

Resource configuration examples

<connectorConfiguration xmlns:icfc="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3">
        <icfc:configurationProperties xmlns:icfcldap="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/com.evolveum.polygon.connector-ldap/com.evolveum.polygon.connector.ldap.ad.AdLdapConnector">
            <icfcldap:host>ad.example.com</icfcldap:host>
            <icfcldap:port>636</icfcldap:port>
            <icfcldap:baseContext>DC=evolveum,DC=com</icfcldap:baseContext>
            <icfcldap:bindDn>CN=midpoint,CN=Users,DC=evolveum,DC=com</icfcldap:bindDn>
            <icfcldap:connectionSecurity>ssl</icfcldap:connectionSecurity>
            <icfcldap:bindPassword>
                <t:clearValue>secret</t:clearValue>
            </icfcldap:bindPassword>
        </icfc:configurationProperties>
        <icfc:resultsHandlerConfiguration>
            <icfc:enableNormalizingResultsHandler>false</icfc:enableNormalizingResultsHandler>
            <icfc:enableFilteredResultsHandler>false</icfc:enableFilteredResultsHandler>
            <icfc:enableAttributesToGetSearchResultsHandler>false</icfc:enableAttributesToGetSearchResultsHandler>
        </icfc:resultsHandlerConfiguration>
    </connectorConfiguration>
    <connectorConfiguration xmlns:icfc="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3">
        <icfc:configurationProperties xmlns:icfcldap="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/com.evolveum.polygon.connector-ldap/com.evolveum.polygon.connector.ldap.ad.AdLdapConnector">
            <icfcldap:host>medusa.lab.evolveum.com</icfcldap:host>
            <icfcldap:port>636</icfcldap:port>
            <icfcldap:baseContext>DC=win,DC=evolveum,DC=com</icfcldap:baseContext>
            <icfcldap:bindDn>CN=midpoint admin1,CN=Users,DC=win,DC=evolveum,DC=com</icfcldap:bindDn>
            <icfcldap:connectionSecurity>ssl</icfcldap:connectionSecurity>
            <icfcldap:bindPassword>
                <t:clearValue>secret</t:clearValue>
            </icfcldap:bindPassword>
            <icfcldap:pagingBlockSize>5</icfcldap:pagingBlockSize> <!-- ridiculously small, just to test paging -->
            <icfcldap:managedAssociationPairs>"user"+memberOf -# "group"+member</icfcldap:managedAssociationPairs>
            <icfcldap:managedAssociationPairs>"group"+ memberOf -# "group"+ member</icfcldap:managedAssociationPairs>
        </icfc:configurationProperties>
    </connectorConfiguration>

See full resource samples for midPoint 4.8 and lower:

See a full resource sample for midPoint 4.9 and higher:

Limitations

Active Directory LDAP schema violates LDAP standards and best practices in a number of ways. The connector is built to tolerate these "quirks" in the AD schema. The underlying LDAP library may complain about the schema issues, however, it is usually safe to ignore these warnings.

Best practices

Passwords

To avoid plain text passwords visible in the repository, refer to String to ProtectedString Connector Configuration.

Full Active Directory schema

Active Directory has a huge schema. When encoded in XSD, the schema has several megabytes. This might require several hundreds of megabytes of memory when processed. Make sure that your midpoint instance has enough memory (heap) to handle that. The impact of the AD schema can be limited by reducing the number of object classes that are processed by midPoint:

    <schema>
       <generationConstraints>
            <generateObjectClass>ri:user</generateObjectClass>
            <generateObjectClass>ri:group</generateObjectClass>
            <generateObjectClass>ri:msDS-ManagedServiceAccount</generateObjectClass>
        </generationConstraints>
    </schema>

See MID-2716

Explicit referential integrity

We recommend turning off explicitReferentialIntegrity for associations with groups. Active Directory will maintain the group membership after renaming accounts automatically.

Example:

...
<association>
    <ref>ri:group</ref>
    <displayName>AD Group Membership</displayName>
    <kind>entitlement</kind>
    <intent>group</intent>
    <direction>objectToSubject</direction>
    <associationAttribute>ri:member</associationAttribute>
    <valueAttribute>ri:dn</valueAttribute>
    <shortcutAssociationAttribute>ri:memberOf</shortcutAssociationAttribute>
    <shortcutValueAttribute>ri:dn</shortcutValueAttribute>
    <explicitReferentialIntegrity>false</explicitReferentialIntegrity>
</association>
...
        <associationType>
            <name>membership</name>
            <subject>
                <objectType>
                    <kind>account</kind>
                    <intent>default</intent>
                </objectType>
                <association>
                    <ref>ri:group</ref>
                    <sourceAttributeRef>ri:group</sourceAttributeRef> <!-- this is the default (the same as "ref") -->
                    <outbound>
                        <name>group-outbound</name>
                        <documentation>
                            Creates an association value from each role that has appropriate projection (to entitlement/group).
                        </documentation>
                        <expression>
                            <associationConstruction>
                                <objectRef>
                                    <mapping>
                                        <expression>
                                            <associationFromLink/>
                                        </expression>
                                    </mapping>
                                </objectRef>
                            </associationConstruction>
                        </expression>
                    </outbound>
                    <inbound>
                        <name>group-inbound</name>
                        <documentation>
                            Creates an assignment from each association value (a group) that has appropriate owner (a role);
                            except for situations where related assignment exists, or where an indirect assignment of the group
                            exists.

                            When the association value is removed, this mapping removes only those assignments that were created
                            by it (in the past).
                        </documentation>
                        <expression>
                            <associationSynchronization>
                                <objectRef>
                                    <correlator/>
                                    <mapping>
                                        <expression>
                                            <shadowOwnerReferenceSearch/>
                                        </expression>
                                        <target>
                                            <path>targetRef</path>
                                        </target>
                                    </mapping>
                                </objectRef>
                                <synchronization>
                                    <reaction>
                                        <situation>unmatched</situation>
                                        <actions>
                                            <addFocusValue/>
                                        </actions>
                                    </reaction>
                                    <reaction>
                                        <situation>matched</situation>
                                        <actions>
                                            <synchronize/>
                                        </actions>
                                    </reaction>
                                    <reaction>
                                        <situation>matchedIndirectly</situation>
                                        <!-- no actions here -->
                                    </reaction>
                                </synchronization>
                            </associationSynchronization>
                        </expression>
                    </inbound>
                    <tolerant>true</tolerant>
                </association>
            </subject>
            <object>
                <objectType>
                    <kind>entitlement</kind>
                    <intent>group</intent>
                </objectType>
            </object>
        </associationType>

National characters

Although the LDAP protocol and data structures are designed to be safe for use with national characters, Active Directory leaves room for improvement in this area. For example, although the LDAP specification states that DNs using different national characters should be considered different identifiers, Active Directory might consider them to be the same (see MID-7355).

Therefore, we strongly recommend to avoid using national characters in Active Directory, especially in identifiers (dn, cn). The midPoint PolyString functionality is designed specifically for this purpose. The following mapping may help create identifiers without national characters:

<attribute>
    <ref>ri:dn</ref>
    <outbound>
        <source>
            <path>givenName</path>
        </source>
        <source>
            <path>familyName</path>
        </source>
        <expression>
            <script>
                <code>
                    'CN=' + basic.concatName(familyName.getNorm(), givenName.getNorm()) + iterationToken + ',OU=Users,DC=example,DC=com'
                </code>
            </script>
        </expression>
    </outbound>
</attribute>

You may need an equivalent mapping for the cn attribute as well.

Increase maxObjects limit

By default, the maxObject option in the connector configuration is set to 10. We recommend to increase this value for production deployments where heavy loads are expected to ensure that all objects are correctly processed by midPoint.

This configuration can also be useful with large groups. For example, the Active directory Domain users group contains all domain users and operations on that group can require more time. Increasing the number of connectors in the pool makes more connector instances available for other operations.

    <connectorConfiguration xmlns:icfc="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3">
        <icfc:connectorPoolConfiguration>
            <icfc:maxObjects>100</icfc:maxObjects>
        </icfc:connectorPoolConfiguration>
          ...
    </connectorConfiguration>
Was this page helpful?
YES NO
Thanks for your feedback