Difference between revisions of "Apache Kerberos Authentication"

From Michael's Information Zone
Jump to navigation Jump to search
 
(9 intermediate revisions by the same user not shown)
Line 16: Line 16:
 
*web server
 
*web server
 
intranet.tld
 
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.<ref>https://community.microstrategy.com/s/article/KB37602-quot-No-credentials-cache-found-while-getting-client</ref><ref>http://plosquare.blogspot.com/2013/02/solution-for-gss-api_8.html</ref>
 +
<br>
 +
<br>
 +
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
 +
<pre>
 +
setspn -d HTTP/your.server.com@YOURDOMAIN.COM serviceaccount
 +
setspn -A HTTP/your.server.com serviceaccount
 +
</pre>
 +
====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.
 +
<br>
 +
NOTE : This is case sensitive.
 +
<pre>
 +
ktpass /out C:\Temp\domain1.keytab /princ HTTP/website@DOMAIN1.TLD /mapuser user /pass <password> /crypto ALL /ptype KRB5_NT_PRINCIPAL /kvno 1
 +
</pre>
 +
On domain2.tld
 +
<pre>
 +
ktpass /out C:\Temp\domain2.keytab /princ HTTP/website@DOMAIN2.TLD /mapuser user /pass <password> /crypto ALL /ptype KRB5_NT_PRINCIPAL /kvno 1
 +
</pre>
 +
====On the web server====
 +
<pre>
 +
[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
 +
</pre>
 +
 
===krb5.conf===
 
===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.
 
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.
Line 73: Line 105:
 
}
 
}
  
 +
</pre>
 +
===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.
 +
<pre>
 +
<IF "'%{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>
 +
 +
</pre>
 +
 +
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) you are limited in options. In my case I ended up allowing a subnet and a single IP to access without kerberos authentication, but all others would be required to use it.
 +
<ref>https://www.jeffgeerling.com/blogs/jeff-geerling/apache-kerberos-authentication</ref>
 +
<ref>https://wiki.apache.org/httpd/BypassAuthenticationOrAuthorizationRequirements</ref>
 +
<ref>https://httpd.apache.org/docs/trunk/mod/mod_access_compat.html</ref>
 +
<pre>
 +
<IF "'%{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 On
 +
Require valid-user
 +
Satisfy any
 +
Deny from all
 +
Allow from xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx/xx
 +
</IF>
 +
</pre>
 +
 +
==Docker==
 +
===Host config===
 +
In this example we are using Amazon Linux
 +
<pre>
 +
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
 +
</pre>
 +
===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.
 +
<pre>
 +
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
 
</pre>
 
</pre>

Latest revision as of 19:00, 6 May 2019

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 "'%{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) you are limited in options. In my case I ended up allowing a subnet and a single IP to access without kerberos authentication, but all others would be required to use it. [4] [5] [6]

<IF "'%{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 On
Require valid-user
Satisfy any
Deny from all
Allow from xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx/xx
</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