We help IT Professionals succeed at work.

Create/manage shadow groups by script

Medium Priority
2,344 Views
Last Modified: 2012-05-11
Hey

I'm looking for a script for managing my shadow groups in Active Directory.

Company -> Dep1 -> Tech
Company -> Dep1 -> Users
Company -> Dep2 -> Tech
Company -> Dep2 -> Users

I would like to have:

Shadow Group Company (all users - including sub ou's)
Shadow Group Company, Dep1 (all users in Dep1 - including sub ou's)
Shadow Group Company, Dep1, Tech (all users in Tech)
... etc. etc...

I have found this: http://www.sole.dk/post/active-directory-shadow-group-script-will-let-you-spend-less-time-on-updating-group-memberships/?p=446

... but I need to have the full OU in the shadow group name

Thanks in advance.

Mike
Comment
Watch Question

Commented:
Do you have Windows Server 2008 R2 DCs or can we use Quest's AD PowerShell snapin?

Author

Commented:
Yes running 2008 R2 DCs...

Commented:
If you run and define the function defined in the attached script you can use it these ways:


- for the whole domain:
sync-shadowgroup -root "dc=yoursubdomain,dc=yourmaindomain" -recurse

for just one OU, but not for sub-OUs:
sync-shadowgroup -root "OU=yourOU,dc=yoursubdomain,dc=yourmaindomain"

for one OU, and all its sub-OUs:
sync-shadowgroup -root "OU=yourOU,dc=yoursubdomain,dc=yourmaindomain" -recurse

It creates the following name for the Shadow Groups:

shadow-yourmaindomain-yoursubdomain-yourmainOU-yoursubOU

It deletes any members from the shadowgroup, which is moved to a different OU and inserts any new user.

Hope this is close to your request.  
Import-Module activedirectory

function sync-shadowgroup {
param(
    [Parameter(
        Mandatory = $true,
        ValueFromPipeline = $true
    )]
    [string] $root,
    [switch] $recurse
)
$ofs = "-"
$oubase = Get-ADObject -Identity $root
$ous = if($recurse){Get-ADOrganizationalUnit -SearchBase $oubase -Filter *}
    else{Get-ADOrganizationalUnit -Identity $oubase}
if(!$ous){throw "Invalid OU or DN root!"}

$ous | %{
$ou = $_
$narr = ($ou.distinguishedname -split ",?\w\w=") | ?{$_}
$fullname = [string] $narr[-1..-($narr.count)]
$shgname = "shadow-$fullname"

$sh = Get-ADGroup -SearchBase $ou -Filter {name -eq $shgname} -ErrorAction silentlycontinue
if(!$sh){
    $sh = New-ADGroup -Path $ou -Name $shgname -GroupCategory security -GroupScope global -PassThru
}

Get-ADUser -ResultSetSize $null -SearchBase $ou -Filter * -Properties memberof |  %{
   if($_.memberof -notcontains $sh.distinguishedname){Add-ADGroupMember -Identity $sh -Members $_}
}
Get-ADGroupMember -Identity $sh | %{
    if($_.distinguishedname -notmatch ([regex]::Escape("$($ou.distinguishedname)"))){
        Remove-ADGroupMember -Identity $sh -Members $_ -Confirm:$false
    }
}
}
}

Open in new window

Commented:
And you can also use it in a pipeline with or without the recurse switch:

Get-ADOrganizationalUnit -Filter {name -eq 'yourOUsSimpleName'} | sync-shadowgroup

Author

Commented:
Hey

Thanks ;) It works...

But... I get the follownig error at my root OU:

Get-ADGroupMember : The size limit for this request was exceeded
At C:\Scripts\SG.ps1:33 char:18
+ Get-ADGroupMember <<<<  -Identity $sh | %{
    + CategoryInfo          : NotSpecified: (CN=PIT_SG_local...=skole,DC=local:ADGroup) [Get-ADGroupMember], ADExcepti
   on
    + FullyQualifiedErrorId : The size limit for this request was exceeded,Microsoft.ActiveDirectory.Management.Comman
   ds.GetADGroupMember

Do you know why?

Commented:
There is a default result size limit of 1000 object for Get-AD.... cmdlets. Here is a corrected script.
Import-Module activedirectory

function sync-shadowgroup {
param(
    [Parameter(
        Mandatory = $true,
        ValueFromPipeline = $true
    )]
    [string] $root,
    [switch] $recurse
)
$ofs = "-"
$oubase = Get-ADObject -Identity $root
$ous = if($recurse){Get-ADOrganizationalUnit -ResultSetSize $null -SearchBase $oubase -Filter * }
    else{Get-ADOrganizationalUnit -Identity $oubase -ResultSetSize $null}
if(!$ous){throw "Invalid OU or DN root!"}

$ous | %{
$ou = $_
$narr = ($ou.distinguishedname -split ",?\w\w=") | ?{$_}
$fullname = [string] $narr[-1..-($narr.count)]
$shgname = "shadow-$fullname"

$sh = Get-ADGroup -SearchBase $ou -Filter {name -eq $shgname} -ErrorAction silentlycontinue
if(!$sh){
    $sh = New-ADGroup -Path $ou -Name $shgname -GroupCategory security -GroupScope global -PassThru
}

Get-ADUser -ResultSetSize $null -SearchBase $ou -Filter * -Properties memberof -ResultSetSize $null |  %{
   if($_.memberof -notcontains $sh.distinguishedname){Add-ADGroupMember -Identity $sh -Members $_}
}
Get-ADGroupMember -Identity $sh -ResultSetSize $null | %{
    if($_.distinguishedname -notmatch ([regex]::Escape("$($ou.distinguishedname)"))){
        Remove-ADGroupMember -Identity $sh -Members $_ -Confirm:$false
    }
}
}
}

Open in new window

Author

Commented:
Hey

Now I get:

Get-ADUser : Cannot bind parameter because parameter 'ResultSetSize' is specified more than once. To provide multiple v
alues to parameters that can accept multiple values, use the array syntax. For example, "-parameter value1,value2,value
3".
At line:24 char:94
+ Get-ADUser -ResultSetSize $null -SearchBase $ou -Filter * -Properties memberof -ResultSetSize <<<<  $null |  %{
    + CategoryInfo          : InvalidArgument: (:) [Get-ADUser], ParameterBindingException
    + FullyQualifiedErrorId : ParameterAlreadyBound,Microsoft.ActiveDirectory.Management.Commands.GetADUser

Get-ADGroupMember : A parameter cannot be found that matches parameter name 'ResultSetSize'.
At line:27 char:47
+ Get-ADGroupMember -Identity $sh -ResultSetSize <<<<  $null | %{
    + CategoryInfo          : InvalidArgument: (:) [Get-ADGroupMember], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember
Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION

Commented:
I found an alternative solution, please test it!
Import-Module activedirectory

function sync-shadowgroup {
param(
    [Parameter(
        Mandatory = $true,
        ValueFromPipeline = $true
    )]
    [string] $root,
    [switch] $recurse
)
$ofs = "-"
$oubase = Get-ADObject -Identity $root
$ous = if($recurse){Get-ADOrganizationalUnit -ResultSetSize $null -SearchBase $oubase -Filter * }
    else{Get-ADOrganizationalUnit -Identity $oubase}
if(!$ous){throw "Invalid OU or DN root!"}

$ous | %{
$ou = $_
$narr = ($ou.distinguishedname -split ",?\w\w=") | ?{$_}
$fullname = [string] $narr[-1..-($narr.count)]
$shgname = "shadow-$fullname"

$sh = Get-ADGroup -SearchBase $ou -Filter {name -eq $shgname} -ErrorAction silentlycontinue
if(!$sh){
    $sh = New-ADGroup -Path $ou -Name $shgname -GroupCategory security -GroupScope global -PassThru
}

Get-ADUser -ResultSetSize $null -SearchBase $ou -Filter * -Properties memberof |  %{
   if($_.memberof -notcontains $sh.distinguishedname){Add-ADGroupMember -Identity $sh -Members $_}
}
$shdn = $sh.distinguishedname
Get-ADUser -ResultSetSize $null -Filter {memberof -eq $shdn} | %{
    if($_.distinguishedname -notmatch $ou.distinguishedname){
        Remove-ADGroupMember -Identity $sh -Members $_ -Confirm:$false
    }
} 
}
}

Open in new window

Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.