Manage Shadow Group Membership - PowerShell Function
I looked at a quick script to update a shadow group here, and then thought, this would make a good function. I have used my function template (refer to that post if you want to know more about how to format a function), to build up a reusable script to update group membership based on user and computer object location in AD.
A traditional shadow group is all members of an OU. In my mind, there are a few assumptions to this statement. Being that you have taken the time to create an OU, put objects in it, and created a group to mirror those objects, you probably have only 1 type of object (i.e. user) and they are all similar in some respect (i.e. same office location). This function takes that in mind and only updates groups with users or computers - not other groups etc.
Moving away from the traditional meaning of shadow group, I have added (for my own benefit as I required the functionality) a parameter to change the searchscope from OneLevel (only objects from the OU specified) to subtree (all objects in the tree below the OU specified). Also, by default the function will get all users and computers (name -like *). If you add the -name parameter you can also filter by name, i.e. comp* (all users and computers that start with comp)
As with PowerShell v2 functions you can use get-help, copy and paste the following code in PowerShell, and then run get-help Update-ShadowGroup -detailed to see the examples I have added.
A couple of new commands (for me anyway) I have used here is write-error within try - catch. When a group or OU name is passed to the function, I try to get both the OU and the group. If the catch grabs an error, it outputs the write-error cmdlet making the function look a bit more professional.
Please send any comments!
I looked at a quick script to update a shadow group here, and then thought, this would make a good function. I have used my function template (refer to that post if you want to know more about how to format a function), to build up a reusable script to update group membership based on user and computer object location in AD.
A traditional shadow group is all members of an OU. In my mind, there are a few assumptions to this statement. Being that you have taken the time to create an OU, put objects in it, and created a group to mirror those objects, you probably have only 1 type of object (i.e. user) and they are all similar in some respect (i.e. same office location). This function takes that in mind and only updates groups with users or computers - not other groups etc.
Moving away from the traditional meaning of shadow group, I have added (for my own benefit as I required the functionality) a parameter to change the searchscope from OneLevel (only objects from the OU specified) to subtree (all objects in the tree below the OU specified). Also, by default the function will get all users and computers (name -like *). If you add the -name parameter you can also filter by name, i.e. comp* (all users and computers that start with comp)
As with PowerShell v2 functions you can use get-help, copy and paste the following code in PowerShell, and then run get-help Update-ShadowGroup -detailed to see the examples I have added.
A couple of new commands (for me anyway) I have used here is write-error within try - catch. When a group or OU name is passed to the function, I try to get both the OU and the group. If the catch grabs an error, it outputs the write-error cmdlet making the function look a bit more professional.
Please send any comments!
function Update-ShadowGroup {
<#
.SYNOPSIS
Updates a shadow group membership based on the user or computer objects within an ou
.DESCRIPTION
Better description
.NOTES
Function Name : Update-ShadowGroup
Author : Adam Stone
Requires : PowerShell V2 with AD management pack
.LINK
http://adadmin.blogspot.com/
.EXAMPLE
Simple usage
PS C:\> Update-ShadowGroup -ou "OU=ShadowOU,OU=Test,DC=domain,DC=com" -group shadowgroup
.EXAMPLE
Simple usage
PS C:\> Update-ShadowGroup "OU=ShadowOU,OU=Test,DC=domain,DC=com" shadowgroup
.EXAMPLE
Specify SearchScope
PS C:\> Update-ShadowGroup "OU=ShadowOU,OU=Test,DC=domain,DC=com" shadowgroup -searchscope Subtree
.EXAMPLE
Specify name filter
PS C:\> Update-ShadowGroup "OU=ShadowOU,OU=Test,DC=domain,DC=com" shadowgroup -name srv*
.PARAMETER OU
DN of the OU - required
.PARAMETER Group
Name of the Group - required
.PARAMETER Name
Search pattern to match for the object name
.PARAMETER SearchScope
Can be either "Base" "OneLevel" or "Subtree" - default OneLevel
#>
param (
[Parameter(Position=0, Mandatory=$true,HelpMessage="Enter the DN of the OU (eg ou=test,dc=domain,dc=com)")]
[string] $ou = ""
,
[Parameter(Position=1, Mandatory=$true,HelpMessage="Enter the name of the group (eg group1)")]
[string] $Group = ""
,
[Parameter(Mandatory=$false)]
#valadate the input against defined set of attributes
[string] $name = "*"
,
[Parameter(Mandatory=$false)]
#valadate the input against defined set of attributes
[validateset("Base","OneLevel","Subtree")]
[string] $searchscope = "OneLevel"
)
#the processes the function will complete
process {
try{
$getOU = Get-ADOrganizationalUnit $ou
}
catch {
write-error -message "OU $ou does not exist" -RecommendedAction "Make sure the OU is spelt correctly and try again" ;break
}
try{
$getgroup = get-adgroup $group
}
catch {
write-error -message "Group $group does not exist" -RecommendedAction "Make sure the Group name is spelt correctly and try again" ;break
}
$objects = $(get-adobject -SearchBase $OU -SearchScope $searchscope -filter {((ObjectCategory -eq "user") -or (ObjectCategory -eq "computer")) -and (name -like $name)})
$groupmembers = Get-ADGroupMember -Identity $Group
If ($objects -eq $null -and $groupmembers -eq $null){break}
If ($objects -eq $null){remove-adgroupmember -identity $group -member $groupmembers -confirm:$false;write-host "$OU was empty, all objects removed"}
If ($groupmembers -eq $null){
add-adgroupmember -identity $group -member $objects;write-host "$group was empty, all objects added"
}Else{
switch (Compare-Object -ReferenceObject $groupmembers -DifferenceObject $objects -property name){
{$_.SideIndicator -eq "=>"} {add-adgroupmember -identity $group -member $(get-adobject -LDAPFilter "(name=$($_.name)*)"); write-host "$($_.name) added to $group"}
{$_.SideIndicator -eq "<="} {remove-adgroupmember -identity $group -member $(get-adobject -LDAPFilter "(name=$($_.name)*)") -confirm:$false; write-host "$($_.name) removed to $group"}
}
}
}
}#end function
I would like to make this automated by task manager where the OU and subtree get added to an group. suggestions?
ReplyDeleteThis is precisely the way i use this function. Some of the things to consider...
DeleteYou will need an account to run the task with that has permission to update the group membership of the shadow groups, nothing more as all accounts have read only access to AD.
It is best to run this sort of task on a server, preferably not a domain controller. If you do this, the account will need the ability to start a scheduled task. This can be achieved by adding them to the Admin group, but normally (depending on OS version) adding them to allow this account to start as a batch is good enough.
hopefully this helps!
cheers