Monday, January 11, 2010

Enabling Kerberos in a Windows Domain for SharePoint 2007 and Teamworks

Notes for configuring Kerberos on a windows 2000/2003 domain for SharePoint 2007 farms.

For a list of gotchas in a SharePoint 2010/Windows server 2008 setup, check out this post: http://www.bryansgeekspeak.com/2010/11/sharepoint-2010-on-windows-server-2008.html

This post explains how I setup a sandbox network configured specifically for testing SharePoint 2007 and Teamworks 6.2.2 using Kerberos authentication on a windows domain.

I used a 5 server setup in this example, including a SharePoint farm (a web application server and a sql server), a teamworks server farm (a teamworks application server and an oracle server) and a primary domain controller. The goal, as shown in the diagram below, is allow domain users to auto-login to to the SharePoint portal. From the SharePoint portal we want to be able to drop the Teamworks for SharePoint web part into a SharePoint page, set it to use integrated authentication in order to pass along the user's SharePoint credentials along to the Teamworks server. The end result is a SSO auto login for the user. They should only need to login to their workstation and not see a login prompt in their browser for access to the portal or Teamworks.



To start, you'll need to get to a point where you have all the servers up and running as shown in the model. The server configuration is outlined below, before I began configuring Kerberos.

Server Software Configuration Prerequisite
  • KDCPDC
    • Microsoft Windows 2003 R2 Enterprise Edition
    • Configured as Primary Domain Controller
  • KDCSQL2008
    • Microsoft Windows 2003 R2 Enterprise Edition
    • MS SQL Server 2008 (2005 works just as well) patched to the latest version, configured for use in your sharepoint farm.
  • KDCMOSS
    • Microsoft Windows 2003 R2 Enterprise Edition
    • MOSS SharePoint 2007 patched with SP2, configured using custom user accounts. (note that I've heard kerberos is much easier to configure if you use the default service accounts rather than creating custom accounts)
  • KDCOracle
    • Microsoft Windows 2003 R2 Enterprise Edition
    • Oracle Server 10.2.0.4 configured for use with Teamworks 6.2.2
  • KDCTW
    • Microsoft Windows 2003 R2 Enterprise Edition
    • Teamworks 6.2.2 Enterprise Edition

With the above server configuration, we then need the names of the service accounts for Teamworks and the SharePoint web application pool where the teamworks web part will be used.


Account Name
Description
KRB\MOSSAppPool
SharePoint Web Application Pool Account
KRB\Teamworks
Teamworks Service Account

Finally, we need to know the fully qualified URLs for each of our web sites - the SharePoint URL and the Teamworks Portal url.  In this case, I added DNS records on the PDC for these URLS:

URL
Description
www.krb.com
The sharepoint site (remember, only use the PDC as the DNS server!)
krbtw.krb.com
Teamworks Portal URL

With all the above information, we can now start configuring kerberos.

Part 1 - Service Principal Names (SPN)

With delegation enabled, we need to map SPNs for the service accounts, to show kerberos that we allow trust those accounts to perform trusted authentication. You need to have the windows 2003 server support tools installed in order to run this command.

c:>setspn -A HTTP/www.krb.com KRB\MossAppPool

c:>setspn -A HTTP/krbtw.krb.com@KRB.COM KRB\Teamworks

When you are done, you can use setspn to list spn mappings for machines and accounts on your domain, which should look similar to what is shown below.



Part 2 - AD Account Delegation

Enable Delegation rights in AD for the SharePoint computer account, the SharePoint application pool account and the Teamworks service account.

Computer Accounts


Note that these examples are for a domain set to a functional level of windows 2000. If your domain functional level is set to windows 2003, delegation works differently.

We only need to configure the SharePoint computer account. The Teamworks server uses a java server application, which will require a different method for enabling kerberos trust/delegation, so dont enable trust delegation for the Teamworks computer account.

With Domain Functional Level Set to Windows 2000


For the computer account KRBMOSS, check the option "Trust computer for delegation".






With Domain Functional Level Set to Windows 2003


For the computer account KRBMOSS, goto the "Delegation" tab, select the option "Trust this computer for delegation to the specified services only" and "User kerberos only". Then add the HTTP service, with a computer account of the sharepoint web site. To add the url of the sharepoint web site, you need to click "Add.." and select the SharePoint application pool user account, where we mapped an SPN for that account to the SharePoint site URL.





Enable Delegation for Service Accounts


Note that constrained delegation works differently. Changes need to be made under the "Delegation" tab in the account properties.

With Domain Functional Level Set to Windows 2000


Check the option "Account is trusted for delegation" for both service accounts. In addition, the Teamworks service account needs the option "Use DES encryption types for this account" checked in order to support Teamworks (I believe this is a java server kerberos requirement).






With Domain Functional Level Set to Windows 2003




Part 3 - Enable Kerberos in SharePoint

Now the easy part! Log into the SharePoint Central Administration site. Under "Application Management" goto the "Authentication Providers" page.

 

Select correct web application from teh "Web Application" drop down, then click the "Default" zone.  Check "Negotiate (kerberos)" under the heading "IIS Authentication Settings" and click "Save".


You'll get a confirmation windows telling you that there are other steps required as domain administrator to enable kerberos.  You can ignore that, we did that in the previous steps by setting the SPNs and configuring delegation.  Be sure to execute an "iisreset" command at the command prompt after enabling negotiate.

c:\>iisreset /noforce

And that's all there is to it for the SharePoint side of things. You can confirm Kerberos is working by logging into the SharePoint site (http://www.krb.com). Then check the event viewer's security logs on the SharePoint server. You should see a 540 event for the user you hit the site as, with a message indicating kerberos authentication was used, similar to that shown below.






Part 4 - Enable Kerberos in Teamworks


Start by shutting down your Teamworks Process Server. It's also a good idea to delete all the log files before you start making changes. In this example, log files are in "c:\Teamworks\process-server\logs\".

Create Kerberos Config File for Teamworks


First, we need to create a kerberos config file on the windows server which Teamworks/Jboss can find, in order contact the KDC properly. The Teamworks SSO documentation explains that Teamworks/Jboss is already configured to look for a file called krb5.ini in the path "C:\winnt\krb5.ini". The content of that text file should look like this, for our example KRB domain:

[libdefaults]
default_realm = KRB.COM
default_tkt_enctypes = des-cbc-crc
default_tgs_enctypes = des-cbc-crc
ticket_lifetime = 600
[realms]
KRB.COM = {
kdc = KRBPDC
admin_server = KRBPDC
default_domain = krb.com
}
[domain_realm]
.domain.com = KRB.COM
[appdefaults]
autologin = true
forward = true
forwardable = true
encrypt = true

Once you've created the file "C:\winnt\krb5.ini" with the above text, you can continue to the next step.

Create Kerberos Token with KTPASS


As the domain administrator, login to the Teamworks server (KRBTW) and run the following command from the command prompt:

ktpass -out sso.keytab -princ HTTP/krbtw.krb.com@KRB.COM -pass MYPASSWORD -mapuser KRB\Teamworks -crypto DES-CBC-CRC -ptype KRB5_NT_PRINCIPAL

Be sure to replace "MYPASSWORD" with the password of your KRB\Teamworks account.

Note that the "-princ" value matches the SPN we created earlier for the Teamworks service account.

If the command is successful, the file "sso.keytab" will be created in your current directory. Copy that file to your Teamworks installation directory. In this example, I copied the file to "c:\Teamworks\sso.keytab".

Generate Kerberos Ticket for Teamworks Account


Login to the Teamworks server (KRBTW) as the Teamworks service account (KRB\Teamworks) and run the following command from a command prompt, again assuming that you installed Teamworks to "c:\Teamworks":

c:\Teamworks\java\bin\kinit.exe -k -t c:\Teamworks\sso.keytab HTTP/krbtw.krb.com@KRB.COM

If the kinit command is successful, it will create a kerberos ticket in the following path which will then be used for kerberos authentication by the Teamworks service from now on.

C:\Documents and Settings\Teamworks\krb5cc_sso

Turn On Kerberos in Teamworks


As described in the Teamworks SSO documentation, we now need to enable kerberos in Teamworks. In this example, we also enable KRB domain users and groups within Teamworks, so that we can manage Teamworks accounts through AD.

  • c:\Teamworks\process-server\conf\login-config.xml
Change the <application-policy name="other"> element to match the following. Be sure to change "MYPASSWORD" and "ENCRYPTEDPASSWORD" to values that work for your accounts. For information on how to encrypt passwords for Teamworks, refer to the Teamworks install documentation from Lombardi.

<application-policy name="other">
    <authentication>
        <!-- Uncomment and configure for SSO autologin -->
        <login-module code="org.jboss.security.auth.NegotiateLoginModule" flag="optional">
            <module-option name="loadBalance">false</module-option>
            <module-option name="domainController">KRBPDC</module-option>
            <module-option name="defaultDomain">KRB</module-option>
            <module-option name="java.security.krb5.realm">KRB.COM</module-option>
            <module-option name="jcifs.http.enableNegotiate">true</module-option>
            <module-option name="jcifs.spnego.servicePrincipal">HTTP/krbtw.krb.com@KRB.COM</module-option>
            <module-option name="jcifs.spnego.servicePassword">ENCRYPTEDPASSWORD</module-option>
        </login-module>

        <login-module code="com.lombardisoftware.security.provider.authentication.jboss.TWInternalLoginModuleImpl" flag="optional">
            <module-option name="password-stacking">useFirstPass</module-option>
        </login-module>
        <!-- Example Active Directory LDAP config -->
           <login-module code="org.jboss.security.auth.spi.LdapExtLoginModule" flag="optional" >
               <module-option name="java.naming.provider.url">ldap://KRBPDC:389/</module-option>
               <module-option name="bindDN">cn=Teamworks,CN=Users,DC=KRB,DC=com</module-option>
               <module-option name="bindCredential">MYPASSWORD</module-option>
               <module-option name="baseCtxDN">cn=Users,DC=KRB,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=KRB,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="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>
        </login-module>
        <login-module code="com.lombardisoftware.security.provider.authentication.jboss.TWAuthenticatedRoleLoginModuleImpl" flag="required">
            <module-option name="authenticatedRole">twuser</module-option>
        </login-module>
        <login-module code="org.jboss.security.ClientLoginModule" flag="required">
            <module-option name="password-stacking">useFirstPass</module-option>
            <module-option name="restore-login-identity">true</module-option>
        </login-module>
    </authentication>
</application-policy>

  • c:\Teamworks\process-server\conf\jboss-service.xml
Uncomment the AdvancedWebCallbackHandler as shown.

<!-- Uncomment for SSO auto-login -->

<attribute name="CallbackHandlerClassName">org.jboss.security.auth.AdvancedWebCallbackHandler</attribute>


  • c:\Teamworks\process-server\applications\portal.war\WEB-INF\context.xml
Modify to match the following code.

<Context>
    <!-- uncomment and configure appropriately for SSO autologin -->
    <Valve className="org.jboss.security.auth.HttpServletRequestResponseValve"
           domainName="KRB"
           domainControllerAddress="KRBPDC"
           loadBalance="false"
           krbServicePrincipalName="HTTP/krbtw.krb.com@KRB.COM"
           krbServicePrincipalPassword="ENCRYPTEDPASSWORD"
           krbRealm="KRB.COM"
           useNegotiate="true"
           useNtlm="false"
           useBasic="false"
           basicRealm="TWRealm"
           userValidatorClass="com.lombardisoftware.userorg.JBossAutologinValidator"/>
    <Valve className="org.apache.catalina.authenticator.FormAuthenticator" characterEncoding="UTF-8" />
</Context>

  • c:\Teamworks\process-server\applications\teamworks.ear\teamworks.war\WEB-INF\context.xml
Modify to match the following code.

<Context>
    <!-- uncomment and configure appropriately for SSO autologin -->
    <Valve className="org.jboss.security.auth.HttpServletRequestResponseValve"
           domainName="KRB"
           domainControllerAddress="KRBPDC"
           loadBalance="false"
           krbServicePrincipalName="HTTP/krbtw.krb.com@KRB.COM"
           krbServicePrincipalPassword="ENCRYPTEDPASSWORD"
           krbRealm="KRB.COM"
           useNegotiate="true"
           useNtlm="false"
           useBasic="false"
           basicRealm="TWRealm"
           userValidatorClass="com.lombardisoftware.userorg.JBossAutologinValidator"/>
    <Valve className="org.apache.catalina.authenticator.FormAuthenticator" characterEncoding="UTF-8" />
</Context>

  • c:\Teamworks\process-server\applications\webapi.war\WEB-INF\context.xml
Modify to match the following code.

<Context>
    <!-- uncomment and configure appropriately for SSO autologin -->
    <Valve className="org.jboss.security.auth.HttpServletRequestResponseValve"
           domainName="KRB"
           domainControllerAddress="KRBPDC"
           loadBalance="false"
           krbServicePrincipalName="HTTP/krbtw.krb.com@KRB.COM"
           krbServicePrincipalPassword="ENCRYPTEDPASSWORD"
           krbRealm="KRB.COM"
           useNegotiate="true"
           useNtlm="false"
           useBasic="true"
           basicRealm="TWRealm"
           userValidatorClass="com.lombardisoftware.userorg.JBossAutologinValidator"/>
</Context>

Thats the last of the Teamworks configuration changes. Restart your process server and check the logs to confirm there are no errors. Next, you will want to login to the teamworks admin site (http:\\krbtw.krb.com\teamworks) as tw_admin to confirm AD groups are visible to Teamworks. From the Teamworks admin portal, go to the "Maintain Logical Roles" page. You should see your domain groups populating the "Available Roles" box as shown below.

 

Once you've confirmed groups are showing up properly, try logging in to the portal site from another computer as a domain user using IE. Be sure to add the url "krbtw.krb.com" to the browser's Local Intranet zone first, to confirm that you are logging in via SSO\Kerberos. You'll know it's working if you see the "Attempting auto-login" screen flash briefly (shown in the screenshot below) before dumping you into the Teamworks portal. If you get a windows password prompt, of if you get the Teamworks form password prompt, you'll know you've hit a problem.




Part 5 - Install Teamworks Web Part


For this example, we will assume the IIS directory path for the web application is located here "c:\Inetpub\wwwroot\wss\VirtualDirectories\80\"

Run Teamworks for SharePoint Installer


I ran the installer as the SharePoint farm administrator. I typically use the same account that was used to run the SharePoint installer and the SharePoint configuration wizard.

I haven't confirmed this, but there seem to be cases where the Teamworks Site Templates in SharePoint are not available, and I think it may have to do with the account used to run the installer.

The SharePoint for Teamworks installer is fairly self explanatory. You need to know the URL of your teamworks server (and the port used for web access, if it is not port 80). I always choose -not- to let the installer modify any configuration files because of several possible bugs with the installer. I feel its safer to manually perform these steps, as shown in this post.

Move Teamworks Web Part DLLs to Web Application Bin


On the SharePoint server (KRBMOSS), search for the Teamworks Web Part assemblies and copy them to the web application bin directory, so that your web application can actually use them. The version of Teamworks for SharePoint I am using installs the assemblies to c:\windows. Both files that need to be copied from

  • c:\windows\Lombardi.Server.WebParts.dll
  • c:\windows\Lombardi.Server.WebParts.Portal.dll

to

  • c:\Inetpub\wwwroot\wss\VirtualDirectories\80\bin\Lombardi.Server.WebParts.dll
  • c:\Inetpub\wwwroot\wss\VirtualDirectories\80\bin\Lombardi.Server.WebParts.Portal.dll

This step should not be necessary. This seems to be a bug with the version of the Teamworks for SharePoint installer that I'm using. One of these days I'll get around to asking Lombardi Teamworks support about it.

Modify Web Application web.config File


For the next few steps in this example, we are editing the following file for our web application.

c:\Inetpub\wwwroot\wss\VirtualDirectories\80\web.config

Add Teamworks Web Part Assemblies to Safe Controls


In web.config, add the Teamworks assemblies as safe controls.

This may change as new versions of the Teamworks for Sharepoint assemblies are released. You may need to confirm the version number and public key token for yourself to get this part working. Check with Lombardi support if you get stuck on this.

<SafeControls>
...
    <SafeControl Assembly="Lombardi.Server.WebParts, Version=1.1.74.0, Culture=neutral, PublicKeyToken=6a9d7f68474317de" Namespace="Lombardi.Server.WebParts" TypeName="*" Safe="True" />
    <SafeControl Assembly="Lombardi.Server.WebParts.Portal, Version=1.1.74.0, Culture=neutral, PublicKeyToken=b45d0da702028bb7" Namespace="Lombardi.Server.WebParts.Portal" TypeName="*" Safe="True" />
</SafeControls>

I believe this is also a bug with the installer. I would think the installer should create these SafeControl entries for you in web.config since the installer does not tell you the version number or PublicKeyToken of the assemblies.

Set Trust Level


In web.config, you will need to set the trust level to something that will work for the Teamworks assemblies. For testing, I simply set the trust level to "full" as shown below.

<trust level="Full" originUrl="" />

Configure SharePoint Site to Allow Teamworks Web Parts


Login to the sharepoint site as an administrator, then go to the site collection root and add the Lombardi Teamworks Web Parts to the Web Part gallery.

From the site collection settings page, click "Web Parts" under "Galleries".



Click the "New" button in the Web Part Gallery list page.

 

Check the box next to each Lombardi.* Web Part, then click "Populate Gallery" to make them available in the site collection for use.

 

Confirm Integrated Authentication Works for Web Part


From a page of your site, edit the page and add the TeamworksSavedSearch Web Part to the page.



Configure the Web Part for Integrated Authentication Mode.



If kerberos is working properly, you should see results similar to the following when you click "Apply" or "Ok" after configuring the Web Part.



The End!


If you were successful, pat yourself on the back and go buy yourself a mocha! Honestly, many people have trouble configuring kerberos on small server farms about this size, and once you get into things like reporting services and load balancing, it gets much more complicated.

When planning and testing kerberos configurations, I suggest always starting with a small example like this one, using all VMs (I use VMWare ESXi 4.0 currently for all my VMs). Once you get a working sandbox network, make a copy of your VM's so you can restore to a known good configuration for kerberos. Then you can safely start your experimenting. Build your more complex scenarios from this known good working example, without fear of losing all that initial leg work.

Resources

A list of links to more kerberos resources can be found here:
http://www.bryansgeekspeak.com/2009/07/teamworks-621-moss-2007-kerberos-sso.html

No comments: