Skip to content

Instantly share code, notes, and snippets.

@evetsleep
Created February 1, 2019 20:19
Show Gist options
  • Save evetsleep/093c9e93919ce8645ff6a44c4acbf1bf to your computer and use it in GitHub Desktop.
Save evetsleep/093c9e93919ce8645ff6a44c4acbf1bf to your computer and use it in GitHub Desktop.
[CmdletBinding(SupportsShouldProcess)]Param()
#region Collect user and group information
<#
Use a custom object to store what the group membership SHOULD look like.
We'll use this later to do a comparison with the current group members
to see who we need to add\remove.
#>
$correctGroupState = [PSCustomObject]@{
Administrative = New-Object -TypeName System.Collections.Generic.List[String]
Advertising = New-Object -TypeName System.Collections.Generic.List[String]
}
# 1st AD query
# Since we only care about people who have a certain segment, we are specific with the AD query.
Get-ADUser -Filter "segment -like 'T90' -or segment -like 'A14' -or segment -like 'B19'" -Properties segment | ForEach-Object {
# Pulling the entry out is necessary because we're using switch. Placeholder variables get funky if you don't.
$userEntry = $PSItem
switch -Regex ($userEntry.segment) {
'^T90$' {
$correctGroupState.Administrative.Add($userEntry.distinguishedname)
}
'^A14$|^B19$' {
$correctGroupState.Advertising.Add($userEntry.distinguishedname)
}
# If we got here the users segment didn't match and we do nothing.
default {}
}
}
#endregion
#region Examine groups for membership changes
<#
First we create a hash table where the key is the group name and the value is a custom PSObject
which contains the group name, and if there are any members to add or remove. This is helpful
to see what it WOULD have done when we're debugging and using -WhatIf.
#>
$groupNames = 'Administrative Staff','Advertising'
$groupUpdates = @{}
$groupNames | ForEach-Object {
$groupObject = [PSCustomObject]@{
GroupName = $PSItem
ToAdd = New-Object -TypeName System.Collections.Generic.List[String]
ToRemove = New-Object -TypeName System.Collections.Generic.List[String]
}
$groupUpdates.Add($PSItem,$groupObject)
}
<#
Go through each group and get it from Active Directory. Well use the object
that is returned to determine if we need to add or remove any members. Since
we are storing the membership as distinguishedNames in $correctGroupState and
the membership in AD is stored as DN's this means we don't need to query AD
multiple times to do comparisons. We just compare DN's.
#>
$groupNames | ForEach-Object {
# 2nd (and 3rd) AD query
$groupData = Get-ADGroup -Identity $PSItem -Properties member
$groupName = $groupData.Name
<#
First we need to see if we need to add anyone. We use a switch statement
in place of a whole bunch of if statements. Not critical, but a design choice. In each
switch block, if the group name matches, we go through each member of who SHOULD
be a member of that group and if they're not we add them to the ToAdd queue.
#>
switch ($groupName) {
'Administrative Staff' {
$correctGroupState.Administrative | ForEach-Object {
if ($groupData.member -notcontains $PSItem) {
$groupUpdates[$groupName].ToAdd.Add($PSItem)
}
}
}
'Advertising' {
$correctGroupState.Advertising | ForEach-Object {
if ($groupData.member -notcontains $PSItem) {
$groupUpdates[$groupName].ToAdd.Add($PSItem)
}
}
}
default {}
}
<#
Now we do the reverse. Go through each group and, based on a match to its name in the
switch statement, we go through each existing member to see if they are supposed to be
in the group. If not, then we add them to the ToRemove queue.
#>
$groupData.member | ForEach-Object {
$member = $PSItem
switch ($groupName) {
'Administrative Staff' {
if ($correctGroupState.Administrative -notcontains $member) {
$groupUpdates[$groupName].ToRemove.Add($member)
}
}
'Advertising' {
if ($correctGroupState.Advertising -notcontains $member) {
$groupUpdates[$groupName].ToRemove.Add($member)
}
}
default {
}
}
}
}
#endregion
#region Perform the updates, if necessary.
# Possibly 4th\5th AD transation, but ONLY if there are updates to be made.
foreach ($group in $groupUpdates.Keys) {
Write-Debug ('Processing {0}' -f $group)
if ($groupUpdates[$group].ToAdd.Count -gt 0 -and $PSCmdlet.ShouldProcess( ('ADD {0} members from {1}' -f $groupUpdates[$group].ToAdd.Count,$group) ) ) {
$groupUpdates[$group].ToAdd | ForEach-Object { Write-Verbose -Message ('Adding {0} to {1}' -f $PSItem,$group) }
Add-ADGroupMember -Identity $group -Members $groupUpdates[$group].ToAdd
}
if ($groupUpdates[$group].ToRemove.Count -gt 0 -and $PSCmdlet.ShouldProcess( ('REMOVE {0} members from {1}' -f $groupUpdates[$group].ToRemove.Count,$group) ) ) {
$groupUpdates[$group].ToRemove | ForEach-Object { Write-Verbose -Message ('Removing {0} from {1}' -f $PSItem,$group) }
Remove-ADGroupMember -Identity $group -Members $groupUpdates[$group].ToRemove -Confirm:$false
}
}
#endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment