Link to home
Start Free TrialLog in
Avatar of mikeydk
mikeydkFlag for Denmark

asked on

Create/manage shadow groups by script

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
Avatar of soostibi
soostibi
Flag of Hungary image

Do you have Windows Server 2008 R2 DCs or can we use Quest's AD PowerShell snapin?
Avatar of mikeydk

ASKER

Yes running 2008 R2 DCs...
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

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

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

ASKER

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?
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

Avatar of mikeydk

ASKER

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
ASKER CERTIFIED SOLUTION
Avatar of soostibi
soostibi
Flag of Hungary image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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