PowerShell är ett kraftfullt verktyg i Windowsmiljön. Med detta skriptspråk kan man göra mycket administrativt arbete, bland annat skapande av användare vilket detta inlägg kommer att gå igenom. Lösningen som kommer att visas här kanske inte passar alla, däremot skall den skapa unika användare i domänen och även skapa ett engångslösenord. Lösenordet sparas med användarinformationen i den aktuella administratörens dokument-mapp. Jag publicerar skriptet här med förhoppningen om att den skall vara intressant och ge en fingervisning i hur man kan skapa användare för de som behöver det.

Alla användare skapas så att deras användarnamn består av de två första tecknen i för- och efternamnet. Heter man Sven Svensson blir alltså användarnamnet svsv. Skulle flera användare få ett likadant användarnamn adderas ett nummer till slutet, så om två Sven Svensson finns blir en svsv och den andra svsv2, på samma sätt adderas en siffra om fler personer skulle heta likadant. Då protokollet LDAP – vilket Active Directory använder sig av – kräver en unik identifierare (Distinguished Name) kan detta skript generera 26 + 1 sådana.

För att skriptet skall fungera bör följande saker finnas;

  • Windows Server med Active Directory
  • En csv-fil innehållande användare

Csv-filen skall eller kan innehålla följande värden:

  • Förnamn
  • Efternamn
  • Stad i vilken användaren finns
  • Avdelning i vilken användaren jobbar
  • Roll (valfritt)

För att exemplifiera csv-filen med två användare, kan det se ut på följande sätt:

Firstname;Lastname;Department;City;Role
Sven;Svensson;IT;Göteborg;Manager
Rut;Johansson;HR;Göteborg

Vad gäller skriptet och csv-filen måste dessa sparas i utf-8 format för att åäö skall visas korrekt. I normala fall sparar program såsom exempelvis Notepad filer i ASCII, som inte innehåller vissa svenska tecken. Istället visas ett tecken som kan liknas vid en romb med ett frågetecken inuti.

Skriptet kommer att spara en användare i example.com/Example/Stad/Avdelning/. Här kan förstås ordet Example bytas ut till namnet på den organisation det gäller.

############## METADATA ############## 
# AUTHOR: KRISTOFFER QVIST
# LICENCE: Apache Licence, v.2
# GOALS:
# * Check that new users actually are
#   unique within domain,
# * Assign unique email-addresses
# * Check for duplicate names within
#   an OU to correct these.
#####################################
 
param([string]$csvfile= [Environment]::GetFolderPath('MyDocuments') + "\thisFile.csv")
 
Import-Module ActiveDirectory
 
while((Test-Path -Path $csvfile) -eq $false) {
    $csvfile = Read-Host "Please, fill in the correct path to the .csv file"
}
 
$users  = Import-Csv -Delimiter ";" -Path $csvfile
 
foreach ($user in $users) {
    $fname      = $user.Firstname
    $fname      = $fname.Trim()
    $sname      = $user.Lastname
    $sname      = $sname.Trim()
    $dplName    = $fname+" "+$sname
    $domain     = "@example.com"
    # Get first two letters of firstname
    $samf       = $fname.substring(0,2)
    # Get first two letters of lastname
    $saml       = $sname.substring(0,2)
    $sam        = $samf+$saml
    $sam        = $sam.ToLower()
    $department = $user.Department
    $city       = $user.City
    $role       = $user.Role
 
    # The user should be added here
    $OU = "OU=$department,OU=$city,OU=Example,DC=example,DC=com"
    $dn = "CN=" + $dplName + "," + $OU
 
    # Place to store groups in
    $GroupOU = "OU=Groups,DC=example,DC=com"
 
    # Check if the OU exists, otherwise create it
    $LDAPOU = "LDAP://" + $OU
    $OUexists = [adsi]::Exists($LDAPOU)
 
    if ($OUexists -eq $false) {
        dsadd ou $OU
    }
 
    # Generate random password 8-byte password
    $length   = 2 # length x 4 equals the password length 
    $password = ""
    $chars    = "ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrtuvxyz".ToCharArray()
    for($i=0; $i -lt $length; $i++) {
        $password += $chars | Get-Random
    }
 
    $chars2 = "0123456789!#%/()".ToCharArray()
    for($i=0; $i -lt $length; $i++) {
        $password += $chars2 | Get-Random
    }
 
    for($i=0; $i -lt $length; $i++) {
        $password += $chars | Get-Random
    }
 
    for($i=0; $i -lt $length; $i++) {
        $password += $chars2 | Get-Random
    }
 
    # Create a clean email address (e.g. from Åsa.Lindén to asa.linden)
    $eaddress    = $fname.ToLower() + "." + $sname.ToLower()
    $eaddress    = $eaddress -replace "é","e"
    $eaddress    = $eaddress -replace "å","a"
    $eaddress    = $eaddress -replace "ä","a"
    $eaddress    = $eaddress -replace "ö","o"
 
    $email = $eaddress + $domain
 
    $emailExists = Get-ADUser -Filter { EmailAddress -like $email }
    $emailBase   = $eaddress
    $i = 2
 
    while ($emailExists -ne $null) {
        $email = $emailBase + "." + $i + $domain
        $emailExists = Get-ADUser -Filter {EmailAddress -like $email }
        $i++
    }
 
    # Create clean login name
    $sam    = $sam -replace "é","e"
    $sam    = $sam -replace "å","a"
    $sam    = $sam -replace "ä","a"
    $sam    = $sam -replace "ö","o"
 
    # Check if the user sam exists in AD already
    $checkADUser = Get-ADUser -LDAPFilter "(SamAccountName=$sam)"
    $i = 2
    $baseSam = $sam
 
    # If user exist, add a number to the end
    while ($checkADUser -ne $null) {
        $sam = $baseSam+$i
        $checkADUser = Get-ADUser -LDAPFilter "(SamAccountName=$sam)"
        $i++
    }
 
    # Check that the user has a unique DN
    $DNExists = Get-ADUser -Filter {distinguishedName -eq $dn }
    $i = 0
    $letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray()
    while ($DNExists -ne $null) {
        $dplName = $fname + " " + $letters[$i] + " " + $sname
        $dn = "CN=" + $dplName + "," + $OU
        #Write-Host $dn
        $DNExists = Get-ADUser -Filter {distinguishedName -eq $dn }
        $i++
    }
 
    # And use it in user principal name
    $upn        = $sam+$domain
 
    # Check if the localisation group exists, otherwise create it
    try {
        Get-ADGroup -Identity $city | out-null
    } catch {
        New-ADGroup -Name $city -GroupScope Global -Path $GroupOU
        Write-Host "New group '$city' created"
    }
 
    # Check if the shadow group exists, otherwise create it
    $ADShadowGroup = "SG_" + $department
    try { 
        Get-ADGroup -Identity $ADShadowGroup | out-null
    } catch {
        New-ADGroup -Name $ADShadowGroup -GroupScope Global -Path $GroupOU
        Write-Host "New group '$ADShadowGroup' created"
    }
 
    # This file will hold the user login credentials
    $file = [Environment]::GetFolderPath('MyDocuments') + "\" + $sam + ".txt"
 
    # Add the user to AD
    New-ADUser -SamAccountName $sam -Name $dplName -GivenName $fname -Surname $sname -DisplayName $dplName -UserPrincipalName $upn -Department $department -City $city -EmailAddress $email -AccountPassword (ConvertTo-SecureString $password -AsPlainText -Force) -AccountExpirationDate $null -ChangePasswordAtLogon $true -Enabled $true -Path $OU -ErrorAction SilentlyContinue
 
    # Add the role as title
    if ( $role -eq $false) {
        $role = $role.Trim()
        if ($role -ne $null) {
            Set-ADUser -Identity $sam -Title $role -ErrorAction SilentlyContinue
        }
    }
 
    # Add the user to an their repective shadow and localisation group
    Add-ADGroupMember $ADShadowGroup $sam
    Add-ADGroupMember $city $sam
 
    # Create file
    New-Item $file -type file -force -value "Login credentials for $dplName
    Domain: $domain
    Login name: $sam
    One time password: $password" | out-null
}
 
Remove-Module ActiveDirectory