Thursday, June 25, 2009

Teamworks 6.2.1 Active Directory Integration Notes

The most difficult thing about setting up AD Integration for Teamworks was figuring out how information is stored in my AD tree. I started by building out a sandbox windows network with a single Primary Domain Controller (PDC) for the domain "WBSSANDBOX", then adding an oracle server and a Teamworks server, both joined to the domain.

With Teamworks 6.2.1 running stable, I went to setup AD integration and found it needs to connect via raw LDAP queries. I then realized I had no idea what LDAP objects were in AD so I couldn't set proper Distinguished Names for LDAP queries. I needed a tool to peek at the raw AD tree, since the windows AD tools like "Active Directory Users and Computers" don't give you exact LDAP Distinguished Names for users and groups. I ended up downloading LDAP Browser 2.6 (a free tool as of this writing) to connect to the AD tree using connection settings shown below (where in my true sandox domain name, and WBSSANDBOX is my pre-win2000 domain name).

With the raw LDAP data in hand, I turned to configuring Teamworks. There are only two config files to update:

  • [teamworks-install-path]/process-server/resources/config/100Custom.xml

  • [teamworks-install-path]/process-server/conf/login-config.xml

100Custom.xml was an easy copy and paste, as shown in one of the Lombardi Teamworks configuration guides. I just added a chunk of code shown below within the <Properties> tag:

<common merge="mergeChildren">
    <security merge="mergeChildren">
            <access-controller merge="append">com.lombardisoftware.userorg.JBossLdapExtUserRegistryModule</access-controller>

login-config.xml was the tricky one, because you need to know your AD LDAP structure to make the changes. There is a commented out Active Directory LDAP example in that config file, I ended up modifying that to get things working as shown below.

<login-module code="" flag="optional" >
    <module-option name="java.naming.provider.url">ldap://</module-option>
    <module-option name="bindDN">cn=TeamworksService,CN=Users,DC=WBSSANDBOX,DC=com</module-option>
    <module-option name="bindCredential">your password here</module-option>
    <module-option name="baseCtxDN">cn=Users,DC=WBSSANDBOX,DC=com</module-option>
    <module-option name="baseFilter">(sAMAccountName={0})</module-option>
    <module-option name="roleFilter">(member={1})</module-option>
    <module-option name="rolesCtxDN">cn=Users,DC=WBSSANDBOX,DC=com</module-option>
    <module-option name="roleAttributeID">cn</module-option>
    <module-option name="roleAttributeIsDN">false</module-option>
    <module-option name="roleNameAttributeID">cn</module-option>
    <module-option name="password-stacking">useFirstPass</module-option>
    <module-option name="java.naming.referral">follow</module-option>
    <module-option name="allowEmptyPasswords">false</module-option>
    <!-- Teamworks UserOrg config. -->
    <!-- Filter for user objects -->
    <module-option name="twUserFilter">(objectClass=person)</module-option>
    <!-- Filter for group objects -->
    <module-option name="twGroupFilter">(objectClass=group)</module-option>
    <!-- Attribute in LDAP that contains the name of a user -->
    <module-option name="twUserNameAttribute">sAMAccountName</module-option>
    <!-- Attribute in LDAP that contains the PrimaryGroupID of a user (omit this option if no such attribute exists) -->
    <module-option name="twUserPrimaryGroupAttribute">primaryGroupID</module-option>
    <!-- Attribute in LDAP that contains the name of a group -->
    <module-option name="twGroupNameAttribute">cn</module-option>
    <!-- Attribute in LDAP that contains the distinguishedname of a group (used for resolving nested groups) -->
    <module-option name="twGroupDNAttribute">distinguishedName</module-option>
    <!-- Attribute in LDAP that contains the primaryGroupToken of a group (omit this option if no such attribute exists) -->
    <module-option name="twGroupPrimaryGroupTokenAttribute">primaryGroupToken</module-option>
    <!-- Attribute in LDAP that contains the description of a user -->
    <module-option name="twUserDescriptionAttribute">cn</module-option>
    <!-- Attribute in LDAP that contains the description of a group -->
    <module-option name="twGroupDescriptionAttribute">description</module-option>
    <!-- Attribute in LDAP that contains the members of a group -->
    <module-option name="twGroupMemberAttribute">member</module-option>

To really break down what your values should be, you'll need to take a peek at your LDAP structure and see where things are. For example, I got hung up on the idea that users and groups would be in separate containers in AD, but as it turns out they're both stored in the Users container.

Once you have all the correct LDAP info set for your domain, save both files and restart your Teamworks service. You can then confirm AD Integration is working by browsing to the Teamworks admin console. Login as the tw_admin account and browse to the "Maintain Logical Roles" screen, you should see your domain groups listed along with the ootb Teamworks roles. You can then try adding Domain Admins to the tw_admins logical role, logout and then try to login as the domain administrator to confirm authentication works.

No comments: