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:
- Kerberos is used for authentication.
- Samba SMBD provides the ability to join the AD
- SSSD provides the integration points for authentication to PAM and nsswitch
- PAM creates home directories when a user first logs in
- sudo provides the ability for certain groups to use sudo
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 nscd (in Debian package unscd) 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 # If this flag is true, reverse name lookup will be used in addition to # forward name lookup to canonicalizing hostnames for use in service principal names. # If dns_canonicalize_hostname is set to false, this flag has no effect. # The default value is true. rdns = false [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 # Default ID mapping configuration for local BUILTIN accounts # and groups on a domain member. The default (*) domain: # - must not overlap with any domain ID mapping configuration! # - must use a read-write-enabled back end, such as tdb. idmap config * : backend = tdb idmap config * : range = 3000-7999 # - You must set a DOMAIN backend configuration # idmap config for the SAMDOM domain idmap config ADEX:backend = ad idmap config ADEX:schema_mode = rfc2307 idmap config ADEX:range = 10000-50000 idmap config ADEX:unix_nss_info = 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:
- The configuration file doesn't exist yet
- The machine isn't joined to the domain yet
# apt-get install sssd # chmod 0600 /etc/sssd/sssd.conf
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 # When running in an unprivileged Linux container these settings # should be uncommented. #ldap_idmap_range_min = 10000 #ldap_idmap_range_max = 50000 #ldap_idmap_range_size = 1000
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.