4040 Invoke-Callback @parameters - Cmdlet $PSCmdlet
4141 Assert-Configuration - Type GroupMemberShips - Cmdlet $PSCmdlet
4242 Set-DMDomainContext @parameters
43+
44+ $resultDefaults = @ {
45+ Server = $Server
46+ ObjectType = ' GroupMembership'
47+ }
48+
49+ # region Functions
50+ function Get-GroupMember {
51+ [CmdletBinding ()]
52+ param (
53+ $ADObject ,
54+
55+ [hashtable ]
56+ $Parameters
57+ )
58+
59+ $ADObject.Members | ForEach-Object {
60+ $distinguishedName = $_
61+ try { Get-ADObject @parameters - Identity $_ - ErrorAction Stop - Properties SamAccountName, objectSid }
62+ catch {
63+ $objectDomainName = $distinguishedName.Split (" ," ).Where { $_ -like " DC=*" } -replace ' ^DC=' -join " ."
64+ $cred = $Parameters | ConvertTo-PSFHashtable - Include Credential
65+ Get-ADObject - Server $objectDomainName @cred - Identity $distinguishedName - ErrorAction Stop - Properties SamAccountName, objectSid
66+ }
67+ }
68+ }
69+
70+ function New-MemberRemovalResult {
71+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute (" PSUseShouldProcessForStateChangingFunctions" , " " )]
72+ [CmdletBinding ()]
73+ param (
74+ $ADObject ,
75+
76+ $ADMember ,
77+
78+ [switch ]
79+ $AssignmentsUnresolved ,
80+
81+ $ResultDefaults
82+ )
83+
84+ $configObject = [PSCustomObject ]@ {
85+ Assignment = $null
86+ ADMember = $adMember
87+ }
88+
89+ $identifier = $ADMember.SamAccountName
90+ if (-not $identifier ) {
91+ try { $identifier = Resolve-Principal - Name $ADMember.ObjectSid - OutputType SamAccountName - ErrorAction Stop }
92+ catch { $identifier = $ADMember.ObjectSid }
93+ }
94+ if (-not $identifier ) { $identifier = $ADMember.ObjectSid }
95+ if ($AssignmentsUnresolved -and ($ADMember.ObjectClass -eq ' foreignSecurityPrincipal' )) {
96+ # Currently a member, is foreignSecurityPrincipal and we cannot be sure we resolved everything that should be member
97+ New-TestResult @resultDefaults - Type Unidentified - Identity " $ ( $ADObject.Name ) þ $ ( $ADMember.ObjectClass ) þ $ ( $identifier ) " - Configuration $configObject - ADObject $ADObject
98+ }
99+ else {
100+ $change = [PSCustomObject ]@ {
101+ PSTypeName = ' DomainManagement.GroupMember.Change'
102+ Action = ' Remove'
103+ Group = $ADObject.Name
104+ Member = $identifier
105+ Type = $ADMember.ObjectClass
106+ }
107+ Add-Member - InputObject $change - MemberType ScriptMethod - Name ToString - Value { ' Remove: {0} -> {1}' -f $this.Member , $this.Group } - Force
108+ New-TestResult @resultDefaults - Type Delete - Identity " $ ( $ADObject.Name ) þ $ ( $ADMember.ObjectClass ) þ $ ( $identifier ) " - Configuration $configObject - ADObject $ADObject - Changed $change
109+ }
110+ }
111+ # endregion Functions
43112 }
44113 process {
114+ # region Configured Memberships
115+ $groupsProcessed = [System.Collections.ArrayList ]@ ()
116+
45117 :main foreach ($groupMembershipName in $script :groupMemberShips.Keys ) {
46118 $resolvedGroupName = Resolve-String - Text $groupMembershipName
47119 $processingMode = ' Constrained'
48120 if ($script :groupMemberShips [$groupMembershipName ].__Configuration.ProcessingMode) {
49121 $processingMode = $script :groupMemberShips [$groupMembershipName ].__Configuration.ProcessingMode
50122 }
51123
52- $resultDefaults = @ {
53- Server = $Server
54- ObjectType = ' GroupMembership'
55- }
56-
57124 # region Resolve Assignments
58125 $failedResolveAssignment = $false
59126 $assignments = foreach ($assignment in $script :groupMemberShips [$groupMembershipName ].Values) {
124191 # region Check Current AD State
125192 try {
126193 $adObject = Get-ADGroup @parameters - Identity $resolvedGroupName - Properties Members - ErrorAction Stop
127- $adMembers = $adObject.Members | ForEach-Object {
128- $distinguishedName = $_
129- try { Get-ADObject @parameters - Identity $_ - ErrorAction Stop - Properties SamAccountName, objectSid }
130- catch {
131- $objectDomainName = $distinguishedName.Split (" ," ).Where { $_ -like " DC=*" } -replace ' ^DC=' -join " ."
132- $cred = $PSBoundParameters | ConvertTo-PSFHashtable - Include Credential
133- Get-ADObject - Server $objectDomainName @cred - Identity $distinguishedName - ErrorAction Stop - Properties SamAccountName, objectSid
134- }
135- }
194+ $null = $groupsProcessed.Add ($adObject.SamAccountName )
195+ $adMembers = Get-GroupMember - ADObject $adObject - Parameters $parameters
136196 }
137197 catch { Stop-PSFFunction - String ' Test-DMGroupMembership.Group.Access.Failed' - StringValues $resolvedGroupName - ErrorRecord $_ - EnableException $EnableException - Continue }
138198 # endregion Check Current AD State
158218 Member = Resolve-String - Text $assignment.ADMember.SamAccountName
159219 Type = $assignment.ADMember.ObjectClass
160220 }
161- Add-Member - InputObject $change - MemberType ScriptMethod - Name ToString - Value { ' Add: {0} -> {1}' -f $this.Member , $this.Group } - Force
221+ [ PSFramework.Object.ObjectHost ]::AddScriptMethod( $change , ' ToString' , { ' Add: {0} -> {1}' -f $this.Member , $this.Group })
162222 New-TestResult @resultDefaults - Type Add - Identity " $ ( Resolve-String - Text $assignment.Assignment.Group ) þ $ ( $assignment.ADMember.ObjectClass ) þ $ ( Resolve-String - Text $assignment.ADMember.SamAccountName ) " - Configuration $assignment - ADObject $adObject - Changed $change
163223 }
164224 # endregion Compare Assignments to existing state
170230 if (" $ ( $adMember.ObjectSID ) " -in ($assignments.ADMember.ObjectSID | ForEach-Object { " $_ " })) {
171231 continue
172232 }
173- $configObject = [PSCustomObject ]@ {
174- Assignment = $null
175- ADMember = $adMember
176- }
177-
178- $identifier = $adMember.SamAccountName
179- if (-not $identifier ) {
180- try { $identifier = Resolve-Principal - Name $adMember.ObjectSid - OutputType SamAccountName - ErrorAction Stop }
181- catch { $identifier = $adMember.ObjectSid }
182- }
183- if (-not $identifier ) { $identifier = $adMember.ObjectSid }
184- if ($failedResolveAssignment -and ($adMember.ObjectClass -eq ' foreignSecurityPrincipal' )) {
185- # Currently a member, is foreignSecurityPrincipal and we cannot be sure we resolved everything that should be member
186- New-TestResult @resultDefaults - Type Unidentified - Identity " $ ( $adObject.Name ) þ $ ( $adMember.ObjectClass ) þ $ ( $identifier ) " - Configuration $configObject - ADObject $adObject
187- }
188- else {
189- $change = [PSCustomObject ]@ {
190- PSTypeName = ' DomainManagement.GroupMember.Change'
191- Action = ' Remove'
192- Group = $adObject.Name
193- Member = $identifier
194- Type = $adMember.ObjectClass
195- }
196- Add-Member - InputObject $change - MemberType ScriptMethod - Name ToString - Value { ' Remove: {0} -> {1}' -f $this.Member , $this.Group } - Force
197- New-TestResult @resultDefaults - Type Delete - Identity " $ ( $adObject.Name ) þ $ ( $adMember.ObjectClass ) þ $ ( $identifier ) " - Configuration $configObject - ADObject $adObject - Changed $change
198- }
233+ New-MemberRemovalResult - ADObject $adObject - ADMember $adMember - AssignmentsUnresolved:$failedResolveAssignment - ResultDefaults $resultDefaults
199234 }
200235 # endregion Compare existing state to assignments
201236 }
237+ # endregion Configured Memberships
238+
239+ # region Groups without configured Memberships
240+ if ($script :contentMode.ExcludeComponents.GroupMembership ) { return }
241+
242+ $foundGroups = foreach ($searchBase in (Resolve-ContentSearchBase @parameters )) {
243+ Get-ADGroup @parameters - LDAPFilter ' (name=*)' - SearchBase $searchBase.SearchBase - SearchScope $searchBase.SearchScope - Properties Members | Where-Object {
244+ $_.SamAccountName -NotIn $groupsProcessed -and
245+ @ ($_.Members ).Count -gt 0
246+ }
247+ }
248+
249+ foreach ($adObject in $foundGroups ) {
250+ $adMembers = Get-GroupMember - ADObject $adObject - Parameters $parameters
251+
252+ foreach ($adMember in $adMembers ) {
253+ New-MemberRemovalResult - ADObject $adObject - ADMember $adMember - ResultDefaults $resultDefaults
254+ }
255+ }
256+ # endregion Groups without configured Memberships
202257 }
203258}
0 commit comments