Active Directory Kerberos authentication with Apache on Linux

, posted: 15-Feb-2020 08:56

Kerberos single sign-on with Apache and AD and LDAP authorization

I always forget how to do this as I only ever need to set it up so infrequently I thought I would document it here to remind myself of the steps. I am looking to create an AD Service Account (standard user) rather than having Linux fully registered with AD (machine account). Below detail the components and steps:

Components involved:

  • AD Service Account - Created on the AD Domain Controller and then using ktpass to create a Keytab file to copy to the Linux host
  • Linux Apache instance - Running Apache 2.4 without full AD / Kerberos federation and will need a working keytab file
  • Windows desktop - A member of the AD Domain that should be able to use the Kerberos ticket using IE, Chrome or Firefox. For IE&Chrome it is via Registry or Group Policy to add the domain/site you want to into the "Local Intranet" and for Firefox it is an advanced setting in firefox.
  • Adding LDAP Group based authorization - So you need to be part of a AD Group to gain access.

1) Active Directory Service Account.

Assuming you are running Windows 2008 or newer (including Forrest and Domain functional level upgraded to 2008 or higher!) then you should be able to use AES256-SHA1 rather than AES128/RC4 or DES crypto, since seriously you should be upgrading to strong crytpo. As per this MS article on Kerberos.

Create service account:

Creating the service account using Powershell to also enable Kerberos 256 on the account.


New-ADUser -Name "ServiceAccountCN" -Path "OU=ServiceAccounts,DC=AD,DC=DOMAIN,DC=LOCAL" -ServicePrincipalNames "HTTP/apachehost.dnsdomain" -SamAccountName "ServiceAccountSAM" -UserPrincipalName "ServiceAccountUPN@AD.DOMAIN.LOCAL" -AccountPassword (ConvertTo-SecureString "**PASSWORD**" -AsPlainText -Force) -passwordNeverExpires $true -Enabled $true -OtherAttributes @{'msDS-SupportedEncryptionTypes'="26"}


The following values should be changed in bold:

Name = This is the CN or how the record will be displayed in AD, it serves no functional use other than how it is displayed in AD Users and Computers

Path = The container to also create the service account, again probably not useful since otherwise users get created in cn=Users including the domain name.

ServicePrincipalNames (SPN) = This should be the Service Principal Name, starting with "HTTP/" in upper case no matter if you have the site http or https, and then the full DNS domain name of the Apache host.

SamAccountName (SAN) = The Sam Account Name, typically the same as the Name / CN but not always and needs to be unique in AD.

UserPrincipalName (UPN) = This is the object UPN, this will be overwritten by ktpass but it will be reference and needs to include the AD domain name in upper case.

AccountPassword = Shown here setting the password in clear text.

passwordNeverExpires, Enabled = You don't want the Service Account password to expire, and want the account enabled when you create it.

msDS-SupportedEncryptionTypes = 26 = This enables Kerberos AES128 and AES256 on the account. If you just want AES256 set it to 18 but I prefer 26.

 

Create keytab:

Now you have a Service Account created you need to create a keytab to import into Apache. To create the keytab file use ktpass. Either you could create a single keytab only supporting AES256, or a keytab with both AES128 and AES256. You shouldn't never add "-setupn" to the command line since then the UPN isn't updated, and the UPN MUST be the Service Principal Name ie "HTTP/servername.domain" otherwise AD doesn't know how to resolve the account name. It also means if you have multiple hostnames you need multiple service accounts and multiple keytabs.

Keytab only supporting AES256:


ktpass -princ HTTP/apachehost.dnsdomain@AD.DOMAIN.LOCAL -mapuser ServiceAccountUPN@AD.DOMAIN.LOCAL -pass **PASSWORD** -crypto AES256-SHA1 -ptype KRB5_NT_PRINCIPAL -out apachehost.keytab


Keytab supporting both AES128 and AES256:


ktpass -princ HTTP/apachehost.dnsdomain@AD.DOMAIN.LOCAL -mapuser ServiceAccountUPN@AD.DOMAIN.LOCAL -pass **PASSWORD** -crypto AES128-SHA1 -ptype KRB5_NT_PRINCIPAL -out apachehost-temp.keytab
ktpass -princ HTTP/apachehost.dnsdomain@AD.DOMAIN.LOCAL -mapuser ServiceAccountUPN@AD.DOMAIN.LOCAL -pass **PASSWORD** -crypto AES256-SHA1 -ptype KRB5_NT_PRINCIPAL -in apachehost-temp.keytab -out apachehost.keytab


Similar values should be change in bold:

princ = The principal of the domain, always prefixed with HTTP/ in upper case no matter if you are connecting over http or https and the ADDOMAIN should always be in upper case.

mapuser = The same value as UPN from above with the ADDOMAIN in upper case.

pass = The password you want to set, typically the same as the random password you used above to create the account, but it can be different.

crypto = AES256-SHA1 or AES128-SHA1

in/out = The name of the file to create, and if you specify an "in" you are loading the first keytab in to create a keytab with multiple records.

 

You should now see the "User logon name" aka UPN in AD Users and Computers "Account" tab has updated to be the same as the SPN. 

Now you should have a working keytab to load on Apache.

2) Linux Apache instance

RHEL/CENTOS:

yum install httpd mod_auth_kerb

Debian/Ubuntu:

apt-get install apache2 libapache2-mod-auth-kerb

Kerberos local configuration

There are numerous posts saying you need to update the /etc/krb5.conf file to resolve your domain. This is required if you want the host to prompt for a password and still be able to resolve the host. It's not strictly a mandatory requirement but helps.

/etc/krb5.conf


[libdefaults]
 default_realm = AD.DOMAIN.LOCAL
 kdc_timesync = 1
 ccache_type = 4
 forwardable = true
 proxiable = true
 dns_lookup_realm = true
[realms]
AD.DOMAIN.LOCAL= {
 kdc = addc.dnsdomain
 admin_server = addc.dnsdomain
}
[domain_realm]
apachehost.dnsdomain = AD.DOMAIN.LOCAL


Similar values should be change in bold:

default_realm = This should be set to the full DNS AD Domain name in upper case ie "COMPANY.ORG.NZ" or whatever the full domain is not just the local domain.

realms = Same value as the default realm to specify where the kdc and admin server are. The AD Domain value again needs to be the full domain and in upper case.

kdc and admin server = A domain controllers DNS name to resolve the DC.

domain_realm = This is the local hostname how you plan to access it exactly like the Service Principal Name but without HTTP/ prefixing it, and that should then map through to the ADDOMAIN full domain name again in upper case.

Apache Configuration:

Copy the keytab from the Windows Domain Controller to /etc/httpd (Centos) or /etc/apache2 (Debian/Ubuntu) or somewhere that Apache can access and has ownership of the file. The keytab should be considered sensitive so you should chmod it to 600 and chown to apache.

conf/kerberos.conf


<Directory "/var/www/html/ad">
  AuthType Kerberos
  AuthName "Active Directory"
  KrbAuthRealms AD.DOMAIN.LOCAL
  KrbServiceName HTTP
  KrbMethodNegotiate on
  KrbMethodK5Passwd off
  Krb5Keytab /etc/httpd/apachehost.keytab
  require valid-user
</Directory>


Similar values should be change in bold:

KrbAuthRealms = This again should point to the AD Domain in upper case, and match the values in the krb5.conf

KrbMethodK5Passwd = If you want to prompt for password, which defeats the whole purpose of Kerberos auth.

Krb5Keytab = The location of the keytab created and copied as part of the ktpass process on the DC.

 

3) Windows Desktop

Natively IE, Edge and Chrome support Kerberos. Few Microsoft references

https://support.microsoft.com/en-us/help/182569/internet-explorer-security-zones-registry-entries-for-advanced-users

 

Local settings for IE, Edge and Chrome:

Control Panel -> Internet Settings -> Security -> Local Intranet -> Sites -> Advanced -> 

Add the host including if it is https or http into the URL ie "https://apachehost.dnsdomain" and / or "http://apachehost.dnsdomain" if the checkbox "Require server verification (https:) for all sites in this zone" then Apache will need to be setup with a a SSL/TLS certificate.

This will add registry keys under: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\ for the dns domain.

Sometimes it is easier (but somewhat less secure) if you want to add the whole local domain as wildcard so you can add "https://*.dnsdomain"

 

Group Policy settings for IE, Edge and Chrome:

These settings can be set via GPO in: https://blogs.manageengine.com/active-directory/2018/08/02/securing-zone-levels-internet-explorer.html or https://blog.thesysadmins.co.uk/group-policy-internet-explorer-security-zones.html

Computer Configuration -> Administrative Templates -> Windows Components -> Internet Explorer -> Internet Control Panel -> Security Page -> Site to Zone Assignment List

Set it to enabled, then add entries with the "Value name" is the site ie "http://apachehost.dnsdomain" and the "Value" to indicate it is for the Local Intranet is set to "1".

Once the GPO has been applied there will be registry keys under:

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMapKey

 

Settings for Firefox:

As Firefox doesn't leverage built in Windows settings you need to set it yourself: https://developer.mozilla.org/en-US/docs/Mozilla/Integrated_authentication

Go to "about:config" and set the value:

network.negotiate-auth.trusted-uris = apachehost.dnsdomain

Or if you want to trust the whole corporate domain add the domain with a preceding dot:

network.negotiate-auth.trusted-uris = .dnsdomain

 

3) AD LDAP Based authorization.

Once you have logged in via Kerberos you need to modify the Directory setting in Apache to include the LDAP lookup.

 


# require valid-user

 AuthLDAPURL "ldaps://AD.DOMAIN.LOCAL/OU=Users,DC=AD,DC=DOMAIN,DC=LOCAL?userPrincipalName?sub?(objectClass=*)"
 AuthLDAPBindDN "CN=ServiceAccountCN,OU=ServiceAccounts,DC=AD,DC=DOMAIN,DC=LOCAL"
 AuthLDAPBindPassword "**Password**"
 require ldap-group CN=ApacheAccess,OU=Unix Access,DC=AD,DC=DOMAIN,DC=LOCAL


The LDAP URL should be LDAPs (as Microsoft are turning of cleartext LDAP), then specify the AD DNS Domain name as that should be able to resolve any DC, or point it to the IP address of your preferred DC. Then the search base should be the OU that contains all your users. The search value is userPrincipalName. That is also why I didn't enable "KrbLocalUserMapping On" since then the domain gets stripped and you are doing a lookup on samAccountName instead of UPN. And stick with the sub and objectclass=* or filter that down if desired.

Then specify the Service Account username & password.

And lastly comment out the "require value-user" and replace it with "require ldap-group CN=..." to the full CN of the AD Group that you want to use and you are done.

 

 


There is numerous blogs around enabling Apache to use Kerberos authentication for single signon to a website. Some of the better ones include:

http://www.grolmsnet.de/kerbtut/

https://imatviyenko.github.io/blog/2018/09/11/Apache-AD-kerberos

But none of them cover all aspects to the solution to make sure it is working and how to debug it if it isn't or perhaps I just have never read them properly and they tend to include lot of it is also outdated talking about NT4 or AES128 ciphers and the correct way to create the keytab file you require.

Other related posts:
APC UPS Smart-UPS 750 XL battery constants






BarTender's profile

Bar Tender
Wellington
New Zealand