====== LDAP e Kerberos ====== ===== Introduzione ===== Questa breve guida illustra i concetti ed i passaggi necessari per configurare OpenStack utilizzando LDAP per la gestione degli utenti e Kerberos per l'autenticazione. Al fine di evitare il polluting della directory((Keystone tende ad utilizzare LDAP come se fosse un database relazionale)), si opterà per una directory LDAP separata da altre istanze. In particolare, in Grizzly Keystone mantiene la struttura "non-standard" con i tenant trasformati in rami LDAP contenenti i ruoli come foglie ed i membri come attributi dei ruoli (si faccia riferimento alle [[https://agenda.infn.it/getFile.py/access?contribId=28&sessionId=2&resId=0&materialId=slides&confId=6179|slide]] della presentazione di Stefano Stalio presso il Workshop CCR 2013 per un'illustrazione dell'albero) e Quantum continua ad autenticarsi diverse volte al minuto contro Keystone, causando in questo modo un numero relativamente elevato di bind alla directory. Per questi motivi, è consigliabile utilizzare una directory dedicata e quanto più "vicina" possibile a Keystone - possibilmente in esecuzione sulla stessa macchina. ===== Requisiti ===== La guida è stata sviluppata e testata nel seguente ambiente: * Ubuntu 12.04.2 (x86_64) * OpenStack Grizzly * Python 2.7 * python-ldap * setup di OpenStack eseguito utilizzando come riferimento il manuale di OpenStack e la [[https://github.com/mseknibilel/OpenStack-Grizzly-Install-Guide/blob/OVS_MultiNode/OpenStack_Grizzly_Install_Guide.rst|guida d'installazione rapida]] presente su GitHub. Non dovrebbe essere complesso adattarla ad ambienti RDO, ma **non** è stata testata con packstack. ===== Setup di OpenStack ===== Si faccia riferimento alla guida, arrestandosi alla configurazione di Keystone. ===== Setup di OpenLDAP ===== Come directory server si è scelto OpenLDAP, ma è ugualmente possibile utilizzare 389ds. Negli esempi (LDIF e file di configurazione di Keystone) si utilizzeranno i seguenti valori: ^ Parametro ^ Valore ^ | Dominio | ostack.lngs.infn.it | | Base DN | dc=ostack,dc=lngs,dc=infn,dc=it | | Admin DN | cn=admin,dc=ostack,dc=lngs,dc=infn,dc=it | | Password | admin_pass | ==== Preparazione della directory ==== Creare un file chiamato ''base.ldif'' col seguente contenuto: # Users dn: ou=Users,dc=ostack,dc=lngs,dc=infn,dc=it objectClass: organizationalUnit ou: Users # Tenants dn: ou=Groups,dc=ostack,dc=lngs,dc=infn,dc=it objectClass: organizationalUnit ou: Groups # Roles dn: ou=Roles,dc=ostack,dc=lngs,dc=infn,dc=it objectClass: organizationalUnit ou: Roles # Hardcoded in OpenStack!!!! dn: cn=9fe2ff9ee4384b1894a90878d3e92bab,ou=Roles,dc=ostack,dc=lngs,dc=infn,dc=it objectClass: organizationalRole ou: _member_ cn: 9fe2ff9ee4384b1894a90878d3e92bab # Enabled bit emulation for users dn: cn=enabled_users,dc=ostack,dc=lngs,dc=infn,dc=it objectClass: groupOfNames cn: enabled_users member: cn=dumb,dc=ostack,dc=lngs,dc=infn,dc=it # Enabled bit emulation for tenants dn: cn=enabled_tenants,dc=ostack,dc=lngs,dc=infn,dc=it objectClass: groupOfNames cn: enabled_tenants member: cn=dumb,dc=ostack,dc=lngs,dc=infn,dc=it Il ruolo con id ''9fe2ff9ee4384b1894a90878d3e92bab'' è hardcoded in OpenStack ed utilizzato per identificare un membro di un determinato tenant nell'API Nova. Normalmente, questo ruolo viene creato da ''keystone-manage db_sync'' durante l'installazione di Keystone. Il membro con DN ''cn=dumb,dc=ostack,dc=lngs,dc=infn,dc=it'' è un membro "dummy" necessario per rendere gli oggetti groupOfNames conformi allo schema. Keystone ignorerà questo membro. Sempre facendo riferimento ad OpenLDAP, applicare le modifiche alla directory con: ldapmodify -W -D cn=admin,dc=ostack,dc=lngs,dc=infn,dc=it -f base.ldif ==== Creazione degli indici ==== (Questa sezione è specifica per OpenLDAP) Al fine di rendere più efficiente l'accesso alla directory((e per evitare che slapd riempia i log di warning)), è necessario creare degli indici sugli attributi più utilizzati da Keystone per effettuare ricerche. Creare un file chiamato ''indexes.ldif'' col seguente contenuto: dn: olcDatabase={1}hdb, cn=config changetype: modify add: olcDbIndex olcDbIndex: cn pres,sub,eq - add: olcDbIndex olcDbIndex: ou pres,sub,eq - add: olcDbIndex olcDbIndex: sn pres,sub,eq - add: olcDbIndex olcDbIndex: roleOccupant pres,eq Ed applicare le modifiche eseguendo **come root**: ldapmodify -Y EXTERNAL -H ldapi:/// -f indexes.ldif Il setup di OpenLDAP è ora completo e si può procedere con la configurazione di Keystone. ===== Configurazione di Keystone ===== Sfortunatamente, la documentazione di Keystone riguardo al supporto ad LDAP è carente o addirittura in aperta contraddizione col codice. Gran parte dei valori corretti sono stati determinati per errori successivi, analisi dei backtrace di Keystone ed in alcuni casi per analisi diretta dei sorgenti. Prima di tutto, è necessario configurare il driver di identity management per utilizzare LDAP al posto di MySQL: [identity] driver = keystone.identity.backends.ldap.Identity Dopodiché è necessario configurare come segue (sempre adattando al vostro ambiente) la sezione ldap di keystone.conf: [ldap] url = ldap://localhost user = cn=admin,dc=ostack,dc=lngs,dc=infn,dc=it password = ldap_pass suffix = dc=ostack,dc=lngs,dc=infn,dc=it use_dumb_member = True allow_subtree_delete = False dumb_member = cn=dumb,dc=ostack,dc=lngs,dc=infn,dc=it user_tree_dn = ou=Users,dc=ostack,dc=lngs,dc=infn,dc=it user_objectclass = inetOrgPerson user_domain_id_attribute = None user_id_attribute = cn user_name_attribute = sn user_mail_attribute = mail user_pass_attribute = userPassword user_enabled_default = True user_attribute_ignore = tenant_id,tenantId,tenants user_allow_create = True user_allow_update = True user_allow_delete = True user_enabled_emulation = True user_enabled_emulation_dn = cn=enabled_users,dc=ostack,dc=lngs,dc=infn,dc=it tenant_tree_dn = ou=Groups,dc=ostack,dc=lngs,dc=infn,dc=it tenant_objectclass = groupOfNames tenant_domain_id_attribute = businessCategory tenant_id_attribute = cn tenant_member_attribute = member tenant_name_attribute = ou tenant_desc_attribute = description tenant_attribute_ignore = tenantId tenant_enabled_emulation = True tenant_enabled_emulation_dn = cn=enabled_tenants,dc=ostack,dc=lngs,dc=infn,dc=it role_tree_dn = ou=Roles,dc=ostack,dc=lngs,dc=infn,dc=it role_objectclass = organizationalRole role_id_attribute = cn role_name_attribute = ou role_member_attribute = roleOccupant role_attribute_ignore = Alcuni parametri meritano una spiegazione a sé: * ''use_dumb_member'' contrariamente a quanto riportato nella documentazione è richiesto per poter creare tenant conformi allo schema per oggetti groupOfNames * ''user_enabled_emulation'', ''user_enabled_emulation_dn'' e i rispettivi parametri per i tenant sono necessari per emulare la presenza di un campo ''enabled'', assente sia da inetOrgPerson che da groupOfNames; entrambe le DN devono puntare ad un oggetto di tipo groupOfNames definito in precedenza durante l'inizializzazione della directory * i parametri ''user_allow_create'' ed ''user_allow_update'' devono essere **temporaneamente** impostati a ''True'' per permettere al setup di Keystone di procedere con successo ===== Prosecuzione del setup di OpenStack ===== A questo punto, il setup di OpenStack può proseguire con la creazione di utenti e ruoli di base, service endpoint e l'installazione/configurazione degli altri servizi. Una volta terminata, è caldamente consigliato impostare ''user_allow_create'' ed ''user_allow_update'' a ''False'' e riavviare Keystone. ===== Kerberos ===== L'integrazione con Kerberos avviene per mezzo di saslauthd e del meccanismo password ''{SASL}'' di OpenLDAP. Prima di procedere, è necessario creare un principal ''host/FQDN'' per il controller node e trasferirlo in ''/etc/krb5.keytab'' sul controller node. ==== Installazione di saslauthd ==== Installare saslauthd ed il relativo plugin per GSSAPI. Su Ubuntu: apt-get -y install sasl2-bin libsasl2-modules-gssapi-mit A questo punto, saslauthd deve essere configurato per utilizzare GSSAPI come backend di autenticazione. Su Ubuntu è sufficiente modificare ''/etc/default/saslauthd'' in modo da avere i seguenti valori: START=yes MECHANISM="kerberos5" E successivamente avviarlo con service saslauthd start A questo punto, è possibile testare il funzionamento con testsaslauthd -s slapd -u user@LNGS.INFN.IT -p 'password' Se il vostro realm non prevede l'uso di AES, è **necessario** abilitare ''allow_weak_crypto'' in ''/etc/krb5.conf''. ==== Configurazione di OpenLDAP ==== È ora necessario definire il meccanismo di autenticazione SASL per slapd, creando ''/usr/lib/sasl2/slapd.conf'' col seguente contenuto: mech_list: plain pwcheck_method: saslauthd saslauthd_path: /var/run/saslauthd/mux Quindi aggiungere l'utente con cui è in esecuzione OpenLDAP al gruppo sasl: gpasswd -a openldap sasl Ed infine riavviare slapd: service slapd restart Da questo momento in poi, tutte le password con meccanismo ''{SASL}'' verranno verificate su Kerberos utilizzando saslauthd come proxy. ===== Gestione degli utenti ===== Per permettere l'autenticazione degli utenti su Kerberos è necessario che ogni utente abbia come attributo userPassword ''{SASL}principal@REALM''. Ciò, purtroppo, non è effettuabile tramite Horizon in quanto Keystone utilizza per default il metodo ''{SSHA}'' per salvare le password su LDAP. Per aggiungere ed abilitare/disabilitare gli utenti, è possibile utilizzare un qualsiasi client LDAP in grado di creare oggetti inetOrgPerson. Presso i LNGS sono in uso una serie di script denominati [[https://github.com/rfc1459/osgsa/|OSGSA]] che effettuano le operazioni di registrazione e abilitazione/disabilitazione degli utenti. Gli script in questione possono essere utilizzati in ambienti OpenStack/LDAP creati secondo le indicazioni di questa guida. Idealmente, dovrebbero essere installati sul controller node e richiedono ''python-ldap'' e ''python-yaml''.