Infrastruttura Single-Signon Unix

Una volta definito l’ambiente in cui verrà sviluppato il modello, si è proceduto alla scelta dei programmi da integrare: la scelta è ricaduta su programmi OpenSource, in quanto più facilmente reperibili ed eventualmente modificabili. È possibile realizzare la stessa infrastruttura con programmi supportati, ma bisogna verificare con il produttore se le funzionalità siano disponibili, ad esempio se l’LDAP server supporta Kerberos come password back-end.

Preparazione del DNS

Kerberos richiede che vi siano alcune entry nel DNS che puntino ai servizi erogati, anche se pochi programmi sembrano cercare queste entry. È bene verificare che il reverse look-up di ciascun server sia garantito: alcuni problemi legati al kerberos sono relativi al fatto di non riuscire a risolvere in modo corretto i nomi. Per quanto riguarda il laboratorio, questo è il DNS relativo alla parte kerberos:

$TTL    604800
$ORIGIN azienda.it.
@       IN      SOA     azienda.it. postmaster.azienda.it. (
                       26010400         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@                       IN  NS ns.azienda.it.

; Kerberos principals (DA AGGIUNGERE!!!!)
_kerberos               IN  TXT "AZIENDA.IT"
_kerberos-master._udp   IN  SRV 0 0 88 kdc
_kerberos-adm._tcp      IN  SRV 0 0 749 kdc
_kpasswd._udp           IN  SRV 0 0 565 kdc
_kerberos._udp          IN  SRV 0 0 88 kdc
_ldap._tcp              IN  SRV 0 0 389 ldap

; Aliases
kdc                     IN  CNAME zeus.azienda.it.
ldap                    IN  CNAME zeus.azienda.it.
ns                      IN  CNAME zeus.azienda.it.
www                     IN  CNAME venere.azienda.it.
mail                    IN  CNAME venere.azienda.it.
time                    IN  CNAME zeus.azienda.it.

; Real IP Addresses
zeus                    IN  A   192.168.0.10
venere                  IN  A   192.168.0.20
cerbero-server          IN  A   192.168.0.1

cerbero-client          IN  A   192.168.1.1
kirk                    IN  A   192.168.1.20
picard                  IN  A   192.168.1.40
spok                    IN  A   192.168.1.60

Come si può notare nell’esempio precedente, le entry importati sono quelle che si riferiscono ai Service Locator (SRV) e al _kerberos che specifica, attraverso il record TXT, il realm della rete locale (nel nostro caso AZIENDA.IT). I numeri successivi alla definizione dei record sono nell’ordine: la priorità (simile alla priorità del record MX), il peso da usare in caso di load-balancing e la porta TCP o UDP su cui è in attesa il servizio. Come accennato precedentemente, non tutti i programmi sfruttano la risoluzione del realm e/o dei servizi tramite DNS, ma è bene provvedere alla loro definizione per una corretta configurazione.

Il server NTP

Un altro prerequisito al funzionamento di Kerberos è la sincronizzazione degli orologi di sistema. A tale scopo è stato creato un NTP server sul sistema zeus.azienda.it a cui viene fatto riferimento con time.azienda.it. Vediamo un esempio di configurazione di un NTP server (file /etc/ntp.conf):

driftfile /var/lib/ntp/ntp.drift
statsdir /var/log/ntpstats/

statistics loopstats peerstats clockstats
filegen loopstats file loopstats type day enable
filegen peerstats file peerstats type day enable
filegen clockstats file clockstats type day enable

authenticate no

## Mettere il proprio server di riferimento, esempio quello
## del vostro provider. Il server time.ien.it si riferisce 
## all'orologio ufficiale italiano, cioè l'Istituto Galileo
## Ferraris di Torino. Prima di usare un NTP server è bene 
## avvisare il relativo l'amministratore di sistema.
server time.ien.it prefer

Per maggiori informazioni su come configurare un server NTP e i relativi client si faccia riferimento alla manualistica del sistema operativo. Nei capitoli successivi si darà per assunto che la sincronizzazione degli orologi sia stata effettuata correttamente.

Il server Kerberos

Il server Kerberos installato è il MIT Kerberos V. Molti sistemi operativi Unix includono ormai un server Kerberos, quindi non mi soffermerò sui dettagli della compilazione del server: si faccia riferimento alla documentazione relativa al proprio vendor, oppure si verifichi per Linux l’elenco dei pacchetti installabili, solitamente libkrb5-dev, krb5-admin-server e krb5-kdc. È possibile scaricarne i sorgenti nella home page del progetto del MIT, ovvero http://web.mit.edu/kerberos/www/. Durante l’installazione del server è bene installare anche i pacchetti relativi allo sviluppo del kerberos, solitamente le librerie e gli include file: tali pacchetti serviranno successivamente per compilare le applicazioni aggiungendo il supporto Kerberos.

Dopo aver installato i pacchetti, è necessario personalizzare il file di configuazione /etc/krb5.conf presente sul KDC: tale file verrà usato sia dal KDC che dal client kerberos della macchina. Nell’esempio seguente si noti il tipo di crittografia specificata: di defaut il MIT Kerberos 5 usa des3-hmac-sha1, ma l’implementazione Kerberos di Windows è in grado solamente di comprendere la crittografia des-cbc-crc o des-cbc-md5. Per assicurare la compatibilità con Windows, si è scelto pertanto di adottare questa crittografia: essendo DES una crittografia debole, è consigliabile usare, quando possibile, comunicazioni protette.

[libdefaults]
        default_realm = AZIENDA.IT
## For Windows 2000 compatibility
        default_tgs_enctypes = des-cbc-crc des-cbc-md5
        default_tkt_enctypes = des-cbc-crc des-cbc-md5
        permitted_enctypes = des-cbc-crc des-cbc-md5
        krb4_config = /etc/krb.conf
        krb4_realms = /etc/krb.realms
        kdc_timesync = 1
        ccache_type = 4
        forwardable = true
        proxiable = true

# The following libdefaults parameters are only 
# for Heimdal Kerberos.
        v4_instance_resolve = false
        v4_name_convert = {
                host = {
                        rcmd = host
                        ftp = ftp
                }
                plain = {
                        something = something-else
                }
        }

[realms]
        AZIENDA.IT = {
                kdc = kdc.azienda.it
                admin_server = kdc.azienda.it
        }

[domain_realm]
        .azienda.it = AZIENDA.IT

[login]
        krb4_convert = true
        krb4_get_tickets = true

Una volta configurato /etc/krb5.conf si è pronti a creare il Realm Kerberos. Da utenza di root è necessario eseguire i seguenti comandi:

# kdb5_util create -s
# kadmin.local -q “ktadd -l /etc/krb5kdc/kadm5.keytab kadmin/admin”
# kadmin.local -q “ktadd -l /etc/krb5kdc/kadm5.keytab kadmin/changepw”
# kadmin.local -q “addprinc -pw miapassword1 krbadm@AZIENDA.IT”
# kadmin.local -q “addprinc -pw miapassword2 ldapadm@AZIENDA.IT”

Le ultime due righe si riferiscono all’aggiunta di due utenze: la prima servirà come amministratore di Kerberos, la seconda invece sarà associata all’amministratore di LDAP. A questo punto siamo pronti per avviare il server:

# krb5kdc &
# kadmind &

Il metodo migliore per avviare i due servizi kerberos (KDC il primo e Admin server il secondo) è attraverso gli script di avvio: riferirsi al manuale del proprio vendor per ulteriori dettagli.

L’ultimo passo per l’installazione di Kerberos è quello relativo alle access lists, in quanto dobbiamo abilitare l’utenza (o il principal) krbadm@AZIENDA.IT ad amministrare il server Kerberos. Il file in oggetto è /etc/krb5kdc/kadm5.acl, vediamone un esempio:

kadmin/admin@AZIENDA.IT       *
krbadm@AZIENDA.IT             *
*/*@AZIENDA.IT                i

L’asterisco dopo l’account significa che può eseguire qualsiasi operazione, mentre la lettera “i” significa che può leggere le informazioni nel database.

La libreria SASL

Precedentemente è stato accennato come la libreria SASL sia in grado di offrire un livello di astrazione per l’autenticazione di protocolli di rete, come definito nell’RFC 2222. Molti sistemi Unix hanno le librerie SASL, ma non tutti supportano GSSAPI come meccanismo: ad esempio Debian è in grado di supportare le GSSAPI attraverso il pacchetto libsasl-gssapi-mit e RedHat attraverso cyrus-sasl-gssapi, ma è necessario contattare il proprio vendor per sapere se implementa o distribuisce SASL e se GSSAPI è un meccanismo valido.

Qualora non si disponesse delle GSSAPI come meccanismo di autenticazione, è possibile scaricare il sorgente di Cyrus SASL dal sito http://asg.web.cmu.edu/sasl/sasl-library.html. Per compilarlo, occorre specificare i seguenti parametri:

# ./configure --prefix=/usr/local --enable-static \
--enable-login--enable-gssapi=/usr/kerberos/ \
--disable-krb4
# make
# make install

È necessario sostituire /usr/kerberos con la directory contenente gli include file del MIT Kerberos V. Anche per la libreria SASL è importante installare i file di include, pertanto quando si installa attraverso i pacchetti della propria distribuzione è necessario installare anche i file di development.

Il server LDAP

Come server LDAP è stato scelto OpenLDAP, disponibile su http://www.openldap.org. Questo server, oltre ad essere gratuito, ha la possibilità di sfruttare Kerberos come back-end delle password utente, pertanto fa al caso nostro. Molte distribuzioni dispongono di openldap server tra i pacchetti disponibili, raramente però viene compilato con le opzioni necessarie, pertanto è necessario ricompilarlo. Come prerequisito dobbiamo avere gli header file e le librerie dei seguenti pacchetti: Kerberos, SASL, OpenSSL e Berkley DB (o equivalente). Le opzioni che ci serviranno in particolare sono:

--disable-cleartext
--disable-rlookups
--with-tls
--enable-kpasswd

Queste sono le opzioni che sono state usate per compilare il server OpenLDAP:

$ ./configure --prefix=/usr/local/ldap --enable-debug \
--enable-syslog --enable-proctitle --enable-cache \
--enable-referrals --enable-ipv6 --enable-local \
--with-readline --with-threads --disable-cleartext \
--enable-multimaster --enable-phonetic --disable-rlookups \
--enable-wrappers --enable-dynamic --enable-dnssrv \
--enable-ldap --enable-ldbm --enable-passwd --enable-shell \
--enable-sql --enable-slurpd --enable-shared
$ make depend
$ make
# make install (da root!)

Prima di configurare il server LDAP è necessario preparare un principal Kerberos e un certificato digitale per usare SSL. Per creare un principal per LDAP, sul sistema zeus.azienda.it si esegue il seguente comando:

# kadmin.local -q "addprinc -randkey ldap/ldap.azienda.it@AZIENDA.IT"
# kadmin.local -q "ktadd ldap/ldap.azienda.it@AZIENDA.IT"

Il primo comando crea il principal, mentre il secondo inserisce la chiave nel file di default /etc/krb5.keytab che verrà usato dal server. Successivamente è necessario ottenere un certificato SSL (X.509) per abilitare SSL con LDAP. Qualora non si disponga già di una Certification Authority (CA), con OpenSSL viene distribuito uno script perl (CA.pl) capace di generare e mantenere una piccola CA. Grazie a questo script è possibile generare una CA ed un certificato di test con i seguenti comandi:

CA.pl -newca
CA.pl -newreq
CA.pl -signreq

Come creare e mantenere una CA è al di fuori dello scopo di questo documento, per maggiori informazioni sull’uso di CA.pl come script, si faccia riferimento al sito http://www.openssl.org/docs/apps/CA.pl.html. Si ottengono due file, newreq.pem e newcert.pem, che andranno rinominati rispettivamente in ldap-priv.pem (la chiave privata) e ldap-pub.pem(la chiave pubblica). Vediamo la configurazione adottata nei nostro esempio in /etc/ldap/slapd.conf:

# LDAP SEVER
# Configuration for: ldap.azienda.it
include         /etc/ldap/schema/core.schema
include         /etc/ldap/schema/cosine.schema
include         /etc/ldap/schema/nis.schema
include         /etc/ldap/schema/inetorgperson.schema
include         /etc/ldap/schema/krb5-kdc.schema
include         /etc/ldap/schema/samba.schema

# Schema check allows for forcing entries to
# match schemas for their objectClasses's
schemacheck     on
pidfile         /var/run/slapd.pid

# Where to store the replica logs
replogfile	/var/lib/ldap/replog

# Read slapd.conf(5) for possible values
loglevel        0

## Kerberos support
sasl-realm	AZIENDA.IT
sasl-host	ldap.azienda.it

## TLS support
TLSCACertificateFile /etc/ldap/cacert.pem
TLSCertificateFile /etc/ldap/ldap-pub.pem
TLSCertificateKeyFile /etc/ldap/ldap-priv.pem
TLSRandFile /dev/random

# The backend type, ldbm, is the default standard
database        ldbm

# The base of your directory
suffix          "dc=azienda,dc=it"

# Where the database file are physically stored
directory       "/var/lib/ldap"

## RootDN
rootdn          "cn=Directory Manager,ou=People,dc=azienda,dc=it"
rootpw          {KERBEROS}ldapadm@AZIENDA.IT

# Indexing options
index objectClass   eq
index cn,mail,surname,givenname   eq,subinitial

# Save the time that the entry gets modified
lastmod on

# Include the access lists
include                 /etc/ldap/slapd.access

Rivediamo brevemente le parti salienti di questa configurazione. La prima parte del file riguarda la definizione degli schema file da includere, ovvero la sintassi degli attributi di LDAP. In particolare sottolineiamo l’inclusione degli schemi relativi al nis (nis.schema), che serviranno ai sistemi Unix per l’assegnazione dei profili agli utenti (contengono gid/uid, home directory, shell, ecc.), e kerberos (krb5-kdc.schema), che permetterà di definire gli attributi per l’interfacciamento con il KDC. Successivamente i parametri sasl realm e sasl host, come si intuisce dal nome, si riferiscono al metodo di interfacciamento con le librerie SASL e definiscono il Kerberos realm il primo (AZIENDA.IT) e il principal relativo al server LDAP il secondo (che coincide con l’hostname, ovvero ldap.azienda.it). A seguire i parametri relativi al TLS per permettere di usare SSL con LDAP (protocollo LDAPS): TLSCACertificateFile specifica il file contenente la chiave pubblica della Certification Autority, TLSCertificateFile contiene la chiave pubblica del server LDAP in formato PEM, TLSCertificateKeyFile punta alla chiave privata del server ed infine TLSRandFile contiene il device /dev/random per la generazione casuale dei file.

Proseguendo con la configurazione si specifica il base dn del nostro LDAP server, ovvero la radice del nostro albero LDAP, con il parametro suffix nel nostro caso impostato a dc=azienda,dc=it. Si identifica poi l’amministratore della directory, solitamente chiamato anche Directory Manager, che viene specificato con il parametro rootdn: da notare che è stato collocato sotto la Organizational Unit (OU) di People, anche se non abbiamo ancora popolato i dati relativi alla struttura. A Directory Manager è stata associata, tramite il parametro rootpw, la relativa password: in questo caso è molto particolare in quanto si riferisce a {KERBEROS}ldapadm@AZIENDA.IT. Come si può intuire, la keyword KERBEROS espressa tra parentesi graffe permette, in congiunzione all’opzione -kpasswd espressa durante la compilazione del server LDAP, di usare Kerberos come password server. Così facendo, quando ci si collegherà all’LDAP server come Directory Manager, andrà specificata la password di ldapadm@AZIENDA.IT (ovvero miapassword2, come specificato precedentemente). Durante l’inserimento dei dati vedremo che questa opzione vale anche per le password utente espresse nel parametro userPassword, ma è da notare che in successive query al database LDAP il contenuto verrà offuscato tramite base64.

L’ultima opzione, ma non ultima come importanza, è l’inclusione di un file esterno per la definizione delle Access List: in LDAP è possibile definire delle ACL con lo scopo di limitare gli utenti, specificando a quali attributi possono accedere e/o modificare. Vediamo una access list di esempio caricata nel file /etc/ldap/slapd.access:

# Attributes visibile to everyone, but can be changed only 
# by the owner
access to attr=cn,givenName,sn,krbName,krb5PrincipalName,gecos
        by dn="cn=Directory Manager,ou=People,dc=azienda,dc=it" write
        by dn="uid=ldapadm.+\+realm=AZIENDA.IT" write
        by self write
        by * read

access to attr=loginShell,gecos
        by dn="cn=Directory Manager,ou=People,dc=azienda,dc=it" write
        by dn="uid=ldapadm.+\+realm=AZIENDA.IT" write
        by self write
        by * read

# Since we’re using {KERBEROS}<PRINCIPAL>, we can't allow 
# the user to change the password. They have to use the 
# Kerberos 'kpasswd' to do this. But the admin can change 
# (if need be). Please see krb5 userPassword attribute
access to attr=userPassword
        by dn="cn=Directory Manager,ou=People,dc=azienda,dc=it" write
        by dn="uid=ldapadm.+\+realm=AZIENDA.IT" write
        by anonymous auth
        by * none

# Directory Manager can do anything
access to *
        by dn="cn=Directory Manager,ou=People,dc=azienda,dc=it" write
        by dn="uid=ldapadm.+\+realm=AZIENDA.IT" write
        by * read

A questo punto è possibile avviare il server con:

# /usr/local/ldap/sbin/slapd -u ldap -g ldap -h “ldaps://0.0.0.0/”

Con l’opzione -h si è specificato quali protocolli e quali IP address il server LDAP deve ascoltare, in questo caso solo ed esclusivamente LDAPS. Inoltre è consigliabile avviare il server LDAP con un utente e gruppo diverso da root, in questo caso è stato avviato con l’utente ldap e gruppo ldap, creando appositamente un utente ldap con home directory /var/lib/ldap (la directory del database). Proviamo quindi se LDAP funziona e se supporta i meccanismi di autenticazione preposti:

  1. ldapsearch -H “ldaps://localhost/” -x -b “” -s base -LLL supportedSASLMechanisms

Il risultato dovrebbe essere come segue, facendo attenzione che ci sia GSSAPI:

supportedSASLMechanisms: PLAIN
supportedSASLMechanisms: LOGIN
supportedSASLMechanisms: ANONYMOUS
supportedSASLMechanisms: GSSAPI

A questo punto siamo pronti per popolare il database LDAP con i dati fittizi, a questo scopo useremo l’utility slapadd e un file temporaneo in cui scrivere i dati, ad esempio /tmp/ldapentries.diff, come segue:

dn: cn=Mario Rossi, ou=People, dc=azienda,dc=it
objectClass: top
objectClass: person
objectClass: inetOrgPerson
objectClass: krb5Principal
objectClass: posixAccount
sn: Rossi
cn: Mario Rossi
givenName: Mario
mail: mrossi@azienda.it
krb5PrincipalName: mrossi@AZIENDA.IT
userPassword:: {KERBEROS}mrossi@AZIENDA.IT
uid: mrossi
uidNumber: 500
homeDirectory: /home/mrossi
gidNumber: 100

dn: ou=People,dc=azienda,dc=it
objectClass: top
objectClass: organizationalUnit
ou: People

dn: cn=Directory Manager,ou=People,dc=azienda,dc=it
objectClass: organizationalRole
cn: Directory Manager
description: Directory Manager

dn: dc=azienda,dc=it
objectClass: dcObject
objectClass: organization
dc: azienda
o: azienda.it
description: Root LDAP

dn: ou=Group,dc=azienda,dc=it
objectClass: top
objectClass: organizationalUnit
ou: Group

dn: cn=users,ou=Group,dc=azienda,dc=it
objectClass: posixGroup
objectClass: top
cn: users
gidNumber: 100
memberUid: mrossi

dn: ou=Computers,dc=azienda,dc=it
objectClass: top
objectClass: organizationalUnit
ou: Computers

Importiamo il file eseguendo il comando:

# slapadd -l /tmp/ldapentries.diff

A questo punto possiamo provare ad effettuare la prima chiamata a LDAP con l’utente Directory Manager, ad esempio con il seguente comando

# ldapsearch -H “ldaps://localhost/” -b “dc=azienda,dc=it” -x -W -D “cn=Directory Manager,ou=People,dc=azienda,dc=it” “objectclass=*”

Il comando dovrebbe restituire l’intero database LDAP. È possibile aggiungere anche una replica a LDAP per avere una maggiore alta affidabilità e disponibilità; si consiglia la lettura dell’ottimo How-To di Turbo Fredriksson LDAPv3 per un approfondimento.

Il Firewall

Come accennato in precedenza, uno degli obiettivi prioritari di questo laboratorio è di riflettere quanto possibile una realtà di produzione. A questo scopo è stato inserito nell’architettura un firewall, in modo da capire le problematiche relative all’aggiunta di un filtro IP. Nella tabella sottostante si riassumono le necessità di cominicazione dai client verso il KDC e i servizi Kerberos all’interno del firewall.

Tipo di macchina Porta di destinazione Descrizione
KDC 88/udp 88/tcp Kerberos 5 erogazione ticket
KDC 749/tcp Kerberos 5, servizio kpasswd per cambio password e servizio di amministrazione remota
LDAP 636/tcp LDAP con SSL per l’accesso ai dati utente

Nel nostro caso, queste necessità si tradurranno in policy da applicare al firewall cerbero. Vediamo nella tabella sottostante queste policy:

Nome della macchina Porta di destinazione Descrizione
zeus.azienda.it 88/udp 88/tcp 749/tcp Accesso alle funzionalità di Kerberos (autenticazione e cambio password)
zeus.azienda.it 636/tcp LDAPS per lookup utenti
venere.azienda.it 80/tcp Accesso al Web server
venere.azienda.it 25/tcp 143/tcp Accesso alla posta elettronica (SMTP ed IMAP)