Windows PowerShellAutomatisieren der Benutzerbereitstellung, Teil 1

Don Jones

Inhalt

Festlegen von Zielen
Erstellen der anfänglichen Struktur
Abrufen von Eingaben
Erweiterung
Vorschau

Dieser Artikel stellt den Anfang einer vierteiligen Reihe über das Erstellen eines praktischen, realistischen Benutzerbereitstellungsskripts in Windows PowerShell dar. Im ersten Teil geht es hauptsächlich um das Erstellen der Struktur für das Skript. Im nächsten Monat erfahren Sie, wie Sie einen neuen, postfachaktivierten Benutzer in Active Directory und Exchange Server 2007 erstellen. Im darauffolgenden Monat wird behandelt, wie Sie Basisverzeichnisse erstellen und die richtigen Zugriffssteuerungslisten (Access Control Lists, ACLs) darauf anwenden. Im abschließenden Teil dieser Reihe wird der neue Benutzer in Gruppen platziert, und es werden zusätzliche Active Directory-Attribute aufgefüllt.

Fragen und Antworten zu Windows PowerShell

F Ich habe auf der MSDN-Website nach Informationen über die Win32_OperatingSystem-WMI-Klasse (Windows Management Instrumentation, Windows-Verwaltungsinstrumentation) gesucht. Dort steht, dass die Klasse Informationen zu Service Pack-Versionen enthält. Wenn ich „Get-WmiObject Win32_OperatingSystem“ in Windows PowerShell ausführe, werden keine Service Pack-Informationen angezeigt. Warum?

A Das Windows PowerShell-Formatierungssubsystem wählt für die Anzeige eine Standardteilmenge der Eigenschaften in dieser Klasse aus. Eine Möglichkeit, die Anzeige aller Eigenschaften durchzusetzen, besteht darin, ein Formatierungs-Cmdlet zu verwenden, um diese Standardeinstellungen außer Kraft zu setzen:

Get-WmiObject Win32_OperatingSystem | Format-List *

Alternativ können Sie wie folgt vorgehen, wenn Sie nur bestimmte Eigenschaften wünschen:

Get-WmiObject Win32_OperatingSystem | 
Format-List BuildNumber,CSName,ServicePackMajorVersion

Festlegen von Zielen

Der schwierigste Teil der Benutzerbereitstellung ist die Entscheidung, woher die anfänglichen Daten kommen werden. Wie können Sie wissen, welche Benutzer Sie erstellen? Wo können Informationen wie Name, E-Mail-Adresse, Postadresse, Abteilung und andere Details abgerufen werden?

Fast jede Umgebung wird eine andere Antwort parat haben. Deshalb soll hier ein Skript erstellt werden, das in der Lage ist, Eingaben aus vielen verschiedenen Quellen zu verarbeiten. Dadurch wird das Skript zwar etwas komplizierter, aber es ist die Mühe letzten Endes wert, weil das Skript flexibler wird. Außerdem soll ein Skript erstellt werden, das in der Lage ist, gleichermaßen einen einzigen neuen Benutzer oder hundert zu erstellen, denn schließlich geht es hier um Automatisierung.

Erstellen der anfänglichen Struktur

In beratender Funktion arbeite ich relativ viel mit verschiedenen Unternehmen zusammen, und dabei geht es hauptsächlich um das Erstellen von Skripts und um die Automatisierung. So sehe ich natürlich viele Skripts, und ich habe festgestellt, dass Administratoren häufig den Ansatz wählen, ein einziges Bereitstellungsskript zu erstellen.

Mit der Zeit bearbeitet der Administrator das Skript, sodass immer mehr Aufgaben bewältigt werden können. Das ist kein schlechter Ansatz, aber wenn Sie sich im Voraus Zeit nehmen, um eine stärker modularisierte Struktur zu erstellen, können Sie ein Skript erstellen, das flexibler und einfacher zu verwalten ist. Das erfordert gar nicht so viel zusätzliche Arbeit.

Im Folgenden soll zunächst die zentrale Funktion namens „Provision“ behandelt werden. Sie tut eigentlich nicht viel: Sie akzeptiert eine Hashtabelle (oder ein assoziatives Array), die die neuen Benutzerinformationen enthält, und ruft dann eine Reihe von Unterfunktionen auf, von denen alle Bereitstellungsaufgaben behandelt werden. Da es sich um Windows PowerShell handelt, will ich, dass all dies in der Pipeline funktioniert. Also sorge ich dafür, dass die Funktion eine Hashtabelle für jeden neuen Benutzer akzeptiert, und ermögliche, dass sie eine ganze Pipeline voller Hashtabellen akzeptiert, um mehrere Benutzer zu erstellen.

Die grundlegende Funktionsvorlage sieht wie folgt aus:

Function Provision {
  PROCESS {
  }
}

Nicht sehr beeindruckend, oder? Mit Windows PowerShell muss dies nicht so sein. Der PROCESS-Skriptblock wird einmal für jedes in die Funktion geleitete Objekt ausgeführt. Innerhalb des PROCESS-Skriptblocks wird die Variable „$_“ verwendet, um auf das aktuelle Pipelineobjekt zuzugreifen.

Abrufen von Eingaben

Mehr Flexibilität ist der Grund dafür, dass die Provision-Funktion selbst keine Daten abruft. Die Funktion soll nicht jedes Mal geändert werden müssen, wenn ein neues Eingabeformular eingeführt wird. Stattdessen werden zwei Funktionen erstellt, die meine Informationen über den neuen Benutzer empfangen: eine von einer CSV-Datei und die andere von einer Datenbank. Vorläufig soll es nur um die CSV-bezogene Funktion gehen, da CSV-Dateien einfach mit Editor oder einem anderen Texteditor (oder sogar Microsoft Excel und den meisten Datenbankanwendungen) erstellt werden können.

Eine Eigenart von CSVs – vor allem wenn sie von technisch nicht sonderlich versierten Personen stammen – ist folgende: Sie können sich nicht darauf verlassen, dass es sich bei den Spaltenüberschriften der Datei um die richtigen Active Directory-Attribute handelt. Das heißt, statt Spaltennamen wie „sn“ und „samAccountName“ erhalten Sie wahrscheinlich Spaltennamen wie „Last Name“ und „Logon Name“. Das ist in Ordnung. Windows PowerShell kann das übersetzen. Ich fange an, indem ich davon ausgehe, dass die CSV-Datei die folgenden Spalten enthält:

  • First Name (Vorname)
  • Last Name (Nachname)
  • City (Stadt)
  • Department (Abteilung)
  • Job Title (Position)
  • Logon Name (Anmeldename)
  • Password (Kennwort)

Sie können diese Liste selbstverständlich erweitern. Wie Sie dies tun, wird in Kürze besprochen. Mit dieser Liste sieht eine CSV-Datei möglicherweise folgendermaßen aus:

First Name,Last Name,City,Department,Job  Title,Logon Name,Password
Don,Jones,Las Vegas,IT,Writer,donj,P@ssw0rd
Greg,Shields,Denver,IT,Administrator,gregs,  P@ssw0rd

Ich erstelle eine Funktion namens „ProvisionInputCSV“, die einen Dateinamen als Eingabeparameter akzeptiert und einfach die CSV-Datei liest:

Function ProvisionInputCSV {
  Param ([string]$filename)
  Import-CSV $filename
}

Ich kann diese Funktion folgendermaßen allein ausführen, um sicherzustellen, dass sie die CSV-Datei liest:

ProvisionInputCSV c:\files\myinput.csv

Nun soll die Funktion jede Zeile der CSV in eine Hashtabelle übersetzen. Statt die Spaltenüberschriften aus der CSV-Datei beizubehalten, sollen sie in Attributnamen übersetzt werden, die für Active Directory akzeptabler sind. Dafür gibt es einige Möglichkeiten in Windows PowerShell, aber ich werde mich an einen Ansatz halten, der relativ einfach ist: Ich verwende eine foreach-Schleife, um jede Zeile der CSV-Datei nacheinander zu verarbeiten. Für jede Zeile der Datei erstelle ich eine Hashtabelle und leite sie an die Pipeline.

Sehen Sie sich die Funktion in Abbildung 1 an. Es gibt einige beachtenswerte Punkte:

  • Innerhalb des foreach-Blocks enthält die $user-Variable einen einzigen Benutzer. Das foreach-Konstrukt durchläuft jede Zeile in der $user-Variablen und füllt $user automatisch mit der nächsten auf.
  • Weil einige der Spaltenüberschriften Leerzeichen enthalten, ist es erforderlich, dass diese Namen in Anführungszeichen gesetzt werden.
  • Ich habe ein anderes Attribut, displayName, hinzugefügt, das aus zwei der CSV-Spalten erstellt wurde: First Name und Last Name.
  • Write-Output wird verwendet, um jede Hashtabelle in die Pipeline zu schreiben.

Abbildung 1 Funktion mit einer foreach-Schleife

Function ProvisionInputCSV {
  Param ([string]$filename)
  $users = Import-CSV $filename
  foreach ($user in $users) {
    $ht = @{'givenName'=$user."First Name";
            'sn'= $user."Last Name";
            'title'= $user."Job Title";
            'department'= $user.Department;
            'displayName'= $user."First Name" + " " + $user."Last Name";
            'city'= $user.City;
            'password'= $user.Password;
            'samAccountName'= $user."Logon Name"
           }
    Write-Output $ht
  }
}                                                  
 

Das Ergebnis all dessen ist, dass ich eine einzelne Funktion verwenden kann, um die CSV-Datei zu lesen und ihre Daten in Hashtabellen zu transformieren. Die Hashtabellen können dann zur Bereitstellungsfunktion geleitet werden:

ProvisionInputCSV c:\data\myinput.csv | Provision

Da die hier erstellte Provision-Funktion eine standardisierte Hashtabelle akzeptiert, können mehrere verschiedene Eingabegenerierungsfunktionen – ProvisionInputDatabase, ProvisionInputSpreadsheet usw. – erstellt werden.

Solange diese Funktionen meine standardisierte Hashtabelle ausgeben, die voll von Benutzerdaten ist, funktioniert die zentrale Provision-Funktion richtig. Dieser Ansatz bedeutet, dass in Zukunft vollständig neue Eingabequellen für neue Benutzerdaten verwendet werden können, ohne die zentrale Provision-Funktion ändern zu müssen.

Erweiterung

Sie können problemlos weitere Spalten zu Ihrer Version der CSV-Datei hinzufügen, um sie z. B. mit Telefonnummern oder anderen gewünschten Daten zu füllen. Sie müssen nur sicherstellen, dass Sie auch die Hashtabelle erweitern, sodass sie diese Informationen enthält. Angenommen, Sie möchten der CSV-Datei „Description“ (Beschreibung) und „Office“ (Büro) hinzufügen. Ich würde die Hashtabelle einfach durch Hinzufügen einiger Zeilen erweitern (siehe Abbildung 2). Anders gesagt, können Sie die grundlegende Struktur verwenden, die ich hier anbiete, um die Anforderungen zu erfüllen, die Ihre Umgebung an die Verzeichnisattribute neuer Benutzerkonten stellt.

Abbildung 2 Überarbeitete Funktion

Function ProvisionInputCSV {
  Param ([string]$filename)
  $users = Import-CSV $filename
  foreach ($user in $users) {
    $ht = @{'givenName'=$user."First Name";
            'sn'= $user."Last Name";
            'title'= $user."Job Title";
            'department'= $user.Department;
            'displayName'= $user."First Name" + " " + $user."Last Name";
            'city'= $user.City;
            'password'= $user.Password;
            'samAccountName'= $user."Logon Name";
            'office' = $user.office;
            'description' = $user.description
           }
    Write-Output $ht
  }
}

Vorschau

Nächsten Monat wird die zentrale Provision-Funktion durch Erstellen einer Unterfunktion aufgefüllt, die neue Benutzerkonten erstellt. Sie erhalten zwei Versionen dieser Unterfunktion: eine für diejenigen, die über Exchange Server 2007 verfügen (das Windows PowerShell-fähig ist), und eine andere für diejenigen, die nicht darüber verfügen. So erhalten Sie am Ende ein sehr brauchbares Skript: Es erstellt einfach nur Benutzerkonten. Da dies aber ein zeitaufwändigerer Aspekt des Umgangs mit neuen Benutzern ist, könnte Ihnen diese Funktion helfen, sofort Zeit zu sparen.

Don Jones ist Mitbegründer von Concentrated Technology, wo er wöchentliche Blogbeiträge zu Windows PowerShell, SQL Server, App-V und anderen Themen verfasst. Kontaktieren Sie ihn über seine Website.