90 lines
3.4 KiB
PowerShell
90 lines
3.4 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Updates Entra ID users based on all available columns in a CSV file.
|
|
|
|
.DESCRIPTION
|
|
Dynamically maps CSV headers to Microsoft Graph User properties.
|
|
Compares CSV values to live data and updates only when a difference is found.
|
|
|
|
.PARAMETER CsvPath
|
|
The full path to the source CSV file.
|
|
|
|
.EXAMPLE
|
|
Update-EntraUsersDynamic -CsvPath ".\Exports\UserUpdate_20260226.csv"
|
|
#>
|
|
function Update-EntraUsersDynamic {
|
|
[CmdletBinding()]
|
|
param (
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateScript({ Test-Path $_ })]
|
|
[string]$CsvPath
|
|
)
|
|
|
|
process {
|
|
Set-StrictMode -Version Latest
|
|
|
|
# 1. Setup Logging
|
|
$LogPath = Join-Path -Path $PSScriptRoot -ChildPath "Logs"
|
|
if (-not (Test-Path $LogPath)) { New-Item -Path $LogPath -ItemType Directory -Force | Out-Null }
|
|
|
|
$Timestamp = Get-Date -Format "yyyyMMdd-HHmm"
|
|
$LogFile = Join-Path -Path $LogPath -ChildPath "DynamicUpdate_$Timestamp.log"
|
|
|
|
try {
|
|
# 2. Load Data and Headers
|
|
$UserData = Import-Csv -Path $CsvPath
|
|
$Columns = $UserData[0].PSObject.Properties.Name
|
|
|
|
# Attributes we should NOT try to update
|
|
$ExcludedAttributes = @('UserPrincipalName', 'Id', 'DeletedDateTime', 'CreatedDateTime')
|
|
|
|
if (-not (Get-MgContext)) { throw "Not connected to Microsoft Graph. Run Connect-MgGraph." }
|
|
|
|
foreach ($Row in $UserData) {
|
|
$UPN = $Row.UserPrincipalName
|
|
if ([string]::IsNullOrWhiteSpace($UPN)) { continue }
|
|
|
|
try {
|
|
# 3. Fetch current user with all properties defined in CSV headers
|
|
Write-Verbose "Processing $UPN..."
|
|
$CurrentTarget = Get-MgUser -UserId $UPN -ErrorAction Stop
|
|
|
|
$UpdateHash = @{}
|
|
|
|
foreach ($Col in $Columns) {
|
|
# Skip excluded columns and empty CSV cells
|
|
if ($Col -in $ExcludedAttributes -or [string]::IsNullOrWhiteSpace($Row.$Col)) {
|
|
continue
|
|
}
|
|
|
|
# 4. Compare CSV value to Current Entra ID value
|
|
$CsvValue = $Row.$Col
|
|
$CurrentValue = $CurrentTarget.$Col
|
|
|
|
if ($CsvValue -ne $CurrentValue) {
|
|
$UpdateHash[$Col] = $CsvValue
|
|
}
|
|
}
|
|
|
|
# 5. Execute Update if changes exist
|
|
if ($UpdateHash.Count -gt 0) {
|
|
Update-MgUser -UserId $UPN @UpdateHash -ErrorAction Stop
|
|
Write-Output "SUCCESS: Updated $UPN ($($UpdateHash.Keys -join ', '))"
|
|
"$Timestamp,$UPN,Updated,$($UpdateHash.Keys -join ';')" | Out-File $LogFile -Append
|
|
}
|
|
else {
|
|
Write-Verbose "SKIP: No changes for $UPN"
|
|
"$Timestamp,$UPN,NoChange,Matched" | Out-File $LogFile -Append
|
|
}
|
|
}
|
|
catch {
|
|
Write-Warning "ERROR: Could not update $UPN - $($_.Exception.Message)"
|
|
"$Timestamp,$UPN,Error,$($_.Exception.Message)" | Out-File $LogFile -Append
|
|
}
|
|
}
|
|
}
|
|
catch {
|
|
Write-Error "Fatal Script Error: $($_.Exception.Message)"
|
|
}
|
|
}
|
|
} |