U.S. +1 (312) 214 3570  |  E.U +34 (91) 320-5524

Symlabs LDAP Proxy Tutorials


Tutorial #1 - Load Balancing

Tutorial #1 - Load Balancing

Click here to download this tutorial as a PDF file.

1 Overview

In this tutorial we will be demonstrating load balancing in around-robin fashion between two directories, Directory 1 and 2. LDAPrequests that come to the LDAP Proxy will be sent in a round-robinfashion first to Directory 1, then to Directory 2, then to Directory 1,then to Directory 2 and so on.

2 Assumptions

  1. LDAP Proxy is installed and configured properly; LDAPProxy is currently running.

  2. Directory 1 & 2 are both installed and accessiblefrom the computer on which LDAP Proxy is installed.

  3. Both of your directories are populated with users.

  4. Directory 1 & 2 are replicating with or are nearlyidentical to one another.

  5. Directory 1 & 2 are both accessible on port 389(default ldap port)

  6. You have a good understanding of the DIT structure of yourdirectories.

  7. Port 3890 is available on the computer in which LDAP Proxyis installed.

  8. You have the ability to view the proper logs in Directory1 and 2.

3 Create a NewConfiguration

  1. Click File on the menu bar, then click New.

  2. Click the OK button when asked which server you want tocreate the new configuration on (the default server is Local).

  3. Enter LoadBalancingTutorial for the filename whenprompted, then click the Save button and the following will appear:

  4. LDAP Proxy New configuration
    Fig-1: LDAP Proxy New configuration

3.1 Server GroupConfiguration

Server Groups are the directories where your user informationis stored. Examples include Active Directory, Sun Directory Server andOracle Internet Directory. For this tutorial we will be creating oneServer Group that contains two directories, Directory 1 and Directory2.

  1. Click on the Output button on the left-hand side of theapplication and the following will appear:

  2. Add a server group
    Fig-2: Add a Server Group

  3. Click on the New Server Group button near the bottom ofthe screen.

  4. Click on ReplicatedDirectories to enter theconfiguration panel for your new Server Group and leave the ServerGroup Type as Automatic and then click the Okay button.

  5. Verify that the Protocol is set to ldap.

  6. Under the Servers tab, enter the Hostname / IP Address andthe Port of Directory 1.

  7. Under the Servers tab, enter the Hostname / IP Address andthe Port of Directory 2.

  8. Configure the server group
    Fig-3: Configure the server group

  9. Click on the Reliability/Performancetab and click on the Load-Balancing radio button.

  10. Enable Load Balancing
    Fig-4: Enable Load Balancing

  11. Click the OK button near the top of the application tosave the ReplicatedDirectories Server Group Configuration.

3.2 ListenerConfiguration

  1. Click on the Input button on the left-hand side of theapplication and the following will appear:

  2. Add an LDAP Proxy Listener
    Fig-5: Add an LDAP Proxy Listener

  3. Click on the New Listener button near the bottom of thescreen.

  4. Enter LoadBalancing for the new input / listener and thenclick the Okay button.

  5. Click on the LoadBalancing node on the left-handside of the screen and the following will appear:

  6. LDAP Proxy Listener configuration
    Fig-6: LDAP Proxy Listener configuration

  7. Under the Main Listener Properties tab, make sure theProtocol is set to ldap.

  8. Under the Main Listener Properties tab, set the port to3890.

  9. Under the Main Listener Properties tab, selectReplicatedDirectories from the dropdown box to the right of DefaultServer Group.

  10. Click the OK button near the top of the screen to save theListener configuration.

4 Health MonitoringConfiguration

Health Checking is an important feature of Directory Extender.You will need it whenever you are using load-balancing or fail-over inserver groups. The principle is simple: LDAP Proxy will periodicallycheck every server by sending simple requests to it. Whenever LDAPProxy notices that a server has gone down or come back up, the serverstatus will change respectively. LDAP Proxy makes use of this stateinformation for deciding where to send each next request.

  1. Click on the Health Monitoring button on the left-handside of the screen and the following will appear:

    LDAP Proxy Health monitoring configuration
    Fig-7: LDAP Proxy Health monitoring configuration

  2. Make sure the Enable Health Checking box is checked andset the Interval to 5 seconds (for testing purposes only).

  3. In the Operation for Health Checking section, make surethe BIND radio-button is selected. Set the Timeout to 5 seconds and theNumber of Iterations to 3.

  4. In the Debug Level section, move the slider to Trace.

  5. In the Health Checking Parameters section, enter theappropriate information for the Bind DN and Password fields. Thesecredentials are used to determine if the directories are up andrunning.

5 Save Configuration

When you created the new configuration you were prompted toenter a filename for your configuration. The file type for this file isldif. The configuration must be saved before the LDAP Proxy can belaunched for the first time. Also, the configuration must be saved andthe LDAP Proxy re-launched before changes to the configuration willtake effect.

  1. Click on the File button on the menu bar.

  2. Click Save and your configuration will then be ready tolaunch.

6 Launch and TestConfiguration

  1. Click the Process button on the menu bar.

  2. Click Run on the drop-down menu. At this point the LDAPProxy is running and is ready to accept LDAP requests.

    LDAP Proxy Launch and test configuration
    Fig-8: LDAP Proxy Launch and test configuration

  3. Click the Extras button on the menu bar.

  4. Click LDAP Browser on the drop-down menu and the followingwill appear:

    The LDAP Browser Connection Window
    Fig-9: The LDAP Browser Connection Window

  5. In the Name textbox, enter Load Balancing.

  6. In the Hostname textbox, enter the IP Address of thecomputer that LDAP Proxy is installed on.

  7. In the Port textbox, enter 3890.

  8. In the Root Suffix textbox, enter the DN you'd like to bethe root of your LDAP request.

  9. In the Bind DN textbox, enter the DN of the user that hasappropriate access to both Directory 1 and 2.

  10. Enter the Password twice for the user specified in thestep above.

  11. Click the Test button.

  12. Assuming you entered the correct information, a TestSuccessful! message will appear. Click the OK button. At this point,the LDAP Proxy routed a Bind request to either Directory 1 or 2 whichyou can verify by viewing the logs for Directory 1 and 2.

  13. Click the Test button again.

  14. Again, a Test Successful! message will appear. Click theOK button. At this point, the LDAP Proxy routed another Bind request toeither Directory 1 or 2. This time however, the Bind request went tothe directory that it did not go last time. Again, this can be verifiedby viewing the logs for Directory 1 and 2.

  15. You can continue testing the connection or viewing entriesin the LDAP browser and you can verify that the LDAP operations arealternating between the two directories by viewing the logs forDirectory 1 and 2.

TOP

Tutorial #2 - Failover

Tutorial #2 - Failover

Click here to download this tutorial as a PDF file.

1 Overview

In this tutorial we will be demonstrating failover with fail-back. We have two directories, Directory 1 and 2 that are replicating with one another. Directory 1 is the default which receives all of LDAP requests from the LDAP Proxy until it becomes unavailable. Once Directory 1 becomes unavailable, all LDAP requests get temporarily routed to Directory 2 until Directory 1 goes back online.

2 Assumptions

  1. LDAP Proxy is installed and configured properly; LDAP Proxy is currently running.

  2. Directory 1 & 2 are both installed and accessible from the computer on which LDAP Proxy is installed.

  3. Both of your directories are populated with users.

  4. Directory 1 & 2 are replicating with or are nearly identical to one another.

  5. Directory 1 & 2 are both accessible on port 389 (default ldap port)

  6. You have a good understanding of the DIT structure of your directories.

  7. Port 3890 is available on the computer in which LDAP Proxy is installed.

  8. You have the ability to view the proper logs in Directory 1 and 2.

3 Create a New Configuration

  1. Click File on the menu bar, then click New.

  2. Click the OK button when asked which server you want to create the new configuration in (the default server is Local).

  3. Enter FailoverTutorial for the filename when prompted, then click the Save button.

3.1 Server Group Configuration

Server Groups are the directories where your user information is stored. Examples include Active Directory, Sun Directory Server and Oracle Internet Directory. For this tutorial we will be creating one Server Group that contains two directories, Directory 1 and Directory 2.

  1. Click on the Output button on the left-hand side of the application to begin to configure a servergroup.

  2. Click on the New Server Group button near the bottom of the screen.

  3. Enter ReplicatedDirectories for your new Server Group and leave the Server Group Type as Automatic and then click the Okay button.

  4. Click on the ReplicatedDirectories button on the left-hand side of the screen.


  5. Fig-1: Configuring a Server Group in DSGUI

  6. Under the Servers tab, enter the Hostname / IP Address and the Port of Directory 1.

  7. Under the Servers tab, enter the Hostname / IP Address and the Port of Directory 2.

  8. Click on the Reliability/Performance tab and verify that the Failover radio button is checked.

  9. In the Fail-over Algorithm section, verify that the default is selected, First available Server, with Fail-back.

  10. Click the OK button near the top of the application to save the ReplicatedDirectories Server Group Configuration.

3.2 Listener Configuration

  1. Click on the Input button on the left-hand side of the application.

  2. Click on the New Listener button near the bottom of the screen.

  3. Enter Failover for the new input / listener and then click the Okay button.

  4. Click on the Failover node on the left-hand side of the screen to begin configuring the listener.


  5. Fig-2: Configuring a Listener

  6. Under the Main Listener Properties tab, make sure the Protocol is set to ldap.

  7. Under the Main Listener Properties tab, set the port to 3890.

  8. Under the Main Listener Properties tab, select ReplicatedDirectories from the dropdown box to the right of Default Server Group.

  9. Click the OK button near the top of the screen to save the Listener configuration.

4 Health Monitoring Configuration

Health Checking is an important feature of Directory Extender. You will need it whenever you are using load-balancing or fail-over in server groups. The principle is simple: LDAP Proxy will periodically check every server by sending simple requests to it. Whenever LDAP Proxy notices that a server has gone down or come back up, the server status will change respectively. LDAP Proxy makes use of this state information for deciding where to send each next request.

  1. Click on the Health Monitoring button on the left-hand side of the screen.

  2. Make sure the Enable Health Checking box is checked and set the Interval to 5 seconds (for testing purposes only).

  3. In the Operation for Health Checking section, make sure the BIND radio-button is selected. Set the Timeout to 5 seconds and the Number of Iterations to 3.

  4. In the Debug Level section, select Warning, Info and Trace.

  5. In the Health Checking Parameters section, enter the appropriate information for the Bind DN and Password fields. These credentials are used to determine if the directories are up and running.


  6. Fig-3: Configure Health Monitoring 6

5 Save Configuration

When you created the new configuration you were prompted to enter a filename for your configuration. The file type for this file is ldif. The configuration must be saved before the LDAP Proxy can be launched for the first time. Also, the configuration must be saved and the LDAP Proxy re-launched before changes to the configuration will take effect.

  1. Click on the File button on the menu bar.

  2. Click Save and your configuration will then be ready to launch.

6 Launch and Test Configuration

  1. Click the Process button on the menu bar.

  2. Click Run on the drop-down menu. At this point the LDAP Proxy is running and is ready to accept LDAP requests.

  3. Click the Extras button on the menu bar.

  4. Click LDAP Browser on the drop-down menu and enter the details required to connect to the listener that you have configured:


  5. Fig-4: Enter the details required to connect to the listener

  6. In the Name textbox, enter Failover.

  7. In the Hostname textbox, enter the IP Address of the computer that LDAP Proxy is installed on.

  8. In the Port textbox, enter 3890.

  9. In the Root Suffix textbox, enter the DN you'd like to be the root of your LDAP request.

  10. In the Bind DN textbox, enter the DN of the user that has appropriate access to both Directory 1 and 2.

  11. Enter the Password twice for the user specified in the step above.

  12. Click the Test button.

  13. Assuming you entered the correct information, a Test Successful! message will appear. Click the OK button. At this point, the LDAP Proxy routed a Bind request to Directory 1 which you can verify by viewing the logs for Directory 1.

  14. Click the Test button again.

  15. Again, a Test Successful! message will appear. Click the OK button. At this point, the LDAP Proxy routed another Bind request to Directory 1. Again, this can be verified by viewing the logs for Directory 1.

  16. Take Directory 1 offline and wait for approximately 1 minute.

  17. Click the Test button again.

  18. Again, a Test Successful! message will appear. Click the OK button. At this point, the LDAP Proxy routed a Bind request to Directory 2. This can be verified by viewing the logs for Directory 2.

TOP

Tutorial #3 - Merging Organizational Units in Active Directory

Tutorial #3 - Merging Active Directory Trees

Click here to download this tutorial as a PDF file.

1 Overview

A common problem faced by users of Active Directory arises when users are stored within the Directory in separate organisational units, and a client application is only able to search a single tree for user data. For instance your Active Directory may be split up into the organisational units: Sales, Marketing, Accounts and Support. Users within each department are stored within their respective organisational units. Unfortunately, many applications will only use a single tree to perform a search for user data. If an application is authenticating against data stored in Active Directory, you may find that the application can only authenticate users from one department, as it is unable to recursively search through all of the other trees.

Symlabs LDAP Proxy is able to overcome this problem easily, using the Merge Trees plugin. Using the LDAP Proxy, you are able to merge all of the trees on the fly, so that a client application can be configured to search a virtual tree that includes all of the users from each organisational unit.

Active Directory can group users in different Organizational Units
Fig-1: Active Directory can group users in different Organizational Units

2 Assumptions

  1. LDAP Proxy is installed and configured properly; LDAP Proxy is currently running.

  2. Active Directory is installed and is currently running and accessible to LDAP Proxy.

  3. Active Directory is configured in such a way that there are a number of different organisational units and that each unit has been populated with differing userdata.

  4. Port 3890 is available on the computer in which LDAP Proxy is installed.

3 Create a New Configuration

  1. Click File on the menu bar, then click New.

  2. Click the OK button when asked which server you want to create the new configuration in (the default server is Local).

  3. Enter MergeTreesTutorial for the filename when prompted, then click the Save button.

3.1 Server Group Configuration

Server Groups are the directories where your user information is stored. For this tutorial we will be creating one Server Group that contains a single directory pointing to your Active Directory server.

  1. Click on the Output button on the left-hand side of the application to begin to configure a servergroup.

  2. Click on the New Server Group button near the bottom of the screen.

  3. Enter ActiveDirectory for your new Server Group and leave the Server Group Type as Automatic and then click the Okay button.

  4. Click on the ActiveDirectory button on the left-hand side of the screen.

  5. Configure a Server Group for your Active Directory server
    Fig-2: Configure a Server Group for your Active Directory server

  6. Under the Servers tab, enter the Hostname / IP Address and the Port of your Active Directory server.

  7. Click OK to save the change.

3.2 Listener Configuration

  1. Click on the Input button on the left-hand side of the application.

  2. Click on the New Listener button near the bottom of the screen.

  3. Enter ActiveListener for the new input / listener and then click the OK button.

  4. Click on the ActiveListener button on the left-hand side of the screen to begin configuring the listener.

  5. Configure a Listener for LDAP Proxy
    Fig-3: Configure a Listener for LDAP Proxy

  6. Under the Main Listener Properties tab, make sure the Protocol is set to ldap.

  7. Under the Main Listener Properties tab, set the port to 3890.

  8. Under the Main Listener Properties tab, select ActiveDirectory from the dropdown box to the right of Default Server Group.

  9. Due to the varied way in which various browsers and servers present attribute information, it is good practice to make use of Canonicalization on Attribute Names to avoid incompatibilities down the line. Check all of the boxes in the Attribute Names window area.

  10. Click the OK button near the top of the screen to save the Listener configuration.

4 Add Processing Stages

In this tutorial, we will also make use of the Add Entries plugin so that our merged trees are visible to browsers searching higher up in the tree, as the Merge Trees plugin will only come into action when the virtual tree that we create is requested. As a result, it will make sense to create two separate Processing Stages to hold these plugins.

  1. Click on Processing in the Navigator on the left.

  2. Click on the New Stage button, and name the stage addEntry.

  3. Add a Processing Stage for each plugin that you use
    Fig-4: Add a Processing Stage for each plugin that you use

  4. Click on the addEntry node that has been created in the Navigator tree, and click on the Add Plugin button.

  5. A pop-up dialog will appear. Scroll through the list of plugins and select the Add Entries plugin. Click OK.

  6. Attach the Add Entries plugin to the stage
    Fig-5: Attach the Add Entries plugin to the stage

  7. Click on the Add Entries plugin listed in the Navigator Tree.

  8. Click on the New Virtual Entry button and name the new entry "allusers".

  9. Click on the Add Entries plugin to create a New Virtual Entry
    Fig-6: Click on the Add Entries plugin to create a New Virtual Entry

  10. Click on the "allusers" node in the Navigator tree.

  11. In the Entry Dn field, provide the DN that you wish to use to refer to the virtual tree. In our example, we will use ou=allusers,ou=LiveOffice,dc=testsymlabs,dc=com. In order to keep our configuration consistent, and because we are using canonicalization, note that all of the Attribute Names in the DN are entered in lower case.

  12. Configure the allusers entry for the virtual tree
    Fig-7: Configure the allusers entry for the virtual tree

  13. You will now need to provide some attributes for the virtual DN that you are creating. In the Attribute Type column of the table, create an attribute type called "objectclass". In the Attribute Values column, enter a value of "top" and a second value of "organizationalunit".

  14. Create a second Attribute type called "ou" and assign it the value "allusers".

  15. Click on the Processing node in the Navigator panel again, and then on the New Stage button. Name the new stage MergeTrees, as this stage will contain the Merge Trees plugin.

  16. Click on the Add Plugins button and scroll through the list of plugins until you can select the Merge Trees plugin. Click OK.

  17. Add the Merge Trees Plugin to the new Processing Stage
    Fig-8: Add the Merge Trees Plugin to the new Processing Stage

  18. Click on the Merge Trees plugin node in the Navigator panel.

  19. In the Condition section of the panel on the right, add a rule to only process if the Base DN matches our virtual tree DN. So in our example, we will enter ou=allusers,ou=LiveOffice,dc=testsymlabs,dc=com. Once again, note that all of the Attribute Names that make up the DN are specified in lowercase in order to take advantage of canonicalization.

  20. In the Joined Tree DN field, enter the DN for the virtual tree that you intend to create. Once again, in our example, we will enter ou=allusers,ou=LiveOffice,dc=testsymlabs,dc=com. And again we have specified all Attribute Names in lower case.

  21. Finally, in the table, enter the DNs for each of the trees that you wish to merge. So, for our example, we will add the following entries:
    ou=Accounts,ou=LiveOffice,dc=testsymlabs,dc=com
    ou=Sales,ou=LiveOffice,dc=testsymlabs,dc=com
    ou=Marketing,ou=LiveOffice,dc=testsymlabs,dc=com
    ou=Support,ou=LiveOffice,dc=testsymlabs,dc=com
    And for each of these entries we will use the Server Group, VirtualDirectory which we created earlier.

  22. Configure the Merge Trees Plugin
    Fig-9: Configure the Merge Trees Plugin

  23. Click OK to save this part of the configuration.

5 Attach the Processing Stages to the Listener

  1. Now go back to the Listener node in the Navigator panel, and click on the ActiveListener that we created earlier.

  2. Click on the Attached Stages tab.

  3. Attach the Processing Stages to the Listener
    Fig-10: Attach the Processing Stages to the Listener

  4. In the Stages list, double click on the first line and select the AddEntry stage.

  5. A new line will appear, double click on it and select the MergeTrees stage.

  6. Click OK to save this change.

  7. Finally click on the Save button in the toolbar, or choose the option to Save Config from the File menu.

6 Testing the configuration.

You should now have completed configuring an instance of LDAP Proxy that will be able to merge different trees within Active Directory to present them as a single virtual tree. To test the new configuration, we will start the LDAP Proxy instance and then connect to it using an LDAP browser. Using the browser, we will be able to see the RDN ou=allusers listed, because the Add Entries plugin will make this available to the browser. When we actually browse this portion of the tree, all of the users that are listed in the other trees will be listed as users within the ou=allusers RDN, because the Merge Trees plugin will make this information available on the fly. Once you are certain that everything is working as expected, you will be able to configure your application to query this virtual tree to access the details of users in all of the DNs that you have configured to be merged by the Merge Trees plugin.

  1. Click on the Start button in the toolbar, to launch an instance of LDAP Proxy using the current configuration.

  2. Once the configuration is running, click on the LDAP Browser icon in the toolbar to launch the LDAP Browser. You could test this using another LDAP Browser if you have a preference, but the built-in browser will let you quickly determine whether your configuration is working as expected.

  3. In the dialog that opens up, enter the relevant details to access the instance of LDAP Proxy that you have just configured. So, in our example, we will enter:
    Hostname: localhost
    Port: 3890
    Root Suffix: DC=testsymlabs,DC=com
    Bind DN: CN=Administrator,CN=Users,DC=testsymlabs,DC=com
    Password: secret

  4. Enter the details to connect to LDAP Proxy into the LDAP Browser
    Fig-11: Enter the details to connect to LDAP Proxy into the LDAP Browser

  5. Click the Test Connection button.

  6. If the test connection was succesful, click OK.

  7. Use the browser to navigate your way through the tree until you have opened the DN that should contain your virtual tree. In our example, this would be: ou=LiveOffice,dc=testsymlabs,dc=com.You should now see the virtual tree listed in the browser. This is available to browse because the Add Entries plugin has inserted the DN into the tree.

  8. Expand the virtual tree (ou=allusers,ou=LiveOffice,dc=testsymlabs,dc=com) and you will now see all of the users listed from the original DNs that have been merged.

  9. The allusers DN should now show all of the users from the merged DNs
    Fig-12: The allusers DN should now show all of the users from the merged DNs

  10. You can now confidently configure your application to search this new virtual tree in the LDAP Proxy to find all users.

TOP

Tutorial #4 - Working with Virtual Trees

Tutorial #4 - Working with Virtual Trees

Click here to download this tutorial as a PDF file.

1 Overview

In this tutorial we will explain how to build a virtual treeusing the Virtual Tree facility that is included with the V5.0 releaseof the LDAP Proxy software. We will show how to configure LDAP Proxy topresent a Virtual Tree, and then show how different mount points canallow you to quickly attach data from different repositories ontodifferent branches within your virtual tree.

2 Assumptions

  1. LDAP Proxy is installed and configured properly; LDAPProxy is currently running.

  2. Directory 1 & 2 are both installed and accessiblefrom the computer on which LDAP Proxy is installed.

  3. Both of your directories are populated with users.

  4. Directory 1 & 2 contain different user data.

  5. Directory 1 & 2 are both accessible on port 389(default ldap port)

  6. You have a good understanding of the DIT structure of yourdirectories.

  7. Port 3890 is available on the computer in which LDAP Proxyis installed.

3 Create a NewConfiguration

  1. Click File on the menu bar, then click New.

  2. Click the OK button when asked which server you want tocreate the new configuration on (the default server is Local).

  3. Enter VirtualTreeTutorial for the filename when prompted,then click the Save button and the following will appear:

  4. LDAP Proxy New configuration
    Fig-1: LDAP Proxy New configuration

3.1 Server GroupConfiguration

Server Groups contain the directories where your userinformation is stored. Examples include Active Directory, Sun DirectoryServer and Oracle Internet Directory. If you have replica directories,they can be stored in a single ServerGroup and you can use the built-inload balancing or failover algorithms to improve availability. However,for this tutorial we will be creating two separate Server Groups thatcontains two different directories, Directory 1 and Directory 2. Tobegin with, we will only configure one of these Server Groups.

  1. Click on the Output button on the left-hand side of theapplication and the following will appear:

  2. Add a server group
    Fig-2: Add a Server Group

  3. Click on the New Server Group button near the bottom ofthe screen.

  4. Enter ServerGroup01 for your new Server Group and leavethe Server Group Type as Automatic and then click the Okay button.

  5. Verify that the Protocol is set to ldap.

  6. Under the Servers tab, enter the Hostname / IP Address andthe Port of Directory 1.

  7. Configure the server group
    Fig-3: Configure the server group

  8. Click on the Connection Pooling taband check the 'Use connection pooling' option.

  9. Select the option to 'Use fixed credentials' and enter theBind DN and password of a trusted user on your directory.

  10. Enable Connection Pooling
    Fig-4: Enable Connection Pooling

  11. Click the OK button near the top of the application tosave the Server Group Configuration.

3.2 ListenerConfiguration

  1. Click on the Input button on the left-hand side of theapplication and the following will appear:

  2. Add an LDAP Proxy Listener
    Fig-5: Add an LDAP Proxy Listener

  3. Click on the New Listener button near the bottom of thescreen.

  4. Enter VirtualTree for the new input / listener and thenclick the Okay button.

  5. Click on the VirtualTree button on the left-hand side ofthe screen and the following will appear:

  6. LDAP Proxy Listener configuration
    Fig-6: LDAP Proxy Listener configuration

  7. Under the Main Listener Properties tab, make sure theProtocol is set to ldap.

  8. Under the Main Listener Properties tab, set the port to3890.

  9. Under the Main Listener Properties tab, in the RoutingInformation box, select the Virtual Tree option.

  10. Click the OK button near the top of the screen to save theListener configuration.

4 Create a VirtualTree

You will now need to define a Virtual Tree that will beattached to the listener that you have created. You can get started byclicking on the New Virtual Entry Root button in the RoutingInformation box on the Main Listener Properties tab of your newlistener. This will prompt you for a name for the root entry of yourVirtual Tree. This should be the base DN that you wish to use for yourtree. In this example, we will use dc=mycompany,dc=com.

  1. Once you have created the root entry for your VirtualTree, it should appear in the navigation panel on the left. Click onit, and you will be able to edit the attributes for the virtual entry.You should, at least, define an 'objectclass' attribute and specify thebase naming attribute. The objectclass attribute, in this case, canhave the values 'top' and 'domain'.

  2. Editing the Virtual Entry Root
    Fig-7: Editing the Virtual Entry Root

  3. You are now able to create a virtual entry, within yourVirtual Tree, by simply right-clicking on the root of your virtual treeand clicking on the New Virtual Entry option in the context menu. Usethis to create an entry with the RDN 'ou=People'.

  4. As with the root entry, you will need to edit theattributes for your virtual entry, creating an objectclass and a namingattribute. In this case, we are defining an 'organizationalunit' as theobjectclass, and the naming attribute 'ou' will have the value 'People'.

  5. Adding and editing a Virtual Entry or branch within your tree
    Fig-8: Adding and editing a Virtual Entry or branch within your tree

  6. Finally, it is also possible to create Virtual MountPoints within your tree. These mount points are used to create virtualbranches where data stored in a backend directory can be attached tothe tree. To do this, you can right-click on the virtual entry'ou=People' in the virtual tree, and select the option to Add a VirtualMount Point, from the context menu.

  7. Provide an appropriate RDN for this new virtual mountpoint. In this case, we will assume that we are attaching a branch froma directory of employees, and we will call the virtual mount point'ou=GeneralStaff'.

  8. Once you have created the mount point, you will need tospecify the Server Group from which to obtain the data that you wish toattach, and the DN where the data is stored. In this case, there shouldonly be one Server Group, ServerGroup01. In our directory, the DN thatwe are attaching is 'ou=People,dc=my_organization,dc=com'. This may bedifferent in your own directory.

  9. Attaching data to your Virtual Tree using a Virtual Mount Point Entry
    Fig-9: Attaching data to your Virtual Tree using a Virtual Mount PointEntry

  10. Now click on the VirtualTree node in the navigation andclick to the Virtual Tree tab. Here, you will need to define a BindException, to forward particular BIND requests on to a backend ServerGroup. In the Bind Request  Exceptions section of theconfiguration panel, add an entry for your administrative user(cn=dirmanager) and select ServerGroup01 as the default servergroup tohandle bind requests for this user.

  11. Define a Bind Request Exception for your virtual tree
    Fig-10: Define a Bind Request Exception for your Virtual Tree

5 Adding Servers andattaching data to the tree

At this point, the Virtual Tree is ready to work, and if youhad to save the configuration and start it, you would be able to accessthe virtual tree with any LDAP client. But before we do this, it may beuseful to explore how easy it is to add other repositories to theconfiguration and to attach data stored in these repositories to thevirtual tree. This will help to demonstrate the true power of usingVirtual Trees within your configuration.

  1. First, let's add a second ServerGroup, by clicking on theOutput node of the configuration navigator and then on the New ServerGroup button.

  2. Enter ServerGroup02 for your new Server Group and leavethe Server Group Type as Automatic and then click the Okay button.

  3. Verify that the Protocol is set to ldap.

  4. Under the Servers tab, enter the Hostname / IP Address andthe Port of Directory 2.

  5. Configure the second server group
    Fig-11: Configure the second server group

  6. Click on the Connection Pooling taband check the 'Use connection pooling' option.

  7. Select the option to 'Use fixed credentials' and enter theBind DN and password of a trusted user on your directory.

  8. Click the OK button near the top of the application tosave the Server Group Configuration.

  9. Return to the "ou=People" node in your Virtual Tree, thathas been created under the VirtualTree listener. Right-click on thenode in the navigator panel and select the option to add a New VirtualMount Point from the context menu.

  10. Provide the new entry with an RDN like 'ou=Accounting'. Inthis example we will assume that the accounting staff for 'mycompany'have their user data stored in a separate directory, Directory 2.

  11. Once the new mount point has been created, you will beable to configure it to use ServerGroup02 as the repository from whichto attach data, and you can specify the DN where the user data isstored on Directory 2. In this case,'ou=users,o=accounting,dc=mycompany.org', however your directory mayhave a different structure.

  12. Configure a second virtual mount point
    Fig-12: Configure a second virtual mount point

6 Launch and TestConfiguration

You can now save the configuration and test it. Simply clickon the File option in the menu bar and click Save, to save all of theconfiguration changes to file. It is now time to start theconfiguration and to test whether your virtual tree works.

  1. Click the Process button on the menu bar.

  2. Click Run on the drop-down menu. At this point the LDAPProxy should be running and ready to accept LDAP requests.

  3. Click the Extras button on the menu bar.

  4. Click LDAP Browser on the drop-down menu and the followingwill appear:

  5. The LDAP Browser Connection Window
    Fig-13: The LDAP Browser Connection Window

  6. In the Name textbox, enter 'demo'.

  7. In the Hostname textbox, enter the IP Address of thecomputer that LDAP Proxy is installed on.

  8. In the Port textbox, enter 3890.

  9. In the Root Suffix textbox, enter the DN of the branch ofthe Virtual Tree that you'd like to browse. In this case'ou=People,dc=mycompany,dc=com'.

  10. In the Bind DN textbox, enter the DN of a user that hasappropriate access to both Directory 1 and 2. This option is relativelyoptional in this case, as the connection pooling configuration shouldmake this step redundant in this configuration.

  11. Enter the Password twice for the user specified in thestep above.

  12. Click the Test button.

  13. Assuming you entered the correct information, a TestSuccessful! message will appear. Click the OK button.

  14. The browser should open now with a presentation of theVirtual Tree that you have created. You can expand the virtual mountpoint nodes to check that the data from each of your backenddirectories has been properly attached.

  15. You can view data within the virtual mount points as if it all belonged to one tree in one repository
    Fig-14: You can view data within the virtual mount points as if it allbelonged to one tree in one repository

TOP

Tutorial #5 - Facilitating Password Changes on Active Directory over LDAPS

Facilitating Password Changes on Active Directory over LDAPS

Click here to download this tutorial as a PDF file.

Overview

While Active Directory interacts perfectly well with most LDAP client applications, it imposes certain limitations on password modifications that makes it difficult to integrate with a wide range of user management applications. The reason for this is twofold. The first hurdle that an administrator will need to overcome is that Active Directory will only allow for password modification requests to be submitted over an SSL connection that offers at least 128bit encryption. Unfortunately, there is little that you can do about this, other than configure SSL on your Active Directory. Microsoft provides a useful support article that will help you to do this at http://support.microsoft.com/kb/321051.

The second problem is that Active Directory stored passwords in the 'unicodepwd' attribute in a format that most LDAP client applications are not designed to work with. Notably, passwords are quoted UTF-16 encoded strings in Active Directory, while most LDAP applications will use UTF-8 by default. As a result many LDAP applications may attempt to perform a password modification, but will fail because the password is not encoded in a way that Active Directory recognizes. In this tutorial, we will explore how it is possible to intercept LDAP modification requests and ensure that password changes are formatted in a way that is compatible with Active Directory, by using a simple scriptlet attached to a processing stage within LDAP Proxy.

As this tutorial will discuss DirectoryScript code at some length, we highly recommend that you read the Scripting Guide PDF that is distributed with your copy of LDAP Proxy before you go any further. This tutorial will assume that you are at least familiar with some basic coding concepts and have a rough understanding of DirectoryScript syntax. To help keep things simple, we have exported a functioning version of the configuration that we will present below, including the required script, and offer it as a download here. You can import this configuration by clicking on the File option in DSGUI's menu bar, and then selecting Import Configuration. Simply navigate to the zip file on your hard disk, and click on it and click Open. You will then be able to open the changeADpass configuration locally.

Building the base configuration

From the previous tutorials, you should have a pretty good idea of the steps involved in creating a basic configuration. As this tutorial will be fairly lengthy, we will run through the steps very quickly here, and assume that you are already at a level where you are able to follow these abbreviated instructions. If you are having trouble with any of the instructions here, we recommend that you refer to some of the previous tutorials, or import the provided configuration.

First, create a new configuration and name it something like 'changeADpass' so that you know what it is intended to do. In the Output part of the configuration, create an Automatic ServerGroup that will connect to the LDAPS interface of your Active Directory server. In our example, we named the ServerGroup AD_SSL. Ensure that the protocol for this ServerGroup is set to LDAPS and that you provide the IP address and port number (usually 636) for the Active Directory backend that you wish to connect to.

The AD_SSL ServerGroup configuration using LDAPS.
Fig-1: The AD_SSL ServerGroup configuration using LDAPS.

Now create a new Listener interface in the Input part of the configuration. In our example configuration, we have named the listener 'main'. Set the port number that the Listener should bind to, and set the default ServerGroup to point at the AD_SSL ServerGroup that you created in the Output part of your configuration. In order to keep things simple, we will configure the Listener to use the LDAP protocol, so that we do not need to configure any SSL parameters.

The main Listener configuration that client applications will connect to.
Fig-2: The main Listener configuration that client applications will connect to.

To help with debugging and to keep track of the operations that are performed using this LDAP Proxy instance, we will also add an Automatic Stage in the Processing section of the configuration and call this 'Log'. In this processing stage, we will add the Operation Dumper plugin. Configure this to "Create New File", so that you can keep a log file for these operations. You could alternatively set this to "Append log to file" or "Append log to dated file" depending on your longer term requirements.

Configuration of the Operation Dumper plugin in the Log processing stage
Fig-3: Configuration of the Operation Dumper plugin in the Log processing stage

In the Listener configuration, ensure that you attach the Log stage to the listener under the "Attached Stages" tab.

Attaching the Log processing stage to the main Listener.
Fig-4: Attaching the Log processing stage to the main Listener.

Creating and configuring a manual processing stage

As Symlabs has not yet provided any plugins to handle the encoding and interception of password request changes for Active Directory instances, we will need to create a Manual Processing Stage and code our own solution. This is actually a fairly trivial task, once you are familiar with the DirectoryScript language and how manual stages work. Please do have a look at the 'Manual Stages' section in the Processing chapter of the User Guide for a more detailed description of this part of the configuration.

Click on the Processing node in the configuration. And click on the New Stage button. Enter the Stage Name 'ADPassFormat' and ensure that you change the Stage Type to 'Manual'.

Ensure that you change the Stage Type to Manual when adding a new stage.
Fig-5: Ensure that you change the Stage Type to Manual when adding a new stage.

Click on the Add Hooks button. A pop-up dialog will allow you to set the protocol to LDAP, and to select the REQ_MODIFY hook from a list of different hooks.

Select the REQ_MODIFY Hook from the list
Fig-6: Select the REQ_MODIFY Hook from the list.

A hook is responsible for intercepting PDUs of a particular type. This makes it possible to view and modify the data contained within particular request or response packets as they traverse the LDAP Proxy instance. In this instance, we are only interested in intercepting MODIFY requests, as these will be the types of requests that will be used to perform a password change. Once this Hook has been added, we will need to attach the scriptlet that we will write to reformat a password modification request. To do this, click on the Add Condition button.

Click on the Add Condition button
Fig-7: Click on the Add Condition button.

Conditions provide a wide range of functionality even before you add any processing scripts to them. Many of the useful functions are discussed both in the User Guide and Reference Manual, and in the Scripting Guide, that comes with LDAP Proxy. In our case, we will only use a condition entry to host a scriplet and to pass it some configuration variables.

The first thing that we need to do, here, is add a processing scriptlet to the condition. On the right of the "File" field, you will see a button marked with a '-' sign. Click on this to open the file browser dialog. In the "Filename" field type 'ADPassword.ds' and click on the "Select DSScript" button.

In the file dialog create a file called ADPassword.ds
Fig-8: In the file dialog create a file called ADPassword.ds.

The "File" field in the Condition Editor will now be populated with 'local/ADPassword.ds'. In the "Function" field type 'codePass'. This will be the name of the primary function that will be invoked within our script file whenever it is triggered by the REQ_MODIFY Hook.

The condition editor is configured to trigger the scriptlet
Fig-9: The condition editor is configured to trigger the scriptlet.

At this point, the script file 'local/ADPassword.ds' does not contain the 'codePass' function. In fact, the script file does not even exist yet. However, we have prepared the configuration for the steps that we are about to take, so click OK to save this part of the configuration to memory. We will return to it shortly.

Creating custom configuration entries

Before we launch into developing the script, we should think about what the script will need to do and whether it will need any configuration variables to be passed to it in order to run properly.

In the current approach, the REQ_MODIFY Hook will intercept all of the modification requests and will trigger the scriptlet that we are going to write. The scriptlet will firstly need to determine whether the modification request is attempting to change a password within Active Directory. If the modification does contain a password change request, the script will need to extract the password contained within the request and reformat it so that it conforms to the password encoding that Active Directory expects, before passing the request on to the Active Directory backend server.

There are two things that come to mind when we consider the behaviour of this script. Firstly, the script should be able to provide some debugging information if something should go wrong. Of course, we may want to code different debugging levels into the script, so that we can control the level of output. If you have read the Scripting Guide, you will be aware that we can use a built-in log-level function to handle this, but we will need to be able to notify our scriptlet of the amount of logging output that we wish to receive. For this purpose, we will need a custom configuration entry that will contain a debugging level variable.

The second thing that comes to mind is that some client applications may submit password modifications for password attribute names that do not conform to the Active Directory schema. One approach to this would be to use the attribute mapping plugin to handle these sorts of application conflicts. Another approach would be to ensure that the scriptlet was more flexible and would perform this sort of attribute transformation on the fly. To do this, we might provide an administrator with the option to specify the different attribute names that may be used by client applications to perform a password modification. To handle this, we will add a second custom configuration entry that will allow the administrator to specify the attribute names for which the script will work.

While it is perfectly legitimate to hard code these parameters within your script, which will mean that your script can be more simple as it will not require any code to read these parameters from a configuration file, this does mean that any changes to these parameters in the future would require a developer to ensure that these entries are properly changed withing the script. A much better approach allows you to store these entries within the actual configuration file, so that an administrator can change these entries in the future without needing to edit the script at all.

To store these custom configuration entries, you will need to add a Generic entry to the configuration file. We will add the Generic Entry within the Manual Processing stage that we have just created to make sure that this data is stored near the function that will require it.

Click on the 'ADPassFormat' node, for your manual stage, within the configuration navigator. Now click on the "Entry" menu in the menu bar, and select the "New Generic Entry" option. You can also find this option by right clicking on the 'ADPassFormat' node, if it is selected. Enter an RDN for the generic entry. In our example, we used 'cn=config'.

The New Generic Entry option under the Entry menu in the menu bar
Fig-10: The New Generic Entry option under the Entry menu in the menu bar.

Click on the new created entry in the configuration navigator, and edit it to contain the following attributes and values:

cn config
objectclass top

extensibleobject
debug 127
pass_attribute unicodepwd

userpassword

 

The cn=config entry after its attributes have been added
Fig-11: The cn=config entry after its attributes have been added

Now that we have a stored these configuration entries within the configuration, we will need to find a way to pass this information to our script. This can be done using the CS_PARAM variable that gets attached to each PDU that moves through the LDAP Proxy instance. To do this, go back to the 'codePass' condition panel attached to the REQ_MODIFY hook, and click on the button to the right of the "Paramater" field (V). This will allow you to attach the newly created configuration entry so that it appears in the field as: cn=config,stage=ADPassFormat,ou=conf,o=dsproxy.

The custom configuration entries will now be passed to the scriptlet with the request PDU as it is processed
Fig-12: The custom configuration entries will now be passed to the scriptlet with the request PDU as it is processed.

Adding the ADpassword Script to the configuration

Now that we have mostly completed the configuration, we will need to create the script file and edit the function that the configuration will attempt to trigger when it intercepts a modification request. You can either use the built-in editor to do this, or use your preferred text editor to work with. This can be controlled from within the Preferences of the DSGUI application. In this tutorial, we will continue to work with the built-in editor.

In the Condition Editor, click on the Edit button next to File parameter that currently contains the value '/local/ADPassword.ds'. This will cause a dialog to pop up, notifying you that the file does not yet exist and offering you the option to create the file. Click Yes to open the editor. Note that this will create a file in your configuration directory at somewhere like 'confs/changeADpass/local/ADpassword.ds' at the root of your installation.

If you are using the default editor, the file will open already partially populated with the following text:

 function codePass (pdu) { return NEXT_CONDITION; }

This function is created as the most basic working scriptlet possible. It will be triggered and will simply exit and allow the next condition within the hook to be triggered, or the PDU to continue to its destination. We will extend this functionality considerably.

The script editor with the most basic function already populated
Fig-13: The script editor with the most basic function already populated.

To keep things simple, we are simply going to provide all of the code that you need for this script to work properly. If you want a more detailed explanation of the code, jump to the end of this tutorial to read our analysis of the code presented here. For now, simply replace everything in this file with the following code:

 #include "plugins/log.ds"
function init(pdu){
confdn=pdu{_CS_PARAM_};
ldifconfig=ds_global_get(pdu{_CS_PARAM_});
if(ldifconfig){
config{"debug"} = ldifconfig{"debug"}[0];
i=0;
foreach attr (ldifconfig{"pass_attribute"}){
config{'pass_attr'}[i]$=ds_tolower(attr);
i++;
}
ds_global_put("_init_conf_${confdn}",config);
DSLOG(L_DEBUGGING,ldifconfig{'debug'}[0],pdu,"AD Password Modifier configuration: " $ dumper(config));
return config;
}
return undef;
}

function codePass (pdu) {
rconf=ds_global_get("_init_conf_${pdu{_CS_PARAM_}}");
if (rconf == undef) {
rconf=init(pdu);
if (!rconf) {
DSLOG(L_CRITICAL,0,pdu,"Configuration Error! Check configuration entry ${pdu{_CS_PARAM_}}");
exit 1;
}
}
DEBUG=rconf{'debug'};
DSLOG(L_INFO,DEBUG,pdu,"Modify Operation Received on "$pdu{_DN_});
DSLOG(L_DUMP,DEBUG,pdu,"Original PDU: "$ dumper(pdu));
DSLOG(L_TRACE,DEBUG,pdu,"Searching for changes on password attributes.");
for (i=0;i<length(pdu{_MODIFIES_});i++) {
if (length(eqgrep(ds_tolower(pdu{_MODIFIES_}[i][1]) , rconf{'pass_attr'} ))) {
DSLOG(L_TRACE,DEBUG,pdu,"Modification on a password attribute found.");
DSLOG(L_TRACE,DEBUG,pdu,"Setting the password attribute to 'unicodepwd' for Active Directory.");
pdu{_MODIFIES_}[i][1]='unicodepwd';
for (j=0;j<length(pdu{_MODIFIES_}[i][0]);j++) {
slen=length(pdu{_MODIFIES_}[i][0][j]);
newval='"'$"\0";
for (k=0;k<slen;k++) {
newval $= substr(pdu{_MODIFIES_}[i][0][j],k,1)$"\0";
}
newval$='"'$"\0";
pdu{_MODIFIES_}[i][0][j]=newval;
}
}
}
DSLOG(L_DUMP,DEBUG,pdu,"Modified PDU: "$ dumper(pdu));
return NEXT_CONDITION;
}

In a brief attempt to explain the above code, you may realize that what we are doing is taking the original password and enclosing it in quotes, while inserting a null bit between each character in the password string. This has a few implications for this script. Firstly, the script will only work for passwords submitted using an 8-bit character set encoding. As a result, some character sets, such as Korean and Chinese will not work with this script. Secondly, the script does not check the existing format of the string that is submitted in the request. This means that if an application submits the password in the format that Active Directory expects, the string will still be modified and the password change request may fail. However, with this in mind, the above script will function perfectly well for most normal LDAP clients.

With this explanation out of the way, save the code in the editor and close the editor.

Attach the manual stage to the Listener

The only thing that remains to be done before the configuration can be used, is to attach the Manual Stage, that we have created, to the 'main' Listener. Click on the 'main' Listener node in the configuration navigator and go to the Attached Stages tab.

Add the ADPassFormat Manual stage to the list of attached stages.

The Manual Stage called ADPassFormat has been attached to the Listener
Fig-14: The Manual Stage called ADPassFormat has been attached to the Listener.

Now make sure that you Save the configuration.

Testing the configuration

Finally, we have reached a point where we can start the configuration. If there are no errors in your script, the SSL on your Active Directory is configured correctly, and the LDAP Proxy configuration is correct, it should run without a problem.

Once the configuration has started, you will need to test that it is working correctly. The first thing to do is check that you are able to browse the tree on your Active Directory through the LDAP Proxy instance. Open an LDAP Browser, like the one included with the product, and connect to the Listener interface on the LDAP Proxy instance, specifying the Base DN for your Active Directory server. You should be able to browse the Active Directory tree as normal.

The LDAP Browser should be able to access the tree on your Active Directory instance
Fig-15: The LDAP Browser should be able to access the tree on your Active Directory instance.

The built-in LDAP Browser does not allow for modify requests, and many browsers will simply not show the unicodepwd attribute, to allow you to change it from within a standard LDAP browser. To test this properly, we will use the ldapmodify command on the command line. This tool can be obtained from a number of ldap vendors including OpenLDAP, OpenDS, Sun and may be obtained for Linux in the commonly named 'ldap-utils' package.

To use this command, it is useful to create an LDIF file that contains the modification request. Create a file called passwordchange.mod on your system, it should contain entries that look something like this:

 dn: CN=Joe Bloggs,OU=People,DC=vdsnet,DC=local
changetype: modify
replace: unicodepwd
unicodepwd: newpassword

Note that the 'dn' value will need to match the DN of a user within your Active Directory domain. The 'unicodepwd' entry will contain the value of the new password. Save the file, and then, in the shell or on the command line, run a command similar to the following:

 ldapmodify -x -h localhost -p 3890 -D "Administrator@vdsnet.local" -w "password" -f passwordchange.mod

Substitute 'Administrator@vdsnet.local' for an authorized user within your domain, and substitute 'secretpassword' for the user's actual password. If you are not in the same directory as the passwordchange.mod file that you created, ensure that you specify the full path to the file.

If the command runs correctly, you should receive output that looks something like this:

 modifying entry "CN=Joe Bloggs,OU=People,DC=vdsnet,DC=local"
modify complete

Use the ldapmodify command to perform a password modification
Fig-16: Use the ldapmodify command to perform a password modification.

In the DSGUI application, you can refer to the log panel to check that the scriptlet is running as expected. In the STDOUT log, you should see plenty of logged output. You can control the amount of logged output by changing the debug value in your custom configuration entry and restarting the instance. If everything has gone according to plan, you should see that the logged output shows how the contents of the PDU have been modified and the password for the user that you have modified will have been updated on your Active Directory server.

The logging panel in DSGUI will help to show you whether the script is functioning as expected
Fig-17: The logging panel in DSGUI will help to show you whether the script is functioning as expected.

Developing the ADPassword.ds Script

In this section, we will look at how the ADPassword.ds script was developed. Once again, we highly recommend that you read through the Scripting Guide before going any further, as some of the concepts presented here will assume that you have a reasonable grasp of the DirectoryScript language already.

The first thing that we would like to do in our script is read and prepare the custom configuration information in such a way as to make it usable within our function. We will use an init script to do this. So, above the current 'codePass' function, enter the following code:

 #include "plugins/log.ds" 
function init(pdu){
confdn=pdu{_CS_PARAM_};
ldifconfig=ds_global_get(pdu{_CS_PARAM_});
if(ldifconfig){
config{"debug"} = ldifconfig{"debug"}[0];
i=0;
foreach attr (ldifconfig{"pass_attribute"}){
config{'pass_attr'}[i]$=ds_tolower(attr);
i++;
}
ds_global_put("_init_conf_${confdn}",config);
DSLOG(L_DEBUGGING,ldifconfig{'debug'}[0],pdu,"AD Password Modifier configuration: " $ dumper(config));
return config;
}
return undef;
}

Let's analyze each line. Before we create the init function, we use an include statement to include the logging functionality contained within the log.ds plugin script. This will allow us to output messages from within our script within the provided logging framework.

Inside the init function, we set a variable called 'confdn' with the data held in the _CS_PARAM_ variable contained in the PDU hash. We will use this variable later to define where we will store modified configuration information.

In the next line, we invoke the 'ds_global_get' command to obtain the custom data from the configuration file and to store it in a hash called 'ldifconfig', which we can work with inside of our script. If this operation fails, we will return an undefined value to notify the main script that the init script has failed. Assuming that all goes well, the first thing that we do is create a hash called config, and populate the 'debug' key with the value stored in the configuration file's debug attribute.

Next, we create a 'foreach' loop, to extract each of the "pass_attribute" values. Inside the loop, we populate the config hash with a 'pass_attr' key that will store an array of the "pass_attribute" values. In order to ensure that we don't run into any problems within our scripts due to case-sensitivity, we ensure that all of the stored attributes are converted to lower case.

We use the 'ds_global_put' function to save the new config hash back into the Global Configuration hash, using the "confdn" variable to define an appropriate location. And finally, we use a DSLOG line (thanks to the included log plugin script) to output information about the configuration that we are storing through the init script.

At completion the init script uses a "return config" statement to return the config hash as output to the main script that has called it.

Now, if we return to the main 'codePass' function, we will need to set it up to obtain the configuration data that has been stored by the init script or, failing that, to invoke the init script to properly format the configuration data. Edit the codePass function so that it looks like this:

 function codePass (pdu) {
rconf=ds_global_get("_init_conf_${pdu{_CS_PARAM_}}");
if (rconf == undef) {
rconf=init(pdu);
if (!rconf) {
DSLOG(L_CRITICAL,0,pdu,"Configuration Error! Check configuration entry ${pdu{_CS_PARAM_}}");
exit 1;
}
}
return NEXT_CONDITION;
}

In this bit of code, we first use the ds_global_get function to attempt to obtain the initialized configuration variables. If these variables are not available, the init script is called to process the original configuration entries. If this fails, a critical error is logged and the script will exit. Finally, the script will return with an instruction to allow the PDU to continue on through to the next processing condition or if there are no further conditions, to allow it to continue on to the backend.

At this point, the script still does not do anything useful with the data contained within the PDU. However, the script is now capable of using the configuration variables, that are passed to it in the _CS_PARAM_ variable, to engage in any further processing. Let's move on to the core processing for this function.

 function codePass (pdu) {
rconf=ds_global_get("_init_conf_${pdu{_CS_PARAM_}}");
if (rconf == undef) {
rconf=init(pdu);
if (!rconf) {
DSLOG(L_CRITICAL,0,pdu,"Configuration Error! Check configuration entry ${pdu{_CS_PARAM_}}");
exit 1;
}
}
DEBUG=rconf{'debug'};
DSLOG(L_INFO,DEBUG,pdu,"Modify Operation Received on "$pdu{_DN_});
DSLOG(L_DUMP,DEBUG,pdu,"Original PDU: "$ dumper(pdu));
DSLOG(L_TRACE,DEBUG,pdu,"Searching for changes on password attributes.");
for (i=0;i<length(pdu{_MODIFIES_});i++) {
if (length(eqgrep(ds_tolower(pdu{_MODIFIES_}[i][1]) , rconf{'pass_attr'} ))) {
DSLOG(L_TRACE,DEBUG,pdu,"Modification on a password attribute found.");
DSLOG(L_TRACE,DEBUG,pdu,"Setting the password attribute to 'unicodepwd' for Active Directory.");
pdu{_MODIFIES_}[i][1]='unicodepwd';
for (j=0;j<length(pdu{_MODIFIES_}[i][0]);j++) {
slen=length(pdu{_MODIFIES_}[i][0][j]);
newval='"'$"\0";
for (k=0;k<slen;k++) {
newval $= substr(pdu{_MODIFIES_}[i][0][j],k,1)$"\0";
}
newval$='"'$"\0";
pdu{_MODIFIES_}[i][0][j]=newval;
}
}
}
DSLOG(L_DUMP,DEBUG,pdu,"Modified PDU: "$ dumper(pdu));
return NEXT_CONDITION;
}

If we ignore the first part of the code here, which we have already discussed, you will see that the first processing directives in this script are largely dedicated to returning debug log info. Each DSLOG line here is set to return information for a different log level. The first DSLOG line will output if the log level is set to INFO. The next line will output the entire contents of the PDU if the log level is set to DUMP. And the third line will simply provide notification that the script is searching for changes on password attributes for a log level set to TRACE.

With some informative logging out of the way, the script begins by looping through the contents of the MODIFIES hash, contained within the decoded PDU. We check to see whether any of the attributes that are going to be modified match any of the attributes that have been configured in our custom configuration, using the eqgrep function to search the array of values. If there is a match, we return some more logging information, and then ensure that the attribute name is reset to 'unicodepwd', which is the attribute name that Active Directory uses to store password data by default. At this point, we have performed a form of attribute mapping. If a client application sends a modify request on an attribute called 'userpassword' and this is configured as one of the attributes that the script will work for, then the request will be converted by the script to submit a request to change the attribute named 'unicodepwd'.

The next step is to loop through the values for the password attribute that is being modified. Usually, there will only be one of these, but as there is no technical limit on a request treating an attribute as multi-valued, it is good practice to code with this in mind. Inside this loop, we measure the length of the password value string, so that we will be able to loop through each character in the string. We also populate a new variable, 'newval', with an opening quote, and a null bit. Next we perform the loop through the characters in the password string. For each iteration of the loop, we append the character and a null bit to the 'newval' variable. When the loop is complete, a final closing quote and null bit are appended to the 'newval' variable. In this way, we have converted an unquoted UTF-8 string to a quoted UTF-16 string. Our final step is to write the 'newval' variable over the original value for the password string within the modification request pdu.

A final DSLOG line will output a dump of the altered PDU so that in debug mode, you are able to check that the script has performed as expected. Finally, the script exits with a 'return NEXT_CONDITION' statement.

As you can see, this script is not entirely foolproof. Certainly there are no checks that the password that is submitted is actually encoded using the UTF-8 character set. However, for most environments, this script will ensure that LDAP applications that are not designed to work with user entries within an Active Directory instance, are able to perform password modifications for a user without a problem. With further development, the script could be altered to check the formatting of the password string to improve compatibility.

TOP

Tutorial #6 - Handling Schema Changes Using ADAM and Symlabs LDAP Proxy

Handling Schema Changes Using ADAM and Symlabs LDAP Proxy


Click here to download this tutorial as a PDF file.

Overview

Schema changes under Active Directory can be very awkward. To begin with, it is not possible to remove Classes or Attributes from the schema once they have been added. This means that when adding to a schema, a simple mistake cannot be undone. Furthermore, schema changes should be replicated across an Active Directory forest, which can become complicated and have wide-reaching implications. Due to the level of impact that a schema change can incur, many administrators will avoid implementing schema changes where possible.

Many applications that make use of LDAP-based backend systems require particular schema modifications in order to work properly. Often an Active Directory administrator may attempt to run a separate directory for the application in order to minimize impact on the existing directory infrastructure. While this approach does offer a modicum of sanctuary from the schema modification problem, it also brings with it a number of integration issues, particularly if the application is designed to work with users or entries already stored in an Active Directory instance, as it will require some form of syncronization.

In this tutorial, we will present a solution that is capable of making the best of both worlds. By creating an ADAM instance, to store data for users specific to the new schema, we can perform a schema modification within a locally hosted directory without impacting on the Active Directory schema. Furthermore, we can use the JoinEntries plugin bundled with Symlabs LDAP Proxy, so that an application can work with entries that are stored in Active Directory as if the schema change had been performed here.

In this tutorial we assume that you already have some experience working with ADAM. If you are uncertain of any of the concepts presented here, or wish to obtain further guidance, please refer to the Microsoft TechNet resource for ADAM. Please also note, that we have only focussed on using ADAM in this tutorial as it is often the preferred LDAP implementation for Active Directory administrators. This solution could be equally achieved using an open source LDAP directory like OpenDS.

Configuring ADAM

ADAM (Active Directory Application Mode) is an LDAP directory service that Microsoft developed to run alongside Active Directory as a user service, as opposed to a system service. ADAM allows Active Directory users to implement separated directory services without impacting on the core Active Directory infrastructure. ADAM is available as a Windows Server 2003 component and can also be downloaded from Microsoft.

For this tutorial, you will need to have ADAM installed, and you will need to have created an ADAM instance. We will assume that you have created an instance called 'MyCompany' with a partition, or Base DN, 'o=payroll,dc=mycompany.org'. This ADAM instance will be used to store information for a payroll application, that requires the addition of a 'PayRollUser' object Class, with the attributes: "prAccountNumber","prBankName","prGrossAnnualSalary" and "prRoutingNumber".

Once you have created an ADAM instance, open the ADAM Schema Editor Snap-In in an MMC console. Connect to your ADAM instance, by entering the hostname and port for the instance that you have created, and then right-click on the Attributes node, to select the Create Attribute option from the menu. You will need to create an attribute for each of the attributes listed above, as these will be required by the new object class.

Add attributes to the ADAM schema.
Fig-1: Add attributes to the ADAM schema

When you have finished adding the attributes, right-click on the Classes node, to select the Create Class option. And create a PayRollUser class. The PayRollUser class will be a Structural class that will have the 'user' class as its parent. Ensure that you add the 'cn' attribute as a mandatory attribute, as we will use this attribute to join the entries stored here to the data stored in the Active Directory instance. Add the additional attributes that we created specifically for this class as optional attributes.

Add the PayRollUser ObjectClass to contain the new attributes.
Fig-2: Add the PayRollUser ObjectClass to contain the new attributes

You have now completed the schema modification required for the Payroll application that you wish to integrate, but the modification has been performed on a separate directory to your Active Directory instance, removing any possibility of the modification impacting on existing data.

You will now need to populate the new ADAM instance with data. For each entry, you will want to provide a value for the CN attribute, that matches the CN attribute of a user in your Active Directory instance. You may do this by creating an LDIF file with each of the entries, or you might manually add the users using the ADAM ADSI Editor.

Manually add entries using the ADAM ADSI Editor.
Fig-3: Manually add entries using the ADAM ADSI Editor

Depending on how you have set up your ADAM instance, and the level of access that you are provisioning, you may want to either set up a 'ProxyUser' entry to authenticate off your backend Active Directory server. Alternatively, you could create a static user entry that can be added to the Administrators role, to provision access using LDAPS to browse and modify the directory with an external client.

Add a static user entry with Administrator privileges to manage the ADAM instance.
Fig-4: Add a static user entry with Administrator privileges to manage the ADAM instance

Configuring LDAP Proxy

At this point, we have an Active Directory instance that contains half of the data that the Payroll application expects to have access to. The other half of the data, is stored in a locally hosted ADAM instance. The entries in the ADAM instance can be matched to the entries in the Active Directory instance, based on the value of the CN attribute. We will now configure LDAP Proxy to join the entries from both of these data sources and present them to the Payroll application as if the data was stored in a single Active Directory instance containing the appropriate schema for the application to function correctly. Open the LDAP Proxy DSGUI configurator and create a new configuration.

First, we will need to create two different ServerGroups. The first ServerGroup will be configured to contain the Active Directory server instance. The second ServerGroup will be configured to contain the ADAM server instance, and should be set up to use a connection pool that is authenticated using credentials that have full access to the ADAM instance. Note that if you have not configured your ADAM instance to allow simple BIND authentication on a non-SSL connection, you will need to ensure that this ServerGroup is configured to use LDAPS. By default, ADAM will usually not allow simple authentication to take place over a non-encrypted channel.

Configure two servergroups, and set up a connection pool for the ADAM server
Fig-5: Configure two servergroups, and set up a connection pool for the ADAM server

Once you have added the two ServerGroups, you will need to attach a Listener to the Input part of the LDAP Proxy configuration. The Listener can be configured to listen on port 3890 and should use the Active Directory ServerGroup as its default ServerGroup. This will mean that by default, all requests will be forwarded on to the Active Directory server instance. Also check the option to Canonicalize the DN for Processing Stages, to ensure that there are no issues with case-sensitivity during the processing phase of the solution.

Configure a Listener to use Active Directory as the Default ServerGroup
Fig-6: Configure a Listener to use Active Directory as the Default ServerGroup

In order to help with any debugging that may be required later, and to track operations being performed through the LDAP Proxy instance, add a Logging Processing stage, and attach the Operation Dumper plugin to generate a log file that we can use if we need it.

Add a Logging Processing Stage, and attach the Operation Dumper plugin
Fig-6: Add a Logging Processing Stage, and attach the Operation Dumper plugin

Remember to attach this processing stage to the Listener to make it effective.

Attach the Logging stage to the Listener
Fig-7: Attach the Logging stage to the Listener

Now we will need to ensure that where, a request is destined for a particular branch of entries on the Active Directory server, the data for each entry returned by the server is "joined" with data for the same entry that is stored on the ADAM server instance. We will do this, by taking advantage of one of the built-in plugins that is included with LDAP Proxy, and will use the CN attribute as a 'key' to match up the entries that should be joined.

First, we need to add an automatic Processing stage to contain the plugin. Once you have created the stage, you will be able to click on the Add Plugin button, to scroll through the list of plugins before selecting the "Join Entries" plugin from the list.

First configure the BaseDN filter for the plugin, so that it only triggers for requests on the branch on the Active Directory instance, where the entries are stored that you wish to perform the join for. In our example, this is on the BaseDN "ou=Managers,dc=mycompany,dc=local".

Next, select the Join Attribute, or the key attribute that is being used to match the entries stored in the two directories. In our example, we have opted to use the CN attribute as a matching attribute. As this attribute is used to form the RDN against which each entry is stored, we check the box for this.

As the schema change that was required, added a new objectclass with its associated attributes, we will also configure this to aggregate the values of the "objectclass" attribute, so that it is presented as a multi-valued attribute with values from both data sources. This will have certain repurcussions that we will discuss later.

Configure the Join Entries plugin by adding a filter on the BaseDN, specifying the Join Attribute, and aggregating the ObjectClass attribute
Fig-8: Configure the Join Entries plugin by adding a filter on the BaseDN, specifying the Join Attribute, and aggregating the ObjectClass attribute

Now we need to Add a Foreign Data Group, to perform the join against the ADAM directory. Click on the Add Foreign Data Group button, and name the group something sensible like 'ADAM Entries'. Once again, set the Join Attribute to the matching attribute that will be used for the ADAM Entries, in this case 'CN'; and check the box if the attribute is used to form the RDN for the stored entry. Select the ServerGroup that contains the ADAM directory, and specify the full DN where the entries that will be joined are stored.

Add a foreign data group, and configure the Join Attribute and the DN where the entries are stored on the ADAM directory
Fig-9: Add a foreign data group, and configure the Join Attribute and the DN where the entries are stored on the ADAM directory

At this point, the configuration is more than likely capable of working adequately, at least for READ only operations. The response from the Active Directory, for any request on the filtered branch, will trigger a subsearch for entries containing the Join Attribute in the ADAM directory server instance. The results for the subsearch are then processed, so that all of the attributes, and their associated values, stored in the ADAM server are appended to the entries returned by the Active Directory for any query, based on the matching CN attribute. However, by aggregating the ObjectClass attribute, it is possible that there may be duplicate values returned and aggregated for the attribute. In general, it is not really possible for an LDAP Server to contain duplicate values for a single attribute. As a result, this could cause any LDAP application to behave unpredictably. What is required is a way to remove the duplicate entries and to append only the values that we wish to include.

There are two possible approaches to resolving this problem. One would be to create a manual processing stage and to include a short scriptlet that would remove the duplicate entries automatically. This would be the preferred approach as it would provide re-usable code and would automate the process for future changes. However, assuming that the schema change is unlikely to require future modification, and that we would like to avoid including any custom scriptlets in our solution, we will opt for a simpler approach. We can simply configure the plugin to not return any of the ObjectClass values for the ADAM directory instance. This would prevent the duplicate values from appearing in the results that are returned. However, we will need to manually include the values for the ObjectClass attribute, that are required for the schema change.

In the Foreign Data Group, where the ADAM Entries are extracted, click on the Read Operation Parameters tab. In this panel ensure that the option to 'Include all attributes except the following:' is set, and in the Attributes table, add an entry to exclude the ObjectClass attribute.

In the Read Operation Parameters tab, opt to exclude the ObjectClass attribute
Fig-10: In the Read Operation Parameters tab, opt to exclude the ObjectClass attribute

Now, under the Read Operation Parameters tab, for the main Join Entries plugin configuration, find the table at the bottom of the panel that allows you to add 'Attributes/Values to be automatically added to each entry'. In this table, add the attribute 'ObjectClass' and then list the additional objectclass that you added to the ADAM schema. In our example, this was the PayRollUser class.

In the Read Operation Parameters tab for the main configuration, add the ObjectClass attribute and the value PayRollUser
Fig-11: In the Read Operation Parameters tab for the main configuration, add the ObjectClass attribute and the value PayRollUser

This configuration will now take care of Read Operations properly, but it may have a problem with Write operations, as it is now unaware that the PayRollUser class actually belongs to the ADAM server instance. This means that it may attempt to write the data that is destined to be stored in the ADAM directory to the Active Directory instance as well. To fix this, simply click on the Write Operation Parameters tab in the main plugin configuration, and set the option to 'Include all attributes except the following:' and list the attributes ("prAccountNumber", "prBankName", "prGrossAnnualSalary" and "prRoutingNumber) that belong to the PayRollUser class and that are actually being stored on the ADAM directory instance.

In the Write Operation Parameters tab for the main configuration, list the attributes that should be excluded from writes to the Active Directory instance
Fig-12: In the Write Operation Parameters tab for the main configuration, list the attributes that should be excluded from writes to the Active Directory instance

The final configuration step, is to simply attach the processing stage to the Listener, under the Attached Stages tab. Once you have attached the processing stage, you can Save the configuration and start it up to check whether it is working as expected.

Attach the Join Entries processing stage to the Listener
Fig-13: Attach the Join Entries processing stage to the Listener

Testing the configuration

It is important that you test the configuration adequately before you use it. Run the configuration instance, and open an LDAP Browser that is capable of performing both READ and WRITE operations. In this example, we will use JXPlorer, which is an open source browser available from http://www.jxplorer.org/.

Connect to the LDAP Proxy instance, as if you were connecting to the Active Directory server instance, with the only difference being that the hostname and port number may differ.

Once you are connected, browse to the DN where the entries that require the schema change are stored. Click on an entry, and ensure that the new schema ObjectClass is listed, and that all of the values for the ObjectClass are unique. Also check that the attributes that are stored on the ADAM server instance have been joined into the data that is being returned.

Testing the configuration using JXPlorer
Fig-14: Testing the configuration using JXPlorer

Now perform a modification to the entry, changing the value for one of the attributes stored on the Active Directory instance, and one of the attributes stored on the ADAM instance. Ensure that the modification is successful.

This tutorial does not cover Add operations, as these transactions need to be designed in such a way as to take into account the exact methodology that will be used to store matching entries in both directories. This will depend entirely on your particular solution and your methodology. If you intend to develop this configuration further, please feel free to contact Symlabs for further assistance.

TOP

About Symlabs
 
Symlabs is the performance leader for virtual directory and identity management solutions.   Benchmarks show Symlabs Virtual Directory Server, LDAP Proxy and Federated Identity Suite are the fastest and most powerful products in the industry for managing and unifying identity data.   Global giants like Sony, IBM, Vodafone, Nokia and United Nations already depend on Symlabs to add flexibility, security, and reliability to their infrastructure.  Symlabs also offers annual support, training and professional services to our clients to help them develop, integrate, and maintain solutions.