Active Directory Single Sign-On for Linux Intranet Servers
I mentioned a while ago that I have a Linux web server set up with Kerberos SSO in our AD domain. Setting it up was a lot more tedious than it seems like it should have been. I found bits and pieces of useful information here and there, and some step-by-step guides to help with specific sub-tasks, but I couldn’t find a good, intranet-specific guide to help me understand the big picture—what pieces I needed (and didn’t need) and how they fit together. So here’s part 1 of my attempt to rectify that situation (part 2 will be the WordPress integration—I’m still working on that part).
Requirements
The basic requirement was to set up a LAMP server running WordPress, which should integrate transparently into our Active Directory network and become the CMS and web front-end for our intranet. To make the integration work, I needed AD-based authentication for:- SSH (for server administrators)
- SFTP (for server administrators and web developers)
- Apache (for all domain users)
Note: In principle I could also have set up SAMBA, but I didn’t want the added complexity or security liability. I don’t think any of this setup would preclude the use of SAMBA if you need it in your environment.
Step 1 – Linux
Install Ubuntu Server 11 64-bit, install all the updates, and do the usual initial setup stuff.Note: some of the file paths and commands in here are Ubuntu-specific; if you’re running a different flavor YMMV.
Caution! Before you go any further, make sure you have a local user account that can SSH, SFTP, and sudo. Keep one SSH session always logged in with this local account. Every time you make a change, open another SSH window and make sure you can still log in with the local account. It’s so easy to make a mistake and lock yourself out. (Not that I’ve ever done that, of course…)
Resources
Step 2 – AD integration for OS, SSH, and SFTP
I was all set to do this the hard way, hand-editing configuration files, but then I stumbled on BeyondTrust Power Broker Identity Services Open (formerly called Likewise Open). I signed up, they sent me an email with some helpful links (download, documentation). I downloaded the PBIS Open 6.5 64-bit Debian package, followed a few directions in their admin guide, and had the machine joined to the AD domain and authenticating me with SSH and SFTP in just a few minutes. Slick!One little tweak: I wanted to be able to log in with just my username—not EXAMPLE\username or username@example.com—so I added one line in the [libdefaults] section of /etc/krb5.conf:
default_realm = EXAMPLE.COM
Note: Kerberos realms must be ALL CAPS or things won’t work.
Caution! Remember to lock down which users can log in with SSH and SFTP. I won’t cover that here, but don’t forget to do it!BeyondTrust also followed up with a phone call within about an hour and got me in touch with a support guy to help answer my questions about the next step…
Resources
Step 3 – Apache, PHP, and mod_auth_kerb.so
I know Apache 2.4 is released, but for now I stuck with 2.2 because there’s an Ubuntu package for it, it does everything I need, and the custom version of mod_auth_kerb.so that’s part of PBIS supports it. Make sure PHP 5 is installed—you’ll need it to test your SSO setup.BeyondTrust Power Broker Identity Services Open will help us here, too. We just have to make a few adjustments to the standard setup. Find the section in the PBIS Installation and Administration Guide about configuring SSO for Apache (starts on page 188)—I followed their procedure for the most part but hit a few pitfalls along the way.
Big thanks to Joshua McClintock at BeyondTrust, who helped me find my way through these pitfalls and come out with a better understanding of how the pieces fit!
Pitfall #1
The PBIS documentation says to run ldd against the Apache binary and check the version of libgssapi_krb5.so.2. Don’t worry about that part—mine didn’t list that library at all and everything still worked fine for me.Pitfall #2
The documentation says that the Apache integration bits (tweaked version of mod_auth_kerb.so) are in their AppIntegration package (which isn’t yet available for PBIS 6.5), but I think that’s an error—at least in version 6.1 it was in the main package. The PBIS 6.5.561 package (current as I write this) doesn’t include the /opt/pbis/apache directory you’re looking for. I’m hoping they fix that packaging error (or release the AppIntegration package) soon, but meanwhile I found what I needed in the 6.1 package. I stashed the 6.1 package in my home directory and then did a little digging:chmod 700 ~/LikewiseOpen-6.1.0.8780-linux-amd64-deb.sh ~/LikewiseOpen-6.1.0.8780-linux-amd64-deb.sh --noexec dpkg --extract ~/LikewiseOpen-6.1.0.8780-linux-amd64-deb/packages/linux/x86_64 ~/LikewiseOpen-6.1.0.8780 sudo cp ~/LikewiseOpen-6.1.0.8780/opt/likewise/apache /opt/pbis/apache
Note: I already had PBIS 6.5 installed and working, so I didn't want to install 6.1--I just extracted the package contents so I could recover the one file I neeeded.If all worked out, /opt/pbis/apache/2.2/mod_auth_kerb.so should now exist. Here’s how we tell Apache to use it:
sudo echo LoadModule auth_kerb_module /opt/pbis/apache/2.2/mod_auth_kerb.so > /etc/apache2/mods-available/auth_kerb_pbis.load sudo rm /etc/apache2/mods-enabled/auth_kerb.load sudo ln –s /etc/apache2/mods-available/auth_kerb_pbis.load /etc/apache2/mods-enabled/auth_kerb_pbis.load
Pitfall #3
If you try to restart Apache at this point, you’ll get an error and it will fail to start up. To avoid that, edit /etc/apache2/envvars and append this line at the end:export LD_LIBRARY_PATH=/opt/pbis/lib:/opt/pbis/lib32That tells Apache to use the PBIS-tweaked version of libcom_err.so.3.
Now we’re ready to restart Apache, so our changes take effect:
sudo service apache2 restart
Resources
Step 4 – AD Domain Admin Stuff
If you’re not an AD domain admin, find one and get on their good side—you’re about to ask them to run a command they’ve probably never heard of, on a domain controller, with full admin privileges. We need to set up a Kerberos Service Principal Name (SPN) for the HTTP service; an SPN needs to be tied to an AD account. An SPN and its associated crypto key are stored in a keytab file (forgive me if my Kerberos terminology isn’t quite right, but you get the idea).First, create a service account in AD for the web server (separate from its machine account). Set the password never to expire, and remember the password for the next step.
Next, create the keytab file:
ktpass /out webserver.keytab /princ HTTP/webserver.example.com@EXAMPLE.COM /mapuser serviceaccountname /pass serviceaccountpassword /ptype KRB5_NT_PRINCIPAL /crypto RC4-HMAC-NT
Note: ktpass must be run on a domain controller, with Administrator privileges. Right-click the Command Prompt icon and choose Run As Administrator. See this post from Scott Lowe describing the error you’ll get otherwise—the answer is in the first comment.
Another note: rumor has it that ktpass.exe wasn’t included with Windows Server 2003—it was part of the Support Tools pack that you had to download and install separately.Transfer the webserver.keytab file to /etc/apache2/auth on the Linux server.
Caution! Use a secure method like SFTP to transfer the keytab file—it contains the keys to the authentication kingdom!Lock down permissions on the keytab file:
sudo chown www-data /etc/apache2/auth/webserver.keytab sudo chmod 400 /etc/apache2/auth/webserver.keytab
Resources
- PBIS Installation and Administration Guide
- Scott Lowe on UAC and ktpass.exe
- Windows Server 2003 SP1 Support Tools (MS KB892777)
Step 5 – Testing SSO
Create a test directory (/var/www/sso for example) with an index.php file:Here’s where we tell Apache to require Kerberos authentication to access the sso directory. Create a new file under /etc/apache2/conf.d (when Apache starts up, it includes any files in that directory as part of its configuration). I called mine dir_sso, but the file name doesn’t really matter:SSO Test \w+)\\\\(?P\w+)/', $_SERVER['REMOTE_USER'], $m)) { $username = strtolower($m[username]); $domain = $m[domain]; } else { $username = $remote_user; } ?> Single Sign-On Test
Welcome! You are logged in as =$username?> (from the =$domain?> domain).
Options MultiViews FollowSymLinks AllowOverride None Order allow,deny Allow from all Require valid-user AuthType Kerberos AuthName "Kerberos Login" KrbAuthRealms EXAMPLE.COM Krb5Keytab /etc/apache2/auth/webserver.keytab KrbMethodNegotiate on KrbMethodK5Passwd off KrbSaveCredentials on
Note: remember to restart Apache so the change takes effect.From a Windows machine that’s a member of the AD domain and logged in as a domain user, point a browser (Chrome and IE work; I haven’t tested anything else) at http://webserver.example.com/sso. If everything is working, it will tell you your AD username and domain.
Resources
Step 6 – MySQL and WordPress
Make sure you have MySQL and the Apache mod_rewrite module installed, and then follow the WordPress “Famous 5-Minute Install.”There’s an Ubuntu package for WordPress that might work for you, but it does some stuff with symlinks that made me nervous: my goal was to have three independent WP installations (development, test, and production) that I could manage, upgrade, break, and fix independently. So I moved everything from /var/www to /var/www/default, changed the path in /etc/apache2/sites-available/default, and restarted Apache. Once I had the default site stuff out of the way, I unzipped WordPress into three different directories:
- /var/www/wpdev
- /var/www/wptest
- /var/www/wpprod
Note: all three WP installs share a single instance of MySQL, but to keep things cleanly separated, I created 3 separate MySQL users and 3 separate databases; for clarity, username and database name are same, e.g. wp_dev, wp_test, wp_prod. There are other ways to do it (one DB with each WP install having a different prefix), but to me this seems like the best balance between isolation and administrative overhead. Your environment may have different requirements, so give it some thought before you commit.You should now have one or more working WordPress installations.
Resources
- Installing WordPress
- GRC Perfect Passwords– I used this to generate random passwords for the MySQL accounts (select about 32 characters, copy, paste to set up MySQL account, and paste again into wp-config.php)
- Random key generator for wp-config.php
- Ubuntu-specific WordPress package (I don’t necessarily recommend this approach)
Step 7 – Enable SSO for WordPress Directories
Note: just to be clear, my end goal is automatic creation of WP accounts, mapping them to AD accounts, and transparent single sign-on to WordPress. I’m not there yet. What this step does is tell Apache to require Kerberos authentication when a user accesses the WP site. WordPress itself—probably via a plugin—will have to handle the rest (and I’ll write it up when it’s done).You’ll need an additional Kerberos keytab entry for each virtual server (DNS alias) that needs SSO. Again, get on a domain admin’s good side, and then ask them to do the ktpass.exe thing again, just like in step 4.
ktpass /out dev.keytab /princ HTTP/intranet-dev.example.com@EXAMPLE.COM /mapuser serviceaccountname /pass serviceaccountpassword /ptype KRB5_NT_PRINCIPAL /crypto RC4-HMAC-NT ktpass /out test.keytab /princ HTTP/intranet-test.example.com@EXAMPLE.COM /mapuser serviceaccountname /pass serviceaccountpassword /ptype KRB5_NT_PRINCIPAL /crypto RC4-HMAC-NT ktpass /out prod.keytab /princ HTTP/intranet.example.com@EXAMPLE.COM /mapuser serviceaccountname /pass serviceaccountpassword /ptype KRB5_NT_PRINCIPAL /crypto RC4-HMAC-NTSFTP these files to /etc/apache2/auth on the Linux server, and remember to lock down the permissions like we did in step 4.
Optional: if you end up with multiple keytabs and want to consolidate the SPNs into a single keytab file, /opt/pbis/bin/ktutil is the tool you seek.The configuration files for Apache virtual servers live under /etc/apache2/sites-available. For each virtual server that needs SSO (these don’t really have to be WordPress sites—that just happens to be what I’m using), make sure the corresponding config file looks like this:
DocumentRoot "/var/www/dev" ServerName intranet-dev.example.com ServerAlias intranet-dev Options +Indexes Allow from all Require valid-user AuthType Kerberos AuthName "Kerberos Login" KrbAuthRealms EXAMPLE.COM Krb5Keytab /etc/apache2/auth/dev.keytab KrbMethodNegotiate on KrbMethodK5Passwd off KrbSaveCredentials on