Kerberos
========

Presentation
------------

This page is about obtaining all the prerequisites for Kerberos to work in your
network. In order to configure LemonLDAP::NG to use Kerberos, refer to the
:doc:`Kerberos authentication module documentation <authkerberos>`

Prerequisites
-------------

Example values
~~~~~~~~~~~~~~

We will use the following values in our examples

-  **EXAMPLE.COM**: First AD domain
-  **ACME.COM**: Second AD domain (optional, in case of a cross-domain trust)
-  **auth.example.com**: DNS of the LL::NG portal
-  **KERB_AUTH**: AD account to generate the keytab for LL::NG server

Service Account
~~~~~~~~~~~~~~~

A service account must be created on the AD server. It must be a user account and not a computer account.

Be sure to set the following options on it:

* Password never expires
* This account supports Kerberos AES encryption (128/256bits)

The second option is required if you are using recent Linux versions, where RC4 is no longer available.

Server time
~~~~~~~~~~~

It is mandatory that LL::NG servers and AD servers have the same time.
It is recommended to use NTP to do this.

DNS
~~~

In our experience, we have observed the following limitations when using Kerberos for web applications in an Active Directory environment

* ``auth.example.com`` should be registered in the DNS server as a ``A`` record. ``CNAME`` usually do not work
* The reverse DNS (``PTR``) for ``auth.example.com``'s IP address should point back to ``auth.example.com``

.. tip::

    If you have a SSO cluster, you must setup a Virtual IP in
    cluster and register this IP in DNS.

.. tip::

   If you cannot configure the PTR record to point to the portal's hostname, it
   may help to run the following command. Assuming that ``proxy.example.com`` is
   the PTR record of the portal's IP address ::

      setspn -s HTTP/proxy.example.com keytab-account

SSL
~~~

SSL is not mandatory, but it is strongly recommended. Your portal URL
should be https://auth.example.com.

Web server configuration
~~~~~~~~~~~~~~~~~~~~~~~~

Apache
^^^^^^

Some Kerberos tickets, especially generated by Active Directory, can get too big for Apache's default header size limit, especially for users with a lot of groups.

Increase it in the global `httpd.conf` configuration ::

    LimitRequestFieldSize 16384


Nginx
^^^^^

Some Kerberos tickets, especially generated by Active Directory, can get too big for Apache's default header size limit, especially for users with a lot of groups.

Increase it in your `portal-nginx.conf` configuration ::

    large_client_header_buffers 4 16k;

Web browser configuration
~~~~~~~~~~~~~~~~~~~~~~~~~

Firefox
^^^^^^^

Type ``about:config`` in a tab and search for ``trusted``. Then edit the
property ``network.negotiate-auth.trusted-uris`` and set value
``example.com``.

Internet Explorer / Edge / Chrome
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Add ``https://auth.example.com`` as trusted site.

Check into security parameters that Kerberos authentication is allowed.

Obtain keytab file
------------------

Standard case
~~~~~~~~~~~~~

You have to run this command on Active Directory:

::

   ktpass -princ HTTP/auth.example.com@EXAMPLE.COM -mapuser KERB_AUTH@EXAMPLE.COM -crypto All -ptype KRB5_NT_PRINCIPAL -mapOp set -pass <PASSWORD> -out c:\auth.keytab


.. attention::

    You must use the UPPERCASE value of the domain name when generating the keytab

The file ``auth.keytab`` should then be copied (with a secure media) to
the Linux server (for example in ``/etc/lemonldap-ng``).

Change rights on keytab file:

::

   chown apache /etc/lemonldap-ng/auth.keytab
   chmod 600 /etc/lemonldap-ng/auth.keytab
   # If you use SELinux
   restorecon /etc/lemonldap-ng/auth.keytab

Special case: multiple AD domains
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You need to obtain a keytab for each node on each domain. This means the
ktpass commands should be run on both AD.

Then you will have 2 keytab files for each node, for example:

-  node1-example.keytab
-  node1-acme.keytab

You need to concatenate the keytab files, thanks to ``ktutil`` command:

::

   ktutil
   ktutil: read_kt node1-example.keytab
   ktutil: read_kt node1-acme.keytab
   ktutil: write_kt /etc/lemonldap-ng/auth.keytab
   ktutil: quit

You can then remove the original keytab files and protect the final
keytab file:

::

   chown apache /etc/lemonldap-ng/auth.keytab
   chmod 600 /etc/lemonldap-ng/auth.keytab

Testing your setup
------------------

This is only needed if your Kerberos configuration is not working and you don't understand why. It explains how request a Kerbeors ticket from a GNU/Linux station (which could be the LL::NG server if you don't have other one).

Of course it requires a valid user account on AD to be able to otbain the Kerberos ticket.

Client Kerberos configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Edit ``/etc/krb5.conf``:

.. code-block:: ini

   [libdefaults]
    default_realm = EXAMPLE.COM
    dns_lookup_kdc = false
    dns_lookup_realm = no
    ticket_lifetime = 24h
    forwardable = yes
    renewable = true

   [realms]
    EXAMPLE.COM = {
     kdc = ad.example.com
     admin_server = ad.example.com
    }

   [domain_realm]
    .example.com = EXAMPLE.COM
    example.com = EXAMPLE.COM

Getting a Kerberos ticket
~~~~~~~~~~~~~~~~~~~~~~~~~

You can check the validity of the keytab file by trying to request a
service ticket, and compare the result with the keytab content.

Open a Kerberos session:

::

   kinit coudot@example.com

Request a service ticket:

::

   kvno HTTP/auth.example.com@EXAMPLE.COM

The result of the command should be:

::

   HTTP/auth.example.com@EXAMPLE.COM: kvno = 3

Read the service ticket:

::

   klist -e

You should see this kind of ticket:

::

   06/04/15 16:28:49  06/05/15 02:28:11  HTTP/auth.example.com@EXAMPLE.COM
           renew until 06/05/15 16:28:07, Etype (skey, tkt): arcfour-hmac, arcfour-hmac

You can close the Kerberos session:

::

   kdestroy

Checking the keytab
~~~~~~~~~~~~~~~~~~~

Now you can compare the above result with the same request done through
the keytab file on LL::NG server:

::

   klist -e -k -t /etc/lemonldap-ng/auth.keytab

The result of the command should be:

::

   Keytab name: FILE:/etc/lemonldap-ng/auth.keytab
   KVNO Timestamp           Principal
   ---- ------------------- ------------------------------------------------------
      3 01/01/1970 01:00:00 HTTP/auth.example.com@EXAMPLE.COM (DEPRECATED:des-cbc-crc)
      3 01/01/1970 01:00:00 HTTP/auth.example.com@EXAMPLE.COM (DEPRECATED:des-cbc-md5)
      3 01/01/1970 01:00:00 HTTP/auth.example.com@EXAMPLE.COM (DEPRECATED:arcfour-hmac)
      3 01/01/1970 01:00:00 HTTP/auth.example.com@EXAMPLE.COM (aes256-cts-hmac-sha1-96)
      3 01/01/1970 01:00:00 HTTP/auth.example.com@EXAMPLE.COM (aes128-cts-hmac-sha1-96)


The important things to check are:

-  KVNO must be the same
-  Principal names must be the same
-  Encryption types must be the same


Multiple AD domains
~~~~~~~~~~~~~~~~~~~

The two domains must be defined in ``/etc/krb5.conf``:

.. code-block:: ini

   [libdefaults]
    default_realm = EXAMPLE.COM
    dns_lookup_kdc = false
    dns_lookup_realm = no
    ticket_lifetime = 24h
    forwardable = yes
    renewable = true

   [realms]
    EXAMPLE.COM = {
     kdc = ad.example.com
     admin_server = ad.example.com
     default_domain = EXAMPLE.COM
    }
    ACME.COM = {
     kdc = ad.acme.com
     admin_server = ad.acme.com
     }

   [domain_realm]
    .example.com = EXAMPLE.COM
    example.com = EXAMPLE.COM
    .acme.com = ACME.COM
    acme.com = ACME.COM

You should then be able to open a Kerberos session on each domain:

::

   kinit coudot@EXAMPLE.COM
   klist -e
   kdestroy

::

   kinit coudot@ACME.COM
   klist -e
   kdestroy

You can then check the tickets and the keytab.
