DRUPAL APACHE KERBEROS

In this blog post, I will write about integrating Kerberos authentication with Drupal 8.

 

What We Want?

  1. Delegate the authentication to the Apache web server, which should restrict access using Basic Authentication (theoretically by whatever means -- htpasswd file, ... -- in our case with an LDAP/Active Directory backend).
  2. Trust the authenticated user whose username is sent to PHP as $_SERVER['REMOTE_USER'] and rely on the Drupal 8 authentication services (in our case the one provided by LDAP SSO) to retrieve additional user information and group membership without checking the password, since Apache did it already.

  3. To ensure these tasks are executed transparently, without having to actively authenticate in Drupal 8

For this to work we need following modules and systems:

  • LDAP module
  • LDAP SSO module
  • Kerberos Authentication for Apache

LDAP module will be used for logging users with LDAP users on our website and LDAP SSO module will be used for authentication with Apache via Kerberos.

About Kerberos

Kerberos is a network authentication system based on the principal of a trusted third party. The other two parties being the user and the service the user wishes to authenticate to. Not all services and applications can use Kerberos, but for those that can, it brings the network environment one step closer to being Single Sign On (SSO).

This section covers installation and configuration of a Kerberos server, and some example client configurations.

Overview

If you are new to Kerberos there are a few terms that are good to understand. Most of the terms will relate to things you may be familiar with in other environments:

Principal: any users, computers, and services provided by servers need to be defined as Kerberos Principals.

Instances: are used for service principals and special administrative principals.

Realms: the unique realm of control provided by the Kerberos installation. Think of it as the domain or group your hosts and users belong to. Convention dictates the realm should be in uppercase. By default, ubuntu will use the DNS domain converted to uppercase (EXAMPLE.COM) as the realm.

Key Distribution Center: (KDC) consist of three parts, a database of all principals, the authentication server, and the ticket granting server. For each realm there must be at least one KDC.

Ticket Granting Ticket: issued by the Authentication Server (AS), the Ticket Granting Ticket (TGT) is encrypted in the user's password which is known only to the user and the KDC.

Ticket Granting Server: (TGS) issues service tickets to clients upon request.

Tickets: confirm the identity of the two principals. One principal being a user and the other a service requested by the user. Tickets establish an encryption key used for secure communication during the authenticated session.

Keytab Files: are files extracted from the KDC principal database and contain the encryption key for a service or host.

To put the pieces together, a Realm has at least one KDC, preferably more for redundancy, which contains a database of Principals. When a user principal logs into a workstation that is configured for Kerberos authentication, the KDC issues a Ticket Granting Ticket (TGT). If the user supplied credentials match, the user is authenticated and can then request tickets for Kerberized services from the Ticket Granting Server (TGS). The service tickets allow the user to authenticate to the service without entering another username and password.

drupal apache kerberos

Kerberos Authentication for Apache

Kerberos is a computer network authentication protocol that works on the basis of tickets to allow nodes communicating over a non-secure network to prove their identity to one another in a secure manner. The protocol was named after the character Kerberos (or Cerberus) from Greek mythology, the ferocious three-headed guard dog of Hades. Its designers aimed it primarily at a client–server model and it provides mutual authentication—both the user and the server verify each other's identity. Kerberos protocol messages are protected against eavesdropping and replay attacks.

Kerberos builds on symmetric key cryptography and requires a trusted third party, and optionally may use public-key cryptography during certain phases of authentication.[1] Kerberos uses UDP port 88 by default.

As per wikipedia explanation for Kerberos is viable option for Apache authentication.

Configuration

I'll show Kerberos configuration for Apache on Ubuntu.

Prerequisites

All servers and clients that participate in a Kerberos realm must be able to communicate with each other and have accurate system clocks. In our case out Windows Server (LDAP/AD) and Ubuntu servers system clocks is in sync (5 minutes are the highest difference you may allow for Kerberos to work properly). Also, your website should have valid domain name, Kerberos authentication will not work with IP addresses. for example you can add 127.0.0.1 apache.drupart.local into /etc/hosts file.

Time Synchronization

You can sync Ubuntu time with Windows Server using NTP. Install NTP with following command:

sudo apt-get install ntp

Restart ntp service:

sudo service ntp restart

Synchronize with Window server

sudo ntpdate -s drupal.drupart.local

Configure Kerberos

Install libapache2-mod-auth-kerb and krb5-user with following command:

sudo apt-get install libapache2-mod-auth-kerb krb5-user

libapache2-mod-auth-kerb package is for Apache to authenticate with Kerberos. krb5-user is not an actual requirement but it will provide handy command-line tools for Kerberos.

In additional to libapache2-mod-auth-kerb, this will install the dependency package krb5-config and then show you a configuration wizard asking for:

1. Default Kerberos version 5 realm. Use DRUPAL.LOCAL (in capital letters).
2 .The KDC. My Active Directory server is drupal.drupart.local, replace by your own.
3. The administration server. This is typically the same as the LDAP/Active Directory server or in case of multiple domain controllers, this should be normally set to the master.

After installing these packages change the content of /etc/krb5.conf file accordingly to your needs. In this file we define Kerberos realm for Apache.

[libdefaults]
    default_realm = DRUPART.LOCAL # Active Directory Domain

# The following krb5.conf variables are only for MIT Kerberos.
    kdc_timesync = 1
    ccache_type = 4
    forwardable = true
    proxiable = true

# The following encryption type specification will be used by MIT Kerberos
# if uncommented.  In general, the defaults in the MIT Kerberos code are
# correct and overriding these specifications only serves to disable new
# encryption types as they are added, creating interoperability problems.
#
# The only time when you might need to uncomment these lines and change
# the enctypes is if you have local software that will break on ticket
# caches containing ticket encryption types it doesn't know about (such as
# old versions of Sun Java).

#   default_tgs_enctypes = des3-hmac-sha1
#   default_tkt_enctypes = des3-hmac-sha1
#   permitted_enctypes = des3-hmac-sha1

# The following libdefaults parameters are only for Heimdal Kerberos.
    fcc-mit-ticketflags = true

[realms]
    ZIRAATKATILIM.LOCAL = {
        kdc = drupal.drupart.local # Active Directory domain controller.
        admin_server = drupal.drupart.local
    }
[domain_realm]
    .drupart.local = DRUPART.LOCAL
    drupart.local = DRUPART.LOCAL

1 . Ping to your Windows server to ensure that Kerberos works. e.g. ping drupal.drupart.local. 2. Have a username and password in Windows Domain DRUPART.LOCAL. In this example hakan is used as username. 3. In terminal type:

kinit hakan@DRUPART.LOCAL

You will be prompted for password.

  1. Type klist in terminal to view initial ticket we got form the KDC.
$ klist
Default principal: hakan@DRUPART.LOCAL

Valid starting    Expires           Service principal
25/02/2019 13:12  26/02/2019 23:11  krbtgt/apache.drupart.local@DRUPART.LOCAL
        renew until 25/02/2019 13:12
  1. With our hakan account lets map the our account to the service principal HTTP/apache.drupart.local@DRUPART.LOCAL on Window command line. Run following command:
C:\>ktpass
-prince HTTP/apache.drupart.local@DRUPART.LOCAL
-mapuser hakan@DRUPART.LOCAL
-crypto RC4-HMAC-NT
-ptype KRB5_NT_PRINCIPAL
-pass 1234567
-out C:\intranetkeytab

This command should have created intranetkeytab file on C:. Copy that file and then paste it into /etc/apache2/ folder as http_intranet.keytab on Apache server.

Check if everything is correctly configured via following commands:

$ kvno HTTP/apache.drupart.local@DRUPART.LOCAL
HTTP/apache.drupart.local@DRUPART.LOCAL: kvno = 4

$ klist -e
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: HTTP/apache.drupart.local@DRUPART.LOCAL

Valid starting    Expires           Service principal
25/02/2019 14:53  25/02/2019 00:52  krbtgt/apache.drupart.local@DRUPART.LOCAL
        renew until 26/02/2019 14:53, Etype (skey, tkt): aes256-cts-hmac-sha1-96, ...
25/02/20194 15:09  25/02/2019 00:52  HTTP/intranet.example.com@EXAMPLE.COM
        renew until 26/02/2019 14:53, Etype (skey, tkt): arcfour-hmac, arcfour-hmac

$ klist -e -k -t /etc/apache2/http_intranet.keytab
Keytab name: FILE:http_intranet.keytab
KVNO Timestamp        Principal
---- ---------------- ---------------------------------------------------------
   4 01/01/1970 01:00 HTTP/apache.drupart.local@DRUPART.LOCAL (aes256-cts-hmac-sha1-96)

  1. Check that the key has been correctly added to the keytab by attempting to use it to authenticate as the service principal, then view the resulting ticket-granting ticket using klist:
$ kinit -k -t /etc/apache2/http_intranet.keytab HTTP/apache.drupart.local@DRUPART.LOCAL
$ klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: HTTP/iapache.drupart.local@DRUPART.LOCAL

Valid starting    Expires           Service principal
25/02/2019 14:11 25/02/2019 00:10  krbtgt/apache.drupart.local@DRUPART.LOCAL
        renew until 26/02/2019 14:11

Configure Apache for Kerberos Authentication

Apache must be told which parts of which web sites are to use authentication provided by mod_auth_kerb. This is done using the AuthType directive with a value of Kerberos.

In order to specify which Kerberos authentication add following snippet to your virtual host configuration:

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html/web

    ServerName apache.drupart.local
    <Location /user/login/sso> # /user/login/sso is required for Drupal LDAP SSO module
        AuthType Kerberos
        AuthName "Kerberos authenticated intranet"
        KrbAuthRealms DRUPART.LOCAL
        Krb5Keytab /etc/apache2/http_intranet.keytab
        KrbServiceName Any
        KrbMethodNegotiate on
    KrbMethodK5Passwd on        
    KrbSaveCredentials on
        KrbVerifyKDC on
        Require valid-user
    </Location>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

  1. Final step is to reload apache configuration:
sudo service apache2 force-reload

Then we you visit apache.drupal.local/user/login/sso it will for user/pass unless if LDAP and LDAP SSO configured correctly you will be automatically authenticated.

Drupal LDAP and LDAP SSO Configurations

As this blog is about Kerberos authentication I will not write about Drupal LDAP module configuration but you can find on the internet how to configure. On the otherside configuring LDAP SSO is straightforward. From now on I will assume that Drupal LDAP module has been configured and working accordingly.

Install LDAP SSO module via composer:

composer require 'drupal/ldap_sso:^1.0'

After installing LDAP SSO module go to /admin/config/people/ldap/sso page then check following values:

  1. Turn on automated single sign-on

When this turned on Drupal will login automatically when open Drupal.

  1. Split user name and realm

If your users are shown as user@realm, you need to enable this. This is the default for mod_auth_kerb but not mod_auth_sspi.

Also the value for should be REMOTE_USER for Server variable containing the user. Then uncheck Redirect users on logout as will try to automatically login if we logout.

That's it if everything is okay then when we login into our Drupal website we will be automatically signed in without any user/pass prompt.