LDAP Objekt-Attribute schreiben
Verzeichnisobjekte bestehen aus einer Menge von Attributen: Dies sind die eigentlichen Daten, die bezogen auf das betreffende Objekt im Verzeichnis gespeichert werden. Es müssen nicht alle Attribute eines Objektes auch wirklich mit Daten gefüllt sein, und viele dieser Attribute erlauben es, mehrere Werte in einer Art Menge oder Array abzuspeichern.
Um Verzeichnisattribute auszulesen, kann man sich verschiedener Techniken
bedienen. Die notwendigen Grundlagen werden in den folgenden Abschnitten
mit Beispielen erläutert:
Attribut-Bezeichnungen
Wenn man auf die Eigenschaften von LDAP-Objekten zugreifen will, muss man die Bezeichnungen der entsprechenden Attribute kennen. Die Menge aller Attribute, die in einem Objek gespeichert werden können, wird im Schema des betreffenden LDAP-Servers gespeichert.
Die Bezeichnungen für die Atribute können je nach Verzeichnisdienst sehr verschieden sein - auch die Anzahl der möglichen Attribute varriert stark. Hier hilft nur ein Blick in die jeweilige Dokumentation oder die Verwendung eines leistungsfähigen LDAP Browsers, der die möglichen Attribute eines konkreten Verzeichnisobjektes aus dem Schema auslesen und anzeigen kann (ein Browser, der dies beherrscht, wäre z.B. LEX - The LDAP Explorer).
Für einige wichtige Objektklassen im Active Directory und für Exchange 5.5-Verzeichnisse habe ich mich bemüht, diejenigen Attribute zu dokumentieren, mit denen man in den grafischen Administrations-Utilities umgeht:
| Attribute für Active DirectoryUser |
| Attribute für Active DirectoryGruppen |
| Attribute für Active DirectoryKontakte |
| Attribute für Exchange 5.5 Mailboxen |
Wenn man die Attribut-Namen eines Objektes nicht kennt, so hat man natürlich die Möglichkeit, das Schema des betreffenden Verzeichnis-Servers auszulesen, die entsprechenden Einträge für die Objektklasse herauszufinden und dort in den Eigenschaften abzulesen, welche Attribute für ein bestimmtes Objekt gespeichert sein könnten.
Es gibt jedoch auch eine Möglichkeit, per Skript und ohne Zugriff auf das Schema die Namen aller Attribute herauszufinden, die bei einem konkreten Objekt gerade explizit gesetzt sind und die nicht als sogenannte "Operational Attributes" behandelt werden. Lesen Sie dazu den SelfADSI Thema "Alle Attribute eines Objekts lesen".
Änderungen mit SetInfo ins Verzeichnis schreiben
Wir werden mehrere Methoden besprechen, mit denen man Attributwerte für ein LDAP-Verzeichnisobjekt schreiben kann. Welchen davon auch immer Sie benutzen wollen, sie müssen stets die Änderungen dem Verzeichnis explizit als Schreiboperation übergeben ('commit'). Ansonsten haben Sie lediglich Ihren lokalen Attribute-Cache geändert, ohne Auswirkungen auf den Verzeichnis-Server selbst:
Set obj = GetObject("LDAP://dc1.cerrotorre.de/cn=PFoeckel,cn=Users,dc=cerrotorre,dc=de")
.
. hier werden irgendwelche Werte geändert...
.
.
obj.SetInfo 'so werden die Änderungen zurück ins Verzeichnis geschrieben
Attribute schreiben als ADSI-Objekteigenschaft
Dies ist die einfachste Methode, um ein Attribut für eine LDAP-Objekte zu schreiben. Voraussetzung hierfür ist, dass man einen LDAP Bind für das betreffende Objekt durchgeführt hat. Entweder man sich mit dem Objekt selbst verbunden, oder man erhält die Verbindung zum Objekt, indem man den Bind-Vorgang für den übergeordneten Container durchgeführt hat, und dann in einer Schleiffe im Script die darin enthaltenen Objekte durchgeht.
Normale Attribute können oft direkt als Objekt-Eigenschaft angesprochen werden, der Attribut-Name wird dann durch einen Punkt getrennt hinter dem Objekt-Namen angegeben - so hat man Zugriff auf den Attribut-Wert:
WScript.Echo obj.displayName 'den Anzeigenamen ausgeben
obj.displayName = "Foeckeler, Philipp" 'einen neuen Anzeigenamen setzen
obj.SetInfo
WScript.Echo obj.displayName 'den Anzeigenamen nochmal ausgeben
obj.sn = "Foeckeler" 'wir können mehrere Attribute auf einmal setzen
obj.givenName = "Philipp"
obj.mail = obj.givenName & "." & obj.sn & "@cerrotorre.de"
obj.SetInfo 'den abschließenden commit nicht vergessen!
WScript.Echo obj.mail
Set ou = GetObject("LDAP://dc1.cerrotorre.de/cn=Users,dc=cerrotorre,dc=de")
For Each obj In ou
if (len(obj.givenName) <> 0) and (len(obj.sn) <> 0) then
obj.mail = obj.givenName & "." & obj.sn & "@cerrotorre.de"
WScript.Echo obj.mail
end if
Next
Diese Syntax verleitet dazu, die so verwendeten Attribute mit den API-Properties zu verwechseln. Diese Properties werden nämlich tatsächlich ausschließlich über die Schreibweise "object.property" zugegriffen. Es handelt sich bei den API-Properties jedoch nicht um Attribute aus dem LDAP-Verzeichnis, sondern um Objekt-Eigenschaften, die die ADSI-Schnittstelle zur Verfügung stellt, z.B. die Eigenschaften ADSPath, Class, Parent und Name. Lesen Sie mehr über diese Properties im Abschnitt "API-Properties von ADSI-Objekten" hier im SelfADSI-Tutorial.
Attribute schreiben mit Put
In einigen Fällen ist es nicht möglich, auf ein LDAP-Attribut einfach als Objekteigenschaft mit der Syntax "object.attributname" zuzugreifen. Denn es könnte sein, dass im Attributnamen ein Minus-Zeichen enthalten ist, und dann kann der Script-Interpreter nicht mehr entscheiden, ob Sie mit dem Ausdruck
user.msRADIUS-FramedIpv6Prefix = "2001:1638:1899::/48"
einen Attribut-Namen "msRADIUS-FramedIpv6Prefix" oder ob sie das Ergebnis einer Subtraktion zwischen mit den Werten "user.msRADIUS" und "FramedIpv6Prefix" ausgeben lassen wollen.
Eine andere Schwierigkeit tritt dann auf, wenn der Variablen-Name selbst wiederum nicht konstant ist.
In diesen Fällen sollten Sie die ADSI-Methode Put anwenden:
WScript.Echo obj.displayName 'get the display name
obj.Put "displayName", "Foeckeler, Philipp" 'einen neuen Anzeigenamen setzen
obj.SetInfo
WScript.Echo obj.displayName 'den Anzeigenamen nochmal ausgeben
obj.Put "sn", "Foeckeler" 'wir können mehrere Attribute auf einmal setzen
obj.Put "givenName", "Philipp"
obj.Put "mail", obj.givenName & "." & obj.sn & "@cerrotorre.de"
obj.SetInfo 'den abschließenden commit nicht vergessen!
WScript.Echo obj.mail
Set ou = GetObject("LDAP://dc1.cerrotorre.de/cn=Users,dc=cerrotorre,dc=de")
For Each obj In ou
if (len(obj.givenName) <> 0) and (len(obj.sn) <> 0) then
obj.Put "mail", obj.givenName & "." & obj.sn & "@cerrotorre.de"
WScript.Echo obj.mail
end if
Next
Etwas umständlicher.... aber denken Sie daran: Sie sind so auf der sicheren Seite, den dies ist der offizielle Weg, der in der ADSI-Schnittstellenbeschreibung angegeben ist.
Multivalue Attribute ändern mit PutEx
Sie sollten darauf achten, dass es sich bei einem Attribut, das Sie schreiben möchten, um einen Multivalue handeln könnte. Das bedeutet, dass in einem einzelnen Attribut ein Array von mehreren Werten gespeichert sein kann. Es muß eine Möglichkeit geben, Werte zu solch einem Array hinzuzufügen, einzelne Werte (aber nicht das gesamte Array) zu löschen, oder Werte in dem Array zu ersetzen. Die ADSI Methode Put ist für den Zugriff auf Multivalue Attribute nicht geeignet - wir müsen hier eine andere Funktion verwenden: PutEx.
object.PutEx <operation identifier>, <attribute name>, <array of attributes>
Im dritten Parameter muß stets ein Array übergeben werden, selbst wenn Sie die Funktion eigenlich mit einem Einzelwert aufrufen wollen. In diesem Fall müssen Sie einfach ein Array erzeugen, das nur aus einem Wert besteht.
Zusätzlich dazu benötigt
PutEx einen Paramete, der dir Art der Operation festlegt, mit der das betreffende Multivalue Attribut zugegriffen wird:
| ADS_PROPERTY_CLEAR | = 1 | Dies löscht das gesamte Attribut, es brauchen im dritten Parameter des PutEx-Aufrufes keine Werte angegeben werden (tatsächlich muß hier ein LEERES Array als Parameter übergeben werden) |
| ADS_PROPERTY_UPDATE | = 2 | Dies ersetzt das gesamte Attribut mit dem Array, das mit dem PutEx-Aufruf als Parameter übergeben wurde. Die alten Inhalte des betreffenden Attributes gehen dadurch verloren! |
| ADS_PROPERTY_APPEND | = 3 | Dies fügt einen oder mehrere Attribut-Werte hinzu, die der PutEx-Funktion in einem Array übergeben werden müssen. |
| ADS_PROPERTY_DELETE | = 4 | Dies löscht einen oder mehrere Attribut-Werte, die der PutEx-Funktion in einem Array übergeben werden müssen. |
Hier sind einige Beispiele für jeden Schreibzugriff auf ein Multivalue-Attribut:
Set obj = GetObject("LDAP://dc1.cerrotorre.de/cn=Domain Admins,cn=Users,dc=cerrotorre,dc=de")
Const ADS_PROPERTY_CLEAR=1
Const ADS_PROPERTY_UPDATE=2
Const ADS_PROPERTY_APPEND=3
Const ADS_PROPERTY_DELETE=4
obj.putex ADS_PROPERTY_UPDATE, "member", _
array("cn=Marten,cn=Users,dc=cerrotorre,dc=de", _
"cn=Michael,cn=Users,dc=cerrotorre,dc=de", _
"cn=Sandra,cn=Users,dc=cerrotorre,dc=de")
obj.setinfo
'Nun sind lediglich Sandra, Marten und Michael Gruppenmitglieder, egal wer vorher in der Gruppe war
obj.putex ADS_PROPERTY_APPEND, "member", array("cn=Juli,cn=Users,dc=cerrotorre,dc=de")
obj.setinfo
'Wir haben Juli der Gruppen hinzugefügt, es gibt nun vier Mitglieder... Sandra, Juli, Marten and Michael
'Beachten Sie, dass wir hier ein Array mit nur einem Wert übergeben!
obj.putex ADS_PROPERTY_DELETE, "member", array("cn=Michael,cn=Users,dc=cerrotorre,dc=de", "cn=Marten,cn=Users,dc=cerrotorre,dc=de")
obj.setinfo
'Momentan in der Gruppe: Sandra and Juli
obj.putex ADS_PROPERTY_CLEAR, "member", array()
obj.setinfo
'Die Gruppe ist nun leer
'Beachten Sie, dass wir auch in diesem Fall ein (leeres) Array als Parameter übergeben
Sie sollten sich stets der Tatsache bewußt sein, dass ein Fehler bei einem einzigen Array-Wert dazu führt, dass der gesamte PutEx-Befehl nicht ausgeführt wird:
Set obj = GetObject("LDAP://dc1.cerrotorre.de/cn=Domain Admins,cn=Users,dc=cerrotorre,dc=de")
Const ADS_PROPERTY_CLEAR=1
Const ADS_PROPERTY_UPDATE=2
Const ADS_PROPERTY_APPEND=3
Const ADS_PROPERTY_DELETE=4
obj.putex ADS_PROPERTY_UPDATE, "member", _
array("cn=Marten,cn=sers,dc=cerrotorre,dc=de", _
"cn=Michael,cn=Users,dc=cerrotorre,dc=de", _
"cn=Sandra,cn=Users,dc=cerrotorre,dc=de")
obj.setinfo
'Wegen einem Schreibfehler eine EINEM der Werte wird KEINER der Array-Werte ins Attribut geschrieben (=>Laufzeitfehler)
obj.putex ADS_PROPERTY_DELETE, "member", array("cn=Michael,cn=Users,dc=cerrotorre,d=de", "cn=Marten,cn=Users,dc=cerrotorre,dc=de")
obj.setinfo
'Wegen einem Schreibfehler eine EINEM der Werte wird KEINER der Array-Werte aus dem Attribut entfernt (=>Laufzeitfehler))
ADSI Reference im MSDN: PutEx()
Spezielle Attribut-Datentypen
Attribute werden unter verschiedenen Datentypen im jeweiligen Verzeichnis gespeichert. Dieser Datentyp wird auch "Attribut Syntax" genannt. Und beim Auslesen von Attributen per Skript spielt es natürlich eine Rolle, ob es sich dabei um Strings, Integer, Longs, Datumsformate oder gar um Hex-Werte handelt. Denn während die Handhabung eines Strings oder Integers und auch die Umwandlung zwischen diesen Datentypen trivial sein mag, so kann es doch erhebliche Schwierigkeiten machen, wenn man aus einem Objektattribut z.B. Uhrzeit- und Datumsformate oder reine binäre Rohdaten auslesen, darstellen und vergleichen muss.
Wenn man mit einem LDAP Bind eine Verbindung zu einem Verzeichnisobjekt hergestellt hat und dessen Attribute ausliest, bekommt man mit herkömmlichen Methoden keine Informationen über den Datentyp - wenn man allerdings die etwas umständlichere ADSI-Funktion GetPropertyItem und einen speziellen Umgang mit dem Property Cache verwendet, dann wird von ADSI die Information zurückgegeben, um was für einen Datentyp es sich handelt. Dementsprechend kann man dann im Skript beim Auslesen der Attribute darauf reagieren. Ein Beispiel für diese Technik können Sie im Artikel "Alle Attribute eines Objektes auslesen" hier im SelfADSI Tutorial untersuchen.
Interessante Abschnitte im SelfADSI-Tutorial zu Attribut-Datentypen:
Objekt Attribute des Typs Octect String: "Octet-String" ist eine LDAP-Syntax und damit ein standardisierter Datetyp für reine Hexadezimalwerte. Den entsprechenden Datentyp Byte[] kennt z.B: ein VBScript jedoch nicht: Man hat Schwierigkeiten, die vom Verzeichnis empfangenen Daten dieses Typs z.B. in einen String anzuzeigen. Lesen Sie in diesem Abschnitt, wie es trotzdem funktioniert und man mit Octet-String-Attributen umgeht. |
|
Objekt Attribute des Typs Provider Specific: Wenn ein LDAP-Server diesen Datentyp zurückgibt, heißt das soviel wie "kann vom Skript aus nicht genau entschieden werden". Es ist schwierig, diese Attribute auszulesen. Hier hilft nur ein Blick ins Schema des betreffenden Verzeichnisdiensten und eine spezielle Methode, um die Daten in ein für eine Skript brauchbares Format umzuwandeln. |
|
| Das Verzeichnis-Schema: Allgemeine Infos über Attribut-Datentypen und Attribut-Syntax und deren Definition im Verzeichnisschema. |

