Apache Kerberos Authentication
Contents
Purpose
To allow users to authenticate using seamless SSO via kerberos.[1]
MultiRealm Authentication
In this case I want to authenticate more than one realm (two domains). After following the common instructions online I was unable to log in using the second realm. The first realm logged in without issue.
NOTE 1 : This is a messy post as I have worked on this for several days and am trying to record what I did before I forget.
NOTE 2 : I am not sure if all of this is necessary, but I wanted to track everything I did regardless
Environment
- Domains
Domain1.tld
Domain2.tld
- web server
intranet.tld
Keytab Creation
Please make sure that you do not have duplicate SPNs in AD. I ran into an issue where I converted a site to use dual realms, but the old one would not authenticate using the new keytab. Eventually I found the duplicate SPN.[2][3]
You can modify spns using two methods. If you like using a GUI, you can open the attribute editor for the service account and scroll down to SPNS and modify accordingly. Or you can use the CLI command setspn
setspn -d HTTP/your.server.com@YOURDOMAIN.COM serviceaccount setspn -A HTTP/your.server.com serviceaccount
On the domain controllers
On domain1.tld, create a user object that will be used for the service. Then create the keytab and map it to the user.
NOTE : This is case sensitive.
ktpass /out C:\Temp\domain1.keytab /princ HTTP/website@DOMAIN1.TLD /mapuser user /pass <password> /crypto ALL /ptype KRB5_NT_PRINCIPAL /kvno 1
On domain2.tld
ktpass /out C:\Temp\domain2.keytab /princ HTTP/website@DOMAIN2.TLD /mapuser user /pass <password> /crypto ALL /ptype KRB5_NT_PRINCIPAL /kvno 1
On the web server
[root@web ~]# ktutil ktutil: read_kt domain1.keytab ktutil: read_kt domain2.keytab ktutil: write_kt merged.keytab ktutil: exit [root@web ~]# mv merged.keytab /etc/httpd [root@web ~]# chgrp apache /etc/httpd/merged.keytab [root@web ~]# chmod 440 /etc/httpd/merged.keytab
krb5.conf
The server I am using was enrolled in domain1 using sssd and the "realm join" command many a year ago. We will be editing the krb5.conf file that was created during this process.
# Configuration snippets may be placed in this directory as well includedir /etc/krb5.conf.d/ includedir /var/lib/sss/pubconf/krb5.include.d/ [logging] default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmind.log [libdefaults] dns_lookup_realm = true ticket_lifetime = 24h renew_lifetime = 7d forwardable = true rdns = false # default_realm = EXAMPLE.COM default_ccache_name = KEYRING:persistent:%{uid} default_realm = DOMAIN1.TLD [realms] # EXAMPLE.COM = { # kdc = kerberos.example.com # admin_server = kerberos.example.com # } DOMAIN1.TLD = { kdc = domain1.tld admin_server = domain1.tld } DOIMAIN2.TLD = { kdc = domain2.tld admin_server = domain2.tld } [domain_realm] # .example.com = EXAMPLE.COM # example.com = EXAMPLE.COM domain1.tld = DOMAIN1.TLD .domain1.tld = DOMAIN1.TLD domain2.tld = DOMAIN2.TLD .domain2.tld = DOMAIN2.TLD [capaths] DOMAIN1.TLD = { DOMAIN2.TLD = . } DOMAIN2.TLD = { DOMAIN1.TLD = . }
VHOST Config
Here I tried using the principle from the keytab, but for some reason the kvno kept getting logged as 3 instead of 6. So for now I told Apache to use any service name. Need to research security risks related to this. Also I might need to keep it at ANY if I can not specify more than one principal.
<IF "'%{REMOTE_ADDR}' != '<trusted IP here>' && '%{REQUEST_URI}' != '/wp-admin'"> AuthType Kerberos AuthName "Kerberos authenticated site" KrbAuthRealms DOMAIN1.TLD DOMAIN2.TLD #KrbServiceName HTTP/user@DOMAIN1.TLD KrbServiceName Any Krb5KeyTab /etc/httpd/merged.keytab KrbMethodNegotiate On KrbMethodK5Passwd Off require valid-user </IF>
If you want to allow access regardless of authentication (i.e. If you use the apache variable as part of your own authentication, but allow manual login if this fails) [4] [5] [6]
<IF "'%{REMOTE_ADDR}' != '<trusted IP here>' && '%{REQUEST_URI}' != '/wp-admin'"> AuthType Kerberos AuthName "Kerberos authenticated site" KrbAuthRealms DOMAIN1.TLD DOMAIN2.TLD #KrbServiceName HTTP/user@DOMAIN1.TLD KrbServiceName Any Krb5KeyTab /etc/httpd/merged.keytab KrbMethodNegotiate On KrbMethodK5Passwd Off Satisfy Any </IF>
Docker
Host config
In this example we are using Amazon Linux
sudo yum -y upgrade sudo yum -y install yum-cron oddjob oddjob-mkhomedir sssd samba-common-tools realmd docker amazon-efs-utils firewalld sudo systemctl enable firewalld sudo systemctl enable docker sudo realm join -U <username> <fqdn> sudo reboot
Container Config
- First, make sure SSSD is installed in the container.
- The container should have the environmental variable for the ticket cache set outside of kernel protected space (i.e. ENV KRB5CCNAME /tmp/ticket)
- Then we mount the local config into the container as read only when starting the container.
docker run --name website -v /var/lib/sss:/var/lib/sss:ro -p 80:80 -p 443:443 -e TZ=America/New_York -d --restart unless-stopped
- ↑ https://www.netiq.com/communities/cool-solutions/kerberos-authentication-against-multiple-domains
- ↑ https://community.microstrategy.com/s/article/KB37602-quot-No-credentials-cache-found-while-getting-client
- ↑ http://plosquare.blogspot.com/2013/02/solution-for-gss-api_8.html
- ↑ https://www.jeffgeerling.com/blogs/jeff-geerling/apache-kerberos-authentication
- ↑ https://wiki.apache.org/httpd/BypassAuthenticationOrAuthorizationRequirements
- ↑ https://httpd.apache.org/docs/trunk/mod/mod_access_compat.html