Mit diesem Beitrag möchte ich ein bereits auf Active-Directory-Faq.de erschienenes Thema noch einmal aufgreifen und erweitern. Im Einzelnen betrachte ich, wie man seltene oder selbstdefinierte AD-Attribute mit PowerShell setzen kann.
Im Artikel AD PowerShell Basics 1: New-ADUser wurde erklärt, wie man mit dem PowerShell Cmdlet New-ADUser einen neuen Nutzer im Active Directory anlegen kann. Außerdem wurde erläutert, wie dies automatisch aus einer CSV-Datei zu bewerkstelligen ist.
Index
Seltene AD Attribute
Für Standardfälle funktioniert das. Was passiert aber, wenn man beim Import AD-Attribute setzen möchte, für die das New-ADUser Cmdlet keinen Schalter anbietet? Beispiele für solche Attribute sind „roomNumber“ oder „otherTelephone“, aber auch selbstdefinierte Attribute.
Ich ergänze also die CSV-Datei testweise um die beiden Attribute:
Neue Attribute aufnehmen mit OtherAttributes
Wie bringe ich dem New-ADUser Cmdlet nun bei, die neuen Attribute zu berücksichtigen? Für solche Fälle gibt es den -OtherAttributes Schalter. Diesem muss man eine Hashtable übergeben. Das Script wird wie folgt geändert:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$import =Import-CSV "C:\ps\test2.csv" -Delimiter ";" foreach ($user in $import) { $otherAttributes = @{ roomNumber = $user.RoomNumber otherTelephone = $user.OtherTelephone } $password = $user.Password | ConvertTo-SecureString -AsPlainText -Force New-ADUser -Path "CN=Users,DC=test,DC=net" ` -Name $user.Name ` -GivenName $user.FirstName ` -Surname $user.LastName ` -AccountPassword $Password ` -ChangePasswordAtLogon $True ` -Enabled $True ` -OtherAttributes $otherAttributes } |
Die $otherAttributes-Variable beinhaltet die beiden Attribute als Key-Value-Pair. Führt man dieses Script aus, erscheinen die neuen Nutzer im AD und die Attribute sind korrekt gesetzt.
Fehlermeldungen, wenn Werte null sind
Alles gut? Leider nein. In Exports wird es immer wieder vorkommen, dass bestimmte Attribute nicht gesetzt sind. Neuer Testfall:
Die nun auftretende Fehlermeldung ist nicht gerade hilfreich:
Interessanterweise ändert sie sich, wenn man den unvollständigen Datensatz an die letzte Stelle kopiert:
Dann heißt es plötzlich:
Interessant. Die Werte dürfen also nicht null sein. Zwar werden die anderen Nutzer, unabhängig vom angezeigten Fehler, dennoch angelegt. Diese roten Meldungen nerven jedoch und verwirren mitunter.
Herausfiltern der leeren Werte
Zur Beseitigung bleibt nichts Anderes übrig, als auf null zu prüfen. Ich mache das Script etwas robuster:
1 2 3 4 5 6 7 8 9 |
$otherAttributes = @{ if(-not [System.String]::IsNullOrWhiteSpace($user.OtherTelephone)) { $otherAttributes.Add('otherTelephone', $user.OtherTelephone) } if(-not [System.String]::IsNullOrWhiteSpace($user.RoomNumber)) { $otherAttributes.Add('roomNumber', $user.RoomNumber) } |
Das Problem ist, dass $otherAttributes evtl. leer bleibt und dann wiederum die obigen Fehler auslöst. Es ist ungünstig, dass das Cmdlet eine leere Hashtable nicht von selbst ignoriert. Ich muss es also selbst abfangen:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
if($otherAttributes.Count -gt 0) { New-ADUser -Path "CN=Users,DC=test,DC=net" ` -Name $user.Name ` -GivenName $user.FirstName ` -Surname $user.LastName ` -AccountPassword $Password ` -ChangePasswordAtLogon $True ` -Enabled $True ` -OtherAttributes $otherAttributes } else { New-ADUser -Path "CN=Users,DC=test,DC=net" ` -Name $user.Name ` -GivenName $user.FirstName ` -Surname $user.LastName ` -AccountPassword $Password ` -ChangePasswordAtLogon $True ` -Enabled $True ` } |
Nun ist die Frage, ob man nun jedes Mal ein weiteres if-Statement einfügen muss, wenn ein neues Attribut in der CSV hinzukommt. Mit der aktuellen Lösung schon! Das lässt sich jedoch flexibler gestalten.
Das komplette Skript
In der Funktion GetUserAttributes iteriert man über die übergebene Hashtable und filtert alle leeren Values heraus. Will man künftig andere Attribute bedienen, muss man lediglich die Hashtable $ht an einer Stelle zentral anpassen. Der restliche Code bleibt unberührt.
Das fertige Script sieht schließlich so aus:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
function GetUserAttributes($ht) { $otherAttributes = @{} foreach ($k in $ht.Keys) { if(-not [System.String]::IsNullOrWhiteSpace($ht[$k])) { $otherAttributes.Add($k,$ht[$k]) } } $otherAttributes } $import =Import-CSV "C:\ps\test2.csv" -Delimiter ";" foreach ($user in $import) { $ht = @{ roomNumber = $user.RoomNumber otherTelephone = $user.OtherTelephone } $otherAttributes = GetUserAttributes($ht) $password = $user.Password | ConvertTo-SecureString -AsPlainText -Force if($otherAttributes.Count -gt 0) { New-ADUser -Path "CN=Users,DC=test,DC=net" ` -Name $user.Name ` -GivenName $user.FirstName ` -Surname $user.LastName ` -AccountPassword $Password ` -ChangePasswordAtLogon $True ` -Enabled $True ` -OtherAttributes $otherAttributes } else { New-ADUser -Path "CN=Users,DC=test,DC=net" ` -Name $user.Name ` -GivenName $user.FirstName ` -Surname $user.LastName ` -AccountPassword $Password ` -ChangePasswordAtLogon $True ` -Enabled $True ` } } |
Diese Lösung ist natürlich noch nicht perfekt, denn momentan funktioniert sie nur für Strings. Für die meisten AD-Attribute reicht das. Es sei darauf hingewiesen, dass Bool-Werte z.B. eine Extra-Behandlung brauchen.
Fazit
Mit dem -OtherAttributes Schalter des New-ADUser Cmdlets kann man auch CSV-Importe ausführen, die eher selten genutzte, und daher nicht direkt als Cmdlet Parameter verfügbare Attribute enthalten. Auch wenn dieser Beitrag keine vollständige Lösung für jedes denkbare Szenario darstellen kann und will, so dient er doch als guter Einstieg auf dem Weg zu einer solchen Lösung.
Leave a Reply
<p>Danke für Ihre Anregungen, Fragen und Hinweise.<br/>Infos zum <a href="https://www.active-directory-faq.dekontakt/">Datenschutz</a></p>