Skip to content

Commit eeb2a39

Browse files
Merge pull request #110 from ActiveDirectoryManagementFramework/gpLink
1.9.234
2 parents 69dd5f1 + e42ccad commit eeb2a39

File tree

18 files changed

+293
-139
lines changed

18 files changed

+293
-139
lines changed

DomainManagement/DomainManagement.psd1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
RootModule = 'DomainManagement.psm1'
44

55
# Version number of this module.
6-
ModuleVersion = '1.9.228'
6+
ModuleVersion = '1.9.234'
77

88
# ID used to uniquely identify this module
99
GUID = '0a405382-ebc2-445b-8325-541535810193'
@@ -26,7 +26,7 @@
2626
# Modules that must be imported into the global environment prior to importing
2727
# this module
2828
RequiredModules = @(
29-
@{ ModuleName = 'PSFramework'; ModuleVersion = '1.12.346' }
29+
@{ ModuleName = 'PSFramework'; ModuleVersion = '1.13.416' }
3030

3131
# Additional Dependencies, cannot declare due to bug in dependency handling in PS5.1
3232
# @{ ModuleName = 'ADSec'; ModuleVersion = '1.0.0' }

DomainManagement/changelog.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Changelog
22

3+
## 1.9.234 (2025-10-31)
4+
5+
- Upd: General - Use the shared managed remoting feature, allowing configuring session options.
6+
- Upd: AccessRules - when failing to resolve the identity of a principal on an existing access rule, the warning now reports the DN of the object
7+
- Upd: Exchange - accepts test results as input for invoke
8+
- Upd: GPLink - Supports cherry-picking results within a single OU.
9+
- Fix: GPOwner - Prints red error messages on screen when failing to resovle the owner
10+
- Fix: Groups - Ignores SamAccountName during creation of new groups
11+
312
## 1.9.228 (2025-10-02)
413

514
- Upd: Group Memberships - added option "ConfigOnly", allowing to define the group processing mode, without specifying any actual memberships.

DomainManagement/en-us/strings.psd1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
'Get-PermissionGuidMapping.Processing' = 'Processing Permission Guids for domain: {0} (This may take a while)' # $identity
2222

2323
'Get-Principal.Resolution.Failed' = 'Failed to resolve principal: SID {0} | Name {1} | ObjectClass {2} | Domain {3}' # $Sid, $Name, $ObjectClass, $Domain
24+
'Get-Principal.Resolution.FailedWithTarget' = 'Failed to resolve principal: SID {0} | Name {1} | ObjectClass {2} | Domain {3} | Target {4}' # $Sid, $Name, $ObjectClass, $Domain, $Target
2425

2526
'Get-SchemaGuidMapping.Processing' = 'Processing Schema Guids for domain: {0} (This may take a while)' # $identity
2627

@@ -76,7 +77,6 @@
7677
'Invoke-DMGPLink.Delete.AllEnabled' = 'Removing all ({0}) policy links (all of which are enabled)' # $countActual
7778
'Invoke-DMGPLink.GpoMissing' = 'Skipping GP Link application for {0} - cannot resolve Group Policies "{1}"' # $testItem.ADObject, (($testItem.Changed | Where-Object Action -eq 'GpoMissing').Policy -join ", ")
7879
'Invoke-DMGPLink.New' = 'Linking {0} group policies (all new links)' # $countConfigured
79-
'Invoke-DMGPLink.New.GpoNotFound' = 'Unable to find Group Policy Object: {0}' # (Resolve-String -Text $_.PolicyName)
8080
'Invoke-DMGPLink.New.NewGPLinkString' = 'Finished gPLink string being applied to {0}: {1}' # $ADObject.DistinguishedName, $gpLinkString
8181
'Invoke-DMGPLink.Update.AllEnabled' = 'Updating GPLink - {0} links configured, {1} links present, {2} links present that are not in configuration (All present and undesired links are enabled)' # $countConfigured, $countActual, $countNotInConfig
8282
'Invoke-DMGPLink.Update.Change' = ' Link update: {0} - {1} ({2})' # $change.Action, $change.Policy, $ADObject.DistinguishedName

DomainManagement/functions/AccessRule/Test-DMAccessRule.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@
160160
$desiredPermissions = $script:accessRules[$key] | Convert-AccessRule @parameters -ADObject $adObject
161161
}
162162

163-
$delta = Compare-AccessRules @parameters -ADRules ($adAclObject.Access | Convert-AccessRuleIdentity @parameters) -ConfiguredRules $desiredPermissions -DefaultRules $defaultPermissions -ADObject $adObject
163+
$delta = Compare-AccessRules @parameters -ADRules ($adAclObject.Access | Convert-AccessRuleIdentity @parameters -Target $adAclObject.DistinguishedName) -ConfiguredRules $desiredPermissions -DefaultRules $defaultPermissions -ADObject $adObject
164164

165165
if ($delta) {
166166
New-TestResult @resultDefaults -Type Update -Changed $delta -ADObject $adAclObject

DomainManagement/functions/exchange/Invoke-DMExchange.ps1

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
.DESCRIPTION
88
Apply the desired exchange domain content update.
99
Use Register-DMExchange to define the exchange update.
10+
11+
.PARAMETER InputObject
12+
Test results provided by the associated test command.
13+
Only the provided changes will be executed, unless none were specified, in which ALL pending changes will be executed.
1014
1115
.PARAMETER Server
1216
The server / domain to work with.
@@ -32,6 +36,9 @@
3236
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseUsingScopeModifierInNewRunspaces', '')]
3337
[CmdletBinding(SupportsShouldProcess = $true)]
3438
param (
39+
[Parameter(ValueFromPipeline = $true)]
40+
$InputObject,
41+
3542
[Parameter(Mandatory = $true)]
3643
[PSFComputer]
3744
$Server,
@@ -133,14 +140,17 @@
133140
}
134141
process
135142
{
136-
$testResult = Test-DMExchange @parameters
143+
if (-not $InputObject) {
144+
$testResult = Test-DMExchange @parameters
145+
}
146+
else { $testResult = $InputObject }
137147

138148
if (-not $testResult) { return }
139149

140150
#region PS Remoting
141151
$psParameter = $PSBoundParameters | ConvertTo-PSFHashtable -Include Credential
142152
$psParameter.ComputerName = $Server
143-
try { $session = New-PSSession @psParameter -ErrorAction Stop }
153+
try { $session = New-AdcPSSession @psParameter -ErrorAction Stop }
144154
catch {
145155
Stop-PSFFunction -String 'Invoke-DMExchange.WinRM.Failed' -StringValues $Server -ErrorRecord $_ -EnableException $EnableException -Cmdlet $PSCmdlet -Target $Server
146156
return

DomainManagement/functions/gplinks/Invoke-DMGPLink.ps1

Lines changed: 65 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,29 @@
8080
$ADObject,
8181

8282
[bool]
83-
$Disable
83+
$Disable,
84+
85+
$Changes,
86+
87+
$Definition
8488
)
8589
$parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential
8690

87-
if (-not $Disable) {
91+
$newChanges = foreach ($change in $Definition) {
92+
if ($change.Policy -notin $Changes.Policy) {
93+
$change.ToLink()
94+
continue
95+
}
96+
if (-not $Disable) { continue }
97+
98+
'[LDAP://{0};1]' -f $change.PolicyDN
99+
}
100+
101+
if (-not $newChanges) {
88102
Set-ADObject @parameters -Identity $ADObject -Clear gPLink -ErrorAction Stop
89103
return
90104
}
91-
Set-ADObject @parameters -Identity $ADObject -Replace @{ gPLink = ($ADObject.gPLink -replace ";\d\]", ";1]") } -ErrorAction Stop -Confirm:$false
105+
Set-ADObject @parameters -Identity $ADObject -Replace @{ gPLink = $newChanges -join '' } -ErrorAction Stop -Confirm:$false
92106
}
93107

94108
function New-Link {
@@ -103,24 +117,11 @@
103117

104118
$ADObject,
105119

106-
$Configuration,
107-
108-
[Hashtable]
109-
$GpoNameMapping
120+
$Changes
110121
)
111122
$parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential
112123

113-
$gpLinkString = ($Configuration.Include | Sort-Object -Property @{ Expression = { $_.Tier }; Descending = $false }, Precedence -Descending | ForEach-Object {
114-
$gpoDN = $GpoNameMapping[(Resolve-String -Text $_.PolicyName)]
115-
if (-not $gpoDN) {
116-
Write-PSFMessage -Level Warning -String 'Invoke-DMGPLink.New.GpoNotFound' -StringValues (Resolve-String -Text $_.PolicyName) -Target $ADObject -FunctionName Invoke-DMGPLink
117-
return
118-
}
119-
$stateID = "0"
120-
if ($_.State -eq 'Enforced') { $stateID = "2" }
121-
if ($_.State -eq 'Disabled') { $stateID = "1" }
122-
"[LDAP://$gpoDN;$stateID]"
123-
}) -Join ""
124+
$gpLinkString = @($Changes | Sort-Object -Property @{ Expression = { $_.Tier }; Descending = $false }, Precedence -Descending).ForEach{ $_.ToLink() } -Join ""
124125
Write-PSFMessage -Level Debug -String 'Invoke-DMGPLink.New.NewGPLinkString' -StringValues $ADObject.DistinguishedName, $gpLinkString -Target $ADObject -FunctionName Invoke-DMGPLink
125126
Set-ADObject @parameters -Identity $ADObject -Replace @{ gPLink = $gpLinkString } -ErrorAction Stop -Confirm:$false
126127
}
@@ -145,21 +146,54 @@
145146
[Hashtable]
146147
$GpoNameMapping,
147148

149+
150+
[AllowNull()]
148151
$Changes
149152
)
150153
$parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential
151154

152-
$gpLinkString = ''
153-
if ($Disable) {
154-
$desiredDNs = $Configuration.ExtendedInclude.PolicyName | Resolve-String | ForEach-Object { $GpoNameMapping[$_] }
155-
$gpLinkString += ($ADobject.LinkedGroupPolicyObjects | Where-Object DistinguishedName -NotIn $desiredDNs | Sort-Object -Property Precedence -Descending | ForEach-Object {
156-
"[LDAP://$($_.DistinguishedName);1]"
157-
}) -join ""
155+
$allItems = $Configuration.Definition | Sort-Object -Property @{ Expression = { $_.Tier }; Descending = $false }, Precedence -Descending
156+
$itemsToInclude = $allItems | Where-Object {
157+
($_.Action -in 'None', 'State', 'Reorder') -or
158+
(
159+
($_.Action -eq 'Add') -and
160+
($_.Policy -in $Changes.Policy)
161+
) -or
162+
(
163+
($_.Action -eq 'Delete') -and
164+
($_.Policy -notin $Changes.Policy) -and
165+
(-not $Disable)
166+
)
158167
}
159-
160-
$gpLinkString += ($Configuration.ExtendedInclude | Where-Object DistinguishedName | Sort-Object -Property @{ Expression = { $_.Tier }; Descending = $false }, Precedence -Descending | ForEach-Object {
161-
$_.ToLink()
162-
}) -Join ""
168+
169+
$dontReorder = $allItems | Where-Object {
170+
($_.Action -eq 'Reorder') -and
171+
($_.Policy -notin $Changes.Policy)
172+
}
173+
foreach ($noReorderItem in $dontReorder | Sort-Object OriginalPosition) {
174+
$below = $null
175+
$above = $null
176+
if ($noReorderItem.OriginalPosition -gt 1) { $below = $allItems | Where-Object OriginalPosition -eq ($noReorderItem.OriginalPosition - 1) }
177+
else { $above = $allItems | Where-Object OriginalPosition -eq ($noReorderItem.OriginalPosition + 1) }
178+
179+
$allOtherItems = $itemsToInclude | Where-Object { $_ -ne $noReorderItem }
180+
if ($above) {
181+
$index = $allOtherItems.IndexOf($above)
182+
$itemsAbove = @()
183+
if ($index -gt 0) { $itemsAbove = @($allOtherItems[0..($index-1)]) }
184+
$itemsBelow = @($allOtherItems[$index..(@($allOtherItems).Count - 1)])
185+
}
186+
else {
187+
$index = $allOtherItems.IndexOf($below)
188+
$itemsAbove = @($allOtherItems[0..($index-1)])
189+
$itemsBelow = @()
190+
if ($index -lt ($allOtherItems.Count - 1)) { $itemsBelow = @($allOtherItems[($index)..($allOtherItems.Count - 1)])}
191+
}
192+
$itemsToInclude = $itemsAbove + $noReorderItem + $itemsBelow
193+
}
194+
195+
$gpLinkString = @($itemsToInclude).ForEach{ $_.ToLink() } -join ""
196+
163197
$msgParam = @{
164198
Level = 'SomewhatVerbose'
165199
Tag = 'change'
@@ -200,19 +234,19 @@
200234
Stop-PSFFunction -String 'General.Invalid.Input' -StringValues 'Test-DMGPLink', $testItem -Target $testItem -Continue -EnableException $EnableException
201235
}
202236

203-
$countConfigured = ($testItem.Configuration | Measure-Object).Count
237+
$countConfigured = ($testItem.Changed | Measure-Object).Count
204238
$countActual = ($testItem.ADObject.LinkedGroupPolicyObjects | Measure-Object).Count
205239
$countNotInConfig = ($testItem.ADObject.LinkedGroupPolicyObjects | Where-Object DistinguishedName -NotIn ($testItem.Configuration.PolicyName | Remove-PSFNull | Resolve-String | ForEach-Object { $gpoDisplayToDN[$_] }) | Measure-Object).Count
206240

207241
switch ($testItem.Type) {
208242
'Delete' {
209243
Invoke-PSFProtectedCommand -ActionString 'Invoke-DMGPLink.Delete.AllEnabled' -ActionStringValues $countActual -Target $testItem -ScriptBlock {
210-
Clear-Link @parameters -ADObject $testItem.ADObject -Disable $Disable -ErrorAction Stop
244+
Clear-Link @parameters -ADObject $testItem.ADObject -Disable $Disable -Changes $testItem.Changed -Definition $testItem.Configuration.Definition -ErrorAction Stop
211245
} -EnableException $EnableException.ToBool() -PSCmdlet $PSCmdlet -Continue
212246
}
213247
'Create' {
214248
Invoke-PSFProtectedCommand -ActionString 'Invoke-DMGPLink.New' -ActionStringValues $countConfigured -Target $testItem -ScriptBlock {
215-
New-Link @parameters -ADObject $testItem.ADObject -Configuration $testItem.Configuration -GpoNameMapping $gpoDisplayToDN -ErrorAction Stop
249+
New-Link @parameters -ADObject $testItem.ADObject -Changes $testItem.Changed -ErrorAction Stop
216250
} -EnableException $EnableException.ToBool() -PSCmdlet $PSCmdlet -Continue
217251
}
218252
'Update' {

0 commit comments

Comments
 (0)