Here’s a Powershell script I wrote to delegate permissions to a service account to manage user objects within a number of OUs. The script takes as input a file containing the distinguished names (DNs) of the OUs. The approach should be reasonably obvious from the comments in the script. The only complexity comes from having to get the correct System.DirectoryServices syntax for the Access Control Entries (ACEs).
#########################################################
#
# Name: Add-UserOUACEs.ps1
# Author: Tony Murray
# Version: 1.0
# Date: 16/04/2012
# Comment: PowerShell script to add Access Control
# entries to a target object
#
#########################################################
Write-Verbose "Script starting..."
# Import the AD module
ipmo ActiveDirectory
# Set the verbosity preference
$VerbosePreference = "Continue" # Default is "SilentlyContinue", i.e. no verbosity
### Set Global Variables
# Specify the import file to use
$impfile = "c:\User_OUs.txt"
# Specify the security principal to which perms will be granted
$svc = Get-ADUser MyServiceAccount
# Get the SID of the security principal
$sid = new-object System.Security.Principal.SecurityIdentifier $svc.SID
###
# Change to the AD drive
CD AD:
$ous = Import-Csv $impfile
foreach ($dn in $ous) {
$ou = $dn.distinguishedname
## Get the DACL of the OU
$acl = get-acl $ou
## Note that bf967aba-0de6-11d0-a285-00aa003049e2 is the schemaIDGuid for the user object class.
$guid = new-object Guid bf967aba-0de6-11d0-a285-00aa003049e2
# ACE for creating and deleting child User objects
$ace1 = new-object System.DirectoryServices.ActiveDirectoryAccessRule $sid,"CreateChild,DeleteChild","Allow",$guid
# ACE for full control over descendent User objects
$ace2 = new-object System.DirectoryServices.ActiveDirectoryAccessRule $sid,"GenericAll","Allow","Descendents ",$guid
## Add the ACE in the ACL and set the ACL on the object
$acl.AddAccessRule($ace1)
$acl.AddAccessRule($ace2)
Write-Verbose "Adding ACEs to ACL on $ou"
set-acl -aclobject $acl $ou
# Clean up variables used in ForEach loop
Clear-Variable -ErrorAction SilentlyContinue -Name dn
Clear-Variable -ErrorAction SilentlyContinue -Name ou
Clear-Variable -ErrorAction SilentlyContinue -Name acl
Clear-Variable -ErrorAction SilentlyContinue -Name guid
Clear-Variable -ErrorAction SilentlyContinue -Name ace1
Clear-Variable -ErrorAction SilentlyContinue -Name ace2
} # End foreach loop
# Clean up Global Variables
Write-Verbose "Cleaning global variables..."
Clear-Variable -ErrorAction SilentlyContinue -Name impfile
Clear-Variable -ErrorAction SilentlyContinue -Name sid
Clear-Variable -ErrorAction SilentlyContinue -Name svc
Clear-Variable -ErrorAction SilentlyContinue -Name ous
# End
Write-Verbose "Script finished"
$VerbosePreference = "SilentlyContinue"
