Entwicklerhandbuch/LDAP: Unterschied zwischen den Versionen
K (hat „Delixs:Entwicklerhandbuch“ nach „Delixs:Entwicklerhandbuch/LDAP“ verschoben) |
(zurück) |
||
Zeile 522: | Zeile 522: | ||
---- | ---- | ||
<div align="right">[[Delixs: | <div align="right">[[Delixs:Entwicklerhandbuch|zurück]] | [[Hauptseite]]</div> |
Version vom 24. April 2008, 19:18 Uhr
Diese Seite sollte nochmals überarbeitet werden. Eine Begründung befindet sich in der Regel unter Diskussion (oben). |
Leben mit Debian: Die Entwickler Richtlinien
Alles was programmiert wird, soll sich an diese Richtlinien halten. Einige Dinge wie die Paketerstellung & -verwaltung, sowie die Konfiguration des Installers müssen sich auch an die "Debian Policy" halten.
Arbeiten mit dem LDAP
die Struktur des LDAP
einen Dump erzeugen
Der Aufruf von "slapcat" liest den gesamten LDAP-Baum aus und zeigt diesen auf der Konsole im LDIF-Format an. Um diesen Dump zu speichern, muss er in eine LDIF-Datei umgelenkt werden
slapcat > Datei
einen Dump wieder einspielen
Zuerst den LDAP stoppen
/etc/init.d/ldap stop
Dann muss die Datenbank des LDAP geleert werden. Dazu alles in /var/lib/ldap löschen, die Datei DB_Config aber lassen!
cd /var/lib/ldap rm * bdb rm __db.* rm log* rm alock
Dann den Dump wieder einspielen
slapadd -l gesamt.ldif
Anm.: den LDAP wieder starten reicht nicht, weil etliche Dienste direkt vom LDAP abhängen und diese Änderungen zum Teil nicht mitbekommen. Also Server neu starten. Sollte es z.B. nur um Entwicklerarbeiten am LDAP gehen, dann reicht statt dessen
/etc/init.d/ldap start
Die folgenden Code-Beispiel dienen nur zur Demonstration des Zugriffs auf den LDAP, wie in der betreffenden Überschrift angegeben. Um die bestmögliche Verständlichkeit der Scripte zu gewährleisten, wurden keinerlei Raffinessen eingebaut. Um verschiedene Möglichkeiten zu demonstrieren, wurde (wenn möglich) für jedes Script eine andere Art der Schreibweise gewählt. Es ist also ratsam, auch einen Blick auf andere (ähnliche) Beispiele zu werfen. Alle angegebenen Scripte sind, so wie sie angegeben sind (korrekte Rechtevergabe und Linux-zeilenumbrüche vorausgesetzt), lauffähig. Es wird dabei vorausgesetzt, dass es den Eintrag für mmustermann mit der GID=101 gibt. Außerdem, dass die LDAP-Base 'dc=erg,c=de' ist. Die Scripte können unter diesem Vorausetzungen und Anpassung der LDAP-Base als Grundlage für eigene Experimente verwendet werden.
ausgewählte Attribute von einem Eintrag anzeigen
Es wird hier demonstriert, wie man von einem Eintrag ausgewählte Attribute ausliest. Der DN spielt dabei eine besondere Rolle. Er wird immer bereitgestellt. In diesem Beispiel wird eine Liste als Value von attrs übergeben. Da das nicht direkt geht, wird eine Referenz auf eine Liste übergeben. Deswegen die eckigen Klammern. Zur Ausgabe folgende Bemerkung: $mesg stellt ein Objekt dar, in der alle gefundenen Einträge (Entries) der Suche enthalten sind und stellen damit eine Liste dar. Hier wird aber nur Element gefunden bzw. ermittelt und deswegen wird mit $entry = $mesg->shift_entry; dieses eine Element aus der Liste geholt.
<source lang="perl">
- !/usr/bin/perl -w
use strict; use Net::LDAP;
my ($ldap, $mesg, $entry, @liste);
- wir verbinden uns mit den LDAP, sonst Abbruch mit Fehlermeldung
$ldap = Net::LDAP->new('127.0.0.1',version => 3) or die "$@"; $ldap->bind or die "konnte mich nicht mit dem Server verbinden";
- wir holen uns das Entry mit uid=mmustermann
$mesg = $ldap->search(base => 'o=SCHULE,dc=erg,c=de',
filter => 'uid=mmustermann', attrs => ['cn', 'sn', 'objectClass'] );
- wenn Fehlercode, dann das Script mit Fehlermeldung sterben lassen
$mesg->code and die $mesg->error;
- wir trennen uns vom LDAP
$ldap->unbind;
- in $mesg ist eine Liste von Entries, hier aber nur mit einem Element
$entry = $mesg->shift_entry;
- wir geben jetzt alle ermittelten Attribute aus
print 'dn: ', $entry->dn, "\n"; print 'cn: ', $entry->get_value('cn'), "\n"; # skalarer Kontext print 'sn: ', $entry->get_value('sn'), "\n"; # skalarer Kontext
- der Aufruf von get_value erfolgt im Listenkontext, der mehrere Values
@liste = $entry->get_value('objectClass'); foreach my $element (@liste) {
print 'objectClass: ', $element, "\n";
}
__END__ </source>
einen (kompletten) Eintrag anzeigen
Wenn alle Attribute ermittelt werden sollen, dann wird einfach 'attrs' nicht angegeben. Mit $entry->attributes erhalten wir die Liste der vorhandenen Attribute und können damit für jedes Attribut den Value dazu abfragen. Da die skalaren ebenso wie die multiplen Values korrekt behandelt werden sollen, wird hier $entry->get_value($attr) durch die Klammer im Listenkontext aufgerufen und immer als Schleife abgearbeitet.
<source lang="perl">
- !/usr/bin/perl -w
use strict; use Net::LDAP;
my ($ldap, $mesg, $entry);
- wir verbinden uns mit den LDAP, sonst Abbruch mit Fehlermeldung
$ldap = Net::LDAP->new('127.0.0.1',version => 3) or die "$@"; $ldap->bind or die "konnte mich nicht mit dem Server verbinden";
- wir holen uns das Entry mit uid=mmustermann
$mesg = $ldap->search(base => 'o=SCHULE,dc=erg,c=de',
filter => 'uid=mmustermann');
- wenn Fehlercode, dann das Script mit Fehlermeldung sterben lassen
$mesg->code and die $mesg->error;
- wir trennen uns vom LDAP
$ldap->unbind;
- in $mesg ist eine Liste von Entries, hier aber nur mit einem Element
$entry = $mesg->shift_entry;
- wir geben den DN des gefundenen Eintrags aus
print 'dn: ', $entry->dn, "\n"; # Sonderbehandlung, da DN kein normales Attribut
- für alle Attribute
foreach my $attr ($entry->attributes) {
# Achtung: wir rufen hier $entry->get_value im Listenkontext auf! foreach my $value ($entry->get_value($attr)) { print "$attr: $value", "\n"; }
}
__END__ </source>
Einträge suchen
Hier wird eine echte Suche über alle User angestossen, wobei das Filterkriterium 'gidNumber=101' ist. Es wird von allen gefundenen Einträgen einmal der DN (wird immer zurückgeliefert) und das Attribut 'uid' zurück gegeben. Weil hier nur ein Attribut für attrs übergeben wurde, wurde dieses gleich als String (also im skalaren Kontext) angegeben. Mit $mesg->entries erhalten wir die Liste der Entries und arbeiten die in einer Schleife ab.
<source lang="perl">
- !/usr/bin/perl -w
use strict; use Net::LDAP;
my ($ldap, $mesg, $entry);
- wir verbinden uns mit den LDAP, sonst Abbruch mit Fehlermeldung
$ldap = Net::LDAP->new('127.0.0.1',version => 3) or die "$@"; $ldap->bind or die "konnte mich nicht mit dem Server verbinden";
- wir holen uns die Logins (uid) von allen Lehrern (gidNumber=101)
$mesg = $ldap->search(base => 'o=SCHULE,dc=erg,c=de',
filter => 'gidNumber=101', attrs => 'uid');
- wenn Fehlercode, dann das Script mit Fehlermeldung sterben lassen
$mesg->code and die $mesg->error;
- wir trennen uns vom LDAP
$ldap->unbind;
- wir geben jetzt die Liste der Einträge aus (jeweils DN und uid)
foreach my $entry ($mesg->entries) {
print 'dn: ', $entry->dn, "\n"; print 'uid: ', $entry->get_value('uid'), "\n\n";
}
__END__ </source>
Attribute einem Eintrags hinzufügen
Im folgenden Script wird gezeigt, wie man einem Eintrag Attribute hinzufügt. Da dieses Mal nicht nur Einträge aus dem LDAP gelesen werden, sondern in den LDAP geschrieben wird, brauchen wir die entsprechenden Rechte. Dazu müssen wir das LDAP-Passwort ermitteln. Es werden in diesem Script folgende Fälle demonstriert: ein singlevalue-Attribut hinzu fügen (mail), ein multivalue-Attribute hinzufügen (telephoneNumber) und diesem Attribut dann eine weitere Telefonnummer hinzufügen.
<source lang="perl">
- !/usr/bin/perl -w
use strict; use Net::LDAP;
my ($ldap, $mesg, $pass);
- da wir in den LDAP schreiben, holen wir uns zuerst das LDAP-Passwort
open DATEI, '<', '/etc/ldap.secret'
or die "konnte ldap.secret nicht oeffnen, $!\n";
$pass = <DATEI>; chomp($pass); # falls Zeilenumbruch, diesen entfernen close DATEI;
- wir verbinden uns mit dem LDAP
$ldap = Net::LDAP->new('127.0.0.1', version => 3) or die "$@"; $ldap->bind( dn => 'cn=admin,dc=erg,c=de',
password => $pass ) or die "konnte mich nicht mit dem Server verbinden, $!\n";
- wir fügen dem Lehrer mmustermann seine Mailadresse hinzu
$mesg = $ldap->modify( 'uid=mmustermann,ou=LEHRER,o=SCHULE,dc=erg,c=de',
add => { mail => 'mmustermann@erg.slf.th.schule.de' } );
- wenn Fehlercode, dann das Script mit Fehlermeldung sterben lassen
$mesg->code and die $mesg->error;
- wir fügen dem Lehrer mmustermann seine 2 Telefonnummern hinzu
$mesg = $ldap->modify( 'uid=mmustermann,ou=LEHRER,o=SCHULE,dc=erg,c=de',
add => { telephoneNumber => ['0123 4567', '0123 88888'] } );
- wenn Fehlercode, dann das Script mit Fehlermeldung sterben lassen
$mesg->code and die $mesg->error;
- wir fügen dem Lehrer mmustermann eine weitere Telefonnummern hinzu
$mesg = $ldap->modify( 'uid=mmustermann,ou=LEHRER,o=SCHULE,dc=erg,c=de',
add => { telephoneNumber => ['0123 99999'] } );
- wenn Fehlercode, dann das Script mit Fehlermeldung sterben lassen
$mesg->code and die $mesg->error;
- wir trennen uns vom LDAP
$ldap->unbind;
__END__ </source>
Attribute eines Eintrags ändern
In diesem Programm wird demonstriert, wie man ein singlevalue-Attribut ändert und (als Vorgriff auf den übernächsten Punkt) wie man ein Value eines multivalue-Attribus ändert.
<source lang="perl">
- !/usr/bin/perl -w
use strict; use Net::LDAP;
my ($ldap, $mesg, $pass);
- da wir in den LDAP schreiben, holen wir uns zuerst das LDAP-Passwort
open DATEI, '<', '/etc/ldap.secret'
or die "konnte ldap.secret nicht oeffnen, $!\n";
$pass = <DATEI>; chomp($pass); # falls Zeilenumbruch, diesen entfernen close DATEI;
- wir verbinden uns mit dem LDAP
$ldap = Net::LDAP->new('127.0.0.1', version => 3) or die "$@"; $ldap->bind( dn => 'cn=admin,dc=erg,c=de',
password => $pass ) or die "konnte mich nicht mit dem Server verbinden, $!\n";
- wir ändern dem Lehrer mmustermann seine Mailadresse
$mesg = $ldap->modify( 'uid=mmustermann,ou=LEHRER,o=SCHULE,dc=erg,c=de',
replace => { mail => 'mmustermann@reinhold-gymnasium.de' } );
- wenn Fehlercode, dann das Script mit Fehlermeldung sterben lassen
$mesg->code and die $mesg->error;
- das Ändern von Werten von multivalue-Attributen muss über Löschen und erneutes
- Eintragen realisiert werden. Das geht auch auf einen Ritt (Vorgriff auf übernächsten Punkt)
- wir ändern von dem Lehrer mmustermann eine seiner Telfonnummern
$mesg = $ldap->modify( 'uid=mmustermann,ou=LEHRER,o=SCHULE,dc=erg,c=de',
changes => [ delete => [ telephoneNumber => '0123 88888' ], add => [ telephoneNumber => '0123 77777' ] ]);
- wenn Fehlercode, dann das Script mit Fehlermeldung sterben lassen
$mesg->code and die $mesg->error;
- wir trennen uns vom LDAP
$ldap->unbind;
__END__ </source>
Attribute eines Eintrags löschen
In diesem Programm wird demonstriert, wie man ein singlevalue-Attribut löscht, wie man ein Value eines multivalue-Attribus löscht und wie man alle (noch vorhandenen) Values eines multivalue-Attributs löscht.
<source lang="perl">
- !/usr/bin/perl -w
use strict; use Net::LDAP;
my ($ldap, $mesg, $pass);
- da wir in den LDAP schreiben, holen wir uns zuerst das LDAP-Passwort
open DATEI, '<', '/etc/ldap.secret'
or die "konnte ldap.secret nicht oeffnen, $!\n";
$pass = <DATEI>; chomp($pass); # falls Zeilenumbruch, diesen entfernen close DATEI;
- wir verbinden uns mit dem LDAP
$ldap = Net::LDAP->new('127.0.0.1', version => 3) or die "$@"; $ldap->bind( dn => 'cn=admin,dc=erg,c=de',
password => $pass ) or die "konnte mich nicht mit dem Server verbinden, $!\n";
- wir löschen vom Lehrer mmustermann seine Mailadresse
$mesg = $ldap->modify( 'uid=mmustermann,ou=LEHRER,o=SCHULE,dc=erg,c=de',
delete => 'mail' );
- wenn Fehlercode, dann das Script mit Fehlermeldung sterben lassen
$mesg->code and die $mesg->error;
- wir löschen dem Lehrer mmustermann eine seiner Telefonnummern
$mesg = $ldap->modify( 'uid=mmustermann,ou=LEHRER,o=SCHULE,dc=erg,c=de',
delete => { telephoneNumber => '0123 99999' } );
- wenn Fehlercode, dann das Script mit Fehlermeldung sterben lassen
$mesg->code and die $mesg->error;
- wir löschen dem Lehrer mmustermann seine (restlichen) Telefonnummern
$mesg = $ldap->modify( 'uid=mmustermann,ou=LEHRER,o=SCHULE,dc=erg,c=de',
delete => { 'telephoneNumber'=> [] } );
- wenn Fehlercode, dann das Script mit Fehlermeldung sterben lassen
$mesg->code and die $mesg->error;
- wir trennen uns vom LDAP
$ldap->unbind;
__END__ </source>
Kombination von Hinzufügen, Ändern und Löschen von Attributen
Im folgenden Beispiel wird gezeigt, wie man add, replace und delete in einem LDAP-Zugriff kombiniert. Es wird hier vorausgesetzt, das für den Lehrer 'mmustermann' als Mailadresse 'mmustermann@erg.slf.th.schule.de' angegeben ist und das telephoneNumber leer ist.
<source lang="perl">
- !/usr/bin/perl -w
use strict; use Net::LDAP;
my ($ldap, $mesg, $pass);
- da wir in den LDAP schreiben, holen wir uns zuerst das LDAP-Passwort
open DATEI, '<', '/etc/ldap.secret'
or die "konnte ldap.secret nicht oeffnen, $!\n";
$pass = <DATEI>; chomp($pass); # falls Zeilenumbruch, diesen entfernen close DATEI;
- wir verbinden uns mit dem LDAP
$ldap = Net::LDAP->new('127.0.0.1', version => 3) or die "$@"; $ldap->bind( dn => 'cn=admin,dc=erg,c=de',
password => $pass ) or die "konnte mich nicht mit dem Server verbinden, $!\n";
- wir bearbeiten den Lehrer mmustermann
$mesg = $ldap->modify( 'uid=mmustermann,ou=LEHRER,o=SCHULE,dc=erg,c=de',
changes => [ add => [ telephoneNumber => ['0123 88888', '0123 77777'] ], replace => [ homeDirectory => '/home/muster' ], replace => [ loginShell => '/bin/false' ], delete => [ mail => 'mmustermann@erg.slf.th.schule.de'] ] );
- wenn Fehlercode, dann das Script mit Fehlermeldung sterben lassen
$mesg->code and die $mesg->error;
- wir trennen uns vom LDAP
$ldap->unbind;
__END__ </source>
Einträge aus einem LDIF-File lesen und in den LDAP schreiben
Es soll im folgenden Beispiel gezeigt werden, wie man Daten in den LDAP schreibt. Dabei wird folgende Situation angenommen und durch dieses Beispiel realisiert. Ein Server ist neu aufgesetzt (hier ein Arktur 4rc6) und es sollen die Daten der User einer alten Beta-Version übernommen werden. Das bedeutet, dass Schema für die User ist nicht das gleiche (hat sich bei der Version beta40 geändert). Es wird weiter angenommen, dass sich die Windows-Domäne geändert hat und ebenso hat sich (z.B. wegen Schulzusammenschließung) der Schulname geändert und damit auch die LDAP-Base. Es sollen deshalb nur die Daten der User aus dem LDIF-File ausgelesen werden, die auf dem neuen Server auch sinnvoll verwendet werden können. Alle anderen Daten werden entweder ermittelt, neu gesetzt oder generiert.
<source lang="perl">
- !/usr/bin/perl
use strict; use Net::LDAP; use Net::LDAP::LDIF; use MIME::Base64;
my ($ldif, $entry, $base, $domain, $pass, %user, $vname, $nname, $klasse, @user, $ldap, $mesg);
- ================== das Einlesen des LDIF-Files ========================
- wir erstellen das LDIF-Objekt zum Einlesen
$ldif = Net::LDAP::LDIF->new( 'dump03.ldif', "r", onerror => 'undef' );
while ( not $ldif->eof() ) {
$entry = $ldif->read_entry();
if ( $ldif->error() ) { print "Error msg: $ldif->error() \n"; print "Error lines: $ldif->error_lines() \n\n"; } else { # den (System-)User games brauchen wir nicht if ( defined($entry->get_value('memberUid')) and $entry->get_value('memberUid') eq 'games') { next; } # einen User erkennen wir nun an "gidNumber: 100 oder 101 oder 102" if ( defined($entry->get_value('gidNumber')) and ( ( $entry->get_value('gidNumber') == 100 ) or ( $entry->get_value('gidNumber') == 101 ) or ( $entry->get_value('gidNumber') == 102 ) ) ) {
# wir holen uns: Login, 3 Passworte, Uid, Gid, GECOS, Home, Shell, Sid my %user = (); # wird ein anonymer Hash $user{uid} = $entry->get_value('uid'); $user{userPassword} = $entry->get_value('userPassword'); # noch encodieren! $user{sambaLMPassword} = $entry->get_value('sambaLMPassword'); $user{sambaNTPassword} = $entry->get_value('sambaNTPassword'); $user{uidNumber} = $entry->get_value('uidNumber'); $user{gidNumber} = $entry->get_value('gidNumber'); $user{gecos} = $entry->get_value('gecos'); $user{homeDirectory} = $entry->get_value('homeDirectory'); $user{loginShell} = $entry->get_value('loginShell'); $user{sambaSID} = $entry->get_value('sambaSID');
# diese Daten kommen als anonymer Hash in die Liste @user push @user, \%user; } # Ende von if } # Ende von else
} # Ende von while
- wir zerstören das LDIF-Objekt
$ldif->done;
- ================== ein paar Daten vom LDAP und verbinden ==============
- wir geben hier die neue LDAP-Base und die neue Domäne vor
$base = 'dc=erg,c=de'; $domain = 'SCHULE';
- da wir in den LDAP schreiben, holen wir uns das LDAP-Passwort
open DATEI, '<', '/etc/ldap.secret' or die "konnte ldap.secret nicht oeffnen, $!\n"; $pass = <DATEI>; chomp($pass); # falls Zeilenumbruch, diesen entfernen close DATEI;
- wir verbinden uns mit dem LDAP
$ldap = Net::LDAP->new('127.0.0.1', version => 3) or die "$@"; $ldap->bind( dn => "cn=admin,$base", password => $pass )
or die "konnte mich nicht mit dem Server verbinden, $!\n";
foreach my $person (@user) {
my %user = %{$person}; # die eingelesenen Attribute stehen zur Verfügung
# ================== wir bauen ein paar fehlende Attribute ==============
# wir bauen uns jetzt den neuen DN if ($user{gidNumber} == 100) { $user{dn} = "uid=$user{uid},ou=PLATZNUTZER,o=$domain,$base"; } elsif ($user{gidNumber} == 101) { $user{dn} = "uid=$user{uid},ou=LEHRER,o=$domain,$base"; } elsif ($user{gidNumber} == 102) { $user{dn} = "uid=$user{uid},ou=SCHUELER,o=$domain,$base"; }
# wir zerlegen den Eintrag von GECOS, da Vorname bzw. Name gebraucht wird ($vname, $nname, $klasse) = $user{gecos} =~ /^(.*) ([^, ]*),(.*)$/;
# das User-Passwort ist im LDIF-File uuencodiert, also decodieren wir $user{userPassword} = &MIME::Base64::decode( $user{userPassword} );
# wir brauchen die aktuelle Zeit $user{currenttime} = time();
# ================== das Eintragen der User in den LDAP =================
$mesg = $ldap->add( dn => $user{dn}, attr => [ objectClass => [ qw(top posixAccount shadowAccount person inetOrgPerson sambaSamAccount) ], uid => $user{uid}, cn => "$vname $nname", sn => $nname, uidNumber => $user{uidNumber}, gidNumber => $user{gidNumber}, homeDirectory => $user{homeDirectory}, gecos => $user{gecos}, loginShell => $user{loginShell}, shadowLastChange => int($user{currenttime} / 3600 / 24), shadowMin => 0, shadowMax => 10000, sambaSID => $user{sambaSID}, displayName => $user{gecos}, userPassword => $user{userPassword}, sambaLMPassword => $user{sambaLMPassword}, sambaNTPassword => $user{sambaNTPassword}, sambaPwdLastSet => $user{currenttime}, sambaPwdCanChange => $user{currenttime}, sambaPwdMustChange => $user{currenttime} + int($user{currenttime} / 3600 ) ] # end attr ); # end $ldap->add
# wir geben noch eine Meldung auf der Konsole ab unless ($mesg->code) { # wenn es keinen Fehlercode gab print "Added $user{dn} \n"; } else { # wenn es einen Fehlercode gab print "Return code: ", $mesg->code; print "\tMessage: ", $mesg->error_name; print " :", $mesg->error_text; print "MessageID: ", $mesg->mesg_id; print "\tDN: ", $mesg->dn; }
} # end foreach
- wir trennen uns vom LDAP
$ldap->unbind;
__END__ </source>