Introduction

This approach was developed on Debian Jessie against AD on Windows 2016 using this excellent RedHat guide Configuration 3 – SSSD/Kerberos/LDAP. It works very well for me. YMMV.

Objectives

This integration provides user authentication against AD. Anyone with an AD account will be able to log in. However, only users who are a member of the Linux Admins group will be able to sudo.

It does not provide file sharing.

Operation:

This isn't necessarily the best way to do it; however it works for me.

Example data

This document uses the following example data:

Hostname

foo

IP address of host

192.168.72.34

Domain

ad.example.com

Netbios domain name

adex

Primary domain controller

dc01.ad.example.com

Admin group in AD

Linux Admins

Hostname and DNS

The hostname must be a FQDN based on the AD domain you wish to join. For example, if the host is named foo and the AD domain is ad.example.com then you should get these results at the CLI:

# hostname
foo.ad.example.com
# hostname --short
foo
# hostname --domain
ad.example.com

DNS should be set to resolve against the AD controller. My systems are running in Azure so I just need to configure the Azure VNet to point to the IP address of dc01.ad.example.com and this gets picked up by DHCP. You may need to edit /etc/resolv.conf, /etc/dnsmasq.conf or any of the myriad ways that Linux systems configure their DNS these days.

You should add your system to /etc/hosts:

192.168.72.34 foo.ad.example.com foo

Note that the order is IP address, FQDN, short hostname in that order.

NTP

Your computer should synchronise its time against the AD server. Kerberos needs the time in sync before it works. Install NTP and set it to use the domain controller as the NTP server:

# apt-get install ntp
# nano /etc/ntp.conf

Remove the current NTP servers - for example server 0.debian.pool.ntp.org and replace with

server dc01.ad.example.com

NSCD

The ndcd duplicates some of the functionality of sssd so must be disabled:

# systemctl stop unscd
# systemctl disable unscd
# rm /var/run/nscd/socket

Kerberos

Install kerberos and edit its configuration file:

# apt-get install krb5-user
# nano /etc/krb5.conf

krb5.conf should contain the following. Note that case is important.

[libdefaults]
    # This relation identifies the default realm to be used in a client host's
    # Kerberos activity.
    default_realm = AD.EXAMPLE.COM

    # Indicate whether DNS TXT records should be used to determine the Kerberos
    # realm of a host. The default is not to use these records.
    dns_lookup_realm = false

    # Indicate whether DNS SRV records should be used to locate the KDCs
    # and other servers for a realm, if they are not listed in the information
    # for the realm. The default is to use these records.
    # We set this explicitly since we're setting the admin_server anyway.
    dns_lookup_kdc = false

    # The value of this tag is the default lifetime for initial tickets. The
    # default value for the tag is 1 day (1d).
    #ticket_lifetime = 24h

    # The value of this tag is the default renewable lifetime for initial
    # tickets. The default value for the tag is 0.
    renew_lifetime = 7d

    # If this flag is set, initial tickets by default will be forwardable.
    # The default value for this flag is false.
    # See https://web.mit.edu/kerberos/krb5-devel/doc/user/tkt_mgmt.html for details.
    #forwardable = true

[realms]
    AD.EXAMPLE.COM = {
        # This relation identifies the host where the administration server
        # is running. Typically this is the Master Kerberos server.
        # Required setting - cannot be looked up via DNS.
        admin_server = DC01.AD.EXAMPLE.COM

        # The name or address of a host running a KDC for that realm.
        # This could be looked up via DNS (dns_lookup_kdc) but we must
        # set the admin_server anyway, and this has the same value.
        kdc = DC01.AD.EXAMPLE.COM
    }

[domain_realm]
    # The [domain_realm] section provides a translation from a hostname to
    # the Kerberos realm name for the services provided by that host.
    #
    # The tag name can be a hostname, or a domain name, where domain names
    # are indicated by a prefix of a period ('.') character. The value of
    # the relation is the Kerberos realm name for that particular host or
    # domain. Host names and domain names should be in lower case.
    #
    # If no translation entry applies, the host's realm is considered to
    # be the hostname's domain portion converted to upper case.
    .ad.example.com = AD.EXAMPLE.COM

[logging]
    # Log everything to syslog. Default is severity of ERR and facility of AUTH.
    default = SYSLOG

Samba SMBD

Install the Samba smbd, stopping the daemons we don't need:

# apt-get install samba samba-common
# systemctl stop nmbd
# systemctl disable nmbd
# systemctl disable samba
# systemctl disable samba-ad-dc

Edit /etc/samba/smb.conf: it should look like this:

# Configures Samba suite for AD
# These parameters seem to work on the devtest domain.

[global]
# Netbios name for the AD domain in upper-case
workgroup=ADEX

# This controls whether the client is allowed or required to use SMB
# signing. Possible values are auto, mandatory and disabled.
#
# When set to auto, SMB signing is offered, but not enforced. When
# set to mandatory, SMB signing is required and if set to disabled,
# SMB signing is not offered either.
#
# Default: client signing = auto
client signing = auto

# This variable controls whether Samba clients will try to use Simple
# and Protected NEGOciation (as specified by rfc2478) with supporting
# servers (including WindowsXP, Windows2000 and Samba 3.0) to agree
# upon an authentication mechanism. This enables Kerberos authentication
# in particular.
#
# Default: client use spnego = yes
client use spnego = yes

# This option specifies the kerberos realm to use. The realm is used as the
# ADS equivalent of the NT4 domain. It is usually set to the DNS name of the
# kerberos server. Since it is kerberos it is in capital letters.
realm=AD.EXAMPLE.COM

# In this mode, Samba will act as a domain member in an ADS realm. To operate
# in this mode, the machine running Samba will need to have Kerberos
# installed and configured and Samba will need to be joined to the ADS realm
# using the net utility.
security=ads

# Use the keytab to store secrets for authenticating against kerberos
# and to identify the kerberos server.
kerberos method = secrets and keytab

# Logging settings

# This option allows you to override the name of the Samba log file (also
# known as the debug file).
#
# This option takes the standard substitutions, allowing you to have separate
# log files for each user or machine.
#
# No default
#
# Example: log file = /usr/local/samba/var/log.%m
log file = /var/log/samba/smbd.log

# The value of the parameter (a astring) allows the debug level (logging
# level) to be specified in the smb.conf file.
# Values seem to be 0 to 10.
#
# Default: log level = 0
log level = 10

# This option (an integer in kilobytes) specifies the max size the log file
# should grow to. Samba periodically checks the size and if it is exceeded it
# will rename the file, adding a .old extension.
#
# A size of 0 means no limit.
#
# Default: max log size = 5000
max log size = 500

# Turn off printing to avoid log spam
load printers = no
printing = bsd
printcap name = /dev/null
disable spoolss = yes

Ensure that smb.conf file is correct. Investigate and fix any errors.

# testparm

Start up smbd and ensure it is enabled:

# systemctl restart smbd
# systemctl enable smbd

SSSD

Install SSSD. Note that it won't start up correctly (you'll get errors in the logs) because:

# apt-get install sssd

Create a configuration file /etc/sssd/sssd.conf:

# Configuration for the System Security Services Daemon (SSSD)
[sssd]

# Syntax of the config file; always 2
config_file_version = 2

# Services that are started when sssd starts
services = nss, pam

# List of domains in the order they will be queried
domains = AD.EXAMPLE.COM

# Configuration for the AD domain
[domain/AD.EXAMPLE.COM]

# Use the Active Directory Provider
id_provider = ad

# Use Active Directory for access control
access_provider = ad

# Turn off sudo support in sssd - we're doing it directly in /etc/sudoers.d/
# and leaving this enabled results in spurious emails being sent to root
sudo_provider = none

# UNIX and Windows use different mechanisms to identify groups and users.
# UNIX uses integers for both; the challenge is to generate these consistently
# across all machines from the objectSID.
#
# Active Directory provides an objectSID for every user and group object in
# the directory. This objectSID can be broken up into components that represent
# the Active Directory domain identity and the relative identifier (RID) of the
# user or group object.
#
# The SSSD ID-mapping algorithm takes a range of available UIDs and divides it into
# equally-sized component sections - called "slices"-. Each slice represents
# the space available to an Active Directory domain.
#
# The default configuration results in configuring 10,000 slices, each capable
# of holding up to 200,000 IDs, starting from 10,001 and going up to
# 2,000,100,000. This should be sufficient for most deployments.
ldap_id_mapping = true

# Define some defaults for accounts that are not already on this box.
# We appear to need these settings as well as the PAM configuration.
fallback_homedir = /home/%d/%u
default_shell = /bin/bash
skel_dir = /etc/skel

You'll now need to check /etc/nsswitch.conf to ensure that the correct lookups are being referred to sssd:

Line starts

Should have sss?

Example

passwd:

Yes

passwd: compat sss

group:

Yes

group: compat sss

netgroup:

Yes

netgroup: nis sss

sudoers:

No

sudoers: files

Note that sudoers line contains sss on sssd installation; you will want to take this out to avoid spurious security emails being sent.

PAM

Create the file /usr/share/pam-configs/my-ad with the extra PAM items:

Name: Guestline AD user home management
Default: yes
Priority: 127

Session-Type: Additional
Session-Interactive-Only: yes
Session:
        required pam_mkhomedir.so skel=/etc/skel/ umask=0022

Update the PAM configuration to use this file:

# /usr/sbin/pam-auth-update --package

SUDO

Create a file /etc/sudoers.d/ad-linux-admins to allow the members of the Linux Admins AD group to sudo to root:

%Linux\ Admins ALL = (ALL) ALL

Configuration Complete!

Your configuration is now complete. Now we need a script to run to join the domain. This is the script I use:

# Script to handle the process of joining the domain.
# Run with username where:
# username is the SAM name for the domain admins account - e.g. brownm for martin.brown
#
# The script produces lots of output to help with debugging any issues. See
# https://www.redhat.com/en/files/resources/en-rhel-intergrating-rhel-6-active-directory.pdf
# for a full description of the process (albeit RedHat rather than Debian).
#
# Note that it is very important that the hostname of the machine is set up correctly!

if [ "$#" != 1 ]
then
  echo "Usage: join-ad.sh username"
  exit 1
fi

username=$1
domain=$(hostname --domain)
echo "Using account ${username} to join domain ${domain}..."
echo ""

# Quit on error
set -e

# Uncomment to debug
#set -x

# Upper-case version of the domain name
upper_domain=$(echo ${domain} | tr [a-z] [A-Z])

# Find the short hostname and get an upper-case version of it
short_hostname=$(hostname --short)
upper_short_hostname=$(echo ${short_hostname} | tr [a-z] [A-Z])

# Log into the domain as the administrator, asking user for password
# The domain part must be in upper-case
echo "Logging into domain as the administrator"
/usr/bin/kinit "${username}@${upper_domain}"
echo ""

# List what kerberos sent back
echo "Listing kerberos tickets for the domain administrator:"
echo "------------------------------------------------------------------------"
klist
echo ""

# Join AD and put the machine credentials in the krb5.keytab
echo "Requesting domain join using administrator kerberos ticket"
net ads join -k

# List the machine credentials
echo "Listing kerberos tickets for the machine:"
echo "------------------------------------------------------------------------"
klist -k
echo ""

# Wait for 5s to allow everything to catch up - sometimes 5s isn't enough
echo "Waiting for everything to catch up..."
sleep 5
echo ""

# Sign in using the machine credentials
echo "Signing in using machine credentials ${upper_short_hostname}$"
kinit -k ${upper_short_hostname}$
echo ""

# Did it work?
joinedAd=$?

if [ $joinedAd -ne 0 ]
then
    echo "Error: could not join the domain with machine credentials ${upper_short_hostname}$"
    exit 1
else
    echo "Joined the domain using machine credentials ${upper_short_hostname}$"
    echo ""
    echo "Listing kerberos machine ticket:"
    echo "------------------------------------------------------------------------"
    klist
    echo ""

    # Now restart SSSD and everything should be happy :-)
    echo "Enabling and restarting sssd"
    systemctl enable sssd
    systemctl restart sssd
    if [ $? -ne 0 ]
    then
      echo "Error: could not start the System Security Services Daemon (SSSD)"
      exit 1
    else
      echo "System Security Services Daemon (SSSD) restarted and enabled."
      echo "AD should now be working!"
    fi
fi

exit 0

Only problem I've encountered is that our AD server can be very slow to synchronise accounts - probably because it isn't set up correctly yet. This is why the 5s sleep is in the script - you may not need this.