User management functions
This commit is contained in:
73
Azure/User-Management/Export-EntraActiveUsers.ps1
Normal file
73
Azure/User-Management/Export-EntraActiveUsers.ps1
Normal file
@@ -0,0 +1,73 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Exports all active Entra ID users and their attributes to a CSV file.
|
||||
|
||||
.DESCRIPTION
|
||||
Connects to Microsoft Graph, retrieves all users where AccountEnabled is true,
|
||||
and exports every available attribute to a timestamped CSV file in an \Exports subfolder.
|
||||
|
||||
.PARAMETER ExportPath
|
||||
The subfolder name where the CSV will be saved. Defaults to 'Exports'.
|
||||
|
||||
.EXAMPLE
|
||||
Export-EntraActiveUsers
|
||||
#>
|
||||
function Export-EntraActiveUsers {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$ExportPathName = "Exports"
|
||||
)
|
||||
|
||||
process {
|
||||
Set-StrictMode -Version Latest
|
||||
|
||||
# 1. Setup Paths and Directories
|
||||
$BasePath = $PSScriptRoot
|
||||
if ([string]::IsNullOrWhiteSpace($BasePath)) {
|
||||
$BasePath = Get-Location
|
||||
}
|
||||
|
||||
$TargetDirectory = Join-Path -Path $BasePath -ChildPath $ExportPathName
|
||||
$Timestamp = Get-Date -Format "yyyyMMdd-HHmm"
|
||||
$FileName = "EntraID_ActiveUsers_$Timestamp.csv"
|
||||
$FullFilePath = Join-Path -Path $TargetDirectory -ChildPath $FileName
|
||||
|
||||
try {
|
||||
Write-Verbose "Ensuring directory exists: $TargetDirectory"
|
||||
if (-not (Test-Path -Path $TargetDirectory)) {
|
||||
New-Item -Path $TargetDirectory -ItemType Directory -Force | Out-Null
|
||||
}
|
||||
|
||||
# 2. Check for Microsoft Graph Connection
|
||||
Write-Verbose "Checking Microsoft Graph connection..."
|
||||
$CurrentContext = Get-MgContext
|
||||
if (-not $CurrentContext) {
|
||||
throw "No active Microsoft Graph connection found. Please run 'Connect-MgGraph' first."
|
||||
}
|
||||
|
||||
# 3. Retrieve Active Users
|
||||
# We filter for AccountEnabled eq true and select all properties (*)
|
||||
Write-Verbose "Fetching active users from Entra ID..."
|
||||
$UserFilter = "accountEnabled eq true"
|
||||
|
||||
# Using -All to ensure we bypass the default page size limits
|
||||
$Users = Get-MgUser -Filter $UserFilter -Property "*" -All -ErrorAction Stop
|
||||
|
||||
if ($null -eq $Users -or $Users.Count -eq 0) {
|
||||
Write-Warning "No active users found in the tenant."
|
||||
return
|
||||
}
|
||||
|
||||
Write-Verbose "Found $($Users.Count) users. Exporting to $FullFilePath..."
|
||||
|
||||
# 4. Export to CSV
|
||||
$Users | Export-Csv -Path $FullFilePath -NoTypeInformation -Encoding utf8
|
||||
|
||||
Write-Output "Export successfully completed: $FullFilePath"
|
||||
}
|
||||
catch {
|
||||
Write-Error "An error occurred during export: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
}
|
||||
28
Azure/User-Management/README.md
Normal file
28
Azure/User-Management/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# User Management Modules
|
||||
These script were written with the use of Gemini and are provided as is. Please test them before using anything in production
|
||||
|
||||
## Prerequisites
|
||||
For running the Modules you need the MSGraph Powershell module installed. Use the command below to install it if not already present on your system
|
||||
```
|
||||
Install-Module -Name Microsoft.Graph
|
||||
```
|
||||
|
||||
## Export Active user
|
||||
Use the following commands to connect to the Graph APi and to export all active users including their attributes.
|
||||
```
|
||||
# Authenticate
|
||||
Connect-MgGraph -Scopes "User.Read.All"
|
||||
|
||||
# Run the function with Verbose output to see progress
|
||||
Export-EntraActiveUsers -Verbose
|
||||
```
|
||||
|
||||
## Update Users
|
||||
In order to update the users, change all attributes you want to change in the CSV and run the following commands. Change the path of the source file.
|
||||
```
|
||||
# Authenticate
|
||||
Connect-MgGraph -Scopes "User.ReadWrite.All"
|
||||
|
||||
# Run the update with overwrite capability
|
||||
Update-EntraUsersOverwrite -CsvPath "$PSScriptRoot\Exports\MasterUserList.csv" -Verbose
|
||||
```
|
||||
90
Azure/User-Management/Update-EntraUsersDynamic.ps1
Normal file
90
Azure/User-Management/Update-EntraUsersDynamic.ps1
Normal file
@@ -0,0 +1,90 @@
|
||||
<#
|
||||
.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 -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 -Property $Columns -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)"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user