private/CreateOrSetGroup.ps1
function CreateOrSetGroup { [CmdletBinding(SupportsShouldProcess=$true)] Param ( [Parameter(Mandatory, ValueFromPipelineByPropertyName)] [String]$Name, [Parameter(Mandatory, ValueFromPipelineByPropertyName)] [String]$Description, [Parameter(Mandatory, ValueFromPipelineByPropertyName)] [String]$Path, [Parameter(Mandatory, ValueFromPipelineByPropertyName)] [String]$GroupScope, [Parameter(ValueFromPipelineByPropertyName)] [String]$Info, [Parameter(ValueFromPipelineByPropertyName)] [String[]]$MemberOf=$null, [Parameter(ValueFromPipelineByPropertyName)] [String[]]$Members=$null, # Clears the 'MemberOf' attribute of the target group by removing it from other groups. # Typically used to remove rights that a role participates in. [Switch]$ResetMembership, # Removes all (right/role) members from this group. This only targets groups and filters by right/role names. # Typically used to remove all roles from a given right without disrupting e.g. service accounts. [Switch]$ResetMembers, [Microsoft.ActiveDirectory.Management.ADDirectoryServer]$Server = (get-addomainController -Writable -Discover) ) Begin{ $CreatedGroups = [System.Collections.Generic.List[String]]::new() $MembershipChanges = [System.Collections.Generic.List[System.collections.hashtable]]::new() write-loghandler -level "Verbose" -message "Initializing OU/Container Processing (DC: $server)" } PROCESS { write-loghandler -level "Debug" -message "Started processing '$name'" -indentLevel 1 $myOut = [ordered]@{ Status = "Pending" Name = $Name Description = $Description } $GroupParams = @{ Description = $Description GroupScope = $groupScope confirm = $false SAMAccountName = $name } $GroupDN = "CN=$name,$path" $PSShouldProcessMsg = $(write-logHandler -passthru -target $GroupDN -message "Set Description and metadata") $Results = if ($PSCmdlet.ShouldProcess.invoke($PSShouldProcessMsg)) { try { Set-ADGroup -server $server -Identity $GroupDN @GroupParams -replace @{info=$info} $myOut['status'] = "..Set" if ($resetMembership) { write-loghandler -level "warning" -message "Resetting membership $GroupDN" get-adgroup -identity $groupDN -properties memberOf -server $server | select-object -expand memberOf | remove-adgroupmember -member $groupDN -confirm:$false -server $server } $myOut['status'] = "-membership" if ($resetMembers) { # TODO: This filter's a bit nasty-- it doesn't account well for the rightsprefix. $removals = @(get-adgroupmember -identity $groupDN -server $server | where-object {$_.objectClass -eq 'group' -and ($_.name -like "*$($settings.Names.RightsName)-*" -or $_.name -like "*$($settings.Names.RolesName)-*")}) if ($removals.count -gt 0) { write-loghandler -level "warning" -message "Resetting members for $GroupDN. $($removals.count) groups to be removed." remove-adgroupMember -server $server -identity $groupDN -Members $Removals } } $myOut['status'] = "-members" if ($members) { add-adgroupMember -server $server -identity $GroupDN -members $members $myOut['status'] = "+members" } $myOut['status'] = "Updated" } Catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] { write-loghandler -level "Verbose" -message " Didn't exist; creating" try { New-ADGroup -server $server -name $name -path $path @GroupParams -groupCategory "Security" -passthru $myOut['status'] = "NEW" $CreatedGroups.add($GroupDN) } catch { write-warning $_.exception.getType().fullname write-loghandler -level "warning" -message ("Error creating {0} at {1}" -f $name,$path) #throw $_ } } } if ($members) { if ($null -eq $groupDN) { write-loghandler -level "Debug" -message "you have null members for $groupDN" } else { $MembershipChanges.add(@{ Identity = $GroupDN Members = $members }) | out-null } } if ($memberOf) { foreach ($g in $memberOf) { if ($null -eq $g) { write-loghandler -level "Debug" -message "you have null memberofs for $groupDN" } else { $MembershipChanges.add(@{ Identity = $g Members = $groupDN }) | out-null } } } [pscustomobject]$myOut } END{ Write-loghandler -level "Debug" -message "Waiting for creation of new Groups" for ($i = 0; $i -lt $CreatedGroups.count; $i++) { $ProgressActivity = "Waiting for creation of new Groups ({0} / {1})" -f $($i+1), $Createdgroups.count $item = $CreatedGroups[$i] $name = $item.split(",")[0].split("=")[1] $status = $name write-Progress -id 1 -Activity $ProgressActivity -status $status -PercentComplete (($i/$createdGroups.count) * 100) -SecondsRemaining $Settings.AppSettings.SleepTimeout for ($j = 0; $j -lt $Settings.AppSettings.SleepTimeout/$Settings.AppSettings.SleepLength; $j+=$Settings.AppSettings.SleepLength) { $itemExists = [bool](Get-ADGroup -server $server -filter "distinguishedName -eq '$item'") Write-Progress -id 1 -Activity $ProgressActivity -Status $status -SecondsRemaining $($Settings.AppSettings.SleepTimeout - $j) -PercentComplete (($i/$createdGroups.count) * 100) if ($itemExists) { break } start-sleep -seconds $Settings.AppSettings.SleepLength } } write-Progress -id 1 $progressActivity -Completed if ($MembershipChanges.count -gt 0) { write-loghandler -level "Verbose" -message "Updating memberships" foreach ($line in $MembershipChanges) { if ($PSCmdlet.ShouldProcess($line.identity,"Add child membership")) { try { add-adgroupMember -server $server @line } catch { write-warning $_.exception.getType().fullname write-loghandler -level "warning" -message ("Error adding {0} to {1}" -f $line.members,$line.identity) #write-loghandler -level "warning" -message "Name: $Name; Description: $Description; Path: $Path; Parent: $g" throw $_ } } } } } } |