lastcentral
Goto Top

AD Benutzer anlegen mit Powershell - Quereinsteiger

Heho,

ich muss hier ein paar Sachen aus einem alten Windows 2012R2 AD migrieren. Für einen Aspekt brauche ich ein paar Benutzer (vielleicht 100 oder so). Dazu brauche ich die Windows-Version von
useradd migration-g1-user01 -g migration-group01
. Ja, ihr seht schon, ich bin Quereinsteiger, komme aus der Linuxwelt.

Ich glaube, man nimmt dazu PowerShell ISE. Da soll man mit Tab vervollständigen können, bei mir kommt aber ein Tab, wenn ich Tab drücke. Außerdem ist das Copy&Paste vom Ausgabefenster sehr merkwürdig, wenn ich einmal kopiert habe, springt es nach beim nächsten klick nach unten, und ich muss erst zurückscrollen, um mehr kopieren zu können. Was mache ich falsch?
Der ISE Editor kann wohl keine Umbrüche und wenn man Wortweise löscht, kann es sein, dass der Cursor nicht mehr angezeigt wird, weil der nicht mehr im sichtbaren Bereich ist. Das hatte ich bei Editoren ja auch nicht nicht. Dann kann man natürlich den Querscrollbalken verschieben, bis man den Cursor wieder sieht, aber das kann ja nicht so gewollt sein. Ich kenne viele IDEs, aber mit der ISE komm ich irgendwie nicht klar. Ist bei mir was kaputt oder ist das normal?

Ich glaube, ich sollte Benutzer mit New-ADUser anlegen. Mit dem Kommando ist das aber sehr umständlich, weil es ungünstige defaults verwendet, so muss ich den Namen beispielsweise vielfach angeben, obwohl ich schon etliche Attribute über einen "Template-User" setze (via $newuserattributes, hier weggelassen):
New-ADUser -Name "migration-g1-user01" -GivenName "migration-g1-user01" -SAMAccountName "migration-g1-user01" -UserPrincipalName "migration-g1-user01 -Instance $newuserattributes -AccountPassword (ConvertTo-SecureString xxxxx -AsPlainText -Force) -ChangePasswordAtLogon $false -Enabled $true -path "OU=migration-group01,OU=migration,DC=dom,DC=com"  
Dabei habe ich partout nicht herausgefunden, wie man die Gruppe setzt.
Jetzt könnte man natürlich (via $groupid, hier weggelassen):
Add-ADGroupMember -Identity "migration-group01" -Members "migration-g1-user01"  
Set-ADUser -Identity "migration-g1-user01" -Replace @{primarygroupid=$groupid}  
Remove-ADGroupMember -Identity "Domänen-Benutzer" -Members "migration-g1-user01" -Confirm:$false  
machen, aber das sieht ja sehr unprofessionell aus (ist auch tatsächlich wild zusammengegoogelt) und hat eine race, nämlich dann der Benutzer kurz viel zu viele Rechte (Domänenuser) hat. Ich könnte die Benutzer natürlich enabled $alse und am Ende aktivieren, aber dann wird das ja noch komplizierter.

Wie legt man unter Windows einen Benutzer einfach und richtig an?

BTW, ich verstehe "-Confirm:$false" nicht und habe dazu Fragen:
- Warum kommt genau ausgerechnet bei Remove-ADGroupMember, aber bei keinem anderen, so eine Sicherheitsabfrage?
- Warum muss man -Confirm kein Leerzeichen, wie bei allen anderen (-Enabled $true), sondern ein Doppelpunkt?
- Warum heißt es "$true" und "$false" und nicht "True" und "False"? Das $ sieht ja aus wie eine Variable.
- Wer kam den auf die glorreiche Idee, dass "-confirm:$true" nicht bedeutet, dass confirmed wird, sondern dass dann explizit danach gefragt wird (also nicht confirmed ist)? Das wirkt für mich total falsch rum. Ich sage doch dem Add-ADGroupMember "Du, das confirme ich hier schon auf der Kommandozeile" und dann braucht er nicht fragen, aber ich muss False einstellen, wenn es automatisch confirmen will (was, wie gesagt, bei den anderen Kommandos gar nicht nötig ist).
Welches System steckt dahinter? Gibt's da eine Einführung zu solchen grundlegenden Konzepten? Ich hab einiges gelesen, Objekt-Ströme und so, aber ich erkenne das System dahinter noch nicht.

Content-ID: 9143324618

Url: https://administrator.de/contentid/9143324618

Ausgedruckt am: 25.11.2024 um 07:11 Uhr

Cloudrakete
Cloudrakete 07.09.2023 um 19:33:56 Uhr
Goto Top
Hallo,

PowerShell ISE ist sehr begrenzt in seinen Fähigkeiten. Für größere Themen empfehle ich VS Code mit der PowerShell Erweiterung.


Mit dem folgenden Code habe ich sowas in der Vergangenheit gemacht. Dazu muss man sagen, dass dies in einer Multimandantenumgebung genutzt wurde, wo ich auf dem Zielhost keine Dateien, sondern nur Text via Zwischenablage hineinbekam. Deshalb kein CSV-Import (Was bei einer großen Menge deutlich sinnvoller wäre)

$users wurde in dem Fall als Array definiert du kannst die gesamte Zeile (mit dem pscustomobject) duplizieren, um einen weiteren User anzulegen.
Ganz am Anschluss jeder Zeile kannst du eine AD-Gruppe einfügen, die wird in der darauffolgenden Schleife nach der Anlage des Users hinzugefügt
$Supportpw = Read-Host "Enter PW for Accounts" -AsSecureString  
$customerenv = "NetBIOS Domainname"   

# Bulk user creation
$users =@(
[pscustomobject]@{Name="Name";DisplayName="Displayname";Description="Beschreibung";SamAccountName="SamAccountName";UserPrinicipalName="UPN";OU="OU=Support,OU=Accounts,OU=Shared Ressources,DC=$customerenv,DC=domain,DC=tld";Group='AD-Gruppe'},  
)

foreach ($user in $users){
New-ADUser -Name $User.name -DisplayName $User.Displayname -Description $user.Description -Surname "" -GivenName "" -SamAccountName $user.samaccountname -UserPrincipalName $user.UserPrincipalName -Path $user.ou -AccountPassword $Supportpw -Enabled $True -ChangePasswordAtLogon $True  
Add-ADGroupMember -Identity $user.group -Members $user.SamAccountName
}
wobit94
wobit94 07.09.2023 aktualisiert um 21:32:41 Uhr
Goto Top
Hallo,

du hast eine ganze Menge Fragen rund um PowerShell und Active Directory! Lass mich versuchen, dir bei den meisten Punkten zu helfen:

PowerShell ISE-Probleme: Ja, die PowerShell ISE hat einige dieser Macken. Wenn du nach einer Alternative suchst, empfehle ich dir Visual Studio Code mit der PowerShell-Erweiterung. Das bietet eine modernere und flexiblere Umgebung zum Arbeiten mit PowerShell.

Benutzer mit New-ADUser anlegen:
Du liegst richtig, in AD wird die Gruppenmitgliedschaft nicht direkt beim Benutzer gesetzt. Stattdessen fügt man den Benutzer zur Gruppe hinzu. Dein Vorgehen mit Add-ADGroupMemberist also korrekt.
Die Sache mit der Primärgruppen-ID: Diese wird meistens auf "Domänen-Benutzer" gesetzt und es ist nicht nötig, sie zu ändern, es sei denn, du hast einen bestimmten Grund dafür.

Zu -Confirm:$false
Der Parameter -Confirm taucht bei vielen cmdlets auf, vor allem, wenn die Aktion potentiell schädlich sein könnte. Die Idee dahinter ist, dich vor möglichen schädlichen Aktionen zu warnen.
Der Doppelpunkt wird verwendet, um Werte direkt an Parameter zu binden, deshalb siehst du Confirm:$true und nicht -Confirm $true.

Das Verhalten des -Confirm-Parameters in PowerShell kann auf den ersten Blick in der Tat etwas gegenintuitiv erscheinen. Aber lass mich versuchen, das Konzept hinter dieser Entscheidung zu klären:

Wenn du in PowerShell den Parameter -Confirm:$true verwendest, forderst du explizit eine Bestätigung an. Das bedeutet, das cmdlet wird dich fragen, ob du sicher bist, bevor es die Aktion ausführt. Dies gibt dir die Möglichkeit, vor potenziell destruktiven Aktionen innezuhalten und sicherzustellen, dass du das wirklich tun möchtest.

Auf der anderen Seite bedeutet -Confirm:$false, dass du die Bestätigung umgehen und direkt fortfahren möchtest, ohne vorher gefragt zu werden.

Dieses Design wurde wahrscheinlich aus Sicherheitsgründen und um menschliche Fehler zu minimieren eingeführt. Es ist besonders sinnvoll bei cmdlets oder Aktionen, die schwerwiegende Folgen haben können, wenn sie fahrlässig ausgeführt werden. Das Hinzufügen von -Confirm:$true gibt dem Benutzer eine zusätzliche Sicherheitsebene und die Möglichkeit, den Vorgang zu überdenken.

Das Konzept hinter dieser Entscheidung ist, dass Skripte und Befehle in der PowerShell oft mächtige Aktionen durchführen, die schwer umkehrbar sind. Daher ist es oft sicherer, nach einer Bestätigung zu fragen, um ungewollte Auswirkungen zu vermeiden.

Zum Thema Einführung: PowerShell basiert auf dem .NET-Framework und ist objektorientiert, d.h. es gibt eine starke Betonung von Objekten und ihren Methoden/Eigenschaften. Wenn du dich intensiver mit PowerShell beschäftigst, empfehle ich, ein fundiertes Buch oder Online-Ressourcen speziell zu diesem Thema zu suchen. Microsofts eigene Dokumentation ist ein guter Startpunkt, und es gibt auch viele Community-geführte Blogs und Foren, die wertvolle Einblicke bieten. Das Konzept der "Pipeline" und "Objekt-Ströme", wie du es erwähnt hast, ist zentral in PowerShell, da es dir erlaubt, Ausgaben von einem Befehl als Eingabe für einen anderen Befehl zu verwenden, ohne zwischenspeichern zu müssen. Das macht viele Aufgaben effizienter und kürzer im Code.


Zum Schluss, hier ist ein vereinfachter Code, um den Benutzer anzulegen:
$newUser = @{
    Name                = "migration-g1-user01"  
    GivenName           = "migration-g1-user01"  
    SAMAccountName      = "migration-g1-user01"  
    UserPrincipalName   = "migration-g1-user01@dom.com"  
    Instance            = $newuserattributes
    AccountPassword     = (ConvertTo-SecureString 'xxxxx' -AsPlainText -Force)  
    ChangePasswordAtLogon = $false
    Enabled             = $true
    Path                = "OU=migration-group01,OU=migration,DC=dom,DC=com"  
}
New-ADUser @newUser
Add-ADGroupMember -Identity "migration-group01" -Members "migration-g1-user01"  
lastcentral
Lösung lastcentral 17.09.2023 um 16:51:35 Uhr
Goto Top
Hi,

danke für eure ausführlichen Infos!

tl;dr: das geht leider nicht besser und man muss es so machen.

Also erstmal ist es anscheinend wirklich so, dass man die Primärgruppe nicht beim Anlegen festlegen kann. Das ist wohl ganz tief hardcoded, selbst die numerische ID ("By default all Active Directory users have a PrimaryGroupID of 513, which is associated with the Domain Users group."). Das ist sogar noch schlimmer, denn es kann sein, dass der neue User sofort auf andere AD repliziert wird, die entfernte Gruppenmitgliedschaft aber bis zu 30 Minuten dauern. Das findet man normal. Na ja, "the S in Active Directory stands for security" :D In meinem Fall ist das alles aber gar kein Problem.

Ach ja, und warum das ISE nicht ging: Ich habe dazu einen neuen User bekommen, mit dem ich auf nem TerminalServer arbeiten sollte. Der User hatte diese komischen defaults wie "Dateierweiterung nicht anzeigen". Die Template, die ich erweitern sollte (war im Wesentlichen ein Copyright drin), hieß "template.ps1.txt", wurde als "template.ps1" angezeigt, auch im ISE, aber weil es kein .ps1 war, hat ISE keine Features angeschaltet. Das ist also wie zu MS-DOS-Zeiten, da wird auf den Dateinamen bzw Erweiterung geguckt, die nicht einmal angezeigt wird, und damit soll man dann arbeiten... Das ist angeblich ein übliches Problem, wurde mir gesagt, aber da es hier auch keiner sofort gesehen hat, muss mir das ja nicht peinlich sein. Ausführen konnte ich es übrigens dennoch (also geschützt hätte das wohl kaum vor bösen Scripten). Nach dem Umbenennen ging dann TAB im ISE.

Lustig auch, warum es denn überhaupt ps1.txt hieß: das hat jemand von einem Kollegen per Mail gebekommen und umbenannt, damit es durch einen ganz tollen Virusscanner geht, yeah. Ich hätte ja gedacht, dass so "doppelte Erweiterungen (wie "naktbild.jpg.exe") gerade geblockt werden, aber hier wohl nicht).

Zur Gruppe, die Gruppe Domain Users ist ja oft schon ziemlich mächtig. Ich brauchte spezielle Accounts, die eben so wenig wie möglich dürfen sollen, damit die nichts (ausser sich selbst bzw ihre Daten) kaputt machen oder auslesen (Datenschutz) können, also nicht aus Versehen irgendwelche geteilten Ordner lesen oder so.

Danke für das Codebeispiele, aber macht ja dann Gruppe = Domain Users. Da muss man aufpassen, denn zusätzlich zur Migrationsgruppe hat der Benutzer dann vielleicht Leserechte auf irgendwelche "Gemeinsamen Ordner" oder so.

Warum man bei "False" nun ein Dollarzeichen voranstellen muss (und sonst nie), habe ich immer noch nicht verstanden, aber ist auch nicht wichtig, ist eben so.

Ich konnte bzw. wollte auch keine CSV auf den Server tun und wäre von der Versionsverwaltung schwierig, denn im Script sind PWs und das kann ich ja nicht einchecken. Vorgegangen bin ich daher noch etwas anders, und zwar habe ich mir einfach das PS Script aus CVS generieren lassen. Dazu hab ich mit nem simplen Bash-Loop sowas in der Art von

tag="$(LC_ALL=de TZ="Europe/Berlin" date +%Y%m%d-%H%M%S)"  
readarray -t names < "$input"  
echo '$accounts = @{' >> "$tag.ps1"  
echo '$accounts = @{' >> "$tag-nopws.ps1"  

for name in ${names[@]} ; do
    pw="$(./gen.sh 1)"  
    printf "    %-20s = %s\n" "'$name'" "'$pw'" >> "$tag.ps1"  
    printf "    %-20s = %s\n" "'$name'" "'*****'" >> "$tag-nopws.ps1"  
done
echo '}' >> "$tag.ps1"  
echo '}' >> "$tag-nopws.ps1"  
Das Script gen.sh ruft "pwgen -c -n -y -s 20 1" auf und entfernt dann im Wesentlichen ' aus den PWs, damit es keine Syntaxfehler gibt, und prüft policies (denn bei 100% Zufall kann es passieren, dass es z.b. kein Kleinbuchstaben gibt, und dann wird das PW aber nicht vom AD akzeptiert). Das *-nopws.ps1 enthält keine Passwörter und ist Teil der IT Dokumentation.

Bash hab ich genommen, weil das in PS eine Bildschirmseite Code geworden wäre. Damit fängt das PS Script an mit
$accounts = @{
   'migration-g1-user01' = '?=9d*+W>O:O#1>W93]^R'  
...
}
foreach($key in $accounts.keys)
....

(das PW ist natürlich ein anderes)

Ja prima, danke nochmal, ich wollte hier nur der Vollständigkeit halber das Ergebnis teilen.