De vorige keer heb ik aan de hand van een provisioning PowerShell script organizational units en groups aangemaakt. Deze keer is het de beurt aan de user accounts en managed service accounts die ik nodig heb in mijn proeftuin. Aan de basis van mijn PowerShell script heeft het Microsoft Technet artikel 'Automating User Provisioning, Part 2' gelegen. Dit script ging uit van Exchange Server 2007 cmdlets en de Quest AD extensies.
Het PowerShell script begint met het goed zetten van de executie rechten voor PowerShell.
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
De volgende stap is het registreren van de PowerShell module voor AD.
# Inlezen Windows PowerShell Module voor Active Directory. Deze module is
# beschikbaar op Windows 2008 R2 (alleen op de Standard, Enterprise en
# DataCenter versies) en, middels 'Windows Server 2008 R2 Remote Server
# Administration Tools (RSAT)', op Windows 7.
Import-Module ActiveDirectory
Het provisioning proces bestaat uit verschillende stappen.
#
# .SYNOPSIS
# Provisioning acties voor (nieuwe) accounts.
#
# .DESCRIPTION
# Centrale provision functie die op basis van een hashtabel waarin de
# (nieuwe) gebruikersgegevens staan allerlei subfuncties aanroept waarmee
# alle feitelijke provisioning taken worden uitgevoerd.
#
function Provision
{
PROCESS {
Create-UserAccountInAD $_ # Aanmaken van nieuw account
Modify-ManagerInAD $_ # Bijwerken manager van het account
Modify-UserAccountInAD $_ # Bijwerken overige gegevens van het account
}
}
De input voor het proces wordt ingelezen middels een CSV bestand waarvan de gegevens in een hashtable worden opgeslagen.
#
# .SYNOPSIS
# Ophalen van gebruikergegevens uit een CSV-bestand.
#
# .DESCRIPTION
# Ophalen van gebruikergegevens uit een CSV-bestand. De eerste regel van
# dit CSV-bestand dient de volgende kolomnamen te bevatten:
#
# Kolom Toelichting
# ------------- --------------------------------------------------
# Gebruikersnaam Mag niet langer zijn dan 20 tekens
# Wachtwoord Dient te voldoen aan de wachtwoord policy
# Omschrijving Doel van het account
# Voornaam Roepnaam
# Middelste_Naam Overige namen
# Achternaam
# Adres Straat + Huisnummer + Toevoeging
# Postcode 9999 ZZ
# Plaats
# Provincie
# Landcode 2 lettercode voor het land (NL = Nederland)
# Postbus "Postbus " + nummer
# Postcode_Postbus 9999 ZZ
# Plaats_Postbus
# Telefoon_Zakelijk (999 | 9999) (9)99 99 99
# Mobiel (06) 99 99 99 99
# Fax (999 | 9999) (9)99 99 99
# Telefoon_Prive (999 | 9999) (9)99 99 99
# Email POP3 / Exchange e-mail adres
# Homepage URL van SharePoint My Site van betreffende account
# Functie
# Kantoor
# Afdeling
# Divisie
# Organisatie
# Bedrijf
# Manager Gebruikersnaam van de manager
# PersoneelsID
# Personeelnummer
# Managed_Account TRUE | FALSE
# OU Het pad in AD waaronder de gebruiker aangemaakt
# dient te worden. Voorbeeld: OU=Users,DC=Contoso,DC=Com
#
# .PARAMETER BestandsNaam
# De naam van het CSV-bestand dat ingelezen dient te worden.
#
# .EXAMPLE
# PS C:\> ProvisionInputCSV -BestandsNaam 'c:\provision\gebruikers.csv'
# Dit voorbeeld toont hoe de ProvisionInputCSV functie aangeroepen dient
# te worden met named parameters.
#
# .EXAMPLE
# PS C:\> ProvisionInputCSV 'c:\provision\gebruikers.csv'
# Dit voorbeeld toont hoe de ProvisionInputCSV functie aangeroepen dient
# te worden met gepositioneerde parameters.
#
# .INPUTS
# System.String
#
# .OUTPUTS
# System.Collections.Hashtable
#
function ProvisionInputCSV
{
Param
(
[System.String] $BestandsNaam
)
# Importeren CSV-bestand
$Gebruikers = Import-Csv -Path $BestandsNaam -Delimiter ";";
# Transformeren van gegevens naar de benodigde AD naamgeving in de hash
# tabel
foreach ($Gebruiker in $Gebruikers)
{
$GebruikerHashTabel =
@{
# --- General ---
'Name' = Replace-EmptyString(($Gebruiker.Voornaam +
" " + $Gebruiker.Achternaam).Trim()); # SarahDavis
'GivenName' = Replace-EmptyString($Gebruiker.Voornaam); # Sanjay
'Initials' = Replace-EmptyString($Gebruiker.Initialen); # L
'OtherName' = Replace-EmptyString($Gebruiker.MiddelsteNaam); # Peter
'Surname' = Replace-EmptyString($Gebruiker.Achternaam); # Patel
'DisplayName' = Replace-EmptyString(($Gebruiker.Voornaam +
" " + $Gebruiker.Achternaam).Trim()); # Sarah Davis Laptop
'Description' = Replace-EmptyString($Gebruiker.Omschrijving); # Description of the object
'Office' = Replace-EmptyString($Gebruiker.Kantoor); # D1042
'OfficePhone' = Replace-EmptyString($Gebruiker.Telefoon_Zakelijk); # +1 (999) 555 1212
'EmailAddress' = Replace-EmptyString($Gebruiker.Email); # sarahdavis@contoso.com
'HomePage' = Replace-EmptyString($Gebruiker.Homepage); # http://employees.contoso.com/sdavis
# --- Address ---
'StreetAddress' = Replace-EmptyString($Gebruiker.Adres); # 1200 Main Street
'POBox' = Replace-EmptyString($Gebruiker.Postbus); # 25662
'City' = Replace-EmptyString($Gebruiker.Plaats); # Las Vegas
'State' = Replace-EmptyString($Gebruiker.Provincie); # Nevada
'PostalCode' = Replace-EmptyString($Gebruiker.Postcode); # 28712
'Country' = Replace-EmptyString($Gebruiker.Landcode); # IN
# --- Account ----
'SamAccountName' = Replace-EmptyString($Gebruiker.Gebruikersnaam); # saradavis
'AccountPassword' = Replace-EmptyString($Gebruiker.Wachtwoord); # <W8woord>
# --- Telephones ---
'HomePhone' = Replace-EmptyString($Gebruiker.Telefoon_Prive); # +1 (999) 555 1212
'MobilePhone' = Replace-EmptyString($Gebruiker.Mobiel); # +1 (999) 555 1212
'Fax' = Replace-EmptyString($Gebruiker.Fax); # +1 (999) 555 1212
# --- Organization ---
'Title' = Replace-EmptyString($Gebruiker.Functie); # Manager
'Department' = Replace-EmptyString($Gebruiker.Afdeling); # Development
'Division' = Replace-EmptyString($Gebruiker.Divisie); # Software
'Organization' = Replace-EmptyString($Gebruiker.Organisatie); # Accounting
'Company' = Replace-EmptyString($Gebruiker.Bedrijf); # Contoso
'Manager' = Replace-EmptyString($Gebruiker.Manager); # saradavis
'EmployeeID' = Replace-EmptyString($Gebruiker.PersoneelsID); # A123456
'EmployeeNumber' = Replace-EmptyString($Gebruiker.Personeelnummer); # 12345678
# --- Additional information ---
'Managed_Account' = [System.Convert]::ToBoolean($Gebruiker.Managed_Account); # true
'OU' = Replace-EmptyString($Gebruiker.OU); # OU=Users,DC=contoso,DC=com
}
# Verzend hash tabel naar het volgende commando in de pipeline
Write-Output $GebruikerHashTabel;
}
}
Het aanmaken van user accounts en managed service accounts is in een function ondergebracht. Er is voor gekozen deze functie alleen het account te laten aanmaken. Het zetten van managers en het vullen van de overige gegevens is belegt in aparte functies. Hiermee is het provisioning script ook in te zetten voor onderhoud op de accounts.
#
# .SYNOPSIS
# Aanmaken van een gebruikersaccount in AD.
#
# .DESCRIPTION
# Aanmaken van een gebruikersaccount in AD op basis van de gegevens uit de
# doorgegeven hash tabel. Het account dat aangemaakt wordt bestaat alleen
# uit een gebruikersnaam en een wachtwoord. Het account is reeds actief
# en bij de eerste keer inloggen hoeft het wachtwoord niet gewijzigd te
# worden.
#
# .PARAMETER Gebruiker
# De hash tabel met gebruikergegevens.
#
# .EXAMPLE
# PS C:\> Create-UserAccountInAD $Gebruiker
# Dit voorbeeld toont hoe de Create-UserAccountInAD functie aangeroepen
# dient te worden met een hash tabel vol gebruikergegevens.
#
# .INPUTS
# System.Collections.Hashtable
#
# .OUTPUTS
# Null
#
function Create-UserAccountInAD
{
param
(
[System.Collections.Hashtable] $Gebruiker
)
# Lokale variabelen
[Microsoft.ActiveDirectory.Management.ADUser] $adUser;
# Controle of het account reeds bestaat in het AD
if ($Gebruiker.Managed_Account -eq $false)
{
$adUser = Get-ADUser -Filter ("SamAccountName -eq '" +
$Gebruiker.SamAccountName + "'");
}
else
{
$adUser = Get-ADServiceAccount -Filter ("SamAccountName -eq '" +
$Gebruiker.SamAccountName + "$'");
}
# Indien het account niet is gevonden dan maken we het aan
if ($adUser -eq $null)
{
Write-Verbose ("Aanmaken AD account voor '" + $Gebruiker.Name + " (" +
$Gebruiker.SamAccountName + ")'.");
# Managed Service account aanmaken?
if ($Gebruiker.Managed_Account -eq $false)
{
# Samenstellen van UserPrincipal object
[System.String] $adUserPrincipal = $Gebruiker.SamAccountName + "@" +
(Get-ADForest -Current LocalComputer).RootDomain;
# Actief gebruikers account met geen verplichte wachtwoord wijziging
if ($Gebruiker.SamAccountName.Length -cle 20)
{
if ($Gebruiker.Name -ne $null)
{
# Gewone accounts zijn niet trusted for delegation
New-ADUser -Name $Gebruiker.Name -Path $Gebruiker.OU -UserPrincipalName $adUserPrincipal -SamAccountName $Gebruiker.SamAccountName -AccountPassword (ConvertTo-SecureString $Gebruiker.AccountPassword -AsPlainText -Force) –ChangePasswordAtLogon $false -Enabled $true -TrustedForDelegation $false;
Write-Debug ("Aangemaakt als: Standaard user account");
trap [Microsoft.ActiveDirectory.Management.ADException]
{
# Fout is niet blokkerend
Write-Warning ("Bij het aanmaken van AD user '" +
$Gebruiker.Name + " (" + $Gebruiker.OU + ")" +
"' is er een fout opgetreden. De opgetreden fout is: '" +
$_.Exception.Message + " (" +
$_.Exception.GetType() + ")'. ");
Continue;
}
}
else
{
# Service accounts zijn trusted for delegation
New-ADUser -Name $Gebruiker.SamAccountName -Path $Gebruiker.OU -UserPrincipalName $adUserPrincipal -SamAccountName $Gebruiker.SamAccountName -AccountPassword (ConvertTo-SecureString $Gebruiker.AccountPassword -AsPlainText -Force) –ChangePasswordAtLogon $false -Enabled $true -TrustedForDelegation $true;
Write-Debug ("Aangemaakt als: Standaard user account");
trap [Microsoft.ActiveDirectory.Management.ADException]
{
# Fout is niet blokkerend
Write-Warning ("Bij het aanmaken van AD user '" +
$Gebruiker.SamAccountName + " (" + $Gebruiker.OU + ")" +
"' is er een fout opgetreden. De opgetreden fout is: '" +
$_.Exception.Message + " (" +
$_.Exception.GetType() + ")'. ");
Continue;
}
}
}
else
{
Write-Warning ("AD user account voor '" + $Gebruiker.Name + " (" +
$Gebruiker.SamAccountName + ")' is niet aangemaakt omdat " +
"opgegeven SamAccountName langer is dan 20 tekens.");
}
}
else
{
# Actief managed service account en trusted for delegation
if ($Gebruiker.SamAccountName.Length -cle 20)
{
New-ADServiceAccount -Name $Gebruiker.SamAccountName -Path $Gebruiker.OU -SamAccountName $Gebruiker.SamAccountName -TrustedForDelegation $true -Enabled $true;
Write-Debug ("Aangemaakt als: Managed Service account");
trap [Microsoft.ActiveDirectory.Management.ADException]
{
# Fout is niet blokkerend
Write-Warning ("Bij het aanmaken van AD Service account '" +
$Gebruiker.SamAccountName + " (" + $Gebruiker.OU + ")" +
"' is er een fout opgetreden. De opgetreden fout is: '" +
$_.Exception.Message + " (" +
$_.Exception.GetType() + ")'. ");
Continue;
}
}
else
{
Write-Warning ("AD Managed Service account voor '" +
$Gebruiker.Name + " (" + $Gebruiker.SamAccountName +
")' is niet aangemaakt omdat opgegeven SamAccountName " +
"langer is dan 20 tekens.");
}
}
}
else
{
Write-Warning ("Aanmaken AD account voor '" + $Gebruiker.Name +
" (" + $Gebruiker.SamAccountName +
")' overgeslagen. Het opgegeven account bestaat reeds.");
}
}
Het bijwerken van niet sleutel gegevens is belegt in een modificatie functie. Het zetten van de manager is apart gehouden. Dit is onder andere gedaan omdat de managed service acounts geen manager veld kennen.
#
# .SYNOPSIS
# Wijzigingen gegevens van een bestaand gebruikersaccount in AD.
#
# .DESCRIPTION
# Wijzigingen van gegevens van een bestaand gebruikersaccount in AD op
# basis van de gegevens uit de doorgegeven hash tabel.
#
# .PARAMETER Gebruiker
# De hash tabel met gebruikergegevens.
#
# .EXAMPLE
# PS C:\> Modify-UserAccountInAD $Gebruiker
# Dit voorbeeld toont hoe de Modify-UserAccountInAD functie aangeroepen
# dient te worden met een hash tabel vol gebruikergegevens.
#
# .INPUTS
# System.Collections.Hashtable
#
# .OUTPUTS
# Null
#
function Modify-UserAccountInAD
{
param
(
[System.Collections.Hashtable] $Gebruiker
)
# Lokale variabelen
[Microsoft.ActiveDirectory.Management.ADUser] $adUser;
# Gegevens account ophalen uit het AD
if ($Gebruiker.Managed_Account -eq $false)
{
$adUser = Get-ADUser -Filter ("SamAccountName -eq '" +
$Gebruiker.SamAccountName + "'");
}
else
{
$adUser = Get-ADServiceAccount -Filter ("SamAccountName -eq '" +
$Gebruiker.SamAccountName + "$'");
}
# We kunnen het account alleen wijzigen als het bestaat
if ($adUser -eq $null)
{
Write-Warning ("Wijzigen gegevens van AD account voor '" +
$Gebruiker.Name + " (" + $Gebruiker.SamAccountName +
")' is mislukt. Het opgegeven account bestaat niet.");
}
else
{
Write-Verbose ("Bijwerken gegevens van AD account van '" +
$Gebruiker.Name + " (" + $Gebruiker.SamAccountName + ")'.");
# Betreft het een Managed Service account?
if ($Gebruiker.Managed_Account -eq $false)
{
# --- General ---
Set-ADUser $adUser -GivenName $Gebruiker.GivenName;
Set-ADUser $adUser -Initials $Gebruiker.Initials;
Set-ADUser $adUser -OtherName $Gebruiker.OtherName;
Set-ADUser $adUser -Surname $Gebruiker.Surname;
Set-ADUser $adUser -DisplayName $Gebruiker.DisplayName;
Set-ADUser $adUser -Description $Gebruiker.Description;
Set-ADUser $adUser -Office $Gebruiker.Office;
Set-ADUser $adUser -OfficePhone $Gebruiker.OfficePhone;
Set-ADUser $adUser -EmailAddress $Gebruiker.EmailAddress;
Set-ADUser $adUser -HomePage $Gebruiker.HomePage;
# --- Address ---
Set-ADUser $adUser -StreetAddress $Gebruiker.StreetAddress;
Set-ADUser $adUser -POBox $Gebruiker.POBox;
Set-ADUser $adUser -City $Gebruiker.City;
Set-ADUser $adUser -State $Gebruiker.State;
Set-ADUser $adUser -PostalCode $Gebruiker.PostalCode;
Set-ADUser $adUser -Country $Gebruiker.Country;
# --- Telephones ---
Set-ADUser $adUser -HomePhone $Gebruiker.HomePhone;
Set-ADUser $adUser -MobilePhone $Gebruiker.MobilePhone;
Set-ADUser $adUser -Fax $Gebruiker.Fax;
# --- Organization ---
Set-ADUser $adUser -Title $Gebruiker.Title;
Set-ADUser $adUser -Department $Gebruiker.Department;
Set-ADUser $adUser -Division $Gebruiker.Division;
Set-ADUser $adUser -Organization $Gebruiker.Organization;
Set-ADUser $adUser -Company $Gebruiker.Company;
Set-ADUser $adUser -EmployeeID $Gebruiker.EmployeeID;
Set-ADUser $adUser -EmployeeNumber $Gebruiker.EmployeeNumber;
}
else
{
# --- General ---
Set-ADServiceAccount $adUser -Description $Gebruiker.Description;
Set-ADServiceAccount $adUser -DisplayName $Gebruiker.DisplayName;
Set-ADServiceAccount $adUser -HomePage $Gebruiker.HomePage;
}
}
}
De functie voor het bijwerken van manager gegevens.
#
# .SYNOPSIS
# Wijzigingen manager gegevens van een bestaand gebruikersaccount in AD.
#
# .DESCRIPTION
# Wijzigingen van manager gegevens van een bestaand gebruikersaccount in
# AD op basis van de gegevens uit de doorgegeven hash tabel.
#
# .PARAMETER Gebruiker
# De hash tabel met gebruikergegevens.
#
# .EXAMPLE
# PS C:\> Modify-ManagerInAD $Gebruiker
# Dit voorbeeld toont hoe de Modify-ManagerInAD functie aangeroepen
# dient te worden met een hash tabel vol gebruikergegevens.
#
# .INPUTS
# System.Collections.Hashtable
#
# .OUTPUTS
# Null
#
function Modify-ManagerInAD
{
param
(
[System.Collections.Hashtable] $Gebruiker
)
# Bijwerken van de manager kan niet op Managed Service accounts.
if ($Gebruiker.Managed_Account -eq $true)
{
return;
}
# Controleer of het AD account bestaat
$adUser = Get-ADUser -Filter ("SamAccountName -eq '" +
$Gebruiker.SamAccountName + "'");
if ($adUser -eq $null)
{
Write-Warning ("Wijzigen manager gegevens van AD account voor '" +
$Gebruiker.Name + " (" + $Gebruiker.SamAccountName +
")' is mislukt. Het opgegeven account bestaat niet.");
}
else
{
Write-Verbose ("Bijwerken manager gegevens van AD account van '" +
$Gebruiker.Name + " (" + $Gebruiker.SamAccountName + ")'.");
# Controleer of het AD account van de manager bestaat
if ($Gebruiker.Manager -ne $null)
{
$adManager = Get-ADUser -Filter ("SamAccountName -eq '" +
$Gebruiker.Manager + "'");
if ($adManager -eq $null)
{
# Overschrijf de bestaande manager
Set-ADUser $adUser -Manager $null;
}
else
{
# Voeg de actuele manager toe
Set-ADUser $adUser -Manager $adManager;
}
}
else
{
Set-ADUser $adUser -Manager $null;
}
}
}
Onderstaande functie zorgt ervoor dat null values uit de CSV goed worden gezet. Doen we dit niet dan treden er fouten op bij het zetten van bepaalde AD velden.
#
# .SYNOPSIS
# Vervang een lege System.String door een Null.
#
# .DESCRIPTION
# Vervang een lege System.String door een Null.
#
# .PARAMETER Str
# De te controleren System.String.
#
# .EXAMPLE
# PS C:\> Replace-EmptyString ''
#
# .INPUTS
# System.String
#
# .OUTPUTS
# Null of System.String
#
function Replace-EmptyString
{
param
(
[System.String] $str
)
# Vervang een empty string door een NULL waarde
if ($str -eq '')
{
Write-Output $null;
}
else
{
Write-Output $str.Trim();
}
}
Het uitvoeren van de provisioning taken dient initieel twee keer te gebeuren. De reden is dat anders de manager velden van de accounts niet overal goed worden gezet.
# Provisioning 2x uitvoeren omdat de eerste ronde de managers niet altijd goed gezet worden
ProvisionInputCSV -BestandsNaam "D:\Projects\PowerShell\Gebruikers\accounts.csv" | Provision
ProvisionInputCSV -BestandsNaam "D:\Projects\PowerShell\Gebruikers\accounts.csv" | Provision
Reacties