Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
centos:ldap_c7:tecbind [17.07.2015 06:03. ] – angelegt django | centos:ldap_c7:tecbind [22.07.2019 15:03. ] (aktuell) – Externe Bearbeitung 127.0.0.1 | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
- | ====== | + | ====== |
+ | {{: | ||
+ | Als wesentliche Erweiterung unseres Open-LDAP-Servers werden wir nun unseren Daemon so konfigurieren, | ||
+ | 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 **[[centos: | ||
+ | |||
+ | ==== 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**) // | ||
+ | |||
+ | Wie auch schon beim Erstellen des **[[centos: | ||
+ | |||
+ | Zur Generierung dieses Passwortes mit der Verschlüsselungsmethode SSHA - entsprechend einem SHA-1 Algorithmus (FIPS 160-1), verwenden wir wieder das Programm **/ | ||
+ | # / | ||
+ | |||
+ | New password: | ||
+ | | ||
+ | | ||
+ | |||
+ | Dieses gekryptete Passwort hinterlegen wir nun in einer passenden ldif-Datei. | ||
+ | # vim / | ||
+ | |||
+ | <file ldif / | ||
+ | # Anlegen eines technischen Users für die Anmeldung am Server (bind) | ||
+ | # https:// | ||
+ | |||
+ | dn: cn=Technischeruser, | ||
+ | cn: Technischeruser | ||
+ | objectClass: | ||
+ | objectClass: | ||
+ | objectClass: | ||
+ | userPassword: | ||
+ | </ | ||
+ | |||
+ | Zum Importieren unseres **DITs** verwenden wir nun folgenden Aufruf. Das Passwort nach dem wir hier gefragt werden, haben wir im Kapitel **[[centos: | ||
+ | # ldapadd -W -x -D cn=Manager, | ||
+ | |||
+ | Enter LDAP Password: | ||
+ | adding new entry " | ||
+ | |||
+ | ==== Abfragetest ==== | ||
+ | Anschließend überprüfen wir, ob die Daten unseres unser **Technischeruser** im DIT richtig angelegt wurde. | ||
+ | |||
+ | # ldapsearch -W -x -b " | ||
+ | " | ||
+ | -H ldaps:// | ||
+ | |||
+ | Enter LDAP Password: | ||
+ | |||
+ | dn: cn=Technischeruser, | ||
+ | cn: Technischeruser | ||
+ | objectClass: | ||
+ | objectClass: | ||
+ | objectClass: | ||
+ | userPassword:: | ||
+ | |||
+ | Im Logfile des slapd-Daemon wird unsere erfolgreiche Abfrage entsprechend protokolliert. | ||
+ | # less / | ||
+ | |||
+ | Jul 17 09:43:05 vml000037 slapd[14264]: | ||
+ | Jul 17 09:43:06 vml000037 slapd[14264]: | ||
+ | Jul 17 09:43:06 vml000037 slapd[14264]: | ||
+ | Jul 17 09:43:06 vml000037 slapd[14264]: | ||
+ | Jul 17 09:43:06 vml000037 slapd[14264]: | ||
+ | Jul 17 09:43:06 vml000037 slapd[14264]: | ||
+ | Jul 17 09:43:06 vml000037 slapd[14264]: | ||
+ | Jul 17 09:43:06 vml000037 slapd[14264]: | ||
+ | Jul 17 09:43:06 vml000037 slapd[14264]: | ||
+ | |||
+ | ===== Deaktivierung des " | ||
+ | In unserer abgesicherten Umgebung sollen ausschließlich authentifizierte Abfragen und Zugriffe auf unseren OpenLADP-Server gestattet sein. Hierzu haben wir uns im vorherigem **[[centos: | ||
+ | |||
+ | ==== Konfiguration ==== | ||
+ | Damit unser Open-LDAP Daemon **__keine__** | ||
+ | |||
+ | Zum Setzen und Ändern der beiden Directiven legen wir uns nun wieder eine passende ldif-Datei an. | ||
+ | # vim / | ||
+ | |||
+ | <file ldif / | ||
+ | # Sperren des „anonymous bind“ und Authentifizierung erzwingen | ||
+ | # https:// | ||
+ | |||
+ | dn: cn=config | ||
+ | changetype: modify | ||
+ | add: olcDisallows | ||
+ | olcDisallows: | ||
+ | - | ||
+ | add: olcRequires | ||
+ | olcRequires: | ||
+ | </ | ||
+ | |||
+ | Wie bei der vorangegangenen Änderungen/ | ||
+ | # ldapmodify -W -x -D cn=config -f / | ||
+ | |||
+ | Enter LDAP Password: | ||
+ | |||
+ | modifying entry " | ||
+ | |||
+ | ==== 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 " | ||
+ | |||
+ | Enter LDAP Password: | ||
+ | |||
+ | < | ||
+ | objectClass: | ||
+ | cn: config | ||
+ | olcArgsFile: | ||
+ | olcIdleTimeout: | ||
+ | olcPidFile: / | ||
+ | olcReferral: | ||
+ | olcTimeLimit: | ||
+ | olcTLSCACertificateFile: | ||
+ | olcTLSCACertificatePath: | ||
+ | olcTLSCertificateFile: | ||
+ | olcTLSCertificateKeyFile: | ||
+ | olcTLSCipherSuite: | ||
+ | olcTLSDHParamFile: | ||
+ | olcTLSProtocolMin: | ||
+ | olcDisallows: | ||
+ | olcRequires: | ||
+ | |||
+ | Im Logfile des slapd-Daemon wird unsere erfolgreiche Abfrage entsprechend protokolliert. | ||
+ | # less / | ||
+ | |||
+ | < | ||
+ | Jul 17 11:40:01 vml000037 slapd[14264]: | ||
+ | Jul 17 11:40:01 vml000037 slapd[14264]: | ||
+ | Jul 17 11:40:01 vml000037 slapd[14264]: | ||
+ | Jul 17 11:40:01 vml000037 slapd[14264]: | ||
+ | Jul 17 11:40:01 vml000037 slapd[14264]: | ||
+ | Jul 17 11:40:01 vml000037 slapd[14264]: | ||
+ | Jul 17 11:40:01 vml000037 slapd[14264]: | ||
+ | Jul 17 11:40:01 vml000037 slapd[14264]: | ||
+ | |||
+ | === 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_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 // | ||
+ | |||
+ | == gültige Abfrage == | ||
+ | Nun wollen wir überprüfen, | ||
+ | |||
+ | # ldapsearch -W -x -b " | ||
+ | -D " | ||
+ | -H ldaps:// | ||
+ | |||
+ | Enter LDAP Password: | ||
+ | |||
+ | < | ||
+ | uid: django | ||
+ | cn: django | ||
+ | objectClass: | ||
+ | objectClass: | ||
+ | objectClass: | ||
+ | objectClass: | ||
+ | userPassword:: | ||
+ | | ||
+ | | ||
+ | shadowLastChange: | ||
+ | shadowMin: 0 | ||
+ | shadowMax: 99999 | ||
+ | shadowWarning: | ||
+ | loginShell: /bin/bash | ||
+ | uidNumber: 1000 | ||
+ | gidNumber: 1000 | ||
+ | homeDirectory: | ||
+ | gecos: django | ||
+ | |||
+ | </ | ||
+ | |||
+ | Im Logfile des slapd-Daemon wird unsere erfolgreiche Abfrage entsprechend protokolliert. | ||
+ | # less / | ||
+ | |||
+ | Jul 17 12:00:02 vml000037 slapd[14264]: | ||
+ | Jul 17 12:00:02 vml000037 slapd[14264]: | ||
+ | Jul 17 12:00:02 vml000037 slapd[14264]: | ||
+ | Jul 17 12:00:02 vml000037 slapd[14264]: | ||
+ | Jul 17 12:00:02 vml000037 slapd[14264]: | ||
+ | Jul 17 12:00:02 vml000037 slapd[14264]: | ||
+ | |||
+ | == Abfrage ohne Passwort == | ||
+ | Der Versuch, sich ohne Passwort anzumelden schlägt natürlich entsprechend fehl. | ||
+ | # ldapsearch -W -x -b " | ||
+ | -D " | ||
+ | -H ldaps:// | ||
+ | |||
+ | 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 / | ||
+ | |||
+ | Jul 17 12:06:33 vml000037 slapd[14264]: | ||
+ | Jul 17 12:06:33 vml000037 slapd[14264]: | ||
+ | Jul 17 12:06:33 vml000037 slapd[14264]: | ||
+ | Jul 17 12:06:33 vml000037 slapd[14264]: | ||
+ | Jul 17 12:06:33 vml000037 slapd[14264]: | ||
+ | Jul 17 12:06:33 vml000037 slapd[14264]: | ||
+ | |||
+ | == 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 " | ||
+ | -D " | ||
+ | -H ldaps:// | ||
+ | |||
+ | Enter LDAP Password: | ||
+ | |||
+ | ldap_bind: Invalid credentials (49) | ||
+ | |||
+ | Auch dies wurde im Logfile des slapd-Daemon natürlich entsprechend protokolliert. | ||
+ | # less / | ||
+ | |||
+ | Jul 17 12:10:08 vml000037 slapd[14264]: | ||
+ | Jul 17 12:10:08 vml000037 slapd[14264]: | ||
+ | Jul 17 12:10:08 vml000037 slapd[14264]: | ||
+ | Jul 17 12:10:08 vml000037 slapd[14264]: | ||
+ | Jul 17 12:10:08 vml000037 slapd[14264]: | ||
+ | |||
+ | Der Error-Code **[[http:// | ||
+ | **LDAP_INVALID_CREDENTIALS**, | ||
+ | |||
+ | ===== 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, | ||
+ | # ldapmodify -Y EXTERNAL -H ldapi:/// -f / | ||
+ | |||
+ | < | ||
+ | SASL username: gidNumber=0+uidNumber=0, | ||
+ | SASL SSF: 0 | ||
+ | modifying entry " | ||
+ | |||
+ | [root@vml000037 ldif]# ldapsearch -W -x -D cn=config -b olcDatabase={2}hdb, | ||
+ | Enter LDAP Password: | ||
+ | # extended LDIF | ||
+ | # | ||
+ | # LDAPv3 | ||
+ | # base < | ||
+ | # filter: (objectclass=*) | ||
+ | # requesting: ALL | ||
+ | # | ||
+ | |||
+ | # {2}hdb, config | ||
+ | dn: olcDatabase={2}hdb, | ||
+ | objectClass: | ||
+ | objectClass: | ||
+ | olcDatabase: | ||
+ | olcDbDirectory: | ||
+ | olcSuffix: dc=nausch, | ||
+ | olcRootDN: cn=Manager, | ||
+ | olcRootPW: {SSHA}lfeku/ | ||
+ | olcDbIndex: objectClass eq,pres | ||
+ | olcDbIndex: ou, | ||
+ | olcDbIndex: uidNumber, | ||
+ | olcDbIndex: uid, | ||
+ | olcDbIndex: nisMapName, | ||
+ | olcDbIndex: uniqueMember eq,pres | ||
+ | |||
+ | # search result | ||
+ | search: 2 | ||
+ | result: 0 Success | ||
+ | |||
+ | # numResponses: | ||
+ | # 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//, // | ||
+ | * **userPassword**, | ||
+ | * **shadowLastChange**, | ||
+ | * **shadowMax** und | ||
+ | * **shadowWarning**. | ||
+ | |||
+ | Folgende Tabelle definiert die unterschiedlichen Berechtigungsklassen. | ||
+ | |||
+ | ^ **Zugriffsformulierung** | ||
+ | | by self write | self (selbst) |schreiben | ||
+ | | by dn=„cn=Manager, | ||
+ | | by dn=„cn=Technischeruser, | ||
+ | | by anonymous auth | anonymous | authentifizieren | ||
+ | | by * none | //alle anderen// | ||
+ | |||
+ | Für die Konfiguration benötigen wir hierzu eine **olc**((**o**n-**l**ine **c**onfiguration))-Directive, | ||
+ | |||
+ | olcAccess: {0}to attrs=userPassword, | ||
+ | write by dn=" | ||
+ | write by dn=" | ||
+ | read by anonymous auth by * none | ||
+ | |||
+ | |||
+ | === Zugriff auf „Manager“ === | ||
+ | Auf den Eintrag " | ||
+ | |||
+ | ^ **Zugriffsformulierung** | ||
+ | | by self write | self (selbst) | schreiben | ||
+ | | by * none | //alle anderen// | ||
+ | |||
+ | Für die Konfiguration benötigen wir hierzu natürlich auch eine **olc**((**o**n-**l**ine **c**onfiguration))-Directive, | ||
+ | |||
+ | olcAccess: {1}to dn=" | ||
+ | |||
+ | === Zugriff auf „Technischeruser“ === | ||
+ | Auf den Eintrag " | ||
+ | |||
+ | ^ **Zugriffsformulierung** | ||
+ | | by self write | self (selbst) | schreiben | ||
+ | | by dn=„cn=Manager, | ||
+ | | by * none | //alle anderen// | ||
+ | |||
+ | Für die Konfiguration benötigen wir hierzu eine **olc**((**o**n-**l**ine **c**onfiguration))-Directive, | ||
+ | |||
+ | olcAccess: {2}to dn=" | ||
+ | write by dn=" | ||
+ | write by * none | ||
+ | |||
+ | |||
+ | === Zugriff auf „Group“ der Domäne === | ||
+ | Für die Gruppeneinträge unserer Domäne " | ||
+ | |||
+ | ^ **Zugriffsformulierung** | ||
+ | | by self write | self (selbst) |schreiben | ||
+ | | by dn=„cn=Manager, | ||
+ | | by dn=„cn=Technischeruser, | ||
+ | | by dn.exact, | ||
+ | | by * none | //alle anderen// | ||
+ | |||
+ | Für die Konfiguration benötigen wir hierzu auch noch eine **olc**((**o**n-**l**ine **c**onfiguration))-Directive, | ||
+ | olcAccess: {3}to dn.regex=" | ||
+ | write by dn=" | ||
+ | write by dn=" | ||
+ | read by dn.exact, | ||
+ | |||
+ | === Zugriff auf „People“ der Domäne === | ||
+ | Für die Personeneinträge unserer Domäne " | ||
+ | |||
+ | ^ **Zugriffsformulierung** | ||
+ | | by self write | self (selbst) |schreiben | ||
+ | | by dn=„cn=Manager, | ||
+ | | by dn=„cn=Technischeruser, | ||
+ | | by dn.exact, | ||
+ | | by * none | //alle anderen// | ||
+ | |||
+ | Für die Konfiguration benötigen wir hierzu auch noch eine **olc**((**o**n-**l**ine **c**onfiguration))-Directive, | ||
+ | olcAccess: {4}to dn.regex=" | ||
+ | write by dn=" | ||
+ | write by dn=" | ||
+ | read by dn.exact, | ||
+ | |||
+ | === Zugriff auf alle anderen Felder (ohne gesonderte Berechtigungen) der Domäne === | ||
+ | Auf alle sonstigen Felder im DIT sollen folgende Berechtigungen gelten. | ||
+ | |||
+ | ^ **Zugriffsformulierung** | ||
+ | | by self write | self (selbst) |schreiben | ||
+ | | by dn=„cn=Manager, | ||
+ | | by * none | //alle anderen// | ||
+ | |||
+ | Für die Konfiguration benötigen wir hierzu auch noch unseren letzten **olc**((**o**n-**l**ine **c**onfiguration))-Directive, | ||
+ | olcAccess: {5}to * by self write by dn.base=" | ||
+ | |||
+ | ==== Konfiguration ==== | ||
+ | Somit ergibt sich für die Konfiguration der Berechtigungen ein e LDIF-Datei mit folgendem Inhalt. | ||
+ | # vim / | ||
+ | <file ldif / | ||
+ | # setzen unterschiedlicher Berechtigungen im DIT unseres OpenLDAP-Servers | ||
+ | # https:// | ||
+ | |||
+ | dn: olcDatabase={2}hdb, | ||
+ | changetype: modify | ||
+ | replace: olcAccess | ||
+ | olcAccess: {0}to attrs=userPassword, | ||
+ | olcAccess: {1}to dn=" | ||
+ | olcAccess: {2}to dn=" | ||
+ | olcAccess: {3}to dn.regex=" | ||
+ | olcAccess: {4}to dn.regex=" | ||
+ | olcAccess: {5}to * by self write by dn.base=" | ||
+ | |||
+ | </ | ||
+ | |||
+ | Abschließend müssen wir nun nur noch mit nachfolgendem Befehl der Inhalt obiger LDIF-Datei im laufendem Betrieb des OpenLDAP-Servers in dessen Konfiguration hinzufügen. | ||
+ | # ldapmodify -Y EXTERNAL -H ldapi:/// -f / | ||
+ | |||
+ | SASL/ | ||
+ | SASL username: gidNumber=0+uidNumber=0, | ||
+ | SASL SSF: 0 | ||
+ | modifying entry " | ||
+ | |||
+ | ==== Abfragetest ==== | ||
+ | Zum Schluss fragen wir nun noch ab, ob die Berechtigungen richtig gesetzt wurden. | ||
+ | # ldapsearch -W -x -D cn=config -b olcDatabase={2}hdb, | ||
+ | |||
+ | Enter LDAP Password: | ||
+ | < | ||
+ | # | ||
+ | # LDAPv3 | ||
+ | # base < | ||
+ | # filter: (objectclass=*) | ||
+ | # requesting: ALL | ||
+ | # | ||
+ | |||
+ | # {2}hdb, config | ||
+ | dn: olcDatabase={2}hdb, | ||
+ | objectClass: | ||
+ | objectClass: | ||
+ | olcDatabase: | ||
+ | olcDbDirectory: | ||
+ | olcSuffix: dc=nausch, | ||
+ | olcRootDN: cn=Manager, | ||
+ | olcRootPW: {SSHA}lffku/ | ||
+ | olcDbIndex: objectClass eq,pres | ||
+ | olcDbIndex: ou, | ||
+ | olcDbIndex: uidNumber, | ||
+ | olcDbIndex: uid, | ||
+ | olcDbIndex: nisMapName, | ||
+ | olcDbIndex: uniqueMember eq,pres | ||
+ | olcAccess: {0}to attrs=userPassword, | ||
+ | y self write by dn=" | ||
+ | | ||
+ | olcAccess: {1}to dn=" | ||
+ | olcAccess: {2}to dn=" | ||
+ | " | ||
+ | olcAccess: {3}to dn.regex=" | ||
+ | by dn=" | ||
+ | | ||
+ | y * none | ||
+ | olcAccess: {4}to dn.regex=" | ||
+ | te by dn=" | ||
+ | | ||
+ | by * none | ||
+ | olcAccess: {5}to * by self write by dn.base=" | ||
+ | e by * read | ||
+ | |||
+ | # search result | ||
+ | search: 2 | ||
+ | result: 0 Success | ||
+ | |||
+ | # numResponses: | ||
+ | # numEntries: 1</ | ||
+ | |||
+ | ====== Links ====== | ||
+ | * **⇐ [[centos: | ||
+ | * **⇒ [[centos: | ||
+ | * **[[centos: | ||
+ | * **[[wiki: | ||
+ | * **[[http:// | ||
- | FIXME |