AD autentisering i Linux med SSSD och Kerberos

Planen är att beskriva den nuvarande metod jag använder med Samba, Kerberos och SSSD.

Operativsystem jag testat detta på är Debian 7, CentOS6/7 och RHEL7.

Debian 7 saknar realmd så join måste göras med samba. CentOS6 och uppåt har realmd som är ett mycket smidigare sätt att göra en join på.

Nätverk

AD behöver en väldans massa portar för att fungera rätt, t.ex. är DNS och tidtjänst kritiska. Här är en lista från en tidigare artikel som jag tror stämmer bra.

Paketinstallation

sudo yum install sssd sssd-client openldap-clients krb5-workstation samba \

realmd oddjob oddjob-mkhomedir selinux-policy-mls # CentOS/RHEL sudo apt-get install sssd sssd-tools ldap-utils krb5-user samba # Debian # lägg till realmd om du kör Debian 8

Windows DC

Installera tillägget //Identity Management for UNIX// på minst en DC i ditt nätverk.

Denna DC kommer få en extra flik för alla AD-objekt som heter UNIX Attributes. De inställningarna används för att ange ett globalt UID och GID för UNIX-användarkonton.

NSS

På Debian måste man redigera ''/etc/nsswitch.conf'' manuellt, men på RHEL kör man bara authconfig.

sudo authconfig --enablesssd --enablesssdauth --enablemkhomedir --update

Då redigeras följande rader.

passwd:     files sss
shadow:     files sss
group:      files sss
hosts:      files dns wins
services:   files sss
netgroup:   files sss
automount:  files sss
sudoers:    files sss

Resten av filen kan lämnas orörd.

Authconfig sköter även PAM i RHEL, men i Debian kan detta skötas av pam-auth-update verktyget. Då får man välja i en meny vilka metoder man vill stödja och pam-filerna redigeras åt dig.

sudo pam-auth-update

Oddjobd i CentOS/RHEL

I CentOS och RHEL använder man oddjob för PAM-modulen oddjob-mkhomedir som skapar hemkataloger åt användare vid inloggning.

Då måste oddjob-tjänsten vara startad.

sudo systemctl enable oddjobd
sudo systemctl start oddjobd

DNS

Se till att alla DCs finns inlagda i ''/etc/resolv.conf'' och att sökdomänen är rätt.

Kerberos

Konfigurationsfilen för Kerberos kan se ut så här, för en domän som heter DOMAIN.TLD.

logging]
 default = FILE:/var/log/krb5libs.log

[libdefaults]
 default_realm = DOMAIN.TLD
 dns_lookup_realm = true
 dns_lookup_kdc = true
 ticket_lifetime = 24h
 renew_lifetime = 7d
 rdns = false
 forwardable = yes
 default_tkt_enctypes = rc4-hmac des-cbc-crc des-cbc-md5
 default_tgs_enctypes = rc4-hmac des-cbc-crc

[realms]
 DOMAIN.TLD = {
    kdc = DC01.DOMAIN.TLD:88
    admin_server = DC01.DOMAIN.TLD:464
    kdc = DC02.DOMAIN.TLD:88
    admin_server = DC02.DOMAIN.TLD:464
    default_domain = DOMAIN.TLD
 }

[domain_realm]
 .domain.tld = DOMAIN.TLD
 domain.tld = DOMAIN.TLD

Samba

Tjänsten Samba behövs inte men konfigurationsfilen måste redigeras för att Samba ska användas vid join till AD.

[global]
workgroup = DOMAIN
client signing = yes
client use spnego = yes
kerberos method = secrets and keytab
log file = /var/log/samba/%m.log
realm = DOMAIN.TLD
security = ads

Observera att i CentOS 7 och Debian 8 kan realmd användas istället.

SSSD

Konfigurationsfilen kan se ut så här.

[sssd]
config_file_version = 2
domains = domain.tld
services = nss, pam
debug_level = 4

[nss]
filter_users = root
filter_groups = root

[pam]
pam_pwd_expiration_warning = 14

[domain/domain.tld]
id_provider = ldap
auth_provider = krb5
chpass_provider = krb5
access_provider = ldap
cache_credentials = true

ldap_sasl_mech = GSSAPI

ldap_schema = rfc2307

ldap_search_base = cn=Users,dc=domain,dc=tld?onelevel?(objectClass=group)?ou=Company,ou=Hosting,dc=domain,dc=tld?subtree?(|(objectClass=group)(objectClass=user))
ldap_user_object_class = user
ldap_user_home_directory = unixHomeDirectory
ldap_user_principal = userPrincipalName

ldap_group_object_class = group

ldap_access_order = filter, expire
ldap_access_filter = &(objectClass=user)(sAMAccountName=*)

ldap_account_expire_policy = ad
ldap_force_upper_case_realm = true
krb5_realm = DOMAIN.TLD

ldap_tls_reqcert = allow

override_shell = /bin/bash
override_homedir = /home/%d/%u
override_space = _

''filter_users'' är bra för att undvika att hämta en lokal administratörsanvändare från AD.

På Debian 8, CentOS 6 och uppåt hade jag hellre använt ''id_provider = ad'', men jag har inte provat det än.

''ldap_search_base'' är ett exempel på ett filter som listar grupperna Domain Users och Domain Admins under ''cn=Users,dc=domain,dc=tld'' samtidigt som jag listar användare under ett annat ou.

Alternativet ''override_shell'' fungerar inte heller i Debian 7 versionen av sssd.

Alternativet ''override_space'' betyder att alla grupp eller användarnamn med mellanslag kommer få ett understreck där istället. Det hjälper lite i Linux, t.ex. blir sudoers regler enklare att skriva.

Starta SSSD

sudo systemctl enable sssd
sudo systemctl start sssd

Eller i Debian.

sudo update-rc.d sssd defaults
sudo service sssd start

Sudoers

Jag väljer att låta Domain Admins köra sudo utan lösenord eftersom jag inte konfat sudo att använda SSS ännu.

User_Alias DOMAINADMINS=%Domain_Admins
DOMAINADMINS ALL=NOPASSWD: ALL

Jag har skrivit Domain_Admins för att ''override_space'' i sssd.conf omvandlar namnen. Precis som i gamla artikeln så kan vi ange gruppnamn med mellanslag om vi skriver så här.

%domain\x20admins

Join

Kör man Debian 7 och uppåt kan man använda Samba.

Antingen kör vi med Kerberos ticket.

  1. ''sudo kinit admin@DOMAIN.TLD''
  2. ''sudo net ads join createupn=host/my-system.domain.tld@DOMAIN.TLD -k''
  3. ''sudo net ads keytab create''
  4. ''sudo net ads keytab add host/my-system.domain.tld@DOMAIN.TLD -k''
  5. ''sudo service sssd stop || sudo systemctl stop sssd''
  6. ''sudo rm /var/lib/sss/db/cache_domain.tld.ldb''
  7. ''sudo service sssd start || sudo systemctl start sssd''

Då ska inget lösenord krävas av samba, bara av kerberos.

Eller kör man bara med samba så krävs lösenord direkt.

sudo net ads join -U admin
Password for admin@DOMAIN.TLD: ******

Vad som ska hända nu är att DNS läggs upp i alla DCs för din nya klient, så testa det först.

Testa sedan så man kan slå upp användare och grupper.

id user
getent group Domain_Admins

I Debian 8, CentOS 6 och uppåt kan vi använda realmd.

sudo realm -v discover DOMAIN.TLD
sudo realm -v join -U admin DOMAIN.TLD

OBS problemet med join i AD är att ett Computers OU måste skapas för datorn. Detta verkar inte fungera bra med verktyget realm och vissa har löst det genom att skapa OU med Pythonskripts men ''sudo net ads join createupn'' fungerar precis lika bra för det syftet.

Re-join

Spara ''/etc/sssd/sssd.conf''.

sudo cp /etc/sssd/sssd.conf ./

Lämna domänen.

sudo realm leave -v -U admin DOMAIN.TLD

Radera hela ''[domain/domain.tld]'' stycket från ''/etc/sssd/sssd.conf''.

Gå med i domänen igen, då skapas konfiguration i ''/etc/sssd/sssd.conf'' som inte duger.

sudo realm join -v -U admin DOMAIN.TLD

Återställ ''/etc/sssd/sssd.conf'' så att de gamla alternativen som ''ldap_search_base'' t.ex. återvänder under blocket ''[domain/domain.tld]'' i filen.

Upprepa sedan steg 5-7 här ovan.

Felsökning

Nya grupper/användare syns inte

En ny grupp läggs till, eller en användare läggs till i en ny grupp och du kan varken se den nya gruppen eller att användaren är medlem i den.

Detta kan hända om t.ex. cachet måste rensas. Rensa då både grupp och användarcache så här på CentOS 7.

sss_cache -u användarnamn
sss_cache -g gruppnamn

Se även till att användaren är tillagd via Unix Attributes fliken på AD-servern. Det räcker tyvärr inte att bara lägga till användaren under Member Of fliken som man normalt gör.

När en användare läggs till via Unix Attributes med hjälp av Identity Management for Unix på en Windows Domänkontrollant så läggs memberUid attributet till. Detta kan kontrolleras med följande ldapsearch, om din användare har en kerberos ticket.

ldapsearch -H 'ldap://dc05.domain.local/' -Y GSSAPI -N -b 'dc=domain,dc=local' '(&(objectClass=group)(cn=gruppnamn))'

Sedan kan det även vara så att ldap_search_base i sssd.conf är för komplex. Jag behövde t.ex. byta ut följande söksträng.

ldap_search_base = cn=Users,dc=domain,dc=local?onelevel?(objectClass=group)?ou=Company,ou=Hosting,dc=domain,dc=local?subtree?(|(objectClass=group)(objectClass=user))

Mot följande mycket enklare söksträng.

ldap_search_base = dc=domain,dc=local?subtree?(|(objectClass=group)(objectClass=user))

Notera att du kan ersätta ''-Y GSSAPI'' med ''-D användarnamn -W'' för att använda användarnamn och lösenord istället för kerberos

Windows DC

Se till att UNIX Attributes fliken är rätt inställd för alla objekt. T.ex. måste grupper ha sina medlemmar listade där under, och användarkonton måste ha ett UID och en primär grupp.

SSSD

Görs ändringar i sökfilter eller SSSD konfiguration så kan man behöva rensa cachet. Detta kan hjälpa för många konstiga problem där nya användare eller grupper inte syns.

sudo sss_cache -E || sudo sss_cache -UGN

Argumenten skiljer sig mellan RHEL och Debian eftersom paketversionerna skiljer.

Eller radera databasfilen och starta om tjänsten.

sudo rm /var/lib/sss/db/cache_domain.tld.ldb
sudo systemctl restart sssd || sudo service sssd restart

DNS

DNS måste fungera, namn måste vara rättstavade i ''/etc/krb5.conf'' och andra filer. Just ''/etc/krb5.conf'' är noga med versaler och gemener.

Se över alla namnservrar i systemet, prova att skicka frågor till dem och se så att alla DCs kan lösas upp vid namn. I RHEL-baserade system är det lätt hänt att tjänsten NetworkManager tar över och skriver över resolv.conf.

sudo systemctl disable NetworkManager
sudo systemctl stop NetworkManager

Jag ser inget behov för den på servrar.

Kerberos

Felsök kerberos enklast genom att begära en ticket och sedan köra ldapsearch med ''-Y GSSAPI'' argumentet.

kinit user@DOMAIN.TLD
ldapsearch -H 'ldap://dc02.domain.tld/' -Y GSSAPI -N -b 'dc=domain,dc=tld' '(&(objectClass=user)(sAMAccountName=user name))'

Använd även klist för att se vilka tickets som finns tillgängliga. klist -ke visar host-tickets som behövs för att hålla datorn ansluten till AD. Tänk createupn argumentet ovan när man går med i AD, det argumentet ska stämma överens med någon host-ticket i klist -ke.

Join av klient i domän

Detta steget är manuellt eftersom det kan vara lite problematiskt att få igång. Helst ska man göra de här stegen.

Out of memory

Men det fungerar inte alltid, man kan få följande fel.

$ sudo net ads join createupn=host/web02.domain.local@DOMAIN.LOCAL -k
Failed to join domain: failed to set machine spn: Out of memory

Det kan betyda att du felsökt mycket och kört många kerberos-kommandon, för det finns ett cache av nycklar i Linux som kan fyllas och då måste det antingen utökas eller startar du om systemet.

Öka nyckelcache så här.

sudo sysctl kernel.keys.root_maxbytes=60000 # För root
sudo sysctl kernel.keys.maxbytes=60000 # För andra användare

Unable to perform DNS update

Ett annat vanligt fel vid join.

$ sudo net ads join createupn=host/web02.domain.local@DOMAIN.LOCAL -k
Using short domain name -- DOMAIN
Joined 'WEB02' to dns domain 'domain.local'
No DNS domain configured for web02. Unable to perform DNS Update.
DNS update failed: NT_STATUS_INVALID_PARAMETER

''Unable to perform DNS update'' kan bero på att den nya maskinens hostnamn inte är inlagt i DNS ännu, så redigera ''/etc/hosts'' och lägg till maskinens ip-adress manuellt och prova igen.

Ibland måste man bara upprepa kommandot tills det fungerar. Är det så att DNS redan fungerar kan felet ignoreras, testa det med host-kommandot t.ex..

host web02.domain.tld dc02.domain.tld

Failed to join domain: failed to set machine spn: Constraint violation

I min erfarenhet har detta att göra med att värdnamnet för maskinen saknas i /etc/hosts. Trots att DNS fungerar så måste jag hårdkoda det korrekta namnet för domänen i ''/etc/hosts''.

Se även RedHat KB artikel om ämnet.

Sammanfattat så beror det antingen på portöppningar, glöm inte UDP! Eller så beror det på att din användare eller AD-användaren du ansluter med inte har tillräckligt med behörighet för att joina en klient i AD.

Failed to join domain: failed to set machine upn: Insufficient access

Användaren du försöker köra join med är inte domänadmin. Den måste också vara root på ad-klienten.

Failed to connect to our DC!

Syns detta felet vid samba join så kan det betyda att du har ett felaktigt hårdkodat värdnamn för maskinen i ''/etc/hosts''.

$ sudo net ads join createupn=host/web01.domain.tld@DOMAIN.TLD -k
Using short domain name -- DOMAIN
Joined 'WEB01' to realm 'domain.tld'
net_update_dns_internal: Failed to connect to our DC!

Failed to join domain: failed to connect to AD: Cannot read password

Får du det felet från join och sedan kör samma join med argumentet ''-d4'' så ser du kanske följande rad.

ads_krb5_mk_req: smb_krb5_get_credentials failed for ldap/web02.domain.tld@DOMAIN.TLD (No credentials found with supported encryption types)

Så kanske man har inkompatibla krypteringstyper tillåtna i Kerberos, jämfört med Windows DCs. Här är ett exempel på en konfiguration som fungerar med Win2k8r2 DC.

[libdefaults]

default_tkt_enctypes = rc4-hmac des-cbc-crc des-cbc-md5 default_tgs_enctypes = rc4-hmac des-cbc-crc

Se också