From an HR export to an AD account: the familiar approach
A new employee is in the HR system. IT gets an export, runs a script and the account appears in Active Directory. Getting from HR to Active Directory this way works, until the exceptions start to pile up.
Almost every IT department with on-premises Active Directory has built it at some point. HR puts new employees in an export, someone runs a script, and the script uses New-ADUser from the ActiveDirectory module to create an account in the right OU. Then the groups are added with Add-ADGroupMember, and through Entra Connect Sync or Cloud Sync the account appears in Microsoft Entra ID some time later. This article starts with that script, because it shows which decisions you have to make whichever way you go. How Joinly does this as a product is described on on-premises Active Directory.
The example below works as written, with a semicolon-separated CSV as a Dutch Excel export produces. It first checks by employee number whether the account already exists, chooses the OU by department, generates a temporary password and adds the employee to the groups for their department.
Import-Module ActiveDirectory
$domein = "bedrijf.nl"
$standaardOU = "OU=Nieuw,OU=Medewerkers,DC=bedrijf,DC=local"
$ouPerAfdeling = @{
"Financien" = "OU=Financien,OU=Medewerkers,DC=bedrijf,DC=local"
"Verkoop" = "OU=Verkoop,OU=Medewerkers,DC=bedrijf,DC=local"
"Logistiek" = "OU=Logistiek,OU=Medewerkers,DC=bedrijf,DC=local"
}
$groepenPerAfdeling = @{
"Financien" = @("GG-Financien", "GG-Alle-medewerkers")
"Verkoop" = @("GG-Verkoop", "GG-CRM-Gebruikers", "GG-Alle-medewerkers")
"Logistiek" = @("GG-Logistiek", "GG-Alle-medewerkers")
}
function New-TijdelijkWachtwoord {
$tekens = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789!#%+?"
-join (1..20 | ForEach-Object { $tekens[(Get-Random -Maximum $tekens.Length)] })
}
$regels = Import-Csv -Path "C:\HR\nieuwe-medewerkers.csv" -Delimiter ";"
foreach ($r in $regels) {
# Is there already someone with this employee number? Then create nothing.
if (Get-ADUser -Filter "EmployeeID -eq '$($r.Personeelsnummer)'") { continue }
$sam = ("{0}.{1}" -f $r.Voornaam, $r.Achternaam).ToLower() -replace "[^a-z0-9.]", ""
if (Get-ADUser -Filter "SamAccountName -eq '$sam'") { $sam = "$sam$($r.Personeelsnummer)" }
$ou = $ouPerAfdeling[$r.Afdeling]
if (-not $ou) { $ou = $standaardOU }
$wachtwoord = New-TijdelijkWachtwoord
$nieuw = @{
Name = "$($r.Voornaam) $($r.Achternaam)"
GivenName = $r.Voornaam
Surname = $r.Achternaam
DisplayName = "$($r.Voornaam) $($r.Achternaam)"
SamAccountName = $sam
UserPrincipalName = "$sam@$domein"
EmployeeID = $r.Personeelsnummer
Department = $r.Afdeling
Title = $r.Functie
Path = $ou
AccountPassword = (ConvertTo-SecureString $wachtwoord -AsPlainText -Force)
ChangePasswordAtLogon = $true
Enabled = $true
}
New-ADUser @nieuw
foreach ($groep in $groepenPerAfdeling[$r.Afdeling]) {
Add-ADGroupMember -Identity $groep -Members $sam
}
Write-Output "$sam aangemaakt in $ou"
}