LDAP
Introductie
Om een centrale plaats te hebben om authenticatie te doen voor www.hcc.nl en sub-sites zoals een forum, is gekozen voor het gebruiken van een LDAP database/directory. Hierin wordt alleen opgeslagen wat nodig is voor het functioneren van de site. Andere persoonsgegevens en HCC specifieke gegevens komen in een (MySQL) database. Dit kan ook een tabel binnen de Drupal omgeving zijn
LDAP server keuze
De voor de hand liggen de keuze is OpenLDAP. Echter zijn er geluiden gehoord dat OpenLDAP niet zou schalen. Alternatieven zijn b.v. 389 maar die is erg slecht gesupport onder Ubuntu. Voorlopig starten we met OpenLDAP.
Loadbalanced
Er zijn twee servers (hcc-ldap-lb1 en hcc-ldap-lb2) die achter een loadbalancer in pomeleoepee mode staat zodat het verkeer altijd server1 gestuurd wordt. Beide servers houden elkaar up-to-date. In de gewone situatie zullen alle reads en writes naar server 1 gaan en server2 wordt door server1 bijgewerkt. Valt server1 weg, dan zal de loadbalancer overschakelen naar server2 waar vanaf dan de read en writes plaatsvinden. Zodra server 1 weer beschikbaar is, wordt die bijgewerkt en zal weer master worden. Dit is nog niet getest en hoe de timing precies is, is nog niet duidelijk...
installatie
installatie van OpenLDAP is simpel:
aptitude install slapd ldap-utils
De configuratie van OpenLDAP is sinds Karmic Koala iets gecompliceerder geworden. cn=config wordt nog steeds gebruikt maar tijdens installatie wordt alleen een skeleton configuratie geïnstalleerd. Er wordt niet meer gevraagd om een password tijdens de installatie en met "dpkg-reconfigure slapd" zet alleen de skeleton configuratie terug. Je moet zelf de database, root dn en acl's opzetten (als root of met sudo). Run dpkg-reconfigure slapd om terug te gaan naar een lege directory.
Initiële database
Direct na installatie (of na dpkg-reconfigure slapd) staat dit in OpenLDAP. Access is alleen geregeld voor root. Dit heeft te maken met het feit dat vanaf Karmic Koala OpenLDAP alleen het minst noodzakelijke bevat om slapd te starten. Het upd_lapd script (zie verderop) maakt een initiële database zoals beschreven is in HowToForge en de OpenLDAP site. Hier volgt het script dat alles toevoegt om weer een configuratie te krijgen als vóór Karmic.
version: 1 # # LDAPv3 # base <cn=config> with scope subtree # filter: (objectclass=*) # requesting: ALL # # config dn: cn=config objectClass: olcGlobal cn: config olcArgsFile: /var/run/slapd/slapd.args olcLogLevel: none olcPidFile: /var/run/slapd/slapd.pid olcToolThreads: 1 # schema, config dn: cn=schema,cn=config objectClass: olcSchemaConfig cn: schema ..... # {0}core, schema, config dn: cn={0}core,cn=schema,cn=config objectClass: olcSchemaConfig cn: {0}core ..... # {-1}frontend, config dn: olcDatabase={-1}frontend,cn=config objectClass: olcDatabaseConfig objectClass: olcFrontendConfig olcDatabase: {-1}frontend olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external ,cn=auth manage by * break olcAccess: {1}to dn.base="" by * read olcAccess: {2}to dn.base="cn=subschema" by * read olcSizeLimit: 500 # {0}config, config dn: olcDatabase={0}config,cn=config objectClass: olcDatabaseConfig olcDatabase: {0}config olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external ,cn=auth manage by * break # search result # numResponses: 6 # numEntries: 5
backend.ldif
Installeert de hdb module, configureert de suffix (hobby.nl), zet er een RootDN en PW op en plaatst indexen op enkele attrs.
# Load dynamic backend modules dn: cn=module,cn=config objectClass: olcModuleList cn: module olcModulepath: /usr/lib/ldap olcModuleload: back_hdb # Create the backend database dn: olcDatabase=hdb,cn=config objectClass: olcDatabaseConfig objectClass: olcHdbConfig olcDatabase: hdb olcDbDirectory: /var/lib/ldap/hobby/ olcSuffix: dc=hobby,dc=nl olcRootDN: cn=admin,dc=hobby,dc=nl olcRootPW: {MD5}Xr4ilOzQ4PCOq3aQ0qbuaQ== olcDbConfig: {0}set_cachesize 0 2097152 0 olcDbConfig: {1}set_lk_max_objects 1500 olcDbConfig: {2}set_lk_max_locks 1500 olcDbConfig: {3}set_lk_max_lockers 1500 olcLastMod: TRUE olcDbCheckpoint: 512 30 olcDbIndex: uid pres,eq,sub olcDbIndex: cn,sn,mail pres,eq,approx,sub olcDbIndex: objectClass eq olcDbIndex: entryUUID eq
frontend.ldif
Hier wordt het root of top object gedefinieerd.
# Create top-level object in domain dn: dc=hobby,dc=nl objectClass: top objectClass: dcObject objectclass: organization o: Thuis Organization dc: hobby description: Top level object hobby.nl # Admin user of top level. dn: cn=admin,dc=hobby,dc=nl objectClass: simpleSecurityObject objectClass: organizationalRole cn: admin description: LDAP administrator for hobby.nl userPassword: {MD5}Xr4ilOzQ4PCOq3aQ0qbuaQ== dn: ou=people,dc=hobby,dc=nl objectClass: organizationalUnit ou: people dn: ou=groups,dc=hobby,dc=nl objectClass: organizationalUnit ou: groups
Voorbeeld van een entry in people en groups
Zodra de eerste twee ldifs geladen zijn kan een entry worden toegevoegd in people,hobby,nl.
dn: uid=egbert,ou=people,dc=hobby,dc=nl objectClass: inetOrgPerson objectClass: posixAccount objectClass: shadowAccount uid: egbert sn: van den Bussche givenName: Egbert Jan cn: Egbert Jan van den Bussche displayName: H.E.J. v.d. Bussche uidNumber: 1000 gidNumber: 1000 userPassword: secret gecos: Egbert Jan van den Bussche loginShell: /bin/bash homeDirectory: /home/egbert shadowExpire: -1 shadowFlag: 0 shadowWarning: 7 shadowMin: 8 shadowMax: 999999 shadowLastChange: 10877 mail: egbert@hobby.nl postalCode: 2636 DE l: SCHIPLUIDEN o: HCC!Hobbynet mobile: +31646094008 homePhone: +31153809909 title: System Administrator postalAddress: initials: HEJvdB dn: cn=egbert,ou=groups,dc=hobby,dc=nl objectClass: posixGroup cn: egbert gidNumber: 1000
config.ldif
In deze ldif wordt de default ACL van de frontend,config en config,config databases gehaald. Ook wordt er een RootDN/PW toegevoegd aan de config,config database.
# Remove any ACL on frontend dn: olcDatabase={-1}frontend,cn=config changetype: modify delete: olcAccess # Put new RootDN in config dn: olcDatabase={0}config,cn=config changetype: modify add: olcRootDN olcRootDN: cn=admin,cn=config # Set the passwd for RootDN dn: olcDatabase={0}config,cn=config changetype: modify add: olcRootPW olcRootPW: {MD5}Xr4ilOzQ4PCOq3aQ0qbuaQ== # Delete any ACL on config dn: olcDatabase={0}config,cn=config changetype: modify delete: olcAccess
acl.ldif.ldif
Acl.ldif plaatst een ALL op de backend database.
dn: olcDatabase={1}hdb,cn=config add: olcAccess olcAccess: to attrs=userPassword,shadowLastChange by dn="cn=admin,dc=hobby,dc=nl" write by anonymous auth by self write by * none olcAccess: to dn.base="" by * read olcAccess: to * by dn="cn=admin,dc=hobby,dc=nl" write by * read
Opmerking: Volgens de OpenLDAP userguide (v2.4) zou by dn="cn=admin,dc=hobby,dc=nl" write overbodig zijn daar RootDN altijd overal toegang heeft.
Shell script
Dit script moet uitgevoerd worden wanneer de 4 minimale ldifs klaar zijn om in OpenLDAP gezet te worden (dynamische configuratie).
# # Initial part. # # Add the three main schemas # Load the database backend module and create the database # Create the base dn and the admin account for the openldap server # There are some acl's set in the openldap setup that prevent phpldapadmin # to interface with the directory, so we will remove them now and set openldap # to the default cn=admin,cn=config. From this moment on the openldap can be # configured and manipulated as before, but no longer by issuing commands like # ldapadd -Y EXTERNAL -H ldapi:/// -f file # but rather # ldapadd -x -D cn=admin,cn=config -W -f file # # Finally restart slapd # # See: http://www.howtoforge.com/install-and-configure-openldap-on-ubuntu-karmic-koala # tmpdir=~/ldap # Cleanup echo "Remove old databases" rm -R /var/lib/ldap/hcc/* rm -R /var/lib/ldap/hobby/* # Add schemas echo "Add the cosine, nis and inetorgperson schema's" ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/cosine.ldif ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/nis.ldif ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/inetorgperson.ldif # Add database module and configure echo "Add backend.ldif" ldapadd -Y EXTERNAL -H ldapi:/// -f $tmpdir/backend.ldif # Add base DN echo "Add frontend.ldif" ldapadd -Y EXTERNAL -H ldapi:/// -f $tmpdir/frontend.ldif # Place RootDN and remove ACLs echo "Add config.ldif" ldapadd -Y EXTERNAL -H ldapi:/// -f $tmpdir/config.ldif # Place ACL echo "Add acl.ldif" ldapmodify -x -D cn=admin,cn=config -W -f $tmpdir/acl.ldif # Restart slapd /etc/init.d/slapd restart
Pre Karmic situatie
Na het uitvoeren vna het script ziet het totaal over zich er zo uit:
# extended LDIF # # LDAPv3 # base <cn=config> with scope subtree # filter: (objectclass=*) # requesting: ALL # # config dn: cn=config objectClass: olcGlobal cn: config olcArgsFile: /var/run/slapd/slapd.args olcLogLevel: none olcPidFile: /var/run/slapd/slapd.pid olcToolThreads: 1 # module{0}, config dn: cn=module{0},cn=config objectClass: olcModuleList cn: module{0} olcModulePath: /usr/lib/ldap olcModuleLoad: {0}back_hdb # schema, config dn: cn=schema,cn=config objectClass: olcSchemaConfig cn: schema ..... # {0}core, schema, config dn: cn={0}core,cn=schema,cn=config objectClass: olcSchemaConfig cn: {0}core ..... # {1}cosine, schema, config dn: cn={1}cosine,cn=schema,cn=config objectClass: olcSchemaConfig cn: {1}cosine ..... # {2}nis, schema, config dn: cn={2}nis,cn=schema,cn=config objectClass: olcSchemaConfig cn: {2}nis ..... # {3}inetorgperson, schema, config dn: cn={3}inetorgperson,cn=schema,cn=config objectClass: olcSchemaConfig cn: {3}inetorgperson ..... # {-1}frontend, config dn: olcDatabase={-1}frontend,cn=config objectClass: olcDatabaseConfig objectClass: olcFrontendConfig olcDatabase: {-1}frontend olcSizeLimit: 500 # {0}config, config dn: olcDatabase={0}config,cn=config objectClass: olcDatabaseConfig olcDatabase: {0}config olcRootDN: cn=admin,cn=config olcRootPW: {MD5}Xr4ilOzQ4PCOq3aQ0qbuaQ== # {1}hdb, config dn: olcDatabase={1}hdb,cn=config objectClass: olcDatabaseConfig objectClass: olcHdbConfig olcDatabase: {1}hdb olcDbDirectory: /var/lib/ldap/hobby/ olcSuffix: dc=hobby,dc=nl olcAccess: {0}to attrs=userPassword,shadowLastChange by dn="cn=admin,dc=hobby, dc=nl" write by anonymous auth by self write by * none olcAccess: {1}to dn.base="" by * read olcAccess: {2}to * by dn="cn=admin,dc=hobby,dc=nl" write by * read olcLastMod: TRUE olcRootDN: cn=admin,dc=hobby,dc=nl olcRootPW: {MD5}Xr4ilOzQ4PCOq3aQ0qbuaQ== olcDbCheckpoint: 512 30 olcDbConfig: {0}set_cachesize 0 2097152 0 olcDbConfig: {1}set_lk_max_objects 1500 olcDbConfig: {2}set_lk_max_locks 1500 olcDbConfig: {3}set_lk_max_lockers 1500 olcDbIndex: uid pres,eq olcDbIndex: cn,sn,mail pres,eq,approx,sub olcDbIndex: objectClass eq # search result search: 2 result: 0 Success # numResponses: 11 # numEntries: 10
Root heeft geen toegang meer. Er is een RootDN in config (cn=admin,cn=config) die overal gebruikt moet worden. De database heeft een eigen RootDN (is dit wel handig?).
Replicatie
Voor master/slave replicatie kan de configuratie in Ubuntu Server Guide gevonden worden.
Uitbreiding tot single master
In ldap terminologie spreken we van een provider. In dit geval en single-master. De provider.ldif:
# Add indexes to the frontend db. dn: olcDatabase={1}hdb,cn=config changetype: modify add: olcDbIndex olcDbIndex: entryCSN eq - add: olcDbIndex olcDbIndex: entryUUID eq #Load the syncprov and accesslog modules. dn: cn=module{0},cn=config changetype: modify add: olcModuleLoad olcModuleLoad: syncprov - add: olcModuleLoad olcModuleLoad: accesslog # Accesslog database definitions dn: olcDatabase={2}hdb,cn=config objectClass: olcDatabaseConfig objectClass: olcHdbConfig olcDatabase: {2}hdb olcDbDirectory: /var/lib/ldap/accesslog olcSuffix: cn=accesslog olcRootDN: cn=admin,dc=example,dc=com olcDbIndex: default eq olcDbIndex: entryCSN,objectClass,reqEnd,reqResult,reqStart # Accesslog db syncprov. dn: olcOverlay=syncprov,olcDatabase={2}hdb,cn=config changetype: add objectClass: olcOverlayConfig objectClass: olcSyncProvConfig olcOverlay: syncprov olcSpNoPresent: TRUE olcSpReloadHint: TRUE # syncrepl Provider for primary db dn: olcOverlay=syncprov,olcDatabase={1}hdb,cn=config changetype: add objectClass: olcOverlayConfig objectClass: olcSyncProvConfig olcOverlay: syncprov olcSpNoPresent: TRUE # accesslog overlay definitions for primary db dn: olcOverlay=accesslog,olcDatabase={1}hdb,cn=config objectClass: olcOverlayConfig objectClass: olcAccessLogConfig olcOverlay: accesslog olcAccessLogDB: cn=accesslog olcAccessLogOps: writes olcAccessLogSuccess: TRUE # scan the accesslog DB every day, and purge entries older than 7 days olcAccessLogPurge: 07+00:00 01+00:00
Pas alle domein strings aan! (wordt nog tot script vertimmerd vbs20110919)
Uitbreiding tot slave
In ldap terminologie spreken we van een consumer. De consumer moet precies zo opgezet worden als de provider maar dan zonder de provider specifieke configuratie. Hiervoor in de plaats komt een consumer-specifieke configuratie.
#Load the syncprov module. dn: cn=module{0},cn=config changetype: modify add: olcModuleLoad olcModuleLoad: syncprov # syncrepl specific indices dn: olcDatabase={1}hdb,cn=config changetype: modify add: olcDbIndex olcDbIndex: entryUUID eq - add: olcSyncRepl olcSyncRepl: rid=0 provider=ldap://ldap01.example.com bindmethod=simple binddn="cn=admin,dc=example,dc=com" credentials=secret searchbase="dc=example,dc=com" logbase="cn=accesslog" logfilter="(&(objectClass=auditWriteObject)(reqResult=0))" schemachecking=on type=refreshAndPersist retry="60 +" syncdata=accesslog - add: olcUpdateRef olcUpdateRef: ldap://ldap01.example.com
Met behulp van deze werkende voorbeelden is een script ontwikkeld dat, nadat dpkg-reconfigure heeft gelopen en de /var/lib/ldap/* gewist zijn, alles opnieuw installeert. Voor dit script zie deze pagina: LDAP script.