public/Update-GWADObject.ps1
<#
.SYNOPSIS Updates the user principal name and organizational unit of an AD object or collection of AD objects .DESCRIPTION This function updates the UserPrincipalName and OrganizationalUnit of user accounts, groups and devices. It supports two modes of operation: - You can provide individual parameters for a single object - You can provide a collection of objects, each containing the properties to be updated. .PARAMETER Identity The identity of the object. This can be a UserPrincipalName, a SamAccountName or a Name. The function will try to find a unique match for that in the current domain, This parameter is used in the 'ByParameters' parameter set. .PARAMETER UserPrincipalName The new UserPrincipalName for the object. This parameter is used in the 'ByParameters' parameter set. .PARAMETER OrganizationalUnit The new Organizational Unit to which the object should be moved. This parameter is used in the 'ByParameters' parameter set. .PARAMETER InputObject A collection of objects where each object has properties 'Identity', 'UserPrincipalName', and 'OrganizationalUnit'. This parameter is used in the 'ByObject' parameter set and supports pipeline input. .PARAMETER Force Force updating the object so that it doesn't ask you to confirm each one (alternative to -Confirm:$False) .EXAMPLE Update-GWADObject -Identity "user1@domain.com" -UserPrincipalName "user1.new@domain.com" -OrganizationalUnit "OU=NewOU,DC=domain,DC=com" Description: This example updates a single object's User Principal Name and moves the object to a new Organizational Unit. .EXAMPLE $objects = @( [PSCustomObject]@{Identity = "user2@domain.com"; UserPrincipalName = "user2.new@domain.com"; OrganizationalUnit = "OU=NewOU,DC=domain,DC=com"}, [PSCustomObject]@{Identity = "Group Name"; UserPrincipalName = $null; OrganizationalUnit = "OU=NewOU,DC=domain,DC=com"} ) $objects | Update-GWADObject Description: This example takes a collection of objects from a pipeline and updates their User Principal Name and/or Organizational Unit .NOTES You can use this function in two ways: by specifying individual parameters for one object or by passing a collection of objects representing multiple objects. .LINK https://geekwolf.cloud/something #> Function Update-GWADObject { [CmdletBinding( DefaultParameterSetName = 'ByParameters', SupportsShouldProcess, ConfirmImpact = 'High') ] param ( # Parameter set for passing individual parameters [Parameter(ParameterSetName = 'ByParameters', Mandatory = $true)] [string]$Identity, [Parameter(ParameterSetName = 'ByParameters', Mandatory = $false)] [string]$UserPrincipalName = $null, [Parameter(ParameterSetName = 'ByParameters', Mandatory = $false)] [string]$OrganizationalUnit = $null, # Parameter set for passing a collection of objects [Parameter(ParameterSetName = 'ByObject', Mandatory = $true, ValueFromPipeline = $true)] [PSObject[]]$InputObject, [Parameter(ParameterSetName = 'ByObject', Mandatory = $false)] [Parameter(ParameterSetName = 'ByParameters', Mandatory = $false)] [switch]$Force ) process { if ($Force -and -not $Confirm){ $ConfirmPreference = 'None' } if ($PSCmdlet.ParameterSetName -eq 'ByParameters') { $ObjectsToProcess = @( @{ Identity=$Identity; UserPrincipalName=$UserPrincipalName; OrganizationalUnit=$OrganizationalUnit } ) } elseif ($PSCmdlet.ParameterSetName -eq 'ByObject') { $ObjectsToProcess = $InputObject } foreach( $ObjectToProcess in $ObjectsToProcess ) { if( [string]::IsNullOrEmpty($ObjectToProcess.Identity) ) { $ObjectsFound = @(Get-ADObject -LDAPFilter ` "(&(|(objectClass=group)(objectClass=user)(objectClass=computer))(anr=$($ObjectToProcess.Identity)))") } else { $ObjectsFound = @(Get-ADObject -LDAPFilter ` "(&(|(objectClass=group)(objectClass=user)(objectClass=computer))(|(userprincipalname=$($ObjectToProcess.Identity))(anr=$($ObjectToProcess.Identity))))") } if( $ObjectsFound.Count -gt 1 ) { # do we have exact match on UPN $Object = @($ObjectsFound | Where-Object { $_.userPrincipalName -eq $ObjectToProcess.Identity }) # if not, do we have exact match on samAccountName if( $Object.count -ne 1 ) { $Object = @($ObjectsFound | Where-Object { $_.SamAccountName -eq $ObjectToProcess.Identity }) } # if not, do we have exact match on Name if( $Object.count -ne 1 ) { $Object = @($ObjectsFound | Where-Object { $_.Name -eq $ObjectToProcess.Identity }) } if( $Object.Count -eq 1 ) { $ObjectsFound = $Object } } $ResultMessage = "" $Succeeded = $True Switch( $ObjectsFound.count ) { 0 { Write-Verbose "No object found for [$($ObjectToProcess.Identity)]" $ResultMessage += "[No such object found]" $Succeeded = $False } 1 { # Validate the OU if it was provided if( [string]::IsNullOrEmpty( $ObjectToProcess.OrganizationalUnit ) -eq $false ) { try { $ADOrganizationalUnit = @(Get-ADObject -Identity $ObjectToProcess.OrganizationalUnit -ErrorAction SilentlyContinue) } catch { $ADOrganizationalUnit = @() } if( $ADOrganizationalUnit.count -eq 0 ) { Write-Verbose "Unable to move [$($ObjectToProcess.Identity)] to [$($ObjectToProcess.OrganizationalUnit)] as OU does not exist" $ResultMessage += "[Object Move Failed OU does not exist]" $Succeeded = $False } } if( $PSCmdLet.ShouldProcess($ObjectToProcess.Identity) ){ # Update the UPN if it was provided if( [string]::IsNullOrEmpty( $ObjectToProcess.UserPrincipalName ) -eq $false ) { try { Set-ADObject -Identity $ObjectsFound[0].ObjectGUID -Replace @{userPrincipalName=$($ObjectToProcess.UserPrincipalName)} | Out-Null $ResultMessage += "[Object Updated Successfully]" } catch { Write-Verbose "Unable to rename [$($ObjectToProcess.Identity)] to [$($ObjectToProcess.UserPrincipalName)] exception: $($_.Exception)" $ResultMessage += "[Object Update Failed ($($_.Exception))]" $Succeeded = $False } } # Update the OU if it was provided if( [string]::IsNullOrEmpty( $ObjectToProcess.OrganizationalUnit ) -eq $false ) { if( $ADOrganizationalUnit.count -eq 1 ) { try { Move-ADObject -Identity $ObjectsFound[0].ObjectGUID -TargetPath $ObjectToProcess.OrganizationalUnit | Out-Null $ResultMessage += "[Object Moved Successfully]" } catch { Write-Verbose "Unable to move [$($ObjectToProcess.Identity)] to [$($ObjectToProcess.OrganizationalUnit)] exception: $($_.Exception)" $ResultMessage += "[Object Move Failed ($($_.Exception))]" $Succeeded = $False } } } } } default { Write-Verbose "Multiple objects found for [$($ObjectToProcess.Identity)]" $ResultMessage += "[Multiple objects found]" $Succeeded = $False } } New-Object PSObject -Property @{ Identity = $ObjectToProcess.Identity; UserPrincipalName = $ObjectToProcess.UserPrincipalName; OrganizationalUnit = $ObjectToProcess.OrganizationalUnit; Succeeded = $Succeeded; ResultMessage = $ResultMessage -replace "`r`n", "\r\n" } } } } |