Zoho Banner September 2011

Archive for April, 2012

Here’s a handy Powershell script to check for duplicate attribute values on AD objects.  Why is this useful?  Well, you might have provisioning systems that assign unique values (e.g. employeeID) to AD objects.  Things can start to go wrong if it turns out that more than one object has been assigned the same attribute value.  In the example below, I have used the adminDisplayname attribute, but you can easily change this to your attribute of choice.

# Import the AD Powershell module
ipmo ActiveDirectory
# Create an array from LDAP search
$adobjs = Get-ADObject -LDAPFilter "(admindisplayname=*)" -pr admindisplayname `
| Select-Object -ExpandProperty admindisplayname
# Create a new empty hash table object
$hash = @{}
# Add each item from the LDAP results to the hash table
$adobjs | % {$hash["$_"] += 1}
# Find the duplicates by examining the hash table
$hash.keys | ? {$hash["$_"] -gt 1} `
| % {write-host "Duplicate attribute value found: $_" }

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"