Public/OU/Set-AdAclCreateDeleteOU.ps1
function Set-AdAclCreateDeleteOU { <# .SYNOPSIS Delegates permissions to create and delete Organizational Units (OUs). .DESCRIPTION The Set-AdAclCreateDeleteOU function delegates permissions to a specified security group to create and delete Organizational Unit (OU) objects within a designated container in Active Directory. This function simplifies the process of delegating OU management by: - Adding the necessary Access Control Entries (ACEs) to allow OU creation - Adding permissions to delete OUs, including tree deletion - Setting the correct inheritance flags to control permission scope - Supporting removal of these delegated permissions when needed The function is part of a comprehensive delegation model that allows for granular permission assignments in Active Directory environments. .PARAMETER Group Specifies the security group that will receive (or from which will be removed) the permissions to create and delete OUs. This parameter accepts: - Security group name (SAM account name) - Distinguished Name - Security Identifier (SID) - Group object from Get-ADGroup .PARAMETER LDAPpath Specifies the Distinguished Name (DN) of the container or OU where the group will be able to create and delete OUs. This is the target location for the permission delegation. .PARAMETER RemoveRule When specified, removes the previously granted permissions for creating and deleting OUs instead of adding them. Use this parameter to revoke previously delegated permissions. .PARAMETER Force When specified, suppresses confirmation prompts when performing the permission changes. Use this parameter in automation scenarios where no user interaction is desired. .EXAMPLE Set-AdAclCreateDeleteOU -Group "SG_SiteAdmins_XXXX" -LDAPPath "OU=Users,OU=XXXX,OU=Sites,DC=EguibarIT,DC=local" Delegates permissions to the SG_SiteAdmins_XXXX group to create and delete OUs within the specified OU. .EXAMPLE Set-AdAclCreateDeleteOU -Group "SG_SiteAdmins_XXXX" -LDAPPath "OU=Users,OU=XXXX,OU=Sites,DC=EguibarIT,DC=local" -RemoveRule Removes the permissions for the SG_SiteAdmins_XXXX group to create and delete OUs within the specified OU. .EXAMPLE $Splat = @{ Group = "SG_SiteAdmins_XXXX" LDAPPath = "OU=Users,OU=XXXX,OU=Sites,DC=EguibarIT,DC=local" Force = $true } Set-AdAclCreateDeleteOU @Splat Delegates OU creation/deletion permissions without prompting for confirmation. .INPUTS System.String Microsoft.ActiveDirectory.Management.ADGroup You can pipe group names or Group objects from Get-ADGroup to this function. .OUTPUTS System.Void This function does not generate any output. .NOTES Used Functions: Name ║ Module/Namespace ═══════════════════════════════════════════╬══════════════════════════════ Set-AclConstructor5 ║ EguibarIT.DelegationPS Set-AclConstructor6 ║ EguibarIT.DelegationPS Get-AttributeSchemaHashTable ║ EguibarIT.DelegationPS Get-AdObjectType ║ EguibarIT.DelegationPS Write-Verbose ║ Microsoft.PowerShell.Utility Test-IsValidDN ║ EguibarIT.DelegationPS .NOTES Version: 2.0 DateModified: 22/May/2025 LastModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar IT http://www.eguibarit.com .LINK https://github.com/vreguibar/EguibarIT.DelegationPS .COMPONENT Active Directory .ROLE Security Administration .FUNCTIONALITY OU Management, Delegation of Control #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] [OutputType([void])] param ( # PARAM1 STRING for the Delegated Group Name [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Group Name which will get the delegation', Position = 0)] [ValidateNotNullOrEmpty()] [Alias('IdentityReference', 'Identity', 'Trustee', 'GroupID')] $Group, #PARAM2 Distinguished Name of the OU were the groups can be changed [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Distinguished Name of the OU that can be Changed', Position = 1)] [ValidateNotNullOrEmpty()] [ValidateScript({ Test-IsValidDN -ObjectDN $_ }, ErrorMessage = 'DistinguishedName provided is not valid! Please Check.')] [Alias('DN', 'DistinguishedName')] [String] $LDAPpath, # PARAM3 SWITCH If present, the access rule will be removed. [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'If present, the access rule will be removed.', Position = 2)] [ValidateNotNullOrEmpty()] [Switch] $RemoveRule, [Parameter(Mandatory = $false, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $false, HelpMessage = 'If present, the function will not ask for confirmation when performing actions.', Position = 3)] [Switch] $Force ) Begin { Set-StrictMode -Version Latest # Display function header if variables exist if ($null -ne $Variables -and $null -ne $Variables.HeaderDelegation) { $txt = ($Variables.HeaderDelegation -f (Get-Date).ToString('dd/MMM/yyyy'), $MyInvocation.Mycommand, (Get-FunctionDisplay -HashTable $PsBoundParameters -Verbose:$False) ) Write-Verbose -Message $txt } #end if ############################## # Module imports ############################## # Variables Definition [Hashtable]$Splat = [hashtable]::New([StringComparer]::OrdinalIgnoreCase) Write-Verbose -Message 'Checking variable $Variables.GuidMap. In case is empty a function is called to fill it up.' Get-AttributeSchemaHashTable # Verify Group exist and return it as Microsoft.ActiveDirectory.Management.AdGroup $CurrentGroup = Get-AdObjectType -Identity $PSBoundParameters['Group'] } #end Begin Process { <# ACE number: 1 -------------------------------------------------------- IdentityReference : XXX ActiveDirectoryRights : CreateChild, DeleteChild AccessControlType : Allow ObjectType : GuidNULL InheritanceType : Descendents InheritedObjectType : organizationalUnit [ClassSchema] IsInherited = False #> $Splat = @{ Id = $CurrentGroup LDAPPath = $PSBoundParameters['LDAPpath'] AdRight = 'CreateChild', 'DeleteChild' AccessControlType = 'Allow' ObjectType = $Variables.GuidMap['All'] AdSecurityInheritance = 'Descendents' InheritedObjectType = $Variables.GuidMap['organizationalUnit'] } # Check if RemoveRule switch is present. If ($PSBoundParameters['RemoveRule']) { if ($Force -or $PSCmdlet.ShouldProcess($PSBoundParameters['Group'], 'Remove permissions for organizationalUnit?')) { # Add the parameter to remove the rule $Splat.Add('RemoveRule', $true) } #end If } #end If If ($Force -or $PSCmdlet.ShouldProcess($PSBoundParameters['Group'], 'Delegate the permissions for organizationalUnit?')) { Set-AclConstructor6 @Splat } #end If <# ACE number: 2 -------------------------------------------------------- IdentityReference : XXX ActiveDirectoryRights : CreateChild, DeleteChild AccessControlType : Allow ObjectType : organizationalUnit [ClassSchema] InheritanceType : All InheritedObjectType : GuidNULL IsInherited = False #> $Splat = @{ Id = $CurrentGroup LDAPPath = $PSBoundParameters['LDAPpath'] AdRight = 'CreateChild', 'DeleteChild' AccessControlType = 'Allow' ObjectType = $Variables.GuidMap['organizationalUnit'] AdSecurityInheritance = 'All' } # Check if RemoveRule switch is present. If ($PSBoundParameters['RemoveRule']) { if ($Force -or $PSCmdlet.ShouldProcess($PSBoundParameters['Group'], 'Remove permissions for organizationalUnit?')) { # Add the parameter to remove the rule $Splat.Add('RemoveRule', $true) } #end If } #end If If ($Force -or $PSCmdlet.ShouldProcess($PSBoundParameters['Group'], 'Delegate the permissions for organizationalUnit?')) { Set-AclConstructor5 @Splat } #end If <# ACE number: 3 -------------------------------------------------------- IdentityReference : XXX ActiveDirectoryRights : CreateChild, DeleteChild AccessControlType : Allow ObjectType : account [ClassSchema] InheritanceType : Descendents InheritedObjectType : organizationalUnit [ClassSchema] IsInherited = False #> $Splat = @{ Id = $CurrentGroup LDAPPath = $PSBoundParameters['LDAPpath'] AdRight = 'CreateChild', 'DeleteChild' AccessControlType = 'Allow' ObjectType = $Variables.GuidMap['account'] AdSecurityInheritance = 'Descendents' InheritedObjectType = $Variables.GuidMap['organizationalUnit'] } # Check if RemoveRule switch is present. If ($PSBoundParameters['RemoveRule']) { if ($Force -or $PSCmdlet.ShouldProcess($PSBoundParameters['Group'], 'Remove permissions for account?')) { # Add the parameter to remove the rule $Splat.Add('RemoveRule', $true) } #end If } #end If If ($Force -or $PSCmdlet.ShouldProcess($PSBoundParameters['Group'], 'Delegate the permissions for account?')) { Set-AclConstructor6 @Splat } #end If } #end Process End { if ($RemoveRule) { Write-Verbose ('Permissions removal process completed for group: {0} on {1}' -f $PSBoundParameters['Group'], $PSBoundParameters['LDAPpath']) } else { Write-Verbose ('Permissions delegation process completed for group: {0} on {1}' -f $PSBoundParameters['Group'], $PSBoundParameters['LDAPpath']) } #end If-Else $txt = ($Variables.FooterDelegation -f $MyInvocation.InvocationName, 'delegating Create/Delete OU.' ) Write-Verbose -Message $txt Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished delegating Create/Delete OU." Write-Verbose -Message '' Write-Verbose -Message '--------------------------------------------------------------------------------' Write-Verbose -Message '' } #end END } |