Kerberos authenticated queries to Active Directory

Tue 29 June 2010 by Lars Kellogg-Stedman Tags ldap active_directory kerberos

There are many guides out there to help you configure your Linux system as an LDAP and Kerberos client to an Active Directory server. Most of these guides solve the problem of authentication by embedding a username and password into a configuration file somewhere on your system. While this works, it presents some problems:

  • If you use a common account for authentication from all of your Linux systems, a compromise on one system means updating the configuration of all of your systems.
  • If you don't want to use a common account, you need to provision a new account for each computer...
  • ...which is silly, because if you join the system to Active Directory there is already a computer object associated with the system that can be used for authentication.

This document describes how to configure a Linux system such that queries generated by nss_ldap will use either the current user's Kerberos credentials, or, for the root user, credentials stored in a Kerberos credentials cache.

  • Your Linux system must have a valid keytab file.

    A keytab is a file containing pairs of Kerberos principals and encrypted keys.

    Joining Active Directory using Samba's net ads join will create the necessary keytab. It is also possible to create the keytab on your Windows domain controller and install it on your Linux systems. Instructions for doing this are beyond the scope of this document.

  • Host objects in Active Directory must have a userPrincipalName attribute.

    For example:

    $ ldapsearch cn=dottiness userPrincipalName
    dn: CN=DOTTINESS,CN=Computers,dc=example,dc=com
    userPrincipalName: host/dottiness.example.com@EXAMPLE.COM
    

    Active Directory does not automatically create a userPrincipalName when a new host object is provisioned. You will either need to provide this value manually or develop an automated process that will populate this field when provisioning new host objects.

Kerberos credentials have a maximum usable lifetime. The cached credentials used for root queries by nss_ldap must be refreshed periodically in order to function.

You will need to install a crontab (e.g., in /etc/cron.d) that looks something like this:

PATH=/bin:/usr/bin:/usr/kerberos/bin
@reboot root kinit -k -c /var/run/ldap_cc > /dev/null 2>&1
@hourly root kinit -k -c /var/run/ldap_cc > /dev/null 2>&1

This periodically reauthenticates to your domain controller used the cached principal in the system keytab (/etc/krb5.keytab) and caches the credentials in /var/run/ldap_cc.

You will need something similar to the following in /etc/ldap.conf:

# This is your domain controller.
uri ldap://dc1.example.com
base dc=example,dc=com
scope one
referrals no
timelimit 120
bind_timelimit 120
idle_timelimit 3600
ldap_version 3

# Authenticate using SASL for user and root queries.
use_sasl on
rootuse_sasl on

# Use SASL's gssapi (Kerberos) mechanism.
sasl_mech gssapi

# Use these cached credentials for root.
krb5_ccname /var/run/ldap_cc

nss_base_group ou=groups,dc=example,dc=com
nss_base_passwd ou=people,dc=example,dc=com
nss_initgroups_ignoreusers root,ldap,named,avahi,haldaemon,dbus,radvd,tomcat,radiusd,news,mailman,nscd,gdm,polkituser

# These are common mappings for working with Active Directory.
nss_map_attribute uid sAMAccountName
nss_map_attribute uniqueMember member
nss_map_objectclass posixAccount user
nss_map_objectclass posixGroup group
nss_map_objectclass shadowAccount user

pam_login_attribute sAMAccountName
pam_member_attribute member
pam_password ad
pam_password_prohibit_message Please visit http://password.example.com to change your password.

pam_filter objectclass=User

The use_sasl on directive configures nss_ldap to use the Kerberos credentials for the current user when looking up user/group/etc information. The rootuse_sasl on attribute does the same thing for processes running as root.

Note that this configuration sets scope one, which means that nss_ldap will not recurse down a directory tree. This is a performance optimization, not a requirement.

As an unprivileged user

Before acquiring Kerberos credentials:

$ getent passwd lars
(times out)

Authenticate to Kerberos:

$ kinit
Password for lars@EXAMPLE.COM:

With valid credentials:

$ getent passwd lars
lars:*:500:500:lars:\\emc00.example.com\staff\l\lars\windows:

As root

Before acquiring Kerberos credentials:

# getent passwd lars
(times out)

Update credentials cache from system keytab:

# kinit -k

With valid credentials:

# getent passwd lars
lars:*:500:500:lars:\\emc00.example.com\staff\l\lars\windows:

This configuration makes the operation of nss_ldap dependent on valid Kerberos credentials. If a user remains logged in after her Kerberos credentials have expired, she will experience degraded behavior, since many name lookup operations will timeout. Similarly, local system accounts that do not have valid Kerberos credentials will experience similar behavior (and will thus only be able to see local users and groups).


Comments