Kerberos SSO with Active Directory Integration

From Request Tracker Wiki
Jump to navigation Jump to search

Goal

Users should transparently log in to Request Tracker with AD domain credentials.

Overview

Apache authenticates users using mod_auth_kerb and passes the authenticated username to RequestTracker. If the users exists in RT, they will be logged in automatically. If the user does not exist, an unprivileged user will be created using details from AD (email, full name etc) and then logged in.

Installation

  • Download all of the relevant files from here
    • If anyone knows how to upload files to wikia, please upload them from my webspace and remove the link :)
    • I will put the patch file in the appendix below, in case my hosting goes down at some stage in the future.
  • Install Request Tracker onto apache
    • Set up your basic configuration, confirm everything is working
  • Install RT::Authen::ExternalAuth (I tested on version 0.09)
    • Setup RT to authenticate against AD using LDAP
    • Test and confirm that everything is working as expected, with manually typed usernames and passwords
  • Install mod_auth_kerb and configure to authenticate against your AD
    • This is the step that will cause the most issues, there is plenty of documentation out there though
    • I suggest setting up a location like /private and testing against that, until you have the authentication working successfully, then apply it to the RT directory/virtualhost and test it further
  • Test and ensure that mod_auth_kerb is authenticating the RT location/virtualhost.
    • If this is setup correctly, RT will still be prompting for a username and password.
  • Update "$RT4_HOME/local/plugins/RT-Authen-ExternalAuth/lib/RT/Authen/ExternalAuth.pm"
    • I have supplied a patch file and also the modified file
  • Add this configuration line to your RT_SiteConfig.pm file:
    • Set($StripStringFromRemoteUser, "\@DOMAIN.LOCAL");
    • You need the backslash to escape the "@" symbol. Single quotes might have worked, but I have not tested them.
    • This removes the domain name from your username before trying to authenticate
  • Check to see if it is now working.

Notes

Kerberos

Kerberos is a pain in the ass. Check that the SPN is valid against the hostname that you are connecting to and that you do not have a duplicate SPN configured in AD. The following code will check for duplicate SPN's

 ldapsearch -h dc01.domain.local -x -W -D "Administrator@domain.local" \
 -b "DC=DOMAIN,DC=LOCAL" 'serviceprincipalname=*' serviceprincipalname | \
 grep 'Name:' | sort | uniq -d

To Generate your keytab, the easiest way is to run this command from the linux host after joining the domain.

 net ads keytab add HTTP -U Administrator

If you are using a virtual server and the name you connect with is not the same as the domain computers name, you will need to generate a keytab for the second hostname. At my company, the computers name is Support01 but we are connecting using rt.domain.local. Authentication will fail if the keytab does not match the hostname/fqdn you connect to. To generate a keytab for another hostname:

  1. Create a new user account for the SPN/keytab to be bound with, set the password never to expire.
  2. From the windows command line run the following command (obviously you will need to replace my values to match your enviroment)
    • ktpass -princ HTTP/rt.domain.local@DOMAIN.LOCAL -out C:\rt.domain.local.keytab -mapuser rt-kerb@domain.local --pass userspassword
  3. Move the keytab to the correct location on the apache host. (specified in the apache config file for your virtual host)

Firefox

Open about:config and change add the RT url to 'network.negotiate-auth.trusted-uris'

Internet Explorer

First, add the RT url to either the Trusted sites or the Intranet zone. Once you have done that, either

  • set the security settings for that zone to allow "automatic logon with the current username and password."
  • OR the lazy (efficient) way: Set the security level for the zone to "Low"

Appendix

This is the patch file:

*** ExternalAuth.pm.vanilla	2011-07-28 10:39:08.024453400 +0800
--- ExternalAuth.pm	2011-07-28 10:39:13.784799000 +0800
***************
*** 81,89 ****
          # safely bypass the password checking later on; primarily because
          # it's VERY unlikely we even have a password to check if an SSO succeeded.
          $pass_bypass = 0;
! 	if(defined($username)) {
! 	    $RT::Logger->debug("Pass not going to be checked, attempting SSO");
!             $pass_bypass = 1;
          } else {

  	    # SSO failed and no $user was passed for a login attempt
--- 81,94 ----
          # safely bypass the password checking later on; primarily because
          # it's VERY unlikely we even have a password to check if an SSO succeeded.
          $pass_bypass = 0;
! 
!         if(defined $ENV{'REMOTE_USER'}) {
!             $username = $ENV{'REMOTE_USER'};
!             if(defined $RT::StripStringFromRemoteUser) {
!                 $username =~ s/$RT::StripStringFromRemoteUser//;
!             }
!             $RT::Logger->debug("REMOTE_USER set to: $username");
!             $pass_bypass = 1; 
          } else {

          # SSO failed and no $user was passed for a login attempt