Dies ist eine alte Version des Dokuments!
Authentifikation mit technischem User beim OpenLDAP Servers unter CentOS 7.x
Als wesentliche Erweiterung unseres Open-LDAP-Servers werden wir nun unseren Daemon so konfigurieren, dass keine anonymen LDAP Abfragen mehr zugelassen werden, sondern hierzu einen speziellen technischen User verwenden.
In abgesicherten Umgebungen wird der Zugriff auf den LDAP-Server nicht von jedermann ohne Passwort, auch anonymous bind genannt unterbunden. Stattdessen muss ich der Klient bei den Anfragen eines technischen Users bedienen, der auch ein Passwort benutzt, welches dem LDAP-Server bekannt ist.
technischer User für LDAP-Zugriff
Bei diesem Anwendungs- und Konfigurationsbeispiel gehen wir von einem bereits installiertem und konfiguriertem OpenLDAP-Server aus, wie in den Kapiteln I - III der Beschreibung zum OpenLDAP Server unter CentOS 7.x beschrieben.
Konfiguration
Im ersten Schritt werden wir uns nun einen eigenen speziellen technischen User anlegen, mit dem später die Anfragen an unseren OpenLDAp-Server gerichtet werden sollen.
Für die Befüllung mit Nutzdaten, die aus Distinguished Names (DN) und einem eindeutigen Objektnamen bestehen, müssen hierzu in den Directory Information Tree (DIT), einer hierarchischen Baumstruktur eingefügt werden.
Wie jedes andere Objekt in unserem Open-LDAP-Verzeichnis werden wir für den technischen User, der für die Anmeldung am Server (bind) benötigt und verwendet werden wird, ein Objekt mit dem Common Name (CN) Technischer_User und den Domain Components(DC) nausch und org für die Domäne nausch.org im DIT hinterlegen.
Wie auch schon beim Erstellen des Master-Passwortes werden wir nun für den Bind-User ein separates Passwort vergeben und so den Zugriff absichern.
Zur Generierung dieses Passwortes mit der Verschlüsselungsmethode SSHA - entsprechend einem SHA-1 Algorithmus (FIPS 160-1), verwenden wir wieder das Programm /usr/sbin/slappasswd mit folgendem Befehl aufgerufen:
# /usr/sbin/slappasswd -h {SSHA}
New password: Re-enter new password: {SSHA}YpKKoS1lV1AdAX1StGe1lTembvZW4XagnkLdWZ2Y4Xkw
Dieses gekryptete Passwort hinterlegen wir nun in einer passenden ldif-Datei.
# vim /etc/openldap/ldif/cn\=config_bindUSER.ldif
- /etc/openldap/ldif/cn=config_bindUSER.ldif
# Django : 2015-07-17 # Anlegen eines technischen Users für die Anmeldung am Server (bind) # https://dokuwiki.nausch.org/doku.php/centos:ldap_c7:tecbind#konfiguration dn: cn=Technischeruser,dc=nausch,dc=org cn: Technischeruser objectClass: organizationalRole objectClass: simpleSecurityObject objectClass: top userPassword: {SSHA}YpKKoS1lV1AdAX1StGe1lTembvZW4XagnkLdWZ2Y4Xkw
Zum Importieren unseres DITs verwenden wir nun folgenden Aufruf. Das Passwort nach dem wir hier gefragt werden, haben wir im Kapitel Manager-Passwort bei der Installation unseres OpenLDAP Server unter CentOS 7.x angelegt.
# ldapadd -W -x -D cn=Manager,dc=nausch,dc=org -f /etc/openldap/ldif/cn\=config_bindUSER.ldif
Enter LDAP Password: adding new entry "cn=Technischeruser,dc=nausch,dc=org"
Abfragetest
Anschließend überprüfen wir, ob die Daten unseres unser Technischeruser im DIT richtig angelegt wurde.
# ldapsearch -W -x -b "dc=nausch,dc=org" "cn=Technischeruser" -D \ "cn=Technischeruser,dc=nausch,dc=org" -LLL \ -H ldaps://openldap.dmz.nausch.org
Enter LDAP Password:
dn: cn=Technischeruser,dc=nausch,dc=org cn: Technischeruser objectClass: organizationalRole objectClass: simpleSecurityObject objectClass: top userPassword:: YpKKoS1lV1AdAX1StGe1lTembvZW4XagnkLdWZ2Y4Xkw
Im Logfile des slapd-Daemon wird unsere erfolgreiche Abfrage entsprechend protokolliert.
# less /var/log/ldap.log
Jul 17 09:43:05 vml000037 slapd[14264]: conn=1041 fd=13 ACCEPT from IP=10.0.0.37:38446 (IP=0.0.0.0:636) Jul 17 09:43:06 vml000037 slapd[14264]: conn=1041 fd=13 TLS established tls_ssf=128 ssf=128 Jul 17 09:43:06 vml000037 slapd[14264]: conn=1041 op=0 BIND dn="cn=Technischeruser,dc=nausch,dc=org" method=128 Jul 17 09:43:06 vml000037 slapd[14264]: conn=1041 op=0 BIND dn="cn=technischeruser,dc=nausch,dc=org" mech=SIMPLE ssf=0 Jul 17 09:43:06 vml000037 slapd[14264]: conn=1041 op=0 RESULT tag=97 err=0 text= Jul 17 09:43:06 vml000037 slapd[14264]: conn=1041 op=1 SRCH base="dc=nausch,dc=org" scope=2 deref=0 filter="(cn=technischer_user)" Jul 17 09:43:06 vml000037 slapd[14264]: conn=1041 op=1 SEARCH RESULT tag=101 err=0 nentries=1 text= Jul 17 09:43:06 vml000037 slapd[14264]: conn=1041 op=2 UNBIND Jul 17 09:43:06 vml000037 slapd[14264]: conn=1041 fd=13 closed
Deaktivierung des "Anonymous bind" beim LDAP-Zugriff
In unserer abgesicherten Umgebung sollen ausschließlich authentifizierte Abfragen und Zugriffe auf unseren OpenLADP-Server gestattet sein. Hierzu haben wir uns im vorherigem Abschnitt eigens einen technischen Useraccount angelegt.
Konfiguration
Damit unser Open-LDAP Daemon keine anonymen Anfragen, oder genauer gesagt keinen zur Verfügung stellen wird, sind nachfolgende Ergänzungen an unserer Konfiguration notwendig. Hierzu werden wir die Directive olcDisallows auf bind_anon und die Directive olcRequires auf authc setzen.
Zum Setzen und Ändern der beiden Directiven legen wir uns nun wieder eine passende ldif-Datei an.
# vim /etc/openldap/ldif/cn\=config_bindANON.ldif
- /etc/openldap/ldif/cn=config_bindANON.ldif
# Django : 2015-07-17 # Sperren des „anonymous bind“ und Authentifizierung erzwingen # https://dokuwiki.nausch.org/doku.php/centos:ldap_c7:tecbind?&#deaktivierung_des_anonymous_bind_beim_ldap-zugriff dn: cn=config changetype: modify add: olcDisallows olcDisallows: bind_anon - add: olcRequires olcRequires: authc
Wie bei der vorangegangenen Änderungen/Konfigurationsbeispielen aktivieren wir nun die Änderungen aus der Datei /etc/openldap/ldif/cn=config_bindANON.ldif mit folgendem Aufruf.
# ldapmodify -W -x -D cn=config -f /etc/openldap/ldif/cn\=config_bindANON.ldif
Enter LDAP Password:
modifying entry "cn=config"
Abfragetest
Konfiuration
Anschließend überprüfen wir, ob die Daten unseres unser Technischeruser im DIT richtig angelegt wurde.
# ldapsearch -W -x -D cn=config -b cn=config "(objectclass=olcGlobal)" -LLL -H ldaps://openldap.dmz.nausch.org
Enter LDAP Password:
dn: cn=config objectClass: olcGlobal cn: config olcArgsFile: /var/run/openldap/slapd.args olcIdleTimeout: 30 olcPidFile: /var/run/openldap/slapd.pid olcReferral: ldap://openldap.dmz.nausch.org olcTimeLimit: 15 olcTLSCACertificateFile: /etc/pki/tls/certs/CAcert_chain.pem olcTLSCACertificatePath: /etc/openldap/certs olcTLSCertificateFile: /etc/pki/tls/certs/openldap.dmz.nausch.org.pem olcTLSCertificateKeyFile: /etc/pki/tls/private/openldap_serverkey.pem olcTLSCipherSuite: HIGH olcTLSDHParamFile: /etc/pki/tls/private/dh_4096.pem olcTLSProtocolMin: 3.1 olcDisallows: bind_anon olcRequires: authc
Im Logfile des slapd-Daemon wird unsere erfolgreiche Abfrage entsprechend protokolliert.
# less /var/log/ldap.log
Jul 17 11:40:01 vml000037 slapd[14264]: conn=1062 fd=13 ACCEPT from IP=10.0.0.37:41464 (IP=0.0.0.0:636) Jul 17 11:40:01 vml000037 slapd[14264]: conn=1062 fd=13 TLS established tls_ssf=128 ssf=128 Jul 17 11:40:01 vml000037 slapd[14264]: conn=1062 op=0 BIND dn="cn=config" method=128 Jul 17 11:40:01 vml000037 slapd[14264]: conn=1062 op=0 BIND dn="cn=config" mech=SIMPLE ssf=0 Jul 17 11:40:01 vml000037 slapd[14264]: conn=1062 op=0 RESULT tag=97 err=0 text= Jul 17 11:40:01 vml000037 slapd[14264]: conn=1062 op=1 SRCH base="cn=config" scope=2 deref=0 filter="(objectClass=olcGlobal)" Jul 17 11:40:01 vml000037 slapd[14264]: conn=1062 op=1 SEARCH RESULT tag=101 err=0 nentries=1 text= Jul 17 11:40:01 vml000037 slapd[14264]: conn=1062 op=2 UNBIND Jul 17 11:40:01 vml000037 slapd[14264]: conn=1062 fd=13 closed
LDAP-Anfragen
ungülige Anfrage - anonymous-bind
Versuchen wir nun eine anonymous-bind Abfrage gegen unseren OpenLDAP-Server hat dies keinen Erfolg und wir bekommen einen entsprechenden Warnhinweis.
# ldapsearch -x -LLL -H ldap://ldap.dmz.nausch.org -b "dc=nausch,dc=org" "uid=django"
ldap_bind: Inappropriate authentication (48) additional info: anonymous bind disallowed
Der Versuch sich mit dem OpenLDAP mit einem anonymous bind zu verbinden scheiterte natürlich.
Die Abfrage unseres Nutzers django erfolgt nun richtiger Weise natürlich mit Hilfe unseres technischen Users Technischeruser, den wir uns hierzu zuvor konfiguriert hatten.
gültige Abfrage
Nun wollen wir überprüfen, ob wir uns mit den Daten unseres technischen Users mit unserem OpenLDAP-server verbinden und auch Daten abfragen können.
# ldapsearch -W -x -b "dc=nausch,dc=org" "uid=django" \ -D "cn=Technischeruser,dc=nausch,dc=org" -LLL \ -H ldaps://openldap.dmz.nausch.org
Enter LDAP Password:
dn: uid=django,ou=People,dc=nausch,dc=org uid: django cn: django objectClass: account objectClass: posixAccount objectClass: top objectClass: shadowAccount userPassword:: $6$34os/lDDY2cAEfyW$fqe3PP3Qo5FDAtC724a7plCieqgeYCWONkaKgYnQKm5 iDx/3WtCq8Tv0VA2MLkYAhW9/IySlhFIJZIU0UyiOv/hUdjBWQTJNTGtZQWhXOS9JeVNsaEZJSlpJ VTBVeWlPdi8= shadowLastChange: 16617 shadowMin: 0 shadowMax: 99999 shadowWarning: 7 loginShell: /bin/bash uidNumber: 1000 gidNumber: 1000 homeDirectory: /home/django gecos: django
Im Logfile des slapd-Daemon wird unsere erfolgreiche Abfrage entsprechend protokolliert.
# less /var/log/ldap.log
Jul 17 12:00:02 vml000037 slapd[14264]: conn=1068 fd=13 ACCEPT from IP=10.0.0.37:41850 (IP=0.0.0.0:636) Jul 17 12:00:02 vml000037 slapd[14264]: conn=1068 fd=13 TLS established tls_ssf=128 ssf=128 Jul 17 12:00:02 vml000037 slapd[14264]: conn=1068 op=0 BIND dn="cn=Technischeruser,dc=nausch,dc=org" method=128 Jul 17 12:00:02 vml000037 slapd[14264]: conn=1068 op=0 RESULT tag=97 err=49 text= Jul 17 12:00:02 vml000037 slapd[14264]: conn=1068 op=1 UNBIND Jul 17 12:00:02 vml000037 slapd[14264]: conn=1068 fd=13 closed
Abfrage ohne Passwort
Der Versuch, sich ohne Passwort anzumelden schlägt natürlich entsprechend fehl.
# ldapsearch -W -x -b "dc=nausch,dc=org" "uid=django" \ -D "cn=Technischeruser,dc=nausch,dc=org" -LLL \ -H ldaps://openldap.dmz.nausch.org
Enter LDAP Password:
ldap_bind: Server is unwilling to perform (53) additional info: unauthenticated bind (DN with no password) disallowed
Dieser Versuch wird natürlich im LDAP-Log entsprechend dokumentiert.
# less /var/log/ldap.log
Jul 17 12:06:33 vml000037 slapd[14264]: conn=1069 fd=13 ACCEPT from IP=10.0.0.37:41969 (IP=0.0.0.0:636) Jul 17 12:06:33 vml000037 slapd[14264]: conn=1069 fd=13 TLS established tls_ssf=128 ssf=128 Jul 17 12:06:33 vml000037 slapd[14264]: conn=1069 op=0 BIND dn="cn=Technischer_User,dc=nausch,dc=org" method=128 Jul 17 12:06:33 vml000037 slapd[14264]: conn=1069 op=0 RESULT tag=97 err=53 text=unauthenticated bind (DN with no password) disallowed Jul 17 12:06:33 vml000037 slapd[14264]: conn=1069 op=1 UNBIND Jul 17 12:06:33 vml000037 slapd[14264]: conn=1069 fd=13 closed
Abfrage mit falschem Passwort
Zu guter letzt testen wir noch was passiert, wenn zwar der richtige User aber das falsche Passwort verwendet wurde.
# ldapsearch -W -x -b "dc=nausch,dc=org" "uid=django" \ -D "cn=Technischeruser,dc=nausch,dc=org" -LLL \ -H ldaps://openldap.dmz.nausch.org
Enter LDAP Password:
ldap_bind: Invalid credentials (49)
Auch dies wurde im Logfile des slapd-Daemon natürlich entsprechend protokolliert.
# less /var/log/ldap.log
Jul 17 12:10:08 vml000037 slapd[14264]: conn=1070 fd=13 TLS established tls_ssf=128 ssf=128 Jul 17 12:10:08 vml000037 slapd[14264]: conn=1070 op=0 BIND dn="cn=Technischer_User,dc=nausch,dc=org" method=128 Jul 17 12:10:08 vml000037 slapd[14264]: conn=1070 op=0 RESULT tag=97 err=49 text= Jul 17 12:10:08 vml000037 slapd[14264]: conn=1070 op=1 UNBIND Jul 17 12:10:08 vml000037 slapd[14264]: conn=1070 fd=13 closed
Der Error-Code 49 steht hierbei für LDAP_INVALID_CREDENTIALS, also ungültige Anmeldedaten.
Zugriffsrechte des (technischen User) beschränken
Da nicht jeder berechtigte Zugriff auf unseren OpenLDAP-Verzeichnisdienst auf alle Daten des DIT erhalten soll, werden wir nun die Berechtigungen noch feingranular setzen.
Kontrolle der existierenden Berechtigungen
Mit Hilfe des nachfolgenden Befehls kontrollieren wir erst einmal, welche Zugriffsrechte in den aktuell enthaltenen Benutzerstrukturen im DIT enthalten sind. Somit kann man sich einen Überblick verschaffen, welche Anpassungen ggf. im DIT anschließend noch vorzunehmen sind.
# ldapmodify -Y EXTERNAL -H ldapi:/// -f /etc/openldap/ldif/cn=\config_DbIndex.ldif
SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 modifying entry "olcDatabase={2}hdb,cn=config" [root@vml000037 ldif]# ldapsearch -W -x -D cn=config -b olcDatabase={2}hdb,cn=config Enter LDAP Password: # extended LDIF # # LDAPv3 # base <olcDatabase={2}hdb,cn=config> with scope subtree # filter: (objectclass=*) # requesting: ALL # # {2}hdb, config dn: olcDatabase={2}hdb,cn=config objectClass: olcDatabaseConfig objectClass: olcHdbConfig olcDatabase: {2}hdb olcDbDirectory: /var/lib/ldap olcSuffix: dc=nausch,dc=org olcRootDN: cn=Manager,dc=nausch,dc=org olcRootPW: {SSHA}lfeku/uaD4x1i$7n3931Le54U111 olcDbIndex: objectClass eq,pres olcDbIndex: ou,cn,mail,surname,givenname eq,pres,sub olcDbIndex: uidNumber,gidNumber,loginShell eq,pres olcDbIndex: uid,memberUid eq,pres,sub olcDbIndex: nisMapName,nisMapEntry eq,pres,sub olcDbIndex: uniqueMember eq,pres # search result search: 2 result: 0 Success # numResponses: 2 # numEntries: 1
Definition der neuen Berechtigungen
Bevor wir nun mit Hilfe einer LDIF-Datei die Benutzerrechte anpassen, machen wir uns erst einmal Gedanken, wie diese nun genau abgestuft sein sollen.
Attribute: „Passwort“
Folgende Felder im DIT sollen für einzelne Benutzer mit unterschiedlicher Berechtigung entweder lesend, schreibend oder nicht zugegriffen werden, können:
- userPassword,
- shadowLastChange,
- shadowMax und
- shadowWarning.
Folgende Tabelle definiert die unterschiedlichen Berechtigungsklassen.
Zugriffsformulierung | Benutzer | Zugriffsberechtigung |
---|---|---|
by self write | self (selbst) | schreiben |
by dn=„cn=Manager,dc=nausch,dc=org“ write | Manager | schreiben |
by dn=„cn=Technischeruser,dc=nausch,dc=org“ read | Ersatzbenutzer | lesen |
by anonymous auth | anonymous | authentifizieren |
by * none | alle anderen | keinerlei Rechte |
Für die Konfiguration benötigen wir hierzu eine olc1)-Directive, die für obige Tabelle wie folgt aussieht (zur besseren Lesbarkeit hier umgebrochen!).
olcAccess: {0}to attrs=userPassword,shadowLastChange,shadowMax,shadowWarning by self write by dn="cn=Manager,dc=nausch,dc=org" write by dn="cn=Technischeruser,dc=nausch,dc=org" read by anonymous auth by * none
Zugriff auf „Manager“
Auf den Eintrag „cn=Manager,dc=nausch,dc=org“ sollen folgende Berechtigungen gelten.
Zugriffsformulierung | Benutzer | Zugriffsberechtigung |
---|---|---|
by self write | self (selbst) | schreiben |
by * none | alle anderen | keinerlei Rechte |
Für die Konfiguration benötigen wir hierzu natürlich auch eine olc2)-Directive, die für obige Tabelle wie folgt aussieht.
olcAccess: {1}to dn="cn=Manager,dc=nausch,dc=org" by self write by * none
Zugriff auf „Technischeruser“
Auf den Eintrag „cn=Technischeruser,dc=nausch,dc=org“ sollen folgende Berechtigungen gelten.
Zugriffsformulierung | Benutzer | Zugriffsberechtigung |
---|---|---|
by self write | self (selbst) | schreiben |
by dn=„cn=Manager,dc=nausch,dc=org“ write | Manager | schreiben |
by * none | alle anderen | keinerlei Rechte |
Für die Konfiguration benötigen wir hierzu eine olc3)-Directive, die für obige Tabelle wie folgt aussieht (zur besseren Lesbarkeit hier umgebrochen!).
olcAccess: {2}to dn="cn=Technischeruser,dc=nausch,dc=org" by self write by dn="cn=Manager,dc=nausch,dc=org" write by * none