From 4db92d16f4137a42b722c2de34a4608eedbe3434 Mon Sep 17 00:00:00 2001 From: Friedrich Weinmann Date: Fri, 22 May 2026 09:31:53 +0200 Subject: [PATCH 1/3] Access Rule Rework --- DomainManagement/DomainManagement.psd1 | 15 +- DomainManagement/changelog.md | 9 +- DomainManagement/en-us/strings.psd1 | 20 -- .../AccessRule/Invoke-DMAccessRule.ps1 | 8 +- .../AccessRule/Test-DMAccessRule.ps1 | 108 +++------- .../AccessRuleMode/Get-DMAccessRuleMode.ps1 | 35 ---- .../Register-DMAccessRuleMode.ps1 | 73 ------- .../Resolve-DMAccessRuleMode.ps1 | 84 -------- .../Unregister-DMAccessRuleMode.ps1 | 52 ----- DomainManagement/functions/acls/Get-DMAcl.ps1 | 12 +- .../functions/acls/Invoke-DMAcl.ps1 | 25 +-- .../functions/acls/Register-DMAcl.ps1 | 49 ++--- .../functions/acls/Test-DMAcl.ps1 | 58 ++++-- .../functions/acls/Unregister-DMAcl.ps1 | 6 +- .../domaindata/Invoke-DMDomainData.ps1 | 2 +- .../functions/gplinks/Test-DMGPLink.ps1 | 1 + .../Register-DMGPPermissionFilter.ps1 | 2 +- .../gppermissions/Invoke-DMGPPermission.ps1 | 4 +- .../gppermissions/Test-DMGPPermission.ps1 | 6 +- .../Test-DMGPRegistrySetting.ps1 | 2 +- .../Invoke-DMGroupMembership.ps1 | 2 +- .../Test-DMGroupMembership.ps1 | 4 +- .../Find-DMObjectCategoryItem.ps1 | 81 -------- .../objectcategories/Get-DMObjectCategory.ps1 | 29 --- .../Register-DMObjectCategory.ps1 | 113 ----------- .../Resolve-DMObjectCategory.ps1 | 72 ------- .../Unregister-DMObjectCategory.ps1 | 32 --- .../functions/other/Convert-DMSchemaGuid.ps1 | 111 ---------- .../other/Get-DMObjectDefaultPermission.ps1 | 125 ------------ .../functions/other/Register-DMBuiltInSID.ps1 | 39 ---- .../Invoke-DMServiceAccount.ps1 | 2 +- .../serviceaccounts/Test-DMServiceAccount.ps1 | 2 +- .../system/Get-DMDomainCredential.ps1 | 34 ---- .../system/Reset-DMDomainCredential.ps1 | 81 -------- .../functions/system/Set-DMContentMode.ps1 | 3 +- .../functions/system/Set-DMDomainContext.ps1 | 10 +- .../system/Set-DMDomainCredential.ps1 | 44 ---- .../internal/functions/Convert-Principal.ps1 | 101 ---------- .../internal/functions/Get-Domain.ps1 | 107 ---------- .../internal/functions/Get-Domain2.ps1 | 51 ----- .../internal/functions/Get-Principal.ps1 | 153 -------------- .../{acl_ace => }/Remove-RedundantAce.ps1 | 0 .../functions/Resolve-ContentSearchBase.ps1 | 2 +- .../internal/functions/Test-DmKdsRootKey.ps1 | 2 +- .../functions/acl_ace/Compare-AccessRules.ps1 | 190 ------------------ .../functions/acl_ace/Compare-Identity.ps1 | 126 ------------ .../acl_ace/Convert-AccessRuleIdentity.ps1 | 75 ------- .../acl_ace/Convert-BuiltInToSID.ps1 | 31 --- .../acl_ace/Get-AdminSDHolderRules.ps1 | 38 ---- .../acl_ace/Get-CategoryBasedRules.ps1 | 76 ------- .../acl_ace/Get-PermissionGuidMapping.ps1 | 74 ------- .../acl_ace/Get-SchemaGuidMapping.ps1 | 68 ------- .../functions/acl_ace/Resolve-Identity.ps1 | 73 ------- .../acl_ace/Test-AccessRuleEquality.ps1 | 57 ------ .../internal/scripts/variables.ps1 | 14 +- .../internal/scripts/variables2.ps1 | 35 +--- .../xml/DomainManagement.Format.ps1xml | 83 -------- 57 files changed, 148 insertions(+), 2563 deletions(-) delete mode 100644 DomainManagement/functions/AccessRuleMode/Get-DMAccessRuleMode.ps1 delete mode 100644 DomainManagement/functions/AccessRuleMode/Register-DMAccessRuleMode.ps1 delete mode 100644 DomainManagement/functions/AccessRuleMode/Resolve-DMAccessRuleMode.ps1 delete mode 100644 DomainManagement/functions/AccessRuleMode/Unregister-DMAccessRuleMode.ps1 delete mode 100644 DomainManagement/functions/objectcategories/Find-DMObjectCategoryItem.ps1 delete mode 100644 DomainManagement/functions/objectcategories/Get-DMObjectCategory.ps1 delete mode 100644 DomainManagement/functions/objectcategories/Register-DMObjectCategory.ps1 delete mode 100644 DomainManagement/functions/objectcategories/Resolve-DMObjectCategory.ps1 delete mode 100644 DomainManagement/functions/objectcategories/Unregister-DMObjectCategory.ps1 delete mode 100644 DomainManagement/functions/other/Convert-DMSchemaGuid.ps1 delete mode 100644 DomainManagement/functions/other/Get-DMObjectDefaultPermission.ps1 delete mode 100644 DomainManagement/functions/other/Register-DMBuiltInSID.ps1 delete mode 100644 DomainManagement/functions/system/Get-DMDomainCredential.ps1 delete mode 100644 DomainManagement/functions/system/Reset-DMDomainCredential.ps1 delete mode 100644 DomainManagement/functions/system/Set-DMDomainCredential.ps1 delete mode 100644 DomainManagement/internal/functions/Convert-Principal.ps1 delete mode 100644 DomainManagement/internal/functions/Get-Domain.ps1 delete mode 100644 DomainManagement/internal/functions/Get-Domain2.ps1 delete mode 100644 DomainManagement/internal/functions/Get-Principal.ps1 rename DomainManagement/internal/functions/{acl_ace => }/Remove-RedundantAce.ps1 (100%) delete mode 100644 DomainManagement/internal/functions/acl_ace/Compare-AccessRules.ps1 delete mode 100644 DomainManagement/internal/functions/acl_ace/Compare-Identity.ps1 delete mode 100644 DomainManagement/internal/functions/acl_ace/Convert-AccessRuleIdentity.ps1 delete mode 100644 DomainManagement/internal/functions/acl_ace/Convert-BuiltInToSID.ps1 delete mode 100644 DomainManagement/internal/functions/acl_ace/Get-AdminSDHolderRules.ps1 delete mode 100644 DomainManagement/internal/functions/acl_ace/Get-CategoryBasedRules.ps1 delete mode 100644 DomainManagement/internal/functions/acl_ace/Get-PermissionGuidMapping.ps1 delete mode 100644 DomainManagement/internal/functions/acl_ace/Get-SchemaGuidMapping.ps1 delete mode 100644 DomainManagement/internal/functions/acl_ace/Resolve-Identity.ps1 delete mode 100644 DomainManagement/internal/functions/acl_ace/Test-AccessRuleEquality.ps1 diff --git a/DomainManagement/DomainManagement.psd1 b/DomainManagement/DomainManagement.psd1 index 59b34b9..d45f8c8 100644 --- a/DomainManagement/DomainManagement.psd1 +++ b/DomainManagement/DomainManagement.psd1 @@ -46,14 +46,11 @@ # Functions to export from this module FunctionsToExport = @( 'Clear-DMConfiguration' - 'Convert-DMSchemaGuid' - 'Find-DMObjectCategoryItem' + 'Convert-AdcSchemaGuid' 'Get-DMAccessRule' - 'Get-DMAccessRuleMode' 'Get-DMAcl' 'Get-DMCallback' 'Get-DMContentMode' - 'Get-DMDomainCredential' 'Get-DMDomainData' 'Get-DMDomainLevel' 'Get-DMExchange' @@ -67,8 +64,6 @@ 'Get-DMGroupPolicy' 'Get-DMNameMapping' 'Get-DMObject' - 'Get-DMObjectCategory' - 'Get-DMObjectDefaultPermission' 'Get-DMOrganizationalUnit' 'Get-DMPasswordPolicy' 'Get-DMServiceAccount' @@ -92,7 +87,6 @@ 'Invoke-DMUser' 'Invoke-DMWmiFilter' 'Register-DMAccessRule' - 'Register-DMAccessRuleMode' 'Register-DMAcl' 'Register-DMBuiltInSID' 'Register-DMCallback' @@ -109,18 +103,13 @@ 'Register-DMGroupPolicy' 'Register-DMNameMapping' 'Register-DMObject' - 'Register-DMObjectCategory' 'Register-DMOrganizationalUnit' 'Register-DMPasswordPolicy' 'Register-DMServiceAccount' 'Register-DMUser' 'Register-DMWmiFilter' - 'Reset-DMDomainCredential' - 'Resolve-DMAccessRuleMode' - 'Resolve-DMObjectCategory' 'Set-DMContentMode' 'Set-DMDomainContext' - 'Set-DMDomainCredential' 'Set-DMRedForestContext' 'Test-DMAccessRule' 'Test-DMAcl' @@ -140,7 +129,6 @@ 'Test-DMUser' 'Test-DMWmiFilter' 'Unregister-DMAccessRule' - 'Unregister-DMAccessRuleMode' 'Unregister-DMAcl' 'Unregister-DMCallback' 'Unregister-DMDomainData' @@ -156,7 +144,6 @@ 'Unregister-DMGroupPolicy' 'Unregister-DMNameMapping' 'Unregister-DMObject' - 'Unregister-DMObjectCategory' 'Unregister-DMOrganizationalUnit' 'Unregister-DMPasswordPolicy' 'Unregister-DMServiceAccount' diff --git a/DomainManagement/changelog.md b/DomainManagement/changelog.md index ac4cb76..0b312ee 100644 --- a/DomainManagement/changelog.md +++ b/DomainManagement/changelog.md @@ -1,5 +1,12 @@ # Changelog +## ??? + +- Upd: ACLs - removed exclusion from considering Containers. +- Upd: Get-DMObjectDefaultPermission - removed the command, as part of the AccessRule switch-over to Admf.Core +- Fix: GPLink - deleting links for GPOs that are not accessible will show with an empty name in the test results +- Fix: GPPermission - fixed error message when using a path-based GPPermission filter and the path does not exist + ## 1.9.249 (2026-02-12) - Fix: ServiceAccounts - fixed typo. @@ -255,7 +262,7 @@ ## 1.3.76 (2020-07-31) -- New: Reset-DMDomainCredential - Resets cached credentials for contacting domains. +- New: Reset-AdcDomainCredential - Resets cached credentials for contacting domains. - Upd: Component Group Membership - now can define Group Processing Mode, introducing Constrained and Additive Modes to a group's memberships. - Upd: Component Group Membership - configured names may now include SIDs, such as the SIDs of built-in accounts or groups. - Fix: Register-DMGroupMembership - explicitly registering empty as $false no longer clears configured settings. diff --git a/DomainManagement/en-us/strings.psd1 b/DomainManagement/en-us/strings.psd1 index 470e705..0ee6d76 100644 --- a/DomainManagement/en-us/strings.psd1 +++ b/DomainManagement/en-us/strings.psd1 @@ -5,26 +5,8 @@ 'Assert-Configuration.NotConfigured' = 'No configuration data provided for: {0}' # ($Type -join ", ") - 'Convert-AccessRule.Identity.ResolutionError' = 'Failed to convert identity. This generally means a configuration error, especially when referencing the parent as identity.' # - - 'Convert-Principal.Processing' = 'Converting principal: {0}' # $Name - 'Convert-Principal.Processing.InputNT' = 'Input detected as NT: {0}' # $Name - 'Convert-Principal.Processing.InputSID' = 'Input detected as SID: {0}' # $Name - 'Convert-Principal.Processing.NT.LdapFilter' = 'Resolving NT identity via AD using the following filter: {0}' # "(samAccountName=$namePart)" - 'Convert-Principal.Processing.NTDetails' = 'Resolved NT identity: Domain = {0} | Name = {1}' # $domainPart, $namePart - - 'Find-DMObjectCategoryItem.ADError' = 'Error retrieving AD Objects for object category {0}' # $Name - 'Find-DMObjectCategoryItem.Category.NotFound' = 'No such object category defined: {0}' # $Name - 'General.Invalid.Input' = 'Invalid input: {1}! This command only accepts output objects from {0}' # 'Test-DMAccessRule', $testItem - 'Get-PermissionGuidMapping.Processing' = 'Processing Permission Guids for domain: {0} (This may take a while)' # $identity - - 'Get-Principal.Resolution.Failed' = 'Failed to resolve principal: SID {0} | Name {1} | ObjectClass {2} | Domain {3}' # $Sid, $Name, $ObjectClass, $Domain - 'Get-Principal.Resolution.FailedWithTarget' = 'Failed to resolve principal: SID {0} | Name {1} | ObjectClass {2} | Domain {3} | Target {4}' # $Sid, $Name, $ObjectClass, $Domain, $Target - - 'Get-SchemaGuidMapping.Processing' = 'Processing Schema Guids for domain: {0} (This may take a while)' # $identity - 'Install-GroupPolicy.CopyingFiles' = 'Copying GPO files for "{0}"' # $Configuration.DisplayName 'Install-GroupPolicy.CopyingFiles.Failed' = 'Failed to copy the GPO files for "{0}"' # $Configuration.DisplayName 'Install-GroupPolicy.DeletingImportFiles' = 'Deleting the GPO files for "{0}"' # $Configuration.DisplayName @@ -180,8 +162,6 @@ 'Resolve-ContentSearchBase.Include.NotFound' = 'Failed to find included ou/container: {0}' # $item.Name 'Resolve-ContentSearchBase.Searchbase.Found' = 'Resolved searchbase in {2}: {0} | {1}' # $searchBase.SearchScope, $searchBase.SearchBase, $script:domainContext.Fqdn - 'Resolve-DMAccessRuleMode.PathResolution.Failed' = 'Unable to resolve path: {0}' # $mode.Path - 'Resolve-GPFilterMapping.Filter.Path.DoesNotExist.SilentlyContinue' = 'Issue resolving filter condition {0}: The specified path {1} could not be found, skipping.' # $Condition.Name, $searchBase 'Resolve-GPTargetServer.Info.ChangingToPDC' = 'Changing target server from "{0}" to the PDC Emulator: "{1}". Group Policy components default to working against the PDC, as most GPO tools (including the default GPMC console) do the same. This behavior can be disabled in the module configuration settings.' # $Server, $domainObject.PDCEmulator diff --git a/DomainManagement/functions/AccessRule/Invoke-DMAccessRule.ps1 b/DomainManagement/functions/AccessRule/Invoke-DMAccessRule.ps1 index 9adb5b4..b213936 100644 --- a/DomainManagement/functions/AccessRule/Invoke-DMAccessRule.ps1 +++ b/DomainManagement/functions/AccessRule/Invoke-DMAccessRule.ps1 @@ -89,7 +89,7 @@ $stillThere = $false foreach ($rule in $aclObject.GetAccessRules($true, $false, [System.Security.Principal.NTAccount])) { - if (Test-AccessRuleEquality -Parameters $parameters -Rule1 $rule -Rule2 $changeEntry.ADObject.OriginalRule) { + if (Test-AdcAccessRuleEquality -Parameters $parameters -Rule1 $rule -Rule2 $changeEntry.ADObject.OriginalRule) { $stillThere = $true $failedCount = $failedCount + 1 break @@ -102,7 +102,7 @@ $stillThere = $false foreach ($rule in $aclObject.GetAccessRules($true, $false, [System.Security.Principal.NTAccount])) { - if (Test-AccessRuleEquality -Parameters $parameters -Rule1 $rule -Rule2 $changeEntry.ADObject.OriginalRule) { + if (Test-AdcAccessRuleEquality -Parameters $parameters -Rule1 $rule -Rule2 $changeEntry.ADObject.OriginalRule) { $stillThere = $true $failedCount = $failedCount + 1 break @@ -123,7 +123,7 @@ try { if (-not $changeEntry.Configuration.ObjectType) { throw "Unknown ObjectType! Unable to translate $($changeEntry.Configuration.ObjectTypeName). Validate the configuration and ensure pending schema updates (e.g. Exchange, Skype, etc.) have been applied." } if (-not $changeEntry.Configuration.InheritedObjectType) { throw "Unknown InheritedObjectType! Unable to translate $($changeEntry.Configuration.InheritedObjectTypeName). Validate the configuration and ensure pending schema updates (e.g. Exchange, Skype, etc.) have been applied." } - $accessRule = [System.DirectoryServices.ActiveDirectoryAccessRule]::new((Convert-Principal @parameters -Name $changeEntry.Configuration.IdentityReference), $changeEntry.Configuration.ActiveDirectoryRights, $changeEntry.Configuration.AccessControlType, $changeEntry.Configuration.ObjectType, $changeEntry.Configuration.InheritanceType, $changeEntry.Configuration.InheritedObjectType) + $accessRule = [System.DirectoryServices.ActiveDirectoryAccessRule]::new((Convert-AdcPrincipal @parameters -Name $changeEntry.Configuration.IdentityReference), $changeEntry.Configuration.ActiveDirectoryRights, $changeEntry.Configuration.AccessControlType, $changeEntry.Configuration.ObjectType, $changeEntry.Configuration.InheritanceType, $changeEntry.Configuration.InheritedObjectType) } catch { $failedCount = $failedCount + 1 @@ -141,7 +141,7 @@ try { if (-not $changeEntry.Configuration.ObjectType) { throw "Unknown ObjectType! Unable to translate $($changeEntry.Configuration.ObjectTypeName). Validate the configuration and ensure pending schema updates (e.g. Exchange, Skype, etc.) have been applied." } if (-not $changeEntry.Configuration.InheritedObjectType) { throw "Unknown InheritedObjectType! Unable to translate $($changeEntry.Configuration.InheritedObjectTypeName). Validate the configuration and ensure pending schema updates (e.g. Exchange, Skype, etc.) have been applied." } - $accessRule = [System.DirectoryServices.ActiveDirectoryAccessRule]::new((Convert-Principal @parameters -Name $changeEntry.Configuration.IdentityReference), $changeEntry.Configuration.ActiveDirectoryRights, $changeEntry.Configuration.AccessControlType, $changeEntry.Configuration.ObjectType, $changeEntry.Configuration.InheritanceType, $changeEntry.Configuration.InheritedObjectType) + $accessRule = [System.DirectoryServices.ActiveDirectoryAccessRule]::new((Convert-AdcPrincipal @parameters -Name $changeEntry.Configuration.IdentityReference), $changeEntry.Configuration.ActiveDirectoryRights, $changeEntry.Configuration.AccessControlType, $changeEntry.Configuration.ObjectType, $changeEntry.Configuration.InheritanceType, $changeEntry.Configuration.InheritedObjectType) } catch { $failedCount = $failedCount + 1 diff --git a/DomainManagement/functions/AccessRule/Test-DMAccessRule.ps1 b/DomainManagement/functions/AccessRule/Test-DMAccessRule.ps1 index 0fb44bf..4b82609 100644 --- a/DomainManagement/functions/AccessRule/Test-DMAccessRule.ps1 +++ b/DomainManagement/functions/AccessRule/Test-DMAccessRule.ps1 @@ -45,70 +45,6 @@ ) begin { - #region Utility Functions - function Convert-AccessRule { - [CmdletBinding()] - param ( - [Parameter(ValueFromPipeline = $true)] - $Rule, - - [Parameter(Mandatory = $true)] - $ADObject, - - [PSFComputer] - $Server, - - [PSCredential] - $Credential - ) - begin { - $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential - $convertCmdName = { Convert-DMSchemaGuid @parameters -OutType Name }.GetSteppablePipeline() - $convertCmdName.Begin($true) - $convertCmdGuid = { Convert-DMSchemaGuid @parameters -OutType Guid }.GetSteppablePipeline() - $convertCmdGuid.Begin($true) - } - process { - foreach ($ruleObject in $Rule) { - $objectTypeGuid = $convertCmdGuid.Process($ruleObject.ObjectType)[0] - $objectTypeName = $convertCmdName.Process($ruleObject.ObjectType)[0] - $inheritedObjectTypeGuid = $convertCmdGuid.Process($ruleObject.InheritedObjectType)[0] - $inheritedObjectTypeName = $convertCmdName.Process($ruleObject.InheritedObjectType)[0] - - try { $identity = Resolve-Identity @parameters -IdentityReference $ruleObject.IdentityReference -ADObject $ADObject } - catch { - if ('True' -ne $ruleObject.Present) { continue } - Stop-PSFFunction -String 'Convert-AccessRule.Identity.ResolutionError' -Target $ruleObject -ErrorRecord $_ -Continue - } - - [PSCustomObject]@{ - PSTypeName = 'DomainManagement.AccessRule.Converted' - IdentityReference = $identity - AccessControlType = $ruleObject.AccessControlType - ActiveDirectoryRights = $ruleObject.ActiveDirectoryRights - InheritanceFlags = $ruleObject.InheritanceFlags - InheritanceType = $ruleObject.InheritanceType - InheritedObjectType = $inheritedObjectTypeGuid - InheritedObjectTypeName = $inheritedObjectTypeName - ObjectFlags = $ruleObject.ObjectFlags - ObjectType = $objectTypeGuid - ObjectTypeName = $objectTypeName - PropagationFlags = $ruleObject.PropagationFlags - Present = $ruleObject.Present - } - } - } - end { - #region Inject Category-Based rules - Get-CategoryBasedRules -ADObject $ADObject @parameters -ConvertNameCommand $convertCmdName -ConvertGuidCommand $convertCmdGuid - #endregion Inject Category-Based rules - - $convertCmdName.End() - $convertCmdGuid.End() - } - } - #endregion Utility Functions - $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential $parameters['Debug'] = $false Assert-ADConnection @parameters -Cmdlet $PSCmdlet @@ -116,11 +52,14 @@ Assert-Configuration -Type accessRules -Cmdlet $PSCmdlet Set-DMDomainContext @parameters - try { $null = Get-DMObjectDefaultPermission -ObjectClass top @parameters } + try { $null = Get-AdcObjectDefaultPermission -ObjectClass top @parameters } catch { Stop-PSFFunction -String 'Test-DMAccessRule.DefaultPermission.Failed' -StringValues $Server -Target $Server -EnableException $false -ErrorRecord $_ return } + + $systemContainer = (Get-ADDomain @parameters).SystemsContainer + $adminSDHolderRules = (Get-AdsAcl -Path "CN=AdminSDHolder,$systemContainer" @parameters).Access } process { if (Test-PSFFunctionInterrupt) { return } @@ -153,14 +92,14 @@ if ($adObject.adminCount) { $defaultPermissions = @() - $desiredPermissions = Get-AdminSDHolderRules @parameters + $desiredPermissions = $adminSDHolderRules } else { - $defaultPermissions = Get-DMObjectDefaultPermission @parameters -ObjectClass $adObject.ObjectClass - $desiredPermissions = $script:accessRules[$key] | Convert-AccessRule @parameters -ADObject $adObject + $defaultPermissions = Get-AdcObjectDefaultPermission @parameters -ObjectClass $adObject.ObjectClass + $desiredPermissions = $script:accessRules[$key] | ConvertFrom-AdcAccessRuleConfiguration @parameters -ADObject $adObject -IncludeCategory -CategoryRules $script:accessCategoryRules } - $delta = Compare-AccessRules @parameters -ADRules ($adAclObject.Access | Convert-AccessRuleIdentity @parameters -Target $adAclObject.DistinguishedName) -ConfiguredRules $desiredPermissions -DefaultRules $defaultPermissions -ADObject $adObject + $delta = Compare-AdcAccessRules @parameters -ADRules ($adAclObject.Access | Convert-AdcAccessRuleIdentity @parameters -Target $adAclObject.DistinguishedName) -ConfiguredRules $desiredPermissions -DefaultRules $defaultPermissions -ADObject $adObject if ($delta) { New-TestResult @resultDefaults -Type Update -Changed $delta -ADObject $adAclObject @@ -169,6 +108,8 @@ } #endregion Process Configured Objects + if ($script:contentMode.ExcludeComponents.AccessRules) { return } + $doParallelize = Get-PSFConfigValue -FullName 'DomainManagement.AccessRules.Parallelize' #region Process Non-Configured AD Objects - Serial if (-not $doParallelize) { @@ -183,9 +124,9 @@ ObjectType = 'AccessRule' } - $convertCmdName = { Convert-DMSchemaGuid @parameters -OutType Name }.GetSteppablePipeline() + $convertCmdName = { Convert-AdcSchemaGuid @parameters -OutType Name }.GetSteppablePipeline() $convertCmdName.Begin($true) - $convertCmdGuid = { Convert-DMSchemaGuid @parameters -OutType Guid }.GetSteppablePipeline() + $convertCmdGuid = { Convert-AdcSchemaGuid @parameters -OutType Guid }.GetSteppablePipeline() $convertCmdGuid.Begin($true) $processed = @{ } @@ -202,20 +143,20 @@ $adAclObject = Get-AdsAcl @parameters -Path $foundADObject.DistinguishedName $compareParam = @{ - ADRules = $adAclObject.Access | Convert-AccessRuleIdentity @parameters - DefaultRules = Get-DMObjectDefaultPermission @parameters -ObjectClass $foundADObject.ObjectClass - ConfiguredRules = Get-CategoryBasedRules -ADObject $foundADObject @parameters -ConvertNameCommand $convertCmdName -ConvertGuidCommand $convertCmdGuid + ADRules = $adAclObject.Access | Convert-AdcAccessRuleIdentity @parameters + DefaultRules = Get-AdcObjectDefaultPermission @parameters -ObjectClass $foundADObject.ObjectClass + ConfiguredRules = Get-AdcCategoryBasedRules -ADObject $foundADObject @parameters -ConvertNameCommand $convertCmdName -ConvertGuidCommand $convertCmdGuid -CategoryRules $script:accessCategoryRules ADObject = $foundADObject } # Protected Objects if ($foundADObject.AdminCount) { $compareParam.DefaultRules = @() - $compareParam.ConfiguredRules = Get-AdminSDHolderRules @parameters + $compareParam.ConfiguredRules = $adminSDHolderRules } $compareParam += $parameters - $delta = Compare-AccessRules @compareParam + $delta = Compare-AdcAccessRules @compareParam if ($delta) { New-TestResult @resultDefaults -Type Update -Changed $delta -ADObject $adAclObject -Identity $foundADObject.DistinguishedName @@ -238,7 +179,7 @@ ObjectType = 'AccessRule' } parameters = $parameters - adminSDHolderRules = Get-AdminSDHolderRules @parameters + adminSDHolderRules = $adminSDHolderRules schemaDefaultPermissions = $script:schemaObjectDefaultPermission["$Server"] accessRuleConfiguration = @{ accessRules = $script:accessRules @@ -248,6 +189,7 @@ stringTable = $script:nameReplacementTable } $modules = @( + (Get-Module ADMF.Core).ModuleBase (Get-Module DomainManagement).ModuleBase (Get-Module ADSec).ModuleBase ) @@ -270,14 +212,14 @@ } } - $global:convertCmdName = { Convert-DMSchemaGuid @parameters -OutType Name }.GetSteppablePipeline() + $global:convertCmdName = { Convert-AdcSchemaGuid @parameters -OutType Name }.GetSteppablePipeline() $global:convertCmdName.Begin($true) - $global:convertCmdGuid = { Convert-DMSchemaGuid @parameters -OutType Guid }.GetSteppablePipeline() + $global:convertCmdGuid = { Convert-AdcSchemaGuid @parameters -OutType Guid }.GetSteppablePipeline() $global:convertCmdGuid.Begin($true) - $global:cmdCompareAccessRules = & (Get-Module DomainManagement) { Get-Command Compare-AccessRules } - $global:cmdConvertAccessRuleIdentity = & (Get-Module DomainManagement) { Get-Command Convert-AccessRuleIdentity } - $global:cmdGetCategoryBasedRules = & (Get-Module DomainManagement) { Get-Command Get-CategoryBasedRules } + $global:cmdCompareAccessRules = Get-Command Compare-AdcAccessRules + $global:cmdConvertAccessRuleIdentity = Get-Command Convert-AdcAccessRuleIdentity + $global:cmdGetCategoryBasedRules = Get-Command Get-AdcCategoryBasedRules } $process = { $count = 0 @@ -287,7 +229,7 @@ $adAclObject = Get-AdsAcl @parameters -Path $foundADObject.DistinguishedName $compareParam = @{ ADRules = & $global:cmdConvertAccessRuleIdentity -InputObject $adAclObject.Access @parameters - DefaultRules = Get-DMObjectDefaultPermission @parameters -ObjectClass $foundADObject.ObjectClass + DefaultRules = Get-AdcObjectDefaultPermission @parameters -ObjectClass $foundADObject.ObjectClass ConfiguredRules = & $global:cmdGetCategoryBasedRules -ADObject $foundADObject @parameters -ConvertNameCommand $convertCmdName -ConvertGuidCommand $convertCmdGuid ADObject = $foundADObject } diff --git a/DomainManagement/functions/AccessRuleMode/Get-DMAccessRuleMode.ps1 b/DomainManagement/functions/AccessRuleMode/Get-DMAccessRuleMode.ps1 deleted file mode 100644 index 6f1a035..0000000 --- a/DomainManagement/functions/AccessRuleMode/Get-DMAccessRuleMode.ps1 +++ /dev/null @@ -1,35 +0,0 @@ -function Get-DMAccessRuleMode -{ - <# - .SYNOPSIS - Retrieve registered AccessRule processing modes. - - .DESCRIPTION - Retrieve registered AccessRule processing modes. - These are used to define, how AccessRules will be processed. - - .PARAMETER Path - Filter by the path the AccessRule processing mode applies to. - - .PARAMETER ObjectCategory - Filter by the object category the AccessRule processing mode applies to. - - .EXAMPLE - PS C:\> Get-DMAccessRuleMode - - List all registered AccessRule processing modes. - #> - [CmdletBinding()] - Param ( - [string] - $Path = '*', - - [string] - $ObjectCategory = '*' - ) - - process - { - $script:accessRuleMode.Values | Where-Object Path -like $Path | Where-Object ObjectCategory -like $ObjectCategory - } -} diff --git a/DomainManagement/functions/AccessRuleMode/Register-DMAccessRuleMode.ps1 b/DomainManagement/functions/AccessRuleMode/Register-DMAccessRuleMode.ps1 deleted file mode 100644 index 4b32ed9..0000000 --- a/DomainManagement/functions/AccessRuleMode/Register-DMAccessRuleMode.ps1 +++ /dev/null @@ -1,73 +0,0 @@ -function Register-DMAccessRuleMode { - <# - .SYNOPSIS - Register the processing mode for access rules on a specified object. - - .DESCRIPTION - Register the processing mode for access rules on a specified object. - This is used by the AccessRule Component exclusively. - - .PARAMETER Path - The path to the AD object to govern. - This should be a distinguishedname. - This path uses name resolution. - For example %DomainDN% will be replaced with the DN of the target domain itself (and should probably be part of everyy single path). - - .PARAMETER PathMode - Whether to only target a specific path or the target path and all items beneath it. - - .PARAMETER ObjectCategory - Instead of a path, define a category to apply the processing mode to. - Categories are defined using Register-DMObjectCategory. - This allows you to apply processing mode to a category of objects, rather than a specific path. - With this you could apply a processing mode to all domain controller objects, for example. - - .PARAMETER Mode - Determines, how the AccessRules are applied on the target object: - - Constrained: All non-defined AccessRules will be removed. - - Defined: Only non-defined AccessRules with identities for which a configuration exists on the object will be deleted. - - Additive: Non-defined AccessRules on the targeted object will be ignored. - By default, with no AccessRuleMode defined, all objects are considered to be in Constrained mode. - - .EXAMPLE - PS C:\> Register-DMAccessRuleMode -Path 'OU=Company,%DomainDN%' -PathMode SubTree -Mode Additive - - Configures the specified OU and all items beneath it to be in additive mode. - Defined AccessRules will be applied if missing, but previously existing rules remain untouched. - #> - [CmdletBinding()] - Param ( - [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Path')] - [string] - $Path, - - [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Path')] - [ValidateSet('SingleItem', 'SubTree')] - [string] - $PathMode = 'SingleItem', - - [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Category')] - [string] - $ObjectCategory, - - [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] - [ValidateSet('Constrained', 'Defined', 'Additive')] - [string] - $Mode - ) - - process { - $identity = 'Path:{0}:{1}' -f $PathMode,$Path - if ($ObjectCategory) { $identity = 'Category:{0}' -f $ObjectCategory } - - $script:accessRuleMode[$identity] = [PSCustomObject]@{ - PSTypeName = 'DomainManagement.AccessRuleMode' - Identity = $identity - Type = $PSCmdlet.ParameterSetName - Path = $Path - PathMode = $PathMode - ObjectCategory = $ObjectCategory - Mode = $Mode - } - } -} diff --git a/DomainManagement/functions/AccessRuleMode/Resolve-DMAccessRuleMode.ps1 b/DomainManagement/functions/AccessRuleMode/Resolve-DMAccessRuleMode.ps1 deleted file mode 100644 index c5b1da4..0000000 --- a/DomainManagement/functions/AccessRuleMode/Resolve-DMAccessRuleMode.ps1 +++ /dev/null @@ -1,84 +0,0 @@ -function Resolve-DMAccessRuleMode -{ - <# - .SYNOPSIS - Resolves the AccessRule processing mode that applies to the specified ADObject. - - .DESCRIPTION - Resolves the AccessRule processing mode that applies to the specified ADObject. - - .PARAMETER ADObject - The AD Object for which to resolve the AccessRule processing mode. - - .PARAMETER Server - The server / domain to work with. - - .PARAMETER Credential - The credentials to use for this operation. - - .EXAMPLE - PS C:\> Resolve-DMAccessRuleMode @parameters -ADObject $adObject - - Resolves the AccessRule processing mode that applies to the specified ADObject. - #> - [OutputType([string])] - [CmdletBinding()] - Param ( - [Parameter(Mandatory = $true)] - $ADObject, - - [PSFComputer] - $Server, - - [PSCredential] - $Credential - ) - - begin - { - $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential - } - process - { - if ($script:accessRuleMode.Count -lt 1) { return 'Constrained' } - - $relevantCategories = @() - if ($script:accessRuleMode.Values.ObjectCategory) { - $relevantCategories = Resolve-DMObjectCategory -ADObject $ADObject @parameters - } - - $applicableModes = :main foreach ($mode in $script:accessRuleMode.Values) { - if ($mode.Path) { - try { $resolvedPath = $mode.Path | Resolve-String @parameters } - catch { - Write-PSFMessage -Level Warning -String 'Resolve-DMAccessRuleMode.PathResolution.Failed' -StringValues $mode.Path -ErrorRecord $_ - $resolvedPath = $mode.Path | Resolve-String - } - switch ($mode.PathMode) { - 'SingleItem' { - if ($ADObject.DistinguishedName -eq $resolvedPath) { $mode } - continue main - } - 'SubTree' { - if ($ADObject.DistinguishedName -like "*$resolvedPath") { $mode } - continue main - } - } - } - if ($mode.ObjectCategory -and ($mode.ObjectCategory -in $relevantCategories.Name)) { - $mode - } - } - - if ($primaryMode = $applicableModes | Where-Object { $_.Type -eq 'Path' -and $_.PathMode -eq 'SingleItem'}) { - return $primaryMode.Mode - } - if ($secondaryMode = $applicableModes | Where-Object Type -eq 'Category' | Select-Object -First 1) { - return $secondaryMode.Mode - } - if ($tertiaryMode = $applicableModes | Where-Object { $_.Type -eq 'Path' -and $_.PathMode -eq 'SubTree'} | Sort-Object { $_.Path.Length } -Descending | Select-Object -First 1) { - return $tertiaryMode.Mode - } - return 'Constrained' - } -} diff --git a/DomainManagement/functions/AccessRuleMode/Unregister-DMAccessRuleMode.ps1 b/DomainManagement/functions/AccessRuleMode/Unregister-DMAccessRuleMode.ps1 deleted file mode 100644 index b9d4f41..0000000 --- a/DomainManagement/functions/AccessRuleMode/Unregister-DMAccessRuleMode.ps1 +++ /dev/null @@ -1,52 +0,0 @@ -function Unregister-DMAccessRuleMode -{ - <# - .SYNOPSIS - Removes previously registered AccessRule processing modes. - - .DESCRIPTION - Removes previously registered AccessRule processing modes. - Prioritizes Identity over Path over ObjectCategory. - - .PARAMETER Identity - The Identity of the AccessRule processing mode to remove. - - .PARAMETER Path - The Path of the AccessRule processing mode to remove. - - .PARAMETER ObjectCagegory - The ObjectCategory of the AccessRule processing mode to remove. - - .EXAMPLE - PS C:\> Get-DMAccessRuleMode | Unregister-DMAccessRuleMode - - Clears all registered AccessRule processing modes. - #> - [CmdletBinding()] - Param ( - [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] - [AllowEmptyString()] - [AllowNull()] - [string] - $Identity, - - [Parameter(ValueFromPipelineByPropertyName = $true)] - [AllowEmptyString()] - [AllowNull()] - [string] - $Path, - - [Parameter(ValueFromPipelineByPropertyName = $true)] - [AllowEmptyString()] - [AllowNull()] - [string] - $ObjectCagegory - ) - - process - { - if ($Identity) { $script:accessRuleMode.Remove($Identity) } - elseif ($Path) { $script:accessRuleMode.Remove("Path:$Path") } - elseif ($ObjectCagegory) { $script:accessRuleMode.Remove("Category:$ObjectCategory") } - } -} diff --git a/DomainManagement/functions/acls/Get-DMAcl.ps1 b/DomainManagement/functions/acls/Get-DMAcl.ps1 index b0e95cd..d1a3e07 100644 --- a/DomainManagement/functions/acls/Get-DMAcl.ps1 +++ b/DomainManagement/functions/acls/Get-DMAcl.ps1 @@ -1,5 +1,4 @@ -function Get-DMAcl -{ +function Get-DMAcl { <# .SYNOPSIS Lists registered acls. @@ -22,10 +21,9 @@ $Path = '*' ) - process - { - ($script:acls.Values) | Where-Object Path -like $Path - ($script:aclsByCategory.Values) | Where-Object Category -like $Path - $script:aclDefaultOwner | Where-Object Path -like $Path + process { + ($script:acls.Values) | Where-Object Path -Like $Path + ($script:aclsByCategory.Values) | Where-Object Category -Like $Path + $script:aclDefaultOwner | Where-Object Path -Like $Path } } diff --git a/DomainManagement/functions/acls/Invoke-DMAcl.ps1 b/DomainManagement/functions/acls/Invoke-DMAcl.ps1 index 69eba1d..d3b4665 100644 --- a/DomainManagement/functions/acls/Invoke-DMAcl.ps1 +++ b/DomainManagement/functions/acls/Invoke-DMAcl.ps1 @@ -1,5 +1,4 @@ -function Invoke-DMAcl -{ +function Invoke-DMAcl { <# .SYNOPSIS Applies the desired ACL configuration. @@ -52,8 +51,7 @@ $EnableException ) - begin - { + begin { $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential $parameters['Debug'] = $false Assert-ADConnection @parameters -Cmdlet $PSCmdlet @@ -61,7 +59,7 @@ Assert-Configuration -Type Acls, AclByCategory, AclDefaultOwner -Cmdlet $PSCmdlet Set-DMDomainContext @parameters } - process{ + process { if (-not $InputObject) { $InputObject = Test-DMAcl @parameters } @@ -73,26 +71,22 @@ } switch ($testItem.Type) { - 'MissingADObject' - { + 'MissingADObject' { Write-PSFMessage -Level Warning -String 'Invoke-DMAcl.MissingADObject' -StringValues $testItem.Identity -Target $testItem continue } - 'NoAccess' - { + 'NoAccess' { Write-PSFMessage -Level Warning -String 'Invoke-DMAcl.NoAccess' -StringValues $testItem.Identity -Target $testItem continue } - 'OwnerNotResolved' - { + 'OwnerNotResolved' { Write-PSFMessage -Level Warning -String 'Invoke-DMAcl.OwnerNotResolved' -StringValues $testItem.Identity, $testItem.ADObject.GetOwner([System.Security.Principal.SecurityIdentifier]) -Target $testItem continue } - 'Update' - { + 'Update' { if ($testItem.Changed.Type -contains 'Owner') { Invoke-PSFProtectedCommand -ActionString 'Invoke-DMAcl.UpdatingOwner' -ActionStringValues ($testItem.Configuration.Owner | Resolve-String) -Target $testItem -ScriptBlock { - Set-AdsOwner @parameters -Path $testItem.Identity -Identity (Convert-Principal @parameters -Name ($testItem.Configuration.Owner | Resolve-String)) -EnableException -Confirm:$false + Set-AdsOwner @parameters -Path $testItem.Identity -Identity (Convert-AdcPrincipal @parameters -Name ($testItem.Configuration.Owner | Resolve-String)) -EnableException -Confirm:$false } -EnableException $EnableException.ToBool() -PSCmdlet $PSCmdlet -Continue } if ($testItem.Changed.Type -contains 'NoInheritance') { @@ -104,8 +98,7 @@ } -EnableException $EnableException.ToBool() -PSCmdlet $PSCmdlet -Continue } } - 'ShouldManage' - { + 'ShouldManage' { Write-PSFMessage -Level Warning -String 'Invoke-DMAcl.ShouldManage' -StringValues $testItem.Identity -Target $testItem continue } diff --git a/DomainManagement/functions/acls/Register-DMAcl.ps1 b/DomainManagement/functions/acls/Register-DMAcl.ps1 index 118d4c0..9b28871 100644 --- a/DomainManagement/functions/acls/Register-DMAcl.ps1 +++ b/DomainManagement/functions/acls/Register-DMAcl.ps1 @@ -1,5 +1,4 @@ -function Register-DMAcl -{ +function Register-DMAcl { <# .SYNOPSIS Registers an active directory acl. @@ -73,42 +72,38 @@ [string] $ContextName = '' ) - process - { + process { switch ($PSCmdlet.ParameterSetName) { - 'path' - { + 'path' { $script:acls[$Path] = [PSCustomObject]@{ - PSTypeName = 'DomainManagement.Acl' - Path = $Path - Owner = $Owner + PSTypeName = 'DomainManagement.Acl' + Path = $Path + Owner = $Owner NoInheritance = $NoInheritance - Optional = $Optional - ContextName = $ContextName + Optional = $Optional + ContextName = $ContextName } } - 'category' - { + 'category' { $script:aclByCategory[$ObjectCategory] = [PSCustomObject]@{ - PSTypeName = 'DomainManagement.Acl' - Category = $ObjectCategory - Owner = $Owner + PSTypeName = 'DomainManagement.Acl' + Category = $ObjectCategory + Owner = $Owner NoInheritance = $NoInheritance - Optional = $Optional - ContextName = $ContextName + Optional = $Optional + ContextName = $ContextName } } - 'DefaultOwner' - { + 'DefaultOwner' { # Array to appease Assert-Configuration $script:aclDefaultOwner = @([PSCustomObject]@{ - PSTypeName = 'DomainManagement.Acl' - Path = '' - Owner = $Owner - NoInheritance = $false - Optional = $null - ContextName = $ContextName - }) + PSTypeName = 'DomainManagement.Acl' + Path = '' + Owner = $Owner + NoInheritance = $false + Optional = $null + ContextName = $ContextName + }) } } } diff --git a/DomainManagement/functions/acls/Test-DMAcl.ps1 b/DomainManagement/functions/acls/Test-DMAcl.ps1 index 60d8b31..dff2ec2 100644 --- a/DomainManagement/functions/acls/Test-DMAcl.ps1 +++ b/DomainManagement/functions/acls/Test-DMAcl.ps1 @@ -1,10 +1,10 @@ function Test-DMAcl { <# .SYNOPSIS - Tests whether the configured groups match a domain's configuration. + Tests whether the configured ACLs match a domain's configuration. .DESCRIPTION - Tests whether the configured groups match a domain's configuration. + Tests whether the configured ACLs match a domain's configuration. .PARAMETER Server The server / domain to work with. @@ -15,7 +15,7 @@ .EXAMPLE PS C:\> Test-DMGroup - Tests whether the configured groups' state matches the current domain group setup. + Tests whether the configured ACLs' state matches the current domain ACL setup. #> [CmdletBinding()] param ( @@ -75,11 +75,27 @@ # Ensure Owner Name is present - may not always resolve $ownerSID = $aclObject.GetOwner([System.Security.Principal.SecurityIdentifier]) - $configuredSID = $Category.Owner | Resolve-String | Convert-Principal @parameters -OutputType SID + $simpleOwner = $true + if ($Category.Owner -match '^__.+__$') { + $simpleOwner = $false + Invoke-PSFProtectedCommand -ActionString 'Test-DMAcl.ResolveOwner' -ActionStringValues $Category.Owner.Trim('_'),$ADObject.DistinguishedName -Target $Category -ScriptBlock { + $ownerSet = Resolve-AdcPrivilegedGroupSet -Type $Category.Owner.Trim('_') @parameters + } -Continue -PSCmdlet $PSCmdlet + } + else { + $configuredSID = $Category.Owner | Resolve-String | Convert-AdcPrincipal @parameters -OutputType SID + } [System.Collections.ArrayList]$changes = @() - if ("$ownerSID" -ne "$configuredSID") { - $null = $changes.Add((New-Change -Identity $ADObject -Type Owner -OldValue $aclObject.Owner -NewValue ($Category.Owner | Resolve-String) -OldSID $ownerSID -NewSID $configuredSID)) + if ($simpleOwner) { + if ("$ownerSID" -ne "$configuredSID") { + $null = $changes.Add((New-Change -Identity $resolvedPath -Type Owner -OldValue $aclObject.Owner -NewValue ($Category.Owner | Resolve-String) -OldSID $ownerSID -NewSID $configuredSID)) + } + } + else { + if ("$ownerSID" -notin $ownerSet.SIDs) { + $null = $changes.Add((New-Change -Identity $resolvedPath -Type Owner -OldValue $aclObject.Owner -NewValue ($Category.Owner | Resolve-String) -OldSID $ownerSID -NewSID $ownerSet.DefaultSID)) + } } if ($Category.NoInheritance -ne $aclObject.AreAccessRulesProtected) { # If AdminCount -eq 1, then inheritance should be disabled, no matter the configuration @@ -111,7 +127,7 @@ if ($aclDefinition.Optional) { continue } Write-PSFMessage -String 'Test-DMAcl.ADObjectNotFound' -StringValues $resolvedPath -Tag 'panic', 'failed' -Target $aclDefinition New-TestResult @resultDefaults -Type 'MissingADObject' - Continue + continue } try { $aclObject = Get-AdsAcl @parameters -Path $resolvedPath -EnableException } @@ -119,15 +135,31 @@ if ($aclDefinition.Optional) { continue } Write-PSFMessage -String 'Test-DMAcl.NoAccess' -StringValues $resolvedPath -Tag 'panic', 'failed' -Target $aclDefinition -ErrorRecord $_ New-TestResult @resultDefaults -Type 'NoAccess' - Continue + continue } # Ensure Owner Name is present - may not always resolve $ownerSID = $aclObject.GetOwner([System.Security.Principal.SecurityIdentifier]) - $configuredSID = $aclDefinition.Owner | Resolve-String | Convert-Principal @parameters -OutputType SID + $simpleOwner = $true + if ($aclDefinition.Owner -match '^__.+__$') { + $simpleOwner = $false + Invoke-PSFProtectedCommand -ActionString 'Test-DMAcl.ResolveOwner' -ActionStringValues $aclDefinition.Owner.Trim('_'),$resolvedPath -Target $aclDefinition -ScriptBlock { + $ownerSet = Resolve-AdcPrivilegedGroupSet + } -Continue -PSCmdlet $PSCmdlet + } + else { + $configuredSID = $aclDefinition.Owner | Resolve-String | Convert-AdcPrincipal @parameters -OutputType SID + } [System.Collections.ArrayList]$changes = @() - if ("$ownerSID" -ne "$configuredSID") { - $null = $changes.Add((New-Change -Identity $resolvedPath -Type Owner -OldValue $aclObject.Owner -NewValue ($aclDefinition.Owner | Resolve-String) -OldSID $ownerSID -NewSID $configuredSID)) + if ($simpleOwner) { + if ("$ownerSID" -ne "$configuredSID") { + $null = $changes.Add((New-Change -Identity $resolvedPath -Type Owner -OldValue $aclObject.Owner -NewValue ($aclDefinition.Owner | Resolve-String) -OldSID $ownerSID -NewSID $configuredSID)) + } + } + else { + if ("$ownerSID" -notin $ownerSet.SIDs) { + $null = $changes.Add((New-Change -Identity $resolvedPath -Type Owner -OldValue $aclObject.Owner -NewValue ($aclDefinition.Owner | Resolve-String) -OldSID $ownerSID -NewSID $ownerSet.DefaultSID)) + } } if ($aclDefinition.NoInheritance -ne $aclObject.AreAccessRulesProtected) { $null = $changes.Add((New-Change -Identity $resolvedPath -Type NoInheritance -OldValue $aclObject.AreAccessRulesProtected -NewValue $aclDefinition.NoInheritance)) @@ -142,7 +174,7 @@ if ($script:contentMode.ExcludeComponents.ACLs) { return } #region check if all ADObjects are managed - $foundADObjects = foreach ($searchBase in (Resolve-ContentSearchBase @parameters -NoContainer)) { + $foundADObjects = foreach ($searchBase in (Resolve-ContentSearchBase @parameters)) { Get-ADObject @parameters -LDAPFilter '(objectCategory=*)' -SearchBase $searchBase.SearchBase -SearchScope $searchBase.SearchScope -Properties AdminCount } @@ -162,7 +194,7 @@ if ($foundADObject.DistinguishedName -in $resolvedConfiguredPaths) { continue } if ($script:aclByCategory.Count -gt 0) { - $category = Resolve-DMObjectCategory -ADObject $foundADObject @parameters + $category = Resolve-AdcObjectCategory -ADObject $foundADObject @parameters if ($matchingCategory = $category | Where-Object Name -In $script:aclByCategory.Keys | Select-Object -First 1) { Get-ChangeByCategory -ADObject $foundADObject -Category $script:aclByCategory[$matchingCategory.Name] -ResultDefaults $resultDefaults -Parameters $parameters continue diff --git a/DomainManagement/functions/acls/Unregister-DMAcl.ps1 b/DomainManagement/functions/acls/Unregister-DMAcl.ps1 index 6e17dc5..ad037f5 100644 --- a/DomainManagement/functions/acls/Unregister-DMAcl.ps1 +++ b/DomainManagement/functions/acls/Unregister-DMAcl.ps1 @@ -1,5 +1,4 @@ -function Unregister-DMAcl -{ +function Unregister-DMAcl { <# .SYNOPSIS Removes a acl that had previously been registered. @@ -30,8 +29,7 @@ $Category ) - process - { + process { foreach ($pathItem in $Path) { if ($pathItem -eq '') { $script:aclDefaultOwner = $null } else { $script:acls.Remove($pathItem) } diff --git a/DomainManagement/functions/domaindata/Invoke-DMDomainData.ps1 b/DomainManagement/functions/domaindata/Invoke-DMDomainData.ps1 index 1a1ef2a..32b8cd3 100644 --- a/DomainManagement/functions/domaindata/Invoke-DMDomainData.ps1 +++ b/DomainManagement/functions/domaindata/Invoke-DMDomainData.ps1 @@ -78,7 +78,7 @@ } #endregion Script not found - $domainObject = Get-Domain2 @parameters + $domainObject = Get-AdcDomain @parameters if (-not $script:cache_DomainData[$domainObject.DNSRoot]) { $script:cache_DomainData[$domainObject.DNSRoot] = @{ } } if ($script:cache_DomainData[$domainObject.DNSRoot][$Name] -and -not $Reset) { return $script:cache_DomainData[$domainObject.DNSRoot][$Name] } diff --git a/DomainManagement/functions/gplinks/Test-DMGPLink.ps1 b/DomainManagement/functions/gplinks/Test-DMGPLink.ps1 index 7134e07..1b98b3d 100644 --- a/DomainManagement/functions/gplinks/Test-DMGPLink.ps1 +++ b/DomainManagement/functions/gplinks/Test-DMGPLink.ps1 @@ -145,6 +145,7 @@ $Action ) + if (-not $PolicyName) { $PolicyName = "" } $update = [PSCustomObject]@{ PSTypeName = 'DomainManagement.GPLink.Update' Policy = $PolicyName diff --git a/DomainManagement/functions/gppermissionfilters/Register-DMGPPermissionFilter.ps1 b/DomainManagement/functions/gppermissionfilters/Register-DMGPPermissionFilter.ps1 index df8b5f7..608f48e 100644 --- a/DomainManagement/functions/gppermissionfilters/Register-DMGPPermissionFilter.ps1 +++ b/DomainManagement/functions/gppermissionfilters/Register-DMGPPermissionFilter.ps1 @@ -34,7 +34,7 @@ Whether the path is optional. By default, when evaluating a path filter, processing of GP permission terminates if the designated path does not exist, as we cannot guarantee a consistent permission-set being applied. With this setting enabled, instead processing silently continues. - (Even if this is enabled, a silent log entry will be added for tracking purposes!) + (Even if this is enabled, a silent log entry will be added for tracking purposes!) .PARAMETER GPName Name of the GP to filter for. diff --git a/DomainManagement/functions/gppermissions/Invoke-DMGPPermission.ps1 b/DomainManagement/functions/gppermissions/Invoke-DMGPPermission.ps1 index dff3f81..0255a94 100644 --- a/DomainManagement/functions/gppermissions/Invoke-DMGPPermission.ps1 +++ b/DomainManagement/functions/gppermissions/Invoke-DMGPPermission.ps1 @@ -150,7 +150,7 @@ try { $acl = Get-AdsAcl -Path $testResult.AdObject.DistinguishedName @parameters -ErrorAction Stop } catch { Stop-PSFFunction -String 'Invoke-DMGPPermission.AD.Access.Error' -StringValues $testResult, $testResult.ADObject.DistinguishedName -ErrorRecord $_ -Continue -EnableException $EnableException } - [string[]]$applicableIdentities = $acl.Access.Identity | Remove-PSFNull | Resolve-String | Convert-Principal @parameters + [string[]]$applicableIdentities = $acl.Access.Identity | Remove-PSFNull | Resolve-String | Convert-AdcPrincipal @parameters # Process Remove actions first, as they might interfere when processed last and replacing permissions. foreach ($change in ($testResult.Changed | Sort-Object Action -Descending)) { @@ -189,7 +189,7 @@ $acl | Set-AdsAcl @parameters -Confirm:$false -EnableException } -Continue -EnableException $EnableException -PSCmdlet $PSCmdlet -Target $testResult Invoke-PSFProtectedCommand -ActionString 'Invoke-DMGPPermission.Gpo.SyncingPermission' -ActionStringValues $testResult.Changed.Count -ScriptBlock { - $domainObject = Get-Domain2 @parameters + $domainObject = Get-AdcDomain @parameters Invoke-Command -Session $session -ScriptBlock { $gpoObject = Get-Gpo -Server localhost -DisplayName $using:testResult.Identity -Domain $using:domainObject.DNSRoot -ErrorAction Stop $gpoObject.MakeAclConsistent() diff --git a/DomainManagement/functions/gppermissions/Test-DMGPPermission.ps1 b/DomainManagement/functions/gppermissions/Test-DMGPPermission.ps1 index d24ee92..1bfe6ed 100644 --- a/DomainManagement/functions/gppermissions/Test-DMGPPermission.ps1 +++ b/DomainManagement/functions/gppermissions/Test-DMGPPermission.ps1 @@ -128,7 +128,7 @@ $identity = Resolve-Identity -IdentityReference $inputItem.Identity if ($identity -is [System.Security.Principal.NTAccount]) { $domainName, $identityName = $identity -replace '^(.+)@(.+)$','$2\$1' -split "\\" - try { $principal = Get-Principal @parameters -Name $identityName -Domain $domainName -ObjectClass $inputItem.ObjectClass } + try { $principal = Get-AdcPrincipal @parameters -Name $identityName -Domain $domainName -ObjectClass $inputItem.ObjectClass } catch { throw } $identity = $principal.ObjectSID } @@ -215,7 +215,7 @@ Write-PSFMessage -String 'Test-DMGPPermission.Filter.Path.DoesNotExist.SilentlyContinue' -StringValues $Condition.Name, $searchBase -Target $condition continue conditions } - Stop-PSFFunction -String 'Test-DMGPPermission.Filter.Path.DoesNotExist.Stop' -StringValues $searchBase -Target $Condition.Name, $condition -EnableException $EnableException -Tag Panic, Error + Stop-PSFFunction -String 'Test-DMGPPermission.Filter.Path.DoesNotExist.Stop' -StringValues $Condition.Name, $searchBase -Target $condition -EnableException $EnableException -Tag Panic, Error return } @@ -255,7 +255,7 @@ #endregion Data Preparation #region Process GPO Permissions - $domainObject = Get-Domain2 @parameters + $domainObject = Get-AdcDomain @parameters $permissionObjects = Invoke-Command -Session $session -ScriptBlock { Update-TypeData -TypeName Microsoft.GroupPolicy.GPPermission -SerializationDepth 4 foreach ($policyObject in $using:allGpos) { diff --git a/DomainManagement/functions/gpregistrysettings/Test-DMGPRegistrySetting.ps1 b/DomainManagement/functions/gpregistrysettings/Test-DMGPRegistrySetting.ps1 index bc3a864..44a81be 100644 --- a/DomainManagement/functions/gpregistrysettings/Test-DMGPRegistrySetting.ps1 +++ b/DomainManagement/functions/gpregistrysettings/Test-DMGPRegistrySetting.ps1 @@ -91,7 +91,7 @@ } else { $pdcParameter = $parameters.Clone() - $pdcParameter.ComputerName = (Get-Domain2 @parameters).PDCEmulator + $pdcParameter.ComputerName = (Get-AdcDomain @parameters).PDCEmulator $pdcParameter.Remove('Server') try { $session = New-AdcPSSession @pdcParameter -ErrorAction Stop } catch { diff --git a/DomainManagement/functions/groupmemberships/Invoke-DMGroupMembership.ps1 b/DomainManagement/functions/groupmemberships/Invoke-DMGroupMembership.ps1 index 7eaa297..c3beae3 100644 --- a/DomainManagement/functions/groupmemberships/Invoke-DMGroupMembership.ps1 +++ b/DomainManagement/functions/groupmemberships/Invoke-DMGroupMembership.ps1 @@ -6,7 +6,7 @@ .DESCRIPTION Applies the desired group memberships to the target domain. Use Register-DMGroupMembership to configure just what is considered desired. - Use Set-DMDomainCredential to prepare authentication as needed for remote domains, when principals from that domain must be resolved. + Use Set-AdcDomainCredential to prepare authentication as needed for remote domains, when principals from that domain must be resolved. .PARAMETER InputObject Test results provided by the associated test command. diff --git a/DomainManagement/functions/groupmemberships/Test-DMGroupMembership.ps1 b/DomainManagement/functions/groupmemberships/Test-DMGroupMembership.ps1 index 545b7d8..10c4862 100644 --- a/DomainManagement/functions/groupmemberships/Test-DMGroupMembership.ps1 +++ b/DomainManagement/functions/groupmemberships/Test-DMGroupMembership.ps1 @@ -138,7 +138,7 @@ $param['Name'] = Resolve-String -Text $assignment.Name $param['ObjectClass'] = $assignment.ItemType } - try { $adResult = Get-Principal @param } + try { $adResult = Get-AdcPrincipal @param } catch { # If it's a member that is allowed to NOT exist, simply skip the entry if ($assignment.Mode -in 'MemberIfExists', 'MayBeMemberIfExists') { continue } @@ -173,7 +173,7 @@ #region Object Category elseif ($assignment.Category) { - try { $adObjects = Find-DMObjectCategoryItem @parameters -Name $assignment.Category -Property ObjectSID, SamAccountName -EnableException } + try { $adObjects = Find-AdcObjectCategoryItem @parameters -Name $assignment.Category -Property ObjectSID, SamAccountName -EnableException } catch { Stop-PSFFunction -String 'Test-DMGroupMembership.Category.Error' -StringValues $assignment.Category, $assignment.Group -ErrorRecord $_ -Continue -ContinueLabel main -EnableException $EnableException -Target $assignment } diff --git a/DomainManagement/functions/objectcategories/Find-DMObjectCategoryItem.ps1 b/DomainManagement/functions/objectcategories/Find-DMObjectCategoryItem.ps1 deleted file mode 100644 index 908438c..0000000 --- a/DomainManagement/functions/objectcategories/Find-DMObjectCategoryItem.ps1 +++ /dev/null @@ -1,81 +0,0 @@ -function Find-DMObjectCategoryItem { -<# - .SYNOPSIS - Searches for items that are part of an object category. - - .DESCRIPTION - Searches for items that are part of an object category. - Caution: A combination of inefficient filters and large scope can lead to significant performance delays in large environments! - - .PARAMETER Name - The name of the object category to search items for. - - .PARAMETER Property - Properties to include when retrieving matching items. - Ensure the property is legal for all potential matches. - - .PARAMETER Server - The server / domain to work with. - - .PARAMETER Credential - The credentials to use for this operation. - - .PARAMETER EnableException - This parameters disables user-friendly warnings and enables the throwing of exceptions. - This is less user friendly, but allows catching exceptions in calling scripts. - - .EXAMPLE - PS C:\> Find-DMObjectCategoryItem -Name 'CAServer' - - Find all objects that are part of the CAServer category. -#> - [CmdletBinding()] - param ( - [Parameter(Mandatory = $true)] - [string] - $Name, - - [string[]] - $Property, - - [PSFComputer] - $Server, - - [PSCredential] - $Credential, - - [switch] - $EnableException - ) - - begin { - $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential - $parameters['Debug'] = $false - } - process { - $category = $script:objectCategories[$Name] - if (-not $category) { - Stop-PSFFunction -String 'Find-DMObjectCategoryItem.Category.NotFound' -StringValues $Name -EnableException $EnableException -Cmdlet $PSCmdlet - return - } - - $searchBase = Resolve-String -Text $category.SearchBase @parameters - if ($category.LdapFilter) { - $filter = '(&(objectClass={0})({1}))' -f $category.ObjectClass, (Resolve-String -Text $category.LdapFilter @parameters) - if ($Property) { $parameters.Properties = $Property } - try { Get-ADObject @parameters -LDAPFilter $filter -SearchBase $searchBase -SearchScope $category.SearchScope -ErrorAction Stop } - catch { - Stop-PSFFunction -String 'Find-DMObjectCategoryItem.ADError' -StringValues $Name -EnableException $EnableException -Cmdlet $PSCmdlet - return - } - } - else { - if ($Property) { $parameters.Properties = $Property } - try { Get-ADObject @parameters -Filter $category.Filter -SearchBase $searchBase -SearchScope $category.SearchScope -ErrorAction Stop } - catch { - Stop-PSFFunction -String 'Find-DMObjectCategoryItem.ADError' -StringValues $Name -EnableException $EnableException -Cmdlet $PSCmdlet - return - } - } - } -} \ No newline at end of file diff --git a/DomainManagement/functions/objectcategories/Get-DMObjectCategory.ps1 b/DomainManagement/functions/objectcategories/Get-DMObjectCategory.ps1 deleted file mode 100644 index 6b9104b..0000000 --- a/DomainManagement/functions/objectcategories/Get-DMObjectCategory.ps1 +++ /dev/null @@ -1,29 +0,0 @@ -function Get-DMObjectCategory -{ - <# - .SYNOPSIS - Returns registered object category objects. - - .DESCRIPTION - Returns registered object category objects. - See description on Register-DMObjectCategory for details on object categories in general. - - .PARAMETER Name - The name to filter by.4 - - .EXAMPLE - PS C:\> Get-DMObjectCategory - - Returns all registered object categories. - #> - [CmdletBinding()] - Param ( - [string] - $Name = '*' - ) - - process - { - ($script:objectCategories.Values | Where-Object Name -like $Name) - } -} diff --git a/DomainManagement/functions/objectcategories/Register-DMObjectCategory.ps1 b/DomainManagement/functions/objectcategories/Register-DMObjectCategory.ps1 deleted file mode 100644 index feb5d67..0000000 --- a/DomainManagement/functions/objectcategories/Register-DMObjectCategory.ps1 +++ /dev/null @@ -1,113 +0,0 @@ -function Register-DMObjectCategory -{ -<# - .SYNOPSIS - Registers a new object category. - - .DESCRIPTION - Registers a new object category. - Object categories are a way to apply settings to a type of object based on a ruleset / filterset. - For example, by registering an object category "Domain Controllers" (with appropriate filters / conditions), - it becomes possible to define access rules that apply to all domain controllers, but not all computers. - - Note: Not all setting types support categories yet. - - .PARAMETER Name - The name of the category. Must be unique. - Will NOT be resolved. - - .PARAMETER ObjectClass - The ObjectClass of the object. - This is the AD attribute of the object. - Each object category can only apply to one class of object, in order to protect system performance. - - .PARAMETER Property - The properties needed for this category. - This attribute is used to optimize object reetrieval in case of multiple categories applying to the same class of object. - - .PARAMETER TestScript - Scriptblock used to determine, whether the input object is part of the category. - Receives the AD object with the requested attributes as input object / argument. - - .PARAMETER Filter - A filter used to find all objects in AD that match this category. - - .PARAMETER LdapFilter - An LDAP filter used to find all objects in AD that match this category. - - .PARAMETER SearchBase - The path under which to look for objects of this category. - Defaults to domain wide. - Supports string resolution. - - .PARAMETER SearchScope - How deep to search for objects of this category under the chosen searchbase. - Supported Values: - - Subtree: All items under the searchbase. (default) - - OneLevel: All items directly under the searchbase. - - Base: Only the searchbase itself is inspected. - - .PARAMETER ContextName - The name of the context defining the setting. - This allows determining the configuration set that provided this setting. - Used by the ADMF, available to any other configuration management solution. - - .EXAMPLE - PS C:\> Register-DMObjectCategory -Name DomainController -ObjectClass computer -Property PrimaryGroupID -TestScript { $args[0].PrimaryGroupID -eq 516 } -LDAPFilter '(&(objectCategory=computer)(primaryGroupID=516))' - - Registers an object category applying to all domain controller's computer object in AD. -#> - [CmdletBinding(DefaultParameterSetName = 'Filter')] - param ( - [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] - [string] - $Name, - - [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] - [string] - $ObjectClass, - - [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] - [string[]] - $Property, - - [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] - [scriptblock] - $TestScript, - - [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Filter')] - [string] - $Filter, - - [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'LdapFilter')] - [string] - $LdapFilter, - - [Parameter(ValueFromPipelineByPropertyName = $true)] - [string] - $SearchBase = '%DomainDN%', - - [Parameter(ValueFromPipelineByPropertyName = $true)] - [ValidateSet('Subtree', 'OneLevel', 'Base')] - [string] - $SearchScope = 'Subtree', - - [string] - $ContextName = '' - ) - - process - { - $script:objectCategories[$Name] = [PSCustomObject]@{ - Name = $Name - ObjectClass = $ObjectClass - Property = $Property - TestScript = $TestScript - Filter = $Filter - LdapFilter = $LdapFilter - SearchBase = $SearchBase - SearchScope = $SearchScope - ContextName = $ContextName - } - } -} diff --git a/DomainManagement/functions/objectcategories/Resolve-DMObjectCategory.ps1 b/DomainManagement/functions/objectcategories/Resolve-DMObjectCategory.ps1 deleted file mode 100644 index 9ccf167..0000000 --- a/DomainManagement/functions/objectcategories/Resolve-DMObjectCategory.ps1 +++ /dev/null @@ -1,72 +0,0 @@ -function Resolve-DMObjectCategory -{ - <# - .SYNOPSIS - Resolves what object categories apply to a given AD Object. - - .DESCRIPTION - Resolves what object categories apply to a given AD Object. - - .PARAMETER ADObject - The AD Object for which to resolve the object categories. - - .PARAMETER Server - The server / domain to work with. - - .PARAMETER Credential - The credentials to use for this operation. - - .EXAMPLE - PS C:\> Resolve-DMObjectCategory @parameters -ADObject $adobject - - Resolves the object categories that apply to $adobject - #> - [CmdletBinding()] - param ( - [Parameter(Mandatory = $true)] - $ADObject, - - [PSFComputer] - $Server, - - [PSCredential] - $Credential - ) - - begin - { - $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential - $parameters['Debug'] = $false - } - process - { - if ($script:objectCategories.Values.ObjectClass -notcontains $ADObject.ObjectClass) - { - return - } - - $filteredObjectCategories = $script:objectCategories.Values | Where-Object ObjectClass -eq $ADobject.ObjectClass - $propertyNames = $filteredObjectCategories.Property | Select-Object -Unique - $adObjectReloaded = Get-Adobject @parameters -Identity $ADObject.DistinguishedName -Properties $propertyNames - :main foreach ($filteredObjectCategory in $filteredObjectCategories) - { - #region Consider Searchbase - $resolvedBase = Resolve-String -Text $filteredObjectCategory.SearchBase @parameters - switch ($filteredObjectCategory.SearchScope) - { - 'Base' { if ($adObjectReloaded.DistinguishedName -ne $resolvedBase) { continue main } } - 'OneLevel' - { - if ($adObjectReloaded.DistinguishedName -notlike "*,$resolvedBase") { continue main } - if (($adObjectReloaded.DistinguishedName -split ",").Count -ne (($resolvedBase -split ",").Count + 1)) { continue main } - } - 'Subtree' { if ($adObjectReloaded.DistinguishedName -notlike "*,$resolvedBase") { continue main } } - } - #endregion Consider Searchbase - if ($filteredObjectCategory.Testscript.Invoke($adObjectReloaded)) - { - $filteredObjectCategory - } - } - } -} diff --git a/DomainManagement/functions/objectcategories/Unregister-DMObjectCategory.ps1 b/DomainManagement/functions/objectcategories/Unregister-DMObjectCategory.ps1 deleted file mode 100644 index f804d28..0000000 --- a/DomainManagement/functions/objectcategories/Unregister-DMObjectCategory.ps1 +++ /dev/null @@ -1,32 +0,0 @@ -function Unregister-DMObjectCategory -{ - <# - .SYNOPSIS - Removes an object category from the list of registered object categories. - - .DESCRIPTION - Removes an object category from the list of registered object categories. - See description on Register-DMObjectCategory for details on object categories in general. - - .PARAMETER Name - The exact name of the object category to unregister. - - .EXAMPLE - PS C:\> Get-DMObjectCategory | Unregister-DMObjectCategory - - Clears all registered object categories. - #> - [CmdletBinding()] - Param ( - [parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] - [string[]] - $Name - ) - - process - { - foreach ($nameItem in $Name) { - $script:objectCategories.Remove($nameItem) - } - } -} diff --git a/DomainManagement/functions/other/Convert-DMSchemaGuid.ps1 b/DomainManagement/functions/other/Convert-DMSchemaGuid.ps1 deleted file mode 100644 index de2ab6a..0000000 --- a/DomainManagement/functions/other/Convert-DMSchemaGuid.ps1 +++ /dev/null @@ -1,111 +0,0 @@ -function Convert-DMSchemaGuid -{ - <# - .SYNOPSIS - Converts names to guid and guids to name as defined in the active directory schema. - - .DESCRIPTION - Converts names to guid and guids to name as defined in the active directory schema. - Can handle both attributes as well as rights. - Uses mapping data generated from active directory. - - .PARAMETER Name - The name to convert. Can be both string or guid. - - .PARAMETER OutType - The data tape to emit: - - Name: Humanly readable name - - Guid: Guid object - - GuidString: Guid as a string - - .PARAMETER Server - The server / domain to work with. - - .PARAMETER Credential - The credentials to use for this operation. - - .EXAMPLE - PS C:\> Convert-DMSchemaGuid -Name Public-Information -OutType GuidString - - Converts the right "Public-Information" into its guid representation (guid returned as a string type) - #> - [CmdletBinding()] - Param ( - [Parameter(ValueFromPipeline = $true)] - [Alias('Guid')] - [string[]] - $Name, - - [ValidateSet('Name', 'Guid', 'GuidString')] - [string] - $OutType = 'Guid', - - [PSFComputer] - $Server, - - [PSCredential] - $Credential - ) - - begin - { - $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential - $parameters['Debug'] = $false - - $guidToName = Get-SchemaGuidMapping @parameters - $nameToGuid = Get-SchemaGuidMapping @parameters -NameToGuid - $guidToRight = Get-PermissionGuidMapping @parameters - $rightToGuid = Get-PermissionGuidMapping @parameters -NameToGuid - } - process - { - :main foreach ($nameString in $Name) { - switch ($OutType) { - 'Name' - { - if ($nameString -as [Guid]) { - if ($guidToName[$nameString]) { - $guidToName[$nameString] - continue main - } - if ($guidToRight[$nameString]) { - $guidToRight[$nameString] - continue main - } - } - else { $nameString } - } - 'Guid' - { - if ($nameString -as [Guid]) { - $nameString -as [Guid] - continue main - } - if ($nameToGuid[$nameString]) { - $nameToGuid[$nameString] -as [guid] - continue main - } - if ($rightToGuid[$nameString]) { - $rightToGuid[$nameString] -as [guid] - continue main - } - } - 'GuidString' - { - if ($nameString -as [Guid]) { - $nameString - continue main - } - if ($nameToGuid[$nameString]) { - $nameToGuid[$nameString] - continue main - } - if ($rightToGuid[$nameString]) { - $rightToGuid[$nameString] - continue main - } - } - } - } - } -} diff --git a/DomainManagement/functions/other/Get-DMObjectDefaultPermission.ps1 b/DomainManagement/functions/other/Get-DMObjectDefaultPermission.ps1 deleted file mode 100644 index 656715f..0000000 --- a/DomainManagement/functions/other/Get-DMObjectDefaultPermission.ps1 +++ /dev/null @@ -1,125 +0,0 @@ -function Get-DMObjectDefaultPermission -{ - <# - .SYNOPSIS - Gathers the default object permissions in AD. - - .DESCRIPTION - Gathers the default object permissions in AD. - Uses PowerShell remoting against the SchemaMaster to determine the default permissions, as local identity resolution is not reliable. - - .PARAMETER ObjectClass - The object class to look up. - - .PARAMETER Server - The server / domain to work with. - - .PARAMETER Credential - The credentials to use for this operation. - - .EXAMPLE - PS C:\> Get-DMObjectDefaultPermission -ObjectClass user - - Returns the default permissions for a user. - #> - [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingEmptyCatchBlock', '')] - [CmdletBinding()] - Param ( - [Parameter(Mandatory = $true)] - [string] - $ObjectClass, - - [PSFComputer] - $Server = '', - - [PSCredential] - $Credential - ) - - begin - { - if (-not $script:schemaObjectDefaultPermission) { - $script:schemaObjectDefaultPermission = @{ } - } - - $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential - - #region Scriptblock that gathers information on default permission - $gatherScript = { - #$domain = Get-ADDomain -Server localhost - #$forest = Get-ADForest -Server localhost - #$rootDomain = Get-ADDomain -Server $forest.RootDomain - $commonAce = @() - <# - $commonAce += New-Object System.DirectoryServices.ActiveDirectoryAccessRule(([System.Security.Principal.NTAccount]'BUILTIN\Pre-Windows 2000 Compatible Access'), 'ReadProperty', 'Allow', '4c164200-20c0-11d0-a768-00aa006e0529', 'Descendents', '4828cc14-1437-45bc-9b07-ad6f015e5f28') - $commonAce += New-Object System.DirectoryServices.ActiveDirectoryAccessRule(([System.Security.Principal.NTAccount]'BUILTIN\Pre-Windows 2000 Compatible Access'), 'ReadProperty', 'Allow', 'bc0ac240-79a9-11d0-9020-00c04fc2d4cf', 'Descendents', '4828cc14-1437-45bc-9b07-ad6f015e5f28') - $commonAce += New-Object System.DirectoryServices.ActiveDirectoryAccessRule(([System.Security.Principal.NTAccount]'BUILTIN\Pre-Windows 2000 Compatible Access'), 'ReadProperty', 'Allow', 'bc0ac240-79a9-11d0-9020-00c04fc2d4cf', 'Descendents', 'bf967aba-0de6-11d0-a285-00aa003049e2') - $commonAce += New-Object System.DirectoryServices.ActiveDirectoryAccessRule(([System.Security.Principal.NTAccount]'BUILTIN\Pre-Windows 2000 Compatible Access'), 'ReadProperty', 'Allow', '59ba2f42-79a2-11d0-9020-00c04fc2d3cf', 'Descendents', '4828cc14-1437-45bc-9b07-ad6f015e5f28') - $commonAce += New-Object System.DirectoryServices.ActiveDirectoryAccessRule(([System.Security.Principal.NTAccount]'BUILTIN\Pre-Windows 2000 Compatible Access'), 'ReadProperty', 'Allow', '59ba2f42-79a2-11d0-9020-00c04fc2d3cf', 'Descendents', 'bf967aba-0de6-11d0-a285-00aa003049e2') - $commonAce += New-Object System.DirectoryServices.ActiveDirectoryAccessRule(([System.Security.Principal.NTAccount]'BUILTIN\Pre-Windows 2000 Compatible Access'), 'ReadProperty', 'Allow', '037088f8-0ae1-11d2-b422-00a0c968f939', 'Descendents', '4828cc14-1437-45bc-9b07-ad6f015e5f28') - $commonAce += New-Object System.DirectoryServices.ActiveDirectoryAccessRule(([System.Security.Principal.NTAccount]'BUILTIN\Pre-Windows 2000 Compatible Access'), 'ReadProperty', 'Allow', '037088f8-0ae1-11d2-b422-00a0c968f939', 'Descendents', 'bf967aba-0de6-11d0-a285-00aa003049e2') - $commonAce += New-Object System.DirectoryServices.ActiveDirectoryAccessRule(([System.Security.Principal.NTAccount]'BUILTIN\Pre-Windows 2000 Compatible Access'), 'ReadProperty', 'Allow', '4c164200-20c0-11d0-a768-00aa006e0529', 'Descendents', 'bf967aba-0de6-11d0-a285-00aa003049e2') - $commonAce += New-Object System.DirectoryServices.ActiveDirectoryAccessRule(([System.Security.Principal.NTAccount]'BUILTIN\Pre-Windows 2000 Compatible Access'), 'ReadProperty', 'Allow', '5f202010-79a5-11d0-9020-00c04fc2d4cf', 'Descendents', 'bf967aba-0de6-11d0-a285-00aa003049e2') - $commonAce += New-Object System.DirectoryServices.ActiveDirectoryAccessRule(([System.Security.Principal.NTAccount]'BUILTIN\Pre-Windows 2000 Compatible Access'), 'ReadProperty', 'Allow', '5f202010-79a5-11d0-9020-00c04fc2d4cf', 'Descendents', '4828cc14-1437-45bc-9b07-ad6f015e5f28') - $commonAce += New-Object System.DirectoryServices.ActiveDirectoryAccessRule(([System.Security.Principal.NTAccount]'BUILTIN\Pre-Windows 2000 Compatible Access'), 'GenericRead', 'Allow', '00000000-0000-0000-0000-000000000000', 'Descendents', 'bf967aba-0de6-11d0-a285-00aa003049e2') - $commonAce += New-Object System.DirectoryServices.ActiveDirectoryAccessRule(([System.Security.Principal.NTAccount]'BUILTIN\Pre-Windows 2000 Compatible Access'), 'GenericRead', 'Allow', '00000000-0000-0000-0000-000000000000', 'Descendents', 'bf967a9c-0de6-11d0-a285-00aa003049e2') - $commonAce += New-Object System.DirectoryServices.ActiveDirectoryAccessRule(([System.Security.Principal.NTAccount]'BUILTIN\Pre-Windows 2000 Compatible Access'), 'GenericRead', 'Allow', '00000000-0000-0000-0000-000000000000', 'Descendents', '4828cc14-1437-45bc-9b07-ad6f015e5f28') - $commonAce += New-Object System.DirectoryServices.ActiveDirectoryAccessRule(([System.Security.Principal.NTAccount]'BUILTIN\Pre-Windows 2000 Compatible Access'), 'ListChildren', 'Allow', '00000000-0000-0000-0000-000000000000', 'All', '00000000-0000-0000-0000-000000000000') - $commonAce += New-Object System.DirectoryServices.ActiveDirectoryAccessRule(([System.Security.Principal.NTAccount]"$($domain.NetBIOSName)\Key Admins"), 'ReadProperty, WriteProperty', 'Allow', '5b47d60f-6090-40b2-9f37-2a4de88f3063', 'All', '00000000-0000-0000-0000-000000000000') - $commonAce += New-Object System.DirectoryServices.ActiveDirectoryAccessRule(([System.Security.Principal.NTAccount]"$($rootDomain.NetBIOSName)\Enterprise Key Admins"), 'ReadProperty, WriteProperty', 'Allow', '5b47d60f-6090-40b2-9f37-2a4de88f3063', 'All', '00000000-0000-0000-0000-000000000000') - $commonAce += New-Object System.DirectoryServices.ActiveDirectoryAccessRule(([System.Security.Principal.NTAccount]"$($rootDomain.NetBIOSName)\Enterprise Admins"), 'GenericAll', 'Allow', '00000000-0000-0000-0000-000000000000', 'All', '00000000-0000-0000-0000-000000000000') - #> - $parameters = @{ Server = $env:COMPUTERNAME } - $rootDSE = Get-ADRootDSE @parameters - $classes = Get-ADObject @parameters -SearchBase $rootDSE.schemaNamingContext -LDAPFilter '(objectCategory=classSchema)' -Properties defaultSecurityDescriptor, lDAPDisplayName - foreach ($class in $classes) { - $acl = [System.DirectoryServices.ActiveDirectorySecurity]::new() - $acl.SetSecurityDescriptorSddlForm($class.defaultSecurityDescriptor) - foreach ($rule in $commonAce) { $acl.AddAccessRule($rule) } - - <# - if ($class.lDAPDisplayName -eq 'organizationalUnit') { - $acl.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule(([System.Security.Principal.NTAccount]'Everyone'), 'DeleteTree, Delete', 'Deny', '00000000-0000-0000-0000-000000000000', 'None', '00000000-0000-0000-0000-000000000000'))) - } - #> - $access = foreach ($accessRule in $acl.Access) { - try { Add-Member -InputObject $accessRule -MemberType NoteProperty -Name SID -Value $accessRule.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]) } - catch { - # Do nothing, don't want the property if no SID is to be had - } - $accessRule - } - - # Workaround to prevent serialization issue. The $null of a loop return converts into an empty PSCustomObject, rather than actually being null, when serialized and deserialized. - if (-not $access) { $access = $null } - - [PSCustomObject]@{ - Class = $class.lDAPDisplayName - Access = $access - } - } - } - #endregion Scriptblock that gathers information on default permission - } - process - { - if ($script:schemaObjectDefaultPermission["$Server"]) { - return $script:schemaObjectDefaultPermission["$Server"].$ObjectClass - } - - #region Process Gathering logic - if ($Server -ne '') { - $parameters['ComputerName'] = $parameters.Server - $parameters.Remove("Server") - } - - try { $data = Invoke-PSFCommand @parameters -ScriptBlock $gatherScript -ErrorAction Stop } - catch { throw } - $script:schemaObjectDefaultPermission["$Server"] = @{ } - foreach ($datum in $data) { - $script:schemaObjectDefaultPermission["$Server"][$datum.Class] = $datum.Access - } - $script:schemaObjectDefaultPermission["$Server"].$ObjectClass - #endregion Process Gathering logic - } -} \ No newline at end of file diff --git a/DomainManagement/functions/other/Register-DMBuiltInSID.ps1 b/DomainManagement/functions/other/Register-DMBuiltInSID.ps1 deleted file mode 100644 index b2c2796..0000000 --- a/DomainManagement/functions/other/Register-DMBuiltInSID.ps1 +++ /dev/null @@ -1,39 +0,0 @@ -function Register-DMBuiltInSID -{ - <# - .SYNOPSIS - Register a name that points at a well-known SID. - - .DESCRIPTION - Register a name that points at a well-known SID. - This is used to reliably be able to compare access rules where built-in SIDs fail (e.g. for Sub-Domains). - This functionality is exposed, in order to be able to resolve these identities, irrespective of name resolution and localization. - - .PARAMETER Name - The name of the builtin entity to map. - - .PARAMETER SID - The SID associated with the builtin entity. - - .EXAMPLE - PS C:\> Register-DMBuiltInSID -Name 'BUILTIN\Incoming Forest Trust Builders' -SID 'S-1-5-32-557' - - Maps the group 'BUILTIN\Incoming Forest Trust Builders' to the SID 'S-1-5-32-557' - Note: This mapping is pre-defined in the module and needs not be applied - #> - [CmdletBinding()] - Param ( - [Parameter(Mandatory = $true, Position = 0, ValueFromPipelineByPropertyName = $true)] - [string] - $Name, - - [Parameter(Mandatory = $true, Position =1, ValueFromPipelineByPropertyName = $true)] - [System.Security.Principal.SecurityIdentifier] - $SID - ) - - process - { - $script:builtInSidMapping[$Name] = $SID - } -} diff --git a/DomainManagement/functions/serviceaccounts/Invoke-DMServiceAccount.ps1 b/DomainManagement/functions/serviceaccounts/Invoke-DMServiceAccount.ps1 index 6fb5d24..398843c 100644 --- a/DomainManagement/functions/serviceaccounts/Invoke-DMServiceAccount.ps1 +++ b/DomainManagement/functions/serviceaccounts/Invoke-DMServiceAccount.ps1 @@ -64,7 +64,7 @@ ) if (-not $Categories.ContainsKey($Name)) { - $Categories[$Name] = (Find-DMObjectCategoryItem -Name $Name @parameters -Property SamAccountName).SamAccountName + $Categories[$Name] = (Find-AdcObjectCategoryItem -Name $Name @parameters -Property SamAccountName).SamAccountName } $Categories[$Name] } diff --git a/DomainManagement/functions/serviceaccounts/Test-DMServiceAccount.ps1 b/DomainManagement/functions/serviceaccounts/Test-DMServiceAccount.ps1 index a857b0c..4568735 100644 --- a/DomainManagement/functions/serviceaccounts/Test-DMServiceAccount.ps1 +++ b/DomainManagement/functions/serviceaccounts/Test-DMServiceAccount.ps1 @@ -75,7 +75,7 @@ $rawCategories = $script:serviceAccounts.Values.ObjectCategory | Remove-PSFNull -Enumerate | Sort-Object -Unique $categories = @{ } foreach ($rawCategory in $rawCategories) { - $categories[$rawCategory] = Find-DMObjectCategoryItem -Name $rawCategory @parameters -Property SamAccountName + $categories[$rawCategory] = Find-AdcObjectCategoryItem -Name $rawCategory @parameters -Property SamAccountName } $renameCurrentSAM = @() #endregion Prepare Object Categories diff --git a/DomainManagement/functions/system/Get-DMDomainCredential.ps1 b/DomainManagement/functions/system/Get-DMDomainCredential.ps1 deleted file mode 100644 index 944fefa..0000000 --- a/DomainManagement/functions/system/Get-DMDomainCredential.ps1 +++ /dev/null @@ -1,34 +0,0 @@ -function Get-DMDomainCredential -{ - <# - .SYNOPSIS - Retrieve credentials stored for accessing the targeted domain. - - .DESCRIPTION - Retrieve credentials stored for accessing the targeted domain. - Returns nothing when no credentials were stored. - This is NOT used by the main commands, but internally for retrieving data regarding foreign principals in one-way trusts. - Generally, these credentials should never have more than reading access to the target domain. - - .PARAMETER Domain - The domain to retrieve credentials for. - Does NOT accept wildcards. - - .EXAMPLE - PS C:\> Get-DMDomainCredential -Domain contoso.com - - Returns the credentials for accessing contoso.com, as long as those have previously been stored. - #> - [CmdletBinding()] - Param ( - [Parameter(Mandatory = $true)] - [string] - $Domain - ) - - process - { - if (-not $script:domainCredentialCache) { return } - $script:domainCredentialCache[$Domain] - } -} diff --git a/DomainManagement/functions/system/Reset-DMDomainCredential.ps1 b/DomainManagement/functions/system/Reset-DMDomainCredential.ps1 deleted file mode 100644 index 1c38c03..0000000 --- a/DomainManagement/functions/system/Reset-DMDomainCredential.ps1 +++ /dev/null @@ -1,81 +0,0 @@ -function Reset-DMDomainCredential -{ -<# - .SYNOPSIS - Resets cached credentials for contacting domains. - - .DESCRIPTION - Resets cached credentials for contacting domains. - Use this command when invalidating credentials you used. - For example in ADMF the credential provider: - If you create one that uses a temporary account, then delete it when done, you need to reset the cache when connecting with your default credentials. - - .PARAMETER Credential - Clear all cache entries using this credential object. - - .PARAMETER Domain - Clear the cached credentials for the target domain. - - .PARAMETER UserName - Clear all cached credentials using this username. - - .PARAMETER All - Clear ALL cached credentials - - .EXAMPLE - PS C:\> Reset-DMDomainCredential -All - - Clear all cached credentials -#> - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSReviewUnusedParameter", "")] - [CmdletBinding()] - param ( - [Parameter(Mandatory = $true, ParameterSetName = 'Credential')] - [PSCredential] - $Credential, - - [Parameter(Mandatory = $true, ParameterSetName = 'Domain')] - [string] - $Domain, - - [Parameter(Mandatory = $true, ParameterSetName = 'Name')] - [string] - $UserName, - - [Parameter(Mandatory = $true, ParameterSetName = 'All')] - [switch] - $All - ) - - process - { - switch ($PSCmdlet.ParameterSetName) - { - 'Credential' - { - [string[]]$keys = $script:domainCredentialCache.Keys - foreach ($key in $keys) - { - if ($script:domainCredentialCache[$key] -eq $Credential) { $script:domainCredentialCache.Remove($key) } - } - } - 'Domain' - { - $script:domainCredentialCache.Remove($Domain) - } - 'Name' - { - [string[]]$keys = $script:domainCredentialCache.Keys - foreach ($key in $keys) - { - if ($script:domainCredentialCache[$key].UserName -eq $UserName) { $script:domainCredentialCache.Remove($key) } - } - } - 'All' - { - $script:domainCredentialCache = @{ } - } - } - } -} \ No newline at end of file diff --git a/DomainManagement/functions/system/Set-DMContentMode.ps1 b/DomainManagement/functions/system/Set-DMContentMode.ps1 index a56012e..77a137f 100644 --- a/DomainManagement/functions/system/Set-DMContentMode.ps1 +++ b/DomainManagement/functions/system/Set-DMContentMode.ps1 @@ -55,7 +55,8 @@ Settings from multiple configuration sets will be merged, rather than fully replacing the old hashtable with a new one. Supported Components: - - ACLs: Excluding them will not test only configured values for ownership and inheritance. + - AccessRules: Excluding them will test only configured paths for access control entries (ACE). + - ACLs: Excluding them will test only configured values for ownership and inheritance. - GPLinks: Excluding them will have it ignore all GPLinks on OUs that have no GP Links configured. OUs with any GP Links defined will be managed as per applicable processing mode. - GroupMembership: Excluding them will cause groups that have no membership configuration to be fundamentally ignored. - Groups: Excluding them will stop all group deletions other than explicit "Delete" configurations. diff --git a/DomainManagement/functions/system/Set-DMDomainContext.ps1 b/DomainManagement/functions/system/Set-DMDomainContext.ps1 index 4da3f9c..7e90c53 100644 --- a/DomainManagement/functions/system/Set-DMDomainContext.ps1 +++ b/DomainManagement/functions/system/Set-DMDomainContext.ps1 @@ -57,6 +57,8 @@ } } + $rootDSE = Get-ADRootDSE @parameters + $script:domainContext.Name = $domainObject.Name $script:domainContext.Fqdn = $domainObject.DNSRoot $script:domainContext.DN = $domainObject.DistinguishedName @@ -72,11 +74,13 @@ Register-DMNameMapping -Name '%RootDomainDN%' -Value $forestRootDomain.DistinguishedName Register-DMNameMapping -Name '%RootDomainSID%' -Value $forestRootSID Register-DMNameMapping -Name '%ForestFqdn%' -Value $forestObject.Name + Register-StringMapping -Name '%ConfigurationDN%' -Value $rootDSE.configurationNamingContext + Register-StringMapping -Name '%SchemaDN%' -Value $rootDSE.schemaNamingContext if ($Credential) { - Set-DMDomainCredential -Domain $domainObject.DNSRoot -Credential $Credential - Set-DMDomainCredential -Domain $domainObject.Name -Credential $Credential - Set-DMDomainCredential -Domain $domainObject.DistinguishedName -Credential $Credential + Set-AdcDomainCredential -Domain $domainObject.DNSRoot -Credential $Credential + Set-AdcDomainCredential -Domain $domainObject.Name -Credential $Credential + Set-AdcDomainCredential -Domain $domainObject.DistinguishedName -Credential $Credential } } } \ No newline at end of file diff --git a/DomainManagement/functions/system/Set-DMDomainCredential.ps1 b/DomainManagement/functions/system/Set-DMDomainCredential.ps1 deleted file mode 100644 index 4655f85..0000000 --- a/DomainManagement/functions/system/Set-DMDomainCredential.ps1 +++ /dev/null @@ -1,44 +0,0 @@ -function Set-DMDomainCredential -{ - <# - .SYNOPSIS - Stores credentials stored for accessing the targeted domain. - - .DESCRIPTION - Stores credentials stored for accessing the targeted domain. - This is NOT used by the main commands, but internally for retrieving data regarding foreign principals in one-way trusts. - Generally, these credentials should never have more than reading access to the target domain. - - .PARAMETER Domain - The domain to store credentials for. - Does NOT accept wildcards. - - .PARAMETER Credential - The credentials to store. - - .EXAMPLE - PS C:\> Set-DMDomainCredential -Domain contoso.com -Credential $cred - - Stores the credentials for accessing contoso.com. - #> - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] - [CmdletBinding()] - Param ( - [Parameter(Mandatory = $true)] - [string] - $Domain, - - [Parameter(Mandatory = $true)] - [PSCredential] - $Credential - ) - - process - { - if (-not $script:domainCredentialCache) { - $script:domainCredentialCache = @{ } - } - - $script:domainCredentialCache[$Domain] = $Credential - } -} diff --git a/DomainManagement/internal/functions/Convert-Principal.ps1 b/DomainManagement/internal/functions/Convert-Principal.ps1 deleted file mode 100644 index cdfe577..0000000 --- a/DomainManagement/internal/functions/Convert-Principal.ps1 +++ /dev/null @@ -1,101 +0,0 @@ -function Convert-Principal { - <# - .SYNOPSIS - Converts a principal to either SID or NTAccount format. - - .DESCRIPTION - Converts a principal to either SID or NTAccount format. - It caches all resolutions, uses Convert-BuiltInToSID to resolve default builtin account names, - uses Get-Domain to resolve foreign domain SIDs and names. - - Basically, it is a best effort attempt to resolve principals in a useful manner. - - .PARAMETER Name - The name of the entity to convert. - - .PARAMETER OutputType - Whether to return an NTAccount or SID. - Defaults to SID - - .PARAMETER Server - The server / domain to work with. - - .PARAMETER Credential - The credentials to use for this operation. - - .EXAMPLE - PS C:\> Convert-Principal @parameters -Name contoso\administrator - - Tries to convert the user contoso\administrator into a SID - #> - [CmdletBinding()] - param ( - [Parameter(Mandatory = $true, ValueFromPipeline = $true)] - [string] - $Name, - - [ValidateSet('SID','NTAccount')] - [string] - $OutputType = 'SID', - - [PSFComputer] - $Server, - - [PSCredential] - $Credential - ) - - begin { - $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential - } - process { - Write-PSFMessage -Level Debug -String 'Convert-Principal.Processing' -StringValues $Name - - # Terminate if already cached - if ($OutputType -eq 'SID' -and $script:cache_PrincipalToSID[$Name]) { return $script:cache_PrincipalToSID[$Name] } - if ($OutputType -eq 'NTAccount' -and $script:cache_PrincipalToNT[$Name]) { return $script:cache_PrincipalToNT[$Name] } - - $builtInIdentity = Convert-BuiltInToSID -Identity $Name - if ($builtInIdentity -ne $Name) { return $builtInIdentity } - - #region Processing Input SID - if ($Name -as [System.Security.Principal.SecurityIdentifier]) { - Write-PSFMessage -Level Debug -String 'Convert-Principal.Processing.InputSID' -StringValues $Name - if ($OutputType -eq 'SID') { - $script:cache_PrincipalToSID[$Name] = $Name -as [System.Security.Principal.SecurityIdentifier] - return $script:cache_PrincipalToSID[$Name] - } - - $script:cache_PrincipalToNT[$Name] = Get-Principal @parameters -Sid $Name -Domain $Name -OutputType NTAccount - return $script:cache_PrincipalToNT[$Name] - } - #endregion Processing Input SID - - Write-PSFMessage -Level Debug -String 'Convert-Principal.Processing.InputNT' -StringValues $Name - $ntAccount = $Name -as [System.Security.Principal.NTAccount] - if ($OutputType -eq 'NTAccount') { - $script:cache_PrincipalToNT[$Name] = $ntAccount - return $script:cache_PrincipalToNT[$Name] - } - - try { - $script:cache_PrincipalToSID[$Name] = $ntAccount.Translate([System.Security.Principal.SecurityIdentifier]) - return $script:cache_PrincipalToSID[$Name] - } - catch { - $domainPart, $namePart = $ntAccount.Value.Split("\", 2) - $domain = Get-Domain @parameters -DnsName $domainPart - Write-PSFMessage -Level Debug -String 'Convert-Principal.Processing.NTDetails' -StringValues $domainPart, $namePart - - $param = @{ - Server = $domain.DNSRoot - } - $cred = Get-DMDomainCredential -Domain $domain.DNSRoot - if ($cred) { $param['Credential'] = $cred } - Write-PSFMessage -Level Debug -String 'Convert-Principal.Processing.NT.LdapFilter' -StringValues "(samAccountName=$namePart)" - $adObject = Get-ADObject @param -LDAPFilter "(samAccountName=$namePart)" -Properties ObjectSID - $script:cache_PrincipalToSID[$Name] = $adObject.ObjectSID - $adObject.ObjectSID - } - } -} \ No newline at end of file diff --git a/DomainManagement/internal/functions/Get-Domain.ps1 b/DomainManagement/internal/functions/Get-Domain.ps1 deleted file mode 100644 index 937ee7f..0000000 --- a/DomainManagement/internal/functions/Get-Domain.ps1 +++ /dev/null @@ -1,107 +0,0 @@ -function Get-Domain -{ - <# - .SYNOPSIS - Returns the domain object associated with a SID or fqdn. - - .DESCRIPTION - Returns the domain object associated with a SID or fqdn. - - This command uses caching to avoid redundant and expensive lookups & searches. - - .PARAMETER Sid - The domain SID to search by. - - .PARAMETER DnsName - The domain FQDN / full dns name. - May _also_ be just the Netbios name, but DNS name will take precedence! - - .PARAMETER Server - The server / domain to work with. - - .PARAMETER Credential - The credentials to use for this operation. - - .EXAMPLE - PS C:\> Get-Domain @parameters -Sid $sid - - Returns the domain object associated with the $sid - #> - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingEmptyCatchBlock", "")] - [CmdletBinding()] - Param ( - [Parameter(Mandatory = $true, ParameterSetName = 'Sid')] - [string] - $Sid, - - [Parameter(Mandatory = $true, ParameterSetName = 'Name')] - [string] - $DnsName, - - [PSFComputer] - $Server, - - [PSCredential] - $Credential - ) - - begin - { - $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential - - # Define variable to prevent superscope lookup - $internalSid = $null - $domainObject = $null - } - process - { - if ($Sid) { - $internalSid = ([System.Security.Principal.SecurityIdentifier]$Sid).AccountDomainSid.Value - } - if ($internalSid -and $script:SIDtoDomain[$internalSid]) { return $script:SIDtoDomain[$internalSid] } - if ($DnsName -and $script:DNStoDomain[$DnsName]) { return $script:DNStoDomain[$DnsName] } - if ($DnsName -and $script:DNStoDomainName[$DnsName]) { return $script:DNStoDomainName[$DnsName] } - if ($DnsName -and $script:NetBiostoDomain[$DnsName]) { return $script:NetBiostoDomain[$DnsName] } - - $identity = $internalSid - if ($DnsName) { $identity = $DnsName } - - $credsToUse = $PSBoundParameters | ConvertTo-PSFHashtable -Include Credential - $forestObject = Get-ADForest @parameters - foreach ($domainName in $forestObject.Domains) { - if ($script:DNSToDomain.Keys -contains $domainName) { continue } - try { - $domainObject = Get-ADDomain -Server $domainName @credsToUse -ErrorAction Stop - $script:SIDtoDomain["$($domainObject.DomainSID)"] = $domainObject - $script:DNStoDomain["$($domainObject.DNSRoot)"] = $domainObject - $script:DNStoDomainName["$($domainObject.Name)"] = $domainObject - $script:NetBiostoDomain["$($domainObject.NetBIOSName)"] = $domainObject - } - catch { } - } - $domainObject = $null - - if ($script:SIDtoDomain[$identity]) { return $script:SIDtoDomain[$identity] } - if ($script:DNStoDomain[$identity]) { return $script:DNStoDomain[$identity] } - if ($script:DNStoDomainName[$identity]) { return $script:DNStoDomainName[$identity] } - if ($script:NetBiostoDomain[$identity]) { return $script:NetBiostoDomain[$identity] } - - try { $domainObject = Get-ADDomain @parameters -Identity $identity -ErrorAction Stop } - catch { - if (-not $domainObject) { - try { $domainObject = Get-ADDomain -Identity $identity -ErrorAction Stop } - catch { } - } - if (-not $domainObject) { throw } - } - - if ($domainObject) { - $script:SIDtoDomain["$($domainObject.DomainSID)"] = $domainObject - $script:DNStoDomain["$($domainObject.DNSRoot)"] = $domainObject - $script:DNStoDomainName["$($domainObject.Name)"] = $domainObject - $script:NetBiostoDomain["$($domainObject.NetBIOSName)"] = $domainObject - if ($DnsName) { $script:DNStoDomain[$DnsName] = $domainObject } - $domainObject - } - } -} \ No newline at end of file diff --git a/DomainManagement/internal/functions/Get-Domain2.ps1 b/DomainManagement/internal/functions/Get-Domain2.ps1 deleted file mode 100644 index 86e13c2..0000000 --- a/DomainManagement/internal/functions/Get-Domain2.ps1 +++ /dev/null @@ -1,51 +0,0 @@ -function Get-Domain2 -{ - <# - .SYNOPSIS - Returns the direct domain object accessible via the server/credential parameter connection. - - .DESCRIPTION - Returns the direct domain object accessible via the server/credential parameter connection. - Caches data for subsequent calls. - - .PARAMETER Server - The server / domain to work with. - - .PARAMETER Credential - The credentials to use for this operation. - - .EXAMPLE - PS C:\> Get-Domain2 @parameters - - Returns the domain associated with the specified connection information - #> - [CmdletBinding()] - Param ( - [PSFComputer] - [Alias('ComputerName')] - $Server = '', - - [PSCredential] - $Credential - ) - - begin - { - # Note: Module Scope variable solely maintained in this file - # Scriptscope for data persistence only - if (-not ($script:directDomainObjectCache)) { - $script:directDomainObjectCache = @{ } - } - } - process - { - if ($script:directDomainObjectCache["$Server"]) { - return $script:directDomainObjectCache["$Server"] - } - - $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential - $adObject = Get-ADDomain @parameters - $script:directDomainObjectCache["$Server"] = $adObject - $adObject - } -} diff --git a/DomainManagement/internal/functions/Get-Principal.ps1 b/DomainManagement/internal/functions/Get-Principal.ps1 deleted file mode 100644 index 8963a1c..0000000 --- a/DomainManagement/internal/functions/Get-Principal.ps1 +++ /dev/null @@ -1,153 +0,0 @@ -function Get-Principal -{ - <# - .SYNOPSIS - Returns a principal's resolved AD object if able to. - - .DESCRIPTION - Returns a principal's resolved AD object if able to. - Will throw an exception if the AD connection fails. - Will return nothing if the target domain does not contain the specified principal. - Uses the credentials provided by Set-DMDomainCredential if available. - - Results will be cached automatically, subsequent callls returning the cached results. - - .PARAMETER Sid - The SID of the principal to search. - - .PARAMETER Name - The name of the principal to search for. - - .PARAMETER ObjectClass - The objectClass of the principal to search for. - - .PARAMETER Domain - The domain in which to look for the principal. - - .PARAMETER OutputType - The format in which the output is being returned. - - ADObject: Returns the full AD object with full information from AD - - NTAccount: Returns a simple NT Account notation. - - .PARAMETER Refresh - Do not use cached data, reload fresh data. - - .PARAMETER Target - The target AD object this access rule applies to. - Used for logging only. - - .PARAMETER Server - The server / domain to work with. - - .PARAMETER Credential - The credentials to use for this operation. - - .EXAMPLE - PS C:\> Get-Principal -Sid $adObject.ObjectSID -Domain $redForestDomainFQDN - - Tries to return the principal from the specified domain based on the SID offered. - #> - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseOutputTypeCorrectly", "")] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingEmptyCatchBlock", "")] - [CmdletBinding()] - Param ( - [Parameter(Mandatory = $true, ParameterSetName = 'SID')] - [string] - $Sid, - - [Parameter(Mandatory = $true, ParameterSetName = 'Name')] - [string] - $Name, - - [Parameter(Mandatory = $true, ParameterSetName = 'Name')] - [string] - $ObjectClass, - - [Parameter(Mandatory = $true)] - [string] - $Domain, - - [ValidateSet('ADObject','NTAccount')] - [string] - $OutputType = 'ADObject', - - [switch] - $Refresh, - - [AllowEmptyString()] - [string] - $Target, - - [PSFComputer] - $Server, - - [PSCredential] - $Credential - ) - - begin - { - $parametersAD = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential - } - process - { - $identity = $Sid - if (-not $Sid) { $identity = "$($Domain)þ$($objectClass)þ$($Name)" } - - if ($script:resolvedPrincipals[$identity] -and -not $Refresh) { - switch ($OutputType) { - 'ADObject' { return $script:resolvedPrincipals[$identity] } - 'NTAccount' - { - if ($script:resolvedPrincipals[$identity].objectSID.AccountDomainSid) { return [System.Security.Principal.NTAccount]"$((Get-Domain @parametersAD -Sid $script:resolvedPrincipals[$identity].objectSID.AccountDomainSid).Name)\$($script:resolvedPrincipals[$identity].SamAccountName)" } - else { return [System.Security.Principal.NTAccount]"BUILTIN\$($script:resolvedPrincipals[$identity].SamAccountName)" } - } - } - } - - try { - if ($Domain -as [System.Security.Principal.SecurityIdentifier]) { - $domainObject = Get-Domain @parametersAD -Sid $Domain - } - else { - $domainObject = Get-Domain @parametersAD -DnsName $Domain - } - $parameters = @{ - Server = $domainObject.DNSRoot - } - $domainName = $domainObject.DNSRoot - } - catch { - $parameters = @{ - Server = $Domain - } - $domainName = $Domain - } - if ($credentials = Get-DMDomainCredential -Domain $domainName) { $parameters['Credential'] = $credentials } - - $filter = "(objectSID=$Sid)" - if (-not $Sid) { $filter = "(&(objectClass=$ObjectClass)(|(name=$Name)(samAccountName=$Name)(distinguishedName=$Name)))" } - - try { $adObject = Get-ADObject @parameters -LDAPFilter $filter -ErrorAction Stop -Properties * | Select-Object -First 1 } - catch { - try { $adObject = Get-ADObject @parametersAD -LDAPFilter $filter -ErrorAction Stop -Properties * | Select-Object -First 1 } - catch { } - if (-not $adObject) { - if ($Target) { Write-PSFMessage -Level Warning -String 'Get-Principal.Resolution.FailedWithTarget' -StringValues $Sid, $Name, $ObjectClass, $Domain, $Target -Target $PSBoundParameters } - else { Write-PSFMessage -Level Warning -String 'Get-Principal.Resolution.Failed' -StringValues $Sid, $Name, $ObjectClass, $Domain -Target $PSBoundParameters } - throw - } - } - if ($adObject) { - $script:resolvedPrincipals[$identity] = $adObject - switch ($OutputType) { - 'ADObject' { return $adObject } - 'NTAccount' - { - if ($adObject.objectSID.AccountDomainSid) { return [System.Security.Principal.NTAccount]"$((Get-Domain @parametersAD -Sid $adObject.objectSID.AccountDomainSid).Name)\$($adObject.SamAccountName)" } - else { [System.Security.Principal.NTAccount]"BUILTIN\$($adObject.SamAccountName)" } - } - } - } - } -} \ No newline at end of file diff --git a/DomainManagement/internal/functions/acl_ace/Remove-RedundantAce.ps1 b/DomainManagement/internal/functions/Remove-RedundantAce.ps1 similarity index 100% rename from DomainManagement/internal/functions/acl_ace/Remove-RedundantAce.ps1 rename to DomainManagement/internal/functions/Remove-RedundantAce.ps1 diff --git a/DomainManagement/internal/functions/Resolve-ContentSearchBase.ps1 b/DomainManagement/internal/functions/Resolve-ContentSearchBase.ps1 index fb7b2b2..7d5ebdc 100644 --- a/DomainManagement/internal/functions/Resolve-ContentSearchBase.ps1 +++ b/DomainManagement/internal/functions/Resolve-ContentSearchBase.ps1 @@ -167,7 +167,7 @@ Set-DMDomainContext @parameters $warningLevel = 'Warning' - $domain = Get-Domain2 @parameters + $domain = Get-AdcDomain @parameters if (@(Get-ADOrganizationalUnit @parameters -ErrorAction Ignore -ResultSetSize 2 -Filter * -SearchBase $domain).Count -eq 1) { $warningLevel = 'Verbose' } } process diff --git a/DomainManagement/internal/functions/Test-DmKdsRootKey.ps1 b/DomainManagement/internal/functions/Test-DmKdsRootKey.ps1 index 14dd0c2..185c811 100644 --- a/DomainManagement/internal/functions/Test-DmKdsRootKey.ps1 +++ b/DomainManagement/internal/functions/Test-DmKdsRootKey.ps1 @@ -45,7 +45,7 @@ return $true } - $domain = Get-Domain2 @parameters + $domain = Get-AdcDomain @parameters $rootKeys = Invoke-Command @parameters { Get-KdsRootKey } if ($rootKeys | Where-Object { $_.EffectiveTime -LT (Get-Date).AddHours(-10) -and diff --git a/DomainManagement/internal/functions/acl_ace/Compare-AccessRules.ps1 b/DomainManagement/internal/functions/acl_ace/Compare-AccessRules.ps1 deleted file mode 100644 index da898d9..0000000 --- a/DomainManagement/internal/functions/acl_ace/Compare-AccessRules.ps1 +++ /dev/null @@ -1,190 +0,0 @@ -function Compare-AccessRules { - <# - .SYNOPSIS - Compare actual access rules to the system default and configured rules. - - .DESCRIPTION - Compare actual access rules to the system default and configured rules. - - .PARAMETER ADRules - The Access Rules actually deployed on the AD Object - - .PARAMETER ConfiguredRules - The Access Rules configured for the AD Object - - .PARAMETER DefaultRules - The default Access Rules for objects of this type - - .PARAMETER ADObject - The AD Object for which Access Rules are being compared - - .PARAMETER Server - The server / domain to work with. - - .PARAMETER Credential - The credentials to use for this operation. - - .EXAMPLE - PS C:\> Compare-AccessRules @parameters -ADRules ($adAclObject.Access | Convert-AccessRuleIdentity @parameters) -ConfiguredRules $desiredPermissions -DefaultRules $defaultPermissions -ADObject $adObject - - Compare actual access rules on the specified AD Object to the system default and configured rules. - #> - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "")] - [CmdletBinding()] - param ( - [AllowEmptyCollection()] - $ADRules, - - [AllowEmptyCollection()] - $ConfiguredRules, - - [AllowEmptyCollection()] - $DefaultRules, - - $ADObject, - - [PSFComputer] - $Server, - - [PSCredential] - $Credential - ) - - $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential - - # Resolve the mode under which it will be evaluated. Either 'Additive' or 'Constrained' - $processingMode = Resolve-DMAccessRuleMode @parameters -ADObject $adObject - - function Write-Result { - [CmdletBinding()] - param ( - [ValidateSet('Create', 'Delete', 'FixConfig', 'Restore')] - [Parameter(Mandatory = $true)] - $Type, - - $Identity, - - [AllowNull()] - $ADObject, - - [AllowNull()] - $Configuration, - - [string] - $DistinguishedName - ) - - $item = [PSCustomObject]@{ - PSTypeName = 'DomainManagement.AccessRule.Change' - Type = $Type - ACT = $ADObject.AccessControlType - Identity = $Identity - Rights = $ADObject.ActiveDirectoryRights - DistinguishedName = $DistinguishedName - ADObject = $ADObject - Configuration = $Configuration - } - if (-not $ADObject) { - $item.ACT = $Configuration.AccessControlType - $item.Rights = $Configuration.ActiveDirectoryRights - } - Add-Member -InputObject $item -MemberType ScriptMethod ToString -Value { '{0}: {1}' -f $this.Type, $this.Identity } -Force -PassThru - } - - $defaultRulesPresent = [System.Collections.ArrayList]::new() - $relevantADRules = :outer foreach ($adRule in $ADRules) { - if ($adRule.OriginalRule.IsInherited) { continue } - #region Skip OUs' "Protect from Accidential Deletion" ACE - if (($adRule.AccessControlType -eq 'Deny') -and ($ADObject.ObjectClass -in 'organizationalUnit','container')) { - if ($adRule.IdentityReference -eq 'everyone') { continue } - $eSid = [System.Security.Principal.SecurityIdentifier]'S-1-1-0' - $eName = $eSid.Translate([System.Security.Principal.NTAccount]) - if ($adRule.IdentityReference -eq $eName) { continue } - if ($adRule.IdentityReference -eq $eSid) { continue } - } - #endregion Skip OUs' "Protect from Accidential Deletion" ACE - - foreach ($defaultRule in $DefaultRules) { - if (Test-AccessRuleEquality -Parameters $parameters -Rule1 $adRule -Rule2 $defaultRule) { - $null = $defaultRulesPresent.Add($defaultRule) - continue outer - } - } - $adRule - } - - #region Foreach non-default AD Rule: Check whether configured and delete if not so - :outer foreach ($relevantADRule in $relevantADRules) { - foreach ($configuredRule in $ConfiguredRules) { - if (Test-AccessRuleEquality -Parameters $parameters -Rule1 $relevantADRule -Rule2 $configuredRule) { - # If explicitly defined for deletion, do so - if ('False' -eq $configuredRule.Present) { - Write-Result -Type Delete -Identity $relevantADRule.IdentityReference -ADObject $relevantADRule -DistinguishedName $ADObject - } - continue outer - } - } - - # Don't generate delete changes - if ($processingMode -eq 'Additive') { continue } - # Don't generate delete changes, unless we have configured a permission level for the affected identity - if ($processingMode -eq 'Defined') { - if (-not ($relevantADRule.IdentityReference | Compare-Identity -Parameters $parameters -ReferenceIdentity $ConfiguredRules.IdentityReference -IncludeEqual -ExcludeDifferent)) { - continue - } - } - - Write-Result -Type Delete -Identity $relevantADRule.IdentityReference -ADObject $relevantADRule -DistinguishedName $ADObject - } - #endregion Foreach non-default AD Rule: Check whether configured and delete if not so - - #region Foreach configured rule: Check whether it exists as defined or make it so - :outer foreach ($configuredRule in $ConfiguredRules) { - # Do not generate Create rules for any rule not configured for creation - if ('True' -ne $configuredRule.Present) { continue } - - foreach ($defaultRule in $DefaultRules) { - if ($configuredRule.NoFixConfig) { break } - if (Test-AccessRuleEquality -Parameters $parameters -Rule1 $defaultRule -Rule2 $configuredRule) { - Write-Result -Type FixConfig -Identity $defaultRule.IdentityReference -ADObject $defaultRule -Configuration $configuredRule -DistinguishedName $ADObject - continue outer - } - } - - foreach ($relevantADRule in $relevantADRules) { - if (Test-AccessRuleEquality -Parameters $parameters -Rule1 $relevantADRule -Rule2 $configuredRule) { - continue outer - } - } - - Write-Result -Type Create -Identity $configuredRule.IdentityReference -Configuration $configuredRule -DistinguishedName $ADObject - } - #endregion Foreach configured rule: Check whether it exists as defined or make it so - - #region Foreach non-existent default rule: Create unless configured otherwise - $domainControllersOUFilter = '*{0}' -f ('OU=Domain Controllers,%DomainDN%' | Resolve-String) - :outer foreach ($defaultRule in $DefaultRules | Where-Object { $_ -notin $defaultRulesPresent.ToArray() }) { - if (-not $DefaultRule) { continue } - - # In Additive Mode, do not restore to schema default - if ($processingMode -eq 'Additive') { break } - - # Do not apply restore to Domain Controllers OU, as it is already deployed intentionally diverging from the OU defaults - if ($ADObject -like $domainControllersOUFilter) { break } - - # Skip 'CREATOR OWNER' Rules, as those should never be restored. - # When creating an AD object that has this group as default permissions, it will instead - # Translate those to the identity creating the object - if ('S-1-3-0' -eq $defaultRule.SID) { continue } - - foreach ($configuredRule in $ConfiguredRules) { - if (Test-AccessRuleEquality -Parameters $parameters -Rule1 $defaultRule -Rule2 $configuredRule) { - # If we explicitly don't want the rule: Skip and do NOT create a restoration action - if ('True' -ne $configuredRule.Present) { continue outer } - } - } - - Write-Result -Type Restore -Identity $defaultRule.IdentityReference -Configuration $defaultRule -DistinguishedName $ADObject - } - #endregion Foreach non-existent default rule: Create unless configured otherwise -} \ No newline at end of file diff --git a/DomainManagement/internal/functions/acl_ace/Compare-Identity.ps1 b/DomainManagement/internal/functions/acl_ace/Compare-Identity.ps1 deleted file mode 100644 index a6f3c23..0000000 --- a/DomainManagement/internal/functions/acl_ace/Compare-Identity.ps1 +++ /dev/null @@ -1,126 +0,0 @@ -function Compare-Identity { - <# - .SYNOPSIS - Compares two sets of identity references, similar to Compare-Object. - - .DESCRIPTION - Compares two sets of identity references, similar to Compare-Object. - Only real difference: Performs identity resolution and compares at the SID level. - - .PARAMETER ReferenceIdentity - One set of identities to compare. - - .PARAMETER DifferenceIdentity - The other set of identities to compare. - - .PARAMETER Parameters - AD connection parameters. - Offer a hashtable containing server or credentials in any combination. - - .PARAMETER IncludeEqual - Return identities that occur in both sets. - - .PARAMETER ExcludeDifferent - Do not return identities that only occur in one set - - .EXAMPLE - PS C:\> $relevantADRule.IdentityReference | Compare-Identity -Parameters $parameters -ReferenceIdentity $ConfiguredRules.IdentityReference -IncludeEqual -ExcludeDifferent - - Compares all identities between the accessrule already existing on the AD object and the ones defined for it. - Only returns existing Active Directory-existing rules if there also is at least one configured rule for its identity. - #> - [CmdletBinding()] - param ( - $ReferenceIdentity, - - [Parameter(ValueFromPipeline = $true)] - $DifferenceIdentity, - - [Hashtable] - $Parameters = @{ }, - - [switch] - $IncludeEqual, - - [switch] - $ExcludeDifferent - ) - - begin { - #region Utility Functions - function ConvertTo-SID { - [CmdletBinding()] - param ( - $IdentityReference, - - [Hashtable] - $Parameters - ) - - $resolved = Convert-BuiltInToSID -Identity $IdentityReference - if ($resolved -is [System.Security.Principal.SecurityIdentifier]) { return $resolved } - - # NTAccount - try { Convert-Principal -Name $resolved -OutputType SID @Parameters } - catch { $resolved } - } - #endregion Utility Functions - - $referenceItems = foreach ($identity in $ReferenceIdentity) { - $sid = ConvertTo-SID -IdentityReference $identity -Parameters $Parameters - [PSCustomObject]@{ - Type = "Reference" - Original = $identity - SID = $sid - SIDString = "$sid" - } - } - - [System.Collections.ArrayList]$differenceItems = @() - } - process { - foreach ($item in $DifferenceIdentity) { - $sid = ConvertTo-SID -IdentityReference $item -Parameters $Parameters - $result = [PSCustomObject]@{ - Type = "Difference" - Original = $identity - SID = $sid - SIDString = "$sid" - } - $null = $differenceItems.Add($result) - } - } - end { - if (-not $ExcludeDifferent) { - foreach ($differenceItem in $differenceItems) { - if ($differenceItem.SIDString -in $referenceItems.SIDString) { continue } - - [PSCustomObject]@{ - Identity = $differenceItem.Original - SID = $differenceItem.SID - Direction = '<=' - } - } - foreach ($referenceItem in $referenceItems) { - if ($referenceItem.SIDString -in $differenceItems.SIDString) { continue } - - [PSCustomObject]@{ - Identity = $referenceItem.Original - SID = $referenceItem.SID - Direction = '=>' - } - } - } - if ($IncludeEqual) { - foreach ($differenceItem in $differenceItems) { - if ($differenceItem.SIDString -notin $referenceItems.SIDString) { continue } - - [PSCustomObject]@{ - Identity = $differenceItem.Original - SID = $differenceItem.SID - Direction = '==' - } - } - } - } -} \ No newline at end of file diff --git a/DomainManagement/internal/functions/acl_ace/Convert-AccessRuleIdentity.ps1 b/DomainManagement/internal/functions/acl_ace/Convert-AccessRuleIdentity.ps1 deleted file mode 100644 index 0d0f149..0000000 --- a/DomainManagement/internal/functions/acl_ace/Convert-AccessRuleIdentity.ps1 +++ /dev/null @@ -1,75 +0,0 @@ -function Convert-AccessRuleIdentity { - <# - .SYNOPSIS - Converts the identity on the specified access rule to NT Account. - - .DESCRIPTION - Converts the identity on the specified access rule to NT Account. - - .PARAMETER InputObject - The Access Rules for which to convert the Identity. - - .PARAMETER Server - The server / domain to work with. - - .PARAMETER Credential - The credentials to use for this operation. - - .PARAMETER Target - The target AD object this access rule applies to. - Used for logging only. - - .EXAMPLE - PS C:\> $adAclObject.Access | Convert-AccessRuleIdentity @parameters - - Converts the identity on all Access Rules in $adAclObject to NT Account. - #> - [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingEmptyCatchBlock', '')] - [CmdletBinding()] - param ( - [Parameter(ValueFromPipeline = $true)] - [System.DirectoryServices.ActiveDirectoryAccessRule[]] - $InputObject, - - [PSFComputer] - $Server, - - [PSCredential] - $Credential, - - [string] - $Target - ) - begin { - $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential - $domainObject = Get-Domain2 @parameters - } - process { - :main foreach ($accessRule in $InputObject) { - if ($accessRule.IdentityReference -is [System.Security.Principal.NTAccount]) { - Add-Member -InputObject $accessRule -MemberType NoteProperty -Name OriginalRule -Value $accessRule -PassThru - continue main - } - - if (-not $accessRule.IdentityReference.AccountDomainSid) { - try { $identity = Get-Principal @parameters -Sid $accessRule.IdentityReference -Domain $domainObject.DNSRoot -OutputType NTAccount -Target $Target } - catch { - # Empty Catch is OK here, warning happens in command - } - } - else { - try { $identity = Get-Principal @parameters -Sid $accessRule.IdentityReference -Domain $accessRule.IdentityReference -OutputType NTAccount -Target $Target} - catch { - # Empty Catch is OK here, warning happens in command - } - } - if (-not $identity) { - $identity = $accessRule.IdentityReference - } - - $newRule = [System.DirectoryServices.ActiveDirectoryAccessRule]::new($identity, $accessRule.ActiveDirectoryRights, $accessRule.AccessControlType, $accessRule.ObjectType, $accessRule.InheritanceType, $accessRule.InheritedObjectType) - # Include original object as property in order to facilitate removal if needed. - Add-Member -InputObject $newRule -MemberType NoteProperty -Name OriginalRule -Value $accessRule -PassThru - } - } -} \ No newline at end of file diff --git a/DomainManagement/internal/functions/acl_ace/Convert-BuiltInToSID.ps1 b/DomainManagement/internal/functions/acl_ace/Convert-BuiltInToSID.ps1 deleted file mode 100644 index a9c2086..0000000 --- a/DomainManagement/internal/functions/acl_ace/Convert-BuiltInToSID.ps1 +++ /dev/null @@ -1,31 +0,0 @@ -function Convert-BuiltInToSID -{ - <# - .SYNOPSIS - Converts pre-configured built in accounts into SID form. - - .DESCRIPTION - Converts pre-configured built in accounts into SID form. - These must be registered using Register-DMBuiltInSID. - Returns all identity references that are not a BuiltIn account that was registered. - - .PARAMETER Identity - The identity reference to translate. - - .EXAMPLE - Convert-BuiltInToSID -Identity $Rule1.IdentityReference - - Converts to IdentityReference of $Rule1 if necessary - #> - [CmdletBinding()] - Param ( - $Identity - ) - - process - { - if ($Identity -as [System.Security.Principal.SecurityIdentifier]) { return ($Identity -as [System.Security.Principal.SecurityIdentifier]) } - if ($script:builtInSidMapping["$Identity"]) { return $script:builtInSidMapping["$Identity"] } - $Identity - } -} \ No newline at end of file diff --git a/DomainManagement/internal/functions/acl_ace/Get-AdminSDHolderRules.ps1 b/DomainManagement/internal/functions/acl_ace/Get-AdminSDHolderRules.ps1 deleted file mode 100644 index c1c23f4..0000000 --- a/DomainManagement/internal/functions/acl_ace/Get-AdminSDHolderRules.ps1 +++ /dev/null @@ -1,38 +0,0 @@ -function Get-AdminSDHolderRules { - <# - .SYNOPSIS - Returns the access rules applied to the AdminSDHolder object. - - .DESCRIPTION - Returns the access rules applied to the AdminSDHolder object. - Used in workflows comparing privileges on the AdminSDHolder object. - - .PARAMETER Server - The server / domain to work with. - - .PARAMETER Credential - The credentials to use for this operation. - - .EXAMPLE - PS C:\> Get-AdminSDHolderRules - - Returns the access rules applied to the AdminSDHolder object of the current domain. - #> - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "")] - [CmdletBinding()] - param ( - [PSFComputer] - $Server, - - [PSCredential] - $Credential - ) - - begin { - $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential - } - process { - $systemContainer = (Get-ADDomain @parameters).SystemsContainer - (Get-AdsAcl -Path "CN=AdminSDHolder,$systemContainer" @parameters).Access - } -} \ No newline at end of file diff --git a/DomainManagement/internal/functions/acl_ace/Get-CategoryBasedRules.ps1 b/DomainManagement/internal/functions/acl_ace/Get-CategoryBasedRules.ps1 deleted file mode 100644 index 12c3bbd..0000000 --- a/DomainManagement/internal/functions/acl_ace/Get-CategoryBasedRules.ps1 +++ /dev/null @@ -1,76 +0,0 @@ -function Get-CategoryBasedRules { - <# - .SYNOPSIS - Returns all access rules applicable to an ad object via category rules. - - .DESCRIPTION - Returns all access rules applicable to an ad object via category rules. - - .PARAMETER ADObject - The AD Object for which to resolve access rules by category. - - .PARAMETER Server - The server / domain to work with. - - .PARAMETER Credential - The credentials to use for this operation. - - .PARAMETER ConvertNameCommand - A steppable pipeline wrapping Convert-DMSchemaGuid converting to name. - - .PARAMETER ConvertGuidCommand - A steppable pipeline wrapping Convert-DMSchemaGuid converting to guid. - - .EXAMPLE - PS C:\> Get-CategoryBasedRules -ADObject $foundADObject @parameters -ConvertNameCommand $convertCmdName -ConvertGuidCommand $convertCmdGuid - - Returns all access rules applicable to $foundADObject via category rules. - #> - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "")] - [CmdletBinding()] - param ( - [Parameter(Mandatory = $true)] - $ADObject, - - [PSFComputer] - $Server, - - [PSCredential] - $Credential, - - $ConvertNameCommand, - - $ConvertGuidCommand - ) - - $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include ADObject, Server, Credential - - $resolvedCategories = Resolve-DMObjectCategory @parameters - foreach ($resolvedCategory in $resolvedCategories) { - foreach ($ruleObject in $script:accessCategoryRules[$resolvedCategory.Name]) { - $objectTypeGuid = $ConvertGuidCommand.Process($ruleObject.ObjectType)[0] - $objectTypeName = $ConvertNameCommand.Process($ruleObject.ObjectType)[0] - $inheritedObjectTypeGuid = $ConvertGuidCommand.Process($ruleObject.InheritedObjectType)[0] - $inheritedObjectTypeName = $ConvertNameCommand.Process($ruleObject.InheritedObjectType)[0] - - try { $identity = Resolve-Identity @parameters -IdentityReference $ruleObject.IdentityReference } - catch { Stop-PSFFunction -String 'Convert-AccessRule.Identity.ResolutionError' -Target $ruleObject -ErrorRecord $_ -Continue } - - [PSCustomObject]@{ - PSTypeName = 'DomainManagement.AccessRule.Converted' - IdentityReference = $identity - AccessControlType = $ruleObject.AccessControlType - ActiveDirectoryRights = $ruleObject.ActiveDirectoryRights - InheritanceFlags = $ruleObject.InheritanceFlags - InheritanceType = $ruleObject.InheritanceType - InheritedObjectType = $inheritedObjectTypeGuid - InheritedObjectTypeName = $inheritedObjectTypeName - ObjectFlags = $ruleObject.ObjectFlags - ObjectType = $objectTypeGuid - ObjectTypeName = $objectTypeName - PropagationFlags = $ruleObject.PropagationFlags - Present = $ruleObject.Present - } - } - } -} \ No newline at end of file diff --git a/DomainManagement/internal/functions/acl_ace/Get-PermissionGuidMapping.ps1 b/DomainManagement/internal/functions/acl_ace/Get-PermissionGuidMapping.ps1 deleted file mode 100644 index 6228644..0000000 --- a/DomainManagement/internal/functions/acl_ace/Get-PermissionGuidMapping.ps1 +++ /dev/null @@ -1,74 +0,0 @@ -function Get-PermissionGuidMapping -{ - <# - .SYNOPSIS - Retrieve a hashtable mapping permission guids to their respective name. - - .DESCRIPTION - Retrieve a hashtable mapping permission guids to their respective name. - This is retrieved from the target forest on first request, then cached for subsequent calls. - The cache is specific to the targeted server and maintained as long as the process runs. - - .PARAMETER NameToGuid - Rather than returning a hashtable mapping guid to name, return a hashtable mapping name to guid. - - .PARAMETER Server - The server / domain to work with. - - .PARAMETER Credential - The credentials to use for this operation. - - .EXAMPLE - PS C:\> Get-PermissionGuidMapping -Server contoso.com - - Returns a hashtable mapping guids to rights from the contoso.com forest. - #> - [CmdletBinding()] - Param ( - [switch] - $NameToGuid, - - [PSFComputer] - $Server = 'default', - - [PSCredential] - $Credential - ) - - begin - { - # Script scope variables declared and maintained in this file only - if (-not $script:schemaGuidToRightMapping) { - $script:schemaGuidToRightMapping = @{ } - } - if (-not $script:schemaRightToGuidMapping) { - $script:schemaRightToGuidMapping = @{ } - } - } - process - { - [string]$identity = $Server - if ($script:schemaGuidToRightMapping[$identity]) { - if ($NameToGuid) { return $script:schemaRightToGuidMapping[$identity] } - else { return $script:schemaGuidToRightMapping[$identity] } - } - Write-PSFMessage -Level Host -String 'Get-PermissionGuidMapping.Processing' -StringValues $identity - $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential - $parameters['Debug'] = $false - - $configurationNC = (Get-ADRootDSE @parameters).configurationNamingContext - $objects = Get-ADObject @parameters -SearchBase "CN=Extended-Rights,$configurationNC" -Properties Name,rightsGUID -LDAPFilter '(objectCategory=controlAccessRight)' # Exclude the schema object itself - $processed = $objects | Select-PSFObject Name, 'rightsGUID to Guid as ID' | Select-PSFObject Name, 'ID to string' - - if (-not $processed) { return } - $script:schemaGuidToRightMapping[$identity] = @{ "$([guid]::Empty)" = '' } - $script:schemaRightToGuidMapping[$identity] = @{ '' = "$([guid]::Empty)" } - - foreach ($processedItem in $processed) { - $script:schemaGuidToRightMapping[$identity][$processedItem.ID] = $processedItem.Name - $script:schemaRightToGuidMapping[$identity][$processedItem.Name] = $processedItem.ID - } - if ($NameToGuid) { return $script:schemaRightToGuidMapping[$identity] } - else { return $script:schemaGuidToRightMapping[$identity] } - } -} diff --git a/DomainManagement/internal/functions/acl_ace/Get-SchemaGuidMapping.ps1 b/DomainManagement/internal/functions/acl_ace/Get-SchemaGuidMapping.ps1 deleted file mode 100644 index ba7b6fd..0000000 --- a/DomainManagement/internal/functions/acl_ace/Get-SchemaGuidMapping.ps1 +++ /dev/null @@ -1,68 +0,0 @@ -function Get-SchemaGuidMapping -{ - <# - .SYNOPSIS - Returns a hashtable mapping schema guids to the name of an attribute / class. - - .DESCRIPTION - Returns a hashtable mapping schema guids to the name of an attribute / class. - This hashtable is being generated (and cached) on a per-Server basis. - - .PARAMETER NameToGuid - Return a hashtable mapping name to guid, rather than one mapping guid to name. - - .PARAMETER Server - The server / domain to work with. - - .PARAMETER Credential - The credentials to use for this operation. - - .EXAMPLE - PS C:\> Get-SchemaGuidMapping @parameters - - Returns a hashtable mapping Guid of attributes or classes to their humanly readable name. - #> - [CmdletBinding()] - Param ( - [switch] - $NameToGuid, - - [PSFComputer] - $Server, - - [PSCredential] - $Credential - ) - - process - { - [string]$identity = '' - if ($Server) { $identity = $Server } - - if (Test-PSFTaskEngineCache -Module DomainManagement -Name "SchemaGuidCache.$Identity") { - if ($NameToGuid) { return (Get-PSFTaskEngineCache -Module DomainManagement -Name "SchemaGuidCache.$Identity").NameToGuid } - else { return (Get-PSFTaskEngineCache -Module DomainManagement -Name "SchemaGuidCache.$Identity").GuidToName } - } - - Write-PSFMessage -Level Host -String 'Get-SchemaGuidMapping.Processing' -StringValues $identity - $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential - $parameters['Debug'] = $false - - $schemaNC = (Get-ADRootDSE @parameters).schemaNamingContext - $objects = Get-ADObject @parameters -SearchBase $schemaNC -Properties Name,SchemaIDGuid -LDAPFilter '(schemaIDGUID=*)' # Exclude the schema object itself - $processed = $objects | Select-PSFObject Name, 'SchemaIDGuid to Guid as ID' | Select-PSFObject Name, 'ID to string' - - if (-not $processed) { return } - $data = [PSCustomObject]@{ - NameToGuid = @{ '' = "$([guid]::Empty)" } - GuidToName = @{ "$([guid]::Empty)" = '' } - } - foreach ($processedItem in $processed) { - $data.GuidToName[$processedItem.ID] = $processedItem.Name - $data.NameToGuid[$processedItem.Name] = $processedItem.ID - } - Set-PSFTaskEngineCache -Module DomainManagement -Name "SchemaGuidCache.$Identity" -Value $data - if ($NameToGuid) { return $data.NameToGuid } - else { return $data.GuidToName } - } -} diff --git a/DomainManagement/internal/functions/acl_ace/Resolve-Identity.ps1 b/DomainManagement/internal/functions/acl_ace/Resolve-Identity.ps1 deleted file mode 100644 index 0c0c48a..0000000 --- a/DomainManagement/internal/functions/acl_ace/Resolve-Identity.ps1 +++ /dev/null @@ -1,73 +0,0 @@ -function Resolve-Identity { - <# - .SYNOPSIS - Resolve an Identity Reference with special rules. - - .DESCRIPTION - Resolve an Identity Reference with special rules. - Resolves to a SID (preferred) or NT Account (Fallback). - - Special Rules: - resolves to the parent object in AD - - This is a helper tool to resolve Identities on Access Rules applied to (or ointended for) AD objects only. - - .PARAMETER IdentityReference - The Identity to resolve. - - .PARAMETER ADObject - The AD Object from which the access rules has been read where the Identity is being resolved. - - .PARAMETER Server - The server / domain to work with. - - .PARAMETER Credential - The credentials to use for this operation. - - .EXAMPLE - PS C:\> Resolve-Identity -Identity $name -ADObject %adObject @parameters - - Resolve the Identity in $name - #> - [OutputType([System.Security.Principal.NTAccount])] - [CmdletBinding()] - param ( - [string] - $IdentityReference, - - $ADObject, - - [PSFComputer] - $Server, - - [PSCredential] - $Credential - ) - - #region Parent Resolution - if ($IdentityReference -eq '') { - $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential - $domainObject = Get-Domain2 @parameters - $parentPath = ($ADObject.DistinguishedName -split ",",2)[1] - $parentObject = Get-ADObject @parameters -Identity $parentPath -Properties SamAccountName, Name, ObjectSID - if (-not $parentObject.ObjectSID) { - Stop-PSFFunction -String 'Resolve-Identity.ParentObject.NoSecurityPrincipal' -StringValues $ADObject, $parentObject.Name, $parentObject.ObjectClass -EnableException $true -Cmdlet $PSCmdlet - } - if ($parentObject.SamAccountName) { return [System.Security.Principal.NTAccount]('{0}\{1}' -f $domainObject.Name, $parentObject.SamAccountName) } - else { return [System.Security.Principal.NTAccount]('{0}\{1}' -f $domainObject.Name, $parentObject.Name) } - } - #endregion Parent Resolution - - #region Default Resolution - $identity = Resolve-String -Text $IdentityReference - if ($identity -as [System.Security.Principal.SecurityIdentifier]) { - $identity = $identity -as [System.Security.Principal.SecurityIdentifier] - } - else { - $identity = $identity -as [System.Security.Principal.NTAccount] - } - if ($null -eq $identity) { $identity = (Resolve-String -Text $IdentityReference) -as [System.Security.Principal.NTAccount] } - - $identity - #endregion Default Resolution -} \ No newline at end of file diff --git a/DomainManagement/internal/functions/acl_ace/Test-AccessRuleEquality.ps1 b/DomainManagement/internal/functions/acl_ace/Test-AccessRuleEquality.ps1 deleted file mode 100644 index 6d0bf6c..0000000 --- a/DomainManagement/internal/functions/acl_ace/Test-AccessRuleEquality.ps1 +++ /dev/null @@ -1,57 +0,0 @@ -function Test-AccessRuleEquality { - <# - .SYNOPSIS - Compares two access rules with each other. - - .DESCRIPTION - Compares two access rules with each other. - - .PARAMETER Rule1 - The first rule to compare - - .PARAMETER Rule2 - The second rule to compare - - .PARAMETER Parameters - Hashtable containing server and credential informations. - - .EXAMPLE - PS C:\> Test-AccessRuleEquality -Rule1 $rule -Rule2 $rule2 - - Compares $rule with $rule2 - #> - [OutputType([System.Boolean])] - [CmdletBinding()] - param ( - $Rule1, - $Rule2, - $Parameters - ) - - function Get-SID { - [CmdletBinding()] - param ( - $Rule, - $Parameters - ) - - if ($Rule.SID) { return $Rule.SID } - if ($Rule.IdentityReference -is [System.Security.Principal.SecurityIdentifier]) { return $Rule.IdentityReference } - - # NTAccount - Convert-Principal -Name $Rule.IdentityReference -OutputType SID @Parameters - } - - if ($Rule1.ActiveDirectoryRights -ne $Rule2.ActiveDirectoryRights) { return $false } - if ($Rule1.InheritanceType -ne $Rule2.InheritanceType) { return $false } - if ($Rule1.ObjectType -ne $Rule2.ObjectType) { return $false } - if ($Rule1.InheritedObjectType -ne $Rule2.InheritedObjectType) { return $false } - if ($Rule1.AccessControlType -ne $Rule2.AccessControlType) { return $false } - if ("$(Convert-BuiltInToSID -Identity $Rule1.IdentityReference)" -ne "$(Convert-BuiltInToSID -Identity $Rule2.IdentityReference)") - { - $oneSID = Get-SID -Rule $Rule1 -Parameters $Parameters - $twoSID = Get-SID -Rule $Rule2 -Parameters $Parameters - if ("$oneSID" -ne "$twoSID") { return $false } - } - return $true -} \ No newline at end of file diff --git a/DomainManagement/internal/scripts/variables.ps1 b/DomainManagement/internal/scripts/variables.ps1 index 9d584e0..751abc5 100644 --- a/DomainManagement/internal/scripts/variables.ps1 +++ b/DomainManagement/internal/scripts/variables.ps1 @@ -50,15 +50,9 @@ $script:aclDefaultOwner = $null # Configured Access Rules - Based on OU / Path $script:accessRules = @{ } -# Configured Access Rule processing Modes -$script:accessRuleMode = @{ } - # Configured Access Rules - Based on Object Category $script:accessCategoryRules = @{ } -# Configured Object Categories -$script:objectCategories = @{ } - # Configured generic objects $script:objects = @{ } @@ -82,13 +76,6 @@ $script:wmifilter = @{ } # Cached Data # #----------------------------------------------------------------------------# -# Cached security principals, used by Get-Principal. Mapping to AD Objects -$script:resolvedPrincipals = @{ } - -# More principal caching, used by Convert-Principal. Mapping to SID or NT Account -$script:cache_PrincipalToSID = @{ } -$script:cache_PrincipalToNT = @{ } - # Cached domain data, used by Invoke-DMDomainData. Can be any script logic result $script:cache_DomainData = @{ } @@ -117,6 +104,7 @@ $script:contentMode = [PSCustomObject]@{ # Note: Also update the help on Set-DMContentMode and on the website Content Mode documentation, when adding new entries here. ExcludeComponents = @{ + AccessRules = $false ACLs = $false GPLinks = $false GroupMembership = $false diff --git a/DomainManagement/internal/scripts/variables2.ps1 b/DomainManagement/internal/scripts/variables2.ps1 index 0f8ee48..a152fa1 100644 --- a/DomainManagement/internal/scripts/variables2.ps1 +++ b/DomainManagement/internal/scripts/variables2.ps1 @@ -1,35 +1,2 @@ -# File for variables that should NOT be reset on context changes -$script:builtInSidMapping = @{ - # English - 'BUILTIN\Administrators' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-544' - 'BUILTIN\Account Operators' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-548' - 'BUILTIN\Server Operators' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-549' - 'BUILTIN\Print Operators' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-550' - 'BUILTIN\Pre-Windows 2000 Compatible Access' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-554' - 'BUILTIN\Incoming Forest Trust Builders' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-557' - 'BUILTIN\Windows Authorization Access Group' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-560' - 'BUILTIN\Terminal Server License Servers' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-561' - 'BUILTIN\Certificate Service DCOM Access' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-574' - 'BUILTIN\RDS Remote Access Servers' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-575' - 'BUILTIN\RDS Endpoint Servers' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-576' - 'BUILTIN\RDS Management Servers' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-577' - 'BUILTIN\Storage Replica Administrators' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-582' - - # Deutsch - 'BUILTIN\Administratoren' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-544' - 'BUILTIN\Konten-Operatoren' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-548' - 'BUILTIN\Server-Operatoren' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-549' - 'BUILTIN\Druck-Operatoren' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-550' - 'BUILTIN\Prä-Windows 2000 kompatibler Zugriff' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-554' - 'BUILTIN\Erstellungen eingehender Gesamtstrukturvertrauensstellung' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-557' - 'BUILTIN\Windows-Autorisierungszugriffsgruppe' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-560' - 'BUILTIN\Terminalserver-Lizenzserver' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-561' - 'BUILTIN\Zertifikatdienst-DCOM-Zugriff' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-574' - # 'BUILTIN\RDS Remote Access Servers' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-575' - # 'BUILTIN\RDS Endpoint Servers' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-576' - # 'BUILTIN\RDS Management Servers' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-577' - # 'BUILTIN\Storage Replica Administrators' = [System.Security.Principal.SecurityIdentifier]'S-1-5-32-582' -} - -# Persistent Cache for Default Permissions +# Persistent Cache for Default Permissions $script:schemaObjectDefaultPermission = @{ } \ No newline at end of file diff --git a/DomainManagement/xml/DomainManagement.Format.ps1xml b/DomainManagement/xml/DomainManagement.Format.ps1xml index 0ff5710..d8f69b2 100644 --- a/DomainManagement/xml/DomainManagement.Format.ps1xml +++ b/DomainManagement/xml/DomainManagement.Format.ps1xml @@ -64,89 +64,6 @@ - - - DomainManagement.AccessRuleMode - - DomainManagement.AccessRuleMode - - - - - - - - - - - - - - - - Type - - - Mode - - - PathMode - - - - -if ($_.Path) { $_.Path } -else { $_.ObjectCategory } - - - - - - - - - - - - DomainManagement.AccessRule.Change - - DomainManagement.AccessRule.Change - - - - - - - - - 80 - - - - - - - - Type - - - ACT - - - Identity - - - Rights - - - DistinguishedName - - - - - - - DomainManagement.Acl From 40cc205fbd893ba442fd166c3c3f68153439aea2 Mon Sep 17 00:00:00 2001 From: Friedrich Weinmann Date: Fri, 19 Jun 2026 09:44:10 +0200 Subject: [PATCH 2/3] version update --- DomainManagement/DomainManagement.psd1 | 8 ++++---- DomainManagement/changelog.md | 6 +++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/DomainManagement/DomainManagement.psd1 b/DomainManagement/DomainManagement.psd1 index d45f8c8..23982d7 100644 --- a/DomainManagement/DomainManagement.psd1 +++ b/DomainManagement/DomainManagement.psd1 @@ -3,7 +3,7 @@ RootModule = 'DomainManagement.psm1' # Version number of this module. - ModuleVersion = '1.9.249' + ModuleVersion = '1.10.257' # ID used to uniquely identify this module GUID = '0a405382-ebc2-445b-8325-541535810193' @@ -152,13 +152,13 @@ ) # Cmdlets to export from this module - CmdletsToExport = '' + CmdletsToExport = @() # Variables to export from this module - VariablesToExport = '' + VariablesToExport = @() # Aliases to export from this module - AliasesToExport = '' + AliasesToExport = @() # List of all modules packaged with this module ModuleList = @() diff --git a/DomainManagement/changelog.md b/DomainManagement/changelog.md index 0b312ee..2265d48 100644 --- a/DomainManagement/changelog.md +++ b/DomainManagement/changelog.md @@ -1,11 +1,15 @@ # Changelog -## ??? +## 1.10.257 (2026-06-19) - Upd: ACLs - removed exclusion from considering Containers. - Upd: Get-DMObjectDefaultPermission - removed the command, as part of the AccessRule switch-over to Admf.Core +- Upd: AccessRules tooling - migrated a large portion of the tooling to Admf.Core - Fix: GPLink - deleting links for GPOs that are not accessible will show with an empty name in the test results - Fix: GPPermission - fixed error message when using a path-based GPPermission filter and the path does not exist +- Rem: AccessRuleMode - Migrated component to Admf.Core. +- Rem: DomainCredential - Migrated component to Admf.Core. +- Rem: ObjectCategories - Migrated component to Admf.Core. ## 1.9.249 (2026-02-12) From 80a077180fc6e971273e22f723c72b409d6660b4 Mon Sep 17 00:00:00 2001 From: Friedrich Weinmann Date: Fri, 19 Jun 2026 12:03:34 +0200 Subject: [PATCH 3/3] Fixing test findings --- DomainManagement/DomainManagement.psd1 | 2 -- DomainManagement/en-us/strings.psd1 | 3 +-- DomainManagement/functions/acls/Test-DMAcl.ps1 | 2 ++ 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/DomainManagement/DomainManagement.psd1 b/DomainManagement/DomainManagement.psd1 index 23982d7..16147c9 100644 --- a/DomainManagement/DomainManagement.psd1 +++ b/DomainManagement/DomainManagement.psd1 @@ -46,7 +46,6 @@ # Functions to export from this module FunctionsToExport = @( 'Clear-DMConfiguration' - 'Convert-AdcSchemaGuid' 'Get-DMAccessRule' 'Get-DMAcl' 'Get-DMCallback' @@ -88,7 +87,6 @@ 'Invoke-DMWmiFilter' 'Register-DMAccessRule' 'Register-DMAcl' - 'Register-DMBuiltInSID' 'Register-DMCallback' 'Register-DMDomainData' 'Register-DMDomainLevel' diff --git a/DomainManagement/en-us/strings.psd1 b/DomainManagement/en-us/strings.psd1 index 0ee6d76..2a19b8e 100644 --- a/DomainManagement/en-us/strings.psd1 +++ b/DomainManagement/en-us/strings.psd1 @@ -166,8 +166,6 @@ 'Resolve-GPTargetServer.Info.ChangingToPDC' = 'Changing target server from "{0}" to the PDC Emulator: "{1}". Group Policy components default to working against the PDC, as most GPO tools (including the default GPMC console) do the same. This behavior can be disabled in the module configuration settings.' # $Server, $domainObject.PDCEmulator - 'Resolve-Identity.ParentObject.NoSecurityPrincipal' = 'Error processing parent of {0} : {1} of type {2} is no legal security principal and cannot be assigned permissions!' # $ADObject, $parentObject.Name, $parentObject.ObjectClass - 'Resolve-PolicyRevision.Result.ErrorOnConfigImport' = 'Failed to read configuration for {0}: {1}' # $Policy.DisplayName, $result.Error.Exception.Message 'Resolve-PolicyRevision.Result.PolicyError' = 'Policy object not found in filesystem: {0}. Check existence and permissions!' # $Policy.DisplayName 'Resolve-PolicyRevision.Result.Result.SuccessNotYetManaged' = 'Policy found: {0}. Has not yet been managed, will need to be overwritten.' # $Policy.DisplayName @@ -182,6 +180,7 @@ 'Test-DMAcl.ADObjectNotFound' = 'The target object could not be found: {0}' # $resolvedPath 'Test-DMAcl.NoAccess' = 'Failed to access Acl on {0}' # $resolvedPath + 'Test-DMAcl.ResolveOwner' = 'Resolving acceptable owners via Privileged Group Set {0} for object {1}' # $Category.Owner.Trim('_'),$ADObject.DistinguishedName 'Test-DMGPLink.OUNotFound' = 'Failed to find the configured OU: {0} - Please validate your OU configuration and bring your OU estate into the desired state first!' # $ouDatum.OrganizationalUnit diff --git a/DomainManagement/functions/acls/Test-DMAcl.ps1 b/DomainManagement/functions/acls/Test-DMAcl.ps1 index dff2ec2..2104536 100644 --- a/DomainManagement/functions/acls/Test-DMAcl.ps1 +++ b/DomainManagement/functions/acls/Test-DMAcl.ps1 @@ -17,6 +17,7 @@ Tests whether the configured ACLs' state matches the current domain ACL setup. #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "")] [CmdletBinding()] param ( [PSFComputer] @@ -60,6 +61,7 @@ Add-Member -InputObject $changeItem -MemberType ScriptMethod -Name ToString -Value { '{0}->{1}' -f $this.Type, $this.New } -Force -PassThru } function Get-ChangeByCategory { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "")] [CmdletBinding()] param ( $ADObject,