functions/acl/Set-AdsOwner.ps1
function Set-AdsOwner { <# .SYNOPSIS Changes the owner of the specified AD object to the target identity. .DESCRIPTION Changes the owner of the specified AD object to the target identity. .PARAMETER Path Path to the object to update .PARAMETER Identity Identity to make the new owner. .PARAMETER WinRMFailover Whether on execution error it should try again using WinRM. Default-Value determined using the configuration setting 'ADSec.WinRM.FailOver' .PARAMETER Server The server / domain to connect to. .PARAMETER Credential The credentials to use for AD operations. .PARAMETER EnableException This parameters disables user-friendly warnings and enables the throwing of exceptions. This is less user friendly, but allows catching exceptions in calling scripts. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .EXAMPLE PS C:\> Set-AdsOwner -Path $dn -Identity 'contoso\Domain Admins' Makes the domain admins owner of the path specified in $dn #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseUsingScopeModifierInNewRunspaces', '')] [CmdletBinding(SupportsShouldProcess = $true)] Param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [Alias('DistinguishedName')] [string[]] $Path, [Parameter(Mandatory = $true)] [string] $Identity, [switch] $WinRMFailover = (Get-PSFConfigValue -FullName 'ADSec.WinRM.FailOver'), [string] $Server, [System.Management.Automation.PSCredential] $Credential, [switch] $EnableException ) begin { $adParameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential Assert-ADConnection @adParameters -Cmdlet $PSCmdlet if ($Identity -as [System.Security.Principal.SecurityIdentifier]) { $idReference = [System.Security.Principal.SecurityIdentifier]$Identity } else { $idReference = [System.Security.Principal.NTAccount]$Identity try { $null = $idReference.Translate([System.Security.Principal.SecurityIdentifier]) } catch { Stop-PSFFunction -String 'Set-AdsOwner.UnresolvedIdentity' -StringValues $Identity -EnableException $EnableException -ErrorRecord $_ -OverrideExceptionMessage return } } $basePath = 'LDAP://{0}' if ($Server) { $basePath = "LDAP://$Server/{0}" } } process { if (Test-PSFFunctionInterrupt) { return } foreach ($pathItem in $Path) { $aclObject = Get-AdsAcl @adParameters -Path $pathItem if ($aclObject.Owner -eq $idReference) { Write-PSFMessage -String 'Set-AdsOwner.AlreadyOwned' -StringValues $pathItem, $idReference continue } # Switching to LDAP as owner changes don't work using AD Module if ($Credential) { $directoryEntry = New-Object System.DirectoryServices.DirectoryEntry(($basePath -f $pathItem), $Credential.UserName, $Credential.GetNetworkCredential().Password) } else { $directoryEntry = New-Object System.DirectoryServices.DirectoryEntry(($basePath -f $pathItem)) } Invoke-PSFProtectedCommand -ActionString 'Set-AdsOwner.UpdatingOwner' -ActionStringValues $idReference -ScriptBlock { try { $secDescriptor = $directoryEntry.InvokeGet('nTSecurityDescriptor') if (-not $secDescriptor) { throw 'Failed to access security information' } $secDescriptor.Owner = "$idReference" $directoryEntry.InvokeSet('nTSecurityDescriptor', $secDescriptor) $directoryEntry.CommitChanges() } catch { if (-not $WinRMFailover) { throw } #region Fallback to WinRM $domainController = Get-ADDomainController @adParameters $credParam = $PSBoundParameters | ConvertTo-PSFHashtable -Include Credential $ldapPath = "LDAP://localhost/$($pathItem)" Invoke-Command -ComputerName $domainController.HostName @credParam -ScriptBlock { param ( $Identity, $LdapPath ) try { $directoryEntry = New-Object System.DirectoryServices.DirectoryEntry($LdapPath) $secDescriptor = $directoryEntry.InvokeGet('nTSecurityDescriptor') if (-not $secDescriptor) { throw 'Failed to access security information' } $secDescriptor.Owner = $Identity $directoryEntry.InvokeSet('nTSecurityDescriptor', $secDescriptor) $directoryEntry.CommitChanges() } catch { throw } } -ArgumentList "$idReference", $ldapPath -ErrorAction Stop #endregion Fallback to WinRM } } -Target $pathItem -EnableException $EnableException.ToBool() -Continue -PSCmdlet $PSCmdlet } } } |