diff --git a/DomainManagement/changelog.md b/DomainManagement/changelog.md index 4557523..dba47f5 100644 --- a/DomainManagement/changelog.md +++ b/DomainManagement/changelog.md @@ -1,5 +1,10 @@ # Changelog +## ??? (???) + +- Fix: Access Rules - "NoFixConfig" option within AccessRules wasn't respected. (issue #81) +- Upd: Access Rules - Add warning message when access rule is applied but redundant or simply not working in the acl object + ## 1.8.202 (2024-01-12) - Upd: Access Rules - added option to parallelize tests (experimental) diff --git a/DomainManagement/en-us/strings.psd1 b/DomainManagement/en-us/strings.psd1 index 961dd32..8fa3bfd 100644 --- a/DomainManagement/en-us/strings.psd1 +++ b/DomainManagement/en-us/strings.psd1 @@ -4,26 +4,26 @@ 'Assert-ADConnection.Failed' = 'Failed to connect to {0}' # $Server '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-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-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 @@ -39,40 +39,41 @@ 'Install-GroupPolicy.UpdatingConfigurationFile.Failed' = 'Failed to update the configuration metadata file for "{0}" on the target domain. This will cause the GPO to not register as managed and will be flagged as to update on the next test. Please validate filesystem write access to the targeted GPO.' # $Configuration.DisplayName 'Install-GroupPolicy.WmiFilter' = 'Applying the WMI Filter {1} to Group Policy {0}' # $Configuration.DisplayName, $Configuration.WmiFilter 'Install-GroupPolicy.WmiFilter.Failed' = 'Failed to update WMI Filter of {0} to {1}: {2}' # $Configuration.DisplayName, $Configuration.WmiFilter, $wmiResult.Message - + 'Invoke-Callback.Invoking' = 'Executing callback: {0}' # $callback.Name 'Invoke-Callback.Invoking.Failed' = 'Error executing callback: {0}' # $callback.Name 'Invoke-Callback.Invoking.Success' = 'Successfully executed callback: {0}' # $callback.Name - + 'Invoke-DMAccessRule.Access.Failed' = 'Failed to access ACL on {0}' # $testItem.Identity 'Invoke-DMAccessRule.AccessRule.Create' = 'Adding access rule for {0}, granting {1} ({2})' # $changeEntry.Configuration.IdentityReference, $changeEntry.Configuration.ActiveDirectoryRights, $changeEntry.Configuration.AccessControlType 'Invoke-DMAccessRule.AccessRule.Creation.Failed' = 'Failed to create accessrule at {0} for {1}' # $testItem.Identity, $changeEntry.Configuration.IdentityReference + 'Invoke-DMAccessRule.AccessRule.Creation.NotApplied' = 'Accessrule at {0} for {1} not applied in ACL. Possibly an equivalent accessrule is already present.' # $testItem.Identity, $changeEntry.Configuration.IdentityReference 'Invoke-DMAccessRule.AccessRule.Remove' = 'Removing access rule for {0}, granting {1} ({2}) from {3}' # $changeEntry.ADObject.IdentityReference, $changeEntry.ADObject.ActiveDirectoryRights, $changeEntry.ADObject.AccessControlType, $changeEntry.DistinguishedName 'Invoke-DMAccessRule.AccessRule.Remove.Failed' = 'Failed to removing access rule for {0}, granting {1} ({2}) from {3} for unknown reasons (sorry). If this persists, consider enabling the alternative deletion mode through the "Domainmanagement.AccessRules.Remove.Option2" configuration setting.' # $changeEntry.ADObject.IdentityReference, $changeEntry.ADObject.ActiveDirectoryRights, $changeEntry.ADObject.AccessControlType, $changeEntry.DistinguishedName 'Invoke-DMAccessRule.AccessRule.Restore' = 'Restoring access rule from schema default for {0}, granting {1} ({2})' # $changeEntry.Configuration.IdentityReference, $changeEntry.Configuration.ActiveDirectoryRights, $changeEntry.Configuration.AccessControlType 'Invoke-DMAccessRule.ADObject.Missing' = 'Cannot process access rules, due to missing AD object: {0}. Please ensure the domain object is created before trying to apply rules to it!' # $testItem.Identity 'Invoke-DMAccessRule.Processing.Execute' = 'Applying {0} out of {1} intended access rule changes' # ($testItem.Changed.Count - $failedCount), $testItem.Changed.Count 'Invoke-DMAccessRule.Processing.Rules' = 'Processing {1} access rule changes on {0}' # $testItem.Identity, $testItem.Changed.Count - + 'Invoke-DMAcl.MissingADObject' = 'The target object could not be found: {0}' # $testItem.Identity 'Invoke-DMAcl.NoAccess' = 'Failed to access Acl on {0}' # $testItem.Identity 'Invoke-DMAcl.OwnerNotResolved' = 'Was unable to resolve the current owner ({1}) of {0}' # $testItem.Identity, $testItem.ADObject.GetOwner([System.Security.Principal.SecurityIdentifier]) 'Invoke-DMAcl.ShouldManage' = 'The ADObject {0} has no defined ACL state and should either be configured or removed' # $testItem.Identity 'Invoke-DMAcl.UpdatingInheritance' = 'Updating inheritance - Inheritance Disabled: {0}' # $testItem.Configuration.NoInheritance 'Invoke-DMAcl.UpdatingOwner' = 'Granting ownership to {0}' # ($testItem.Configuration.Owner | Resolve-String) - + 'Invoke-DMDomainData.Invocation.Error' = 'An exception was thrown while executing the domain data script "{0}".' # $Name 'Invoke-DMDomainData.Invocation.Error.Terminate' = 'Critical Error: An exception was thrown while executing the domain data script "{0}".' # $Name 'Invoke-DMDomainData.Script.NotFound' = 'Could not find a registered DomainData set with the name "{0}". Be sure to register an appropriate configuration and check for typos.' # $Name 'Invoke-DMDomainData.Script.NotFound.Error' = 'Critical error: Could not find a registered DomainData set with the name "{0}". Be sure to register an appropriate configuration and check for typos.' # $Name - + 'Invoke-DMDomainLevel.Raise.Level' = 'Raising domain level to {0}' # $testItem.Configuration.Level - + 'Invoke-DMExchange.Installing' = 'Installing Exchange domain System Objects for {0}' # $testResult.Configuration 'Invoke-DMExchange.IsoPath.Missing' = 'Cannot find ISO file on target server in path {0}' # $testResult.Configuration.LocalImagePath 'Invoke-DMExchange.Updating' = 'Updating Exchange domain System Objects to {0}' # $testResult.Configuration 'Invoke-DMExchange.WinRM.Failed' = 'Failed to connect to {0} via WinRM' # $Server - + 'Invoke-DMGPLink.Delete.AllEnabled' = 'Removing all ({0}) policy links (all of which are enabled)' # $countActual 'Invoke-DMGPLink.GpoMissing' = 'Skipping GP Link application for {0} - cannot resolve Group Policies "{1}"' # $testItem.ADObject, (($testItem.Changed | Where-Object Action -eq 'GpoMissing').Policy -join ", ") 'Invoke-DMGPLink.New' = 'Linking {0} group policies (all new links)' # $countConfigured @@ -82,10 +83,10 @@ 'Invoke-DMGPLink.Update.Change' = ' Link update: {0} - {1} ({2})' # $change.Action, $change.Policy, $ADObject.DistinguishedName 'Invoke-DMGPLink.Update.NewGPLinkString' = 'Finished gPLink string being applied to {0}: {1}' # $ADObject.DistinguishedName, $gpLinkString 'Invoke-DMGPLink.Update.OldGPLinkString' = 'Previous gPLink string being overwritten on {0}: {1}' # $ADObject.DistinguishedName, $ADObject.gPLink - + 'Invoke-DMGPOwner.Invalid.Input' = 'The input object was not recognized as a valid test result for Group Policy Ownership: {0' # $testResult 'Invoke-DMGPOwner.Update.Owner' = 'Changing the owner from {0} to {1} on Group Policy {2}' # $testResult.Changed.Old, $testResult.Changed.New, $testResult.Identity - + 'Invoke-DMGPPermission.AccessRule.Error' = 'Error creating accessrule for identity "{0}" of principal "{1}". Make sure the principal exists' # $change.Identity, $change.DisplayName 'Invoke-DMGPPermission.AD.Access.Error' = 'Error accessing Active Directory for {0} ({1})' # $testResult, $testResult.ADObject.DistinguishedName 'Invoke-DMGPPermission.AD.UpdatingPermission' = 'Updating {0} permission changes on the AD object' # $testResult.Changed.Count @@ -93,10 +94,10 @@ 'Invoke-DMGPPermission.Invalid.Input' = 'The input object was not recognized as a valid test result for Group Policy Permissions: {0}' # $testResult 'Invoke-DMGPPermission.Result.Access.Error' = 'The test for {0} failed, due to access error during the test phase!' # $testResult.Identity 'Invoke-DMGPPermission.WinRM.Failed' = 'Failed to connect to {0}' # $computerName - - 'Invoke-DMGroup.Group.Create' = 'Creating active directory group' # + + 'Invoke-DMGroup.Group.Create' = 'Creating active directory group' # 'Invoke-DMGroup.Group.Create.OUExistsNot' = 'Cannot create group {1} : Path does not exist: {0}' # $targetOU, $testItem.Identity - 'Invoke-DMGroup.Group.Delete' = 'Deleting active directory group' # + 'Invoke-DMGroup.Group.Delete' = 'Deleting active directory group' # 'Invoke-DMGroup.Group.InvalidScope' = 'Invalid scope defined for {0}: {1} is not a legal group scope.' # $testItem, $targetScope 'Invoke-DMGroup.Group.Move' = 'Moving active directory group to {0}' # $targetOU 'Invoke-DMGroup.Group.MultipleOldGroups' = 'Cannot rename group to {0}: More than one group exists owning one of the previous names. Conflicting groups: {1}. Please investigate and manually resolve.' # $testItem.Identity, ($testItem.ADObject.Name -join ', ') @@ -105,43 +106,43 @@ 'Invoke-DMGroup.Group.Update.Name' = 'Renaming to {0}' # $change.NewValue 'Invoke-DMGroup.Group.Update.OUExistsNot' = 'Cannot move active directory group {0} - OU does not exist: {1}' # $testItem.Identity, $targetOU 'Invoke-DMGroup.Group.Update.Scope' = 'Updating the group scope of {0} from {1} to {2}' # $testItem, $testItem.ADObject.GroupScope, $targetScope - + 'Invoke-DMGroupMembership.GroupMember.Add' = 'Adding member to {0}' # $testItem.ADObject.Name 'Invoke-DMGroupMembership.GroupMember.Remove' = 'Removing member from {0}' # $testItem.ADObject.Name 'Invoke-DMGroupMembership.GroupMember.RemoveUnidentified' = 'Removing unidentified foreign security principal from {0}' # $testItem.ADObject.Name 'Invoke-DMGroupMembership.Unidentified' = 'Could not identify current group member: {0}' # $testItem.Identity 'Invoke-DMGroupMembership.Unresolved' = 'Could not identify required group member: {0}' # $testItem.Identity - + 'Invoke-DMGroupPolicy.Delete' = 'Deleting group policy object: {0}.' # $testItem.Identity - + 'Invoke-DMGroupPolicy.Install.OnConfigError' = 'Re-applying GPO "{0}" after failing to read its configuration' # $testItem.Identity 'Invoke-DMGroupPolicy.Install.OnManage' = 'Re-Applying GPO "{0}" for the first time to bring it under management' # $testItem.Identity - - + + 'Invoke-DMGroupPolicy.Install.OnNew' = 'GPO "{0}" not found in AD, creating new GPO' # $testItem.Identity 'Invoke-DMGroupPolicy.Install.OnUpdate' = 'New GPO definition available, updating GPO "{0}"' # $testItem.Identity 'Invoke-DMGroupPolicy.Remote.WorkingDirectory.Failed' = 'Failed to create working directory on {0}. This is required for importing GPOs' # $computerName 'Invoke-DMGroupPolicy.Skipping.InCriticalState' = 'Critical error validating {0}. The GPO will be skipped, please manually verify the GPO and bring it into a supportable state.' # $testItem.Identity 'Invoke-DMGroupPolicy.Update.Detail' = 'Correcting {0} ({1} -> {2}) on {3}' # $change.Property, $change.Old, $change.New, $change.Identity 'Invoke-DMGroupPolicy.WinRM.Failed' = 'Failed to connect to "{0}" via WinRM/PowerShell Remoting.' # $computerName - + 'Invoke-DMObject.Object.Change' = 'Updating the properties {0}' # ($testItem.Changed.Property -join ", ") 'Invoke-DMObject.Object.Create' = 'Creating {0} object in {1}' # $testItem.Configuration.ObjectClass, $testItem.Identity - - 'Invoke-DMOrganizationalUnit.OU.Create' = 'Creating organizational unit' # + + 'Invoke-DMOrganizationalUnit.OU.Create' = 'Creating organizational unit' # 'Invoke-DMOrganizationalUnit.OU.Create.OUExistsNot' = 'Cannot create OU {1}, parent OU does not exist: {0}' # $targetOU, $testItem.Identity - 'Invoke-DMOrganizationalUnit.OU.Delete' = 'Deleting organizational unit' # + 'Invoke-DMOrganizationalUnit.OU.Delete' = 'Deleting organizational unit' # 'Invoke-DMOrganizationalUnit.OU.Delete.HasChildren' = 'Skipping the deletion of {0} - OU has {1} childitem(s) that would also be deleted. Please manually handle these before proceeding.' # $testItem.ADObject.DistinguishedName, ($childObjects | Measure-Object).Count 'Invoke-DMOrganizationalUnit.OU.Delete.NoAction' = 'Skipping the deletion of {0} - OU deletion has been disabled' # $testItem.Identity 'Invoke-DMOrganizationalUnit.OU.MultipleOldOUs' = 'Cannot rename organizational unit to {0}: More than one organizational unit exists owning one of the previous names. Conflicting organizational unit: {1}. Please investigate and manually resolve.' # $testItem.Identity, ($testItem.ADObject.Name -join ', ') 'Invoke-DMOrganizationalUnit.OU.Rename' = 'Renaming organizational unit to {0}' # (Resolve-String -Text $testItem.Configuration.Name) 'Invoke-DMOrganizationalUnit.OU.Update' = 'Updating {0} on organizational unit' # ($changes.Keys -join ", ") - - 'Invoke-DMPasswordPolicy.PSO.Create' = 'Creating new PSO object' # - 'Invoke-DMPasswordPolicy.PSO.Delete' = 'Deleting PSO object' # + + 'Invoke-DMPasswordPolicy.PSO.Create' = 'Creating new PSO object' # + 'Invoke-DMPasswordPolicy.PSO.Delete' = 'Deleting PSO object' # 'Invoke-DMPasswordPolicy.PSO.Update' = 'Updating properties: {0}' # ($changes.Keys -join ", ") 'Invoke-DMPasswordPolicy.PSO.Update.GroupAssignment' = 'Assigning PSO to {0}' # (Resolve-String -Text $testItem.Configuration.SubjectGroup) - + 'Invoke-DMServiceAccount.Computer.NotFound' = 'Error processing service account {1}: Cannot find computer {0}, will be unable to assign this access permission to the service account.' # $name, $resolvedName 'Invoke-DMServiceAccount.Computer.Optional.NotFound' = 'Error processing service account {1}: Cannot find computer {0}, will be unable to assign this access permission to the service account.' # $name, $resolvedName 'Invoke-DMServiceAccount.Creating' = 'Creating a new service account: {0}' # $testItem.Identity @@ -150,15 +151,15 @@ 'Invoke-DMServiceAccount.Enabling' = 'Enabling service account {0}' # $testItem.Identity 'Invoke-DMServiceAccount.Group.NotFound' = 'Error processing service account {1}: Cannot find group {0}, will be unable to assign this access permission to the service account.' # $name, $resolvedName 'Invoke-DMServiceAccount.Moving' = 'Moving service account {0} to {1}' # $testItem.Identity, $testItem.Changed.NewValue - 'Invoke-DMServiceAccount.NoKdsRootKey' = 'There is no valid KDS Root Key in the target domain, cannot apply service accounts' # + 'Invoke-DMServiceAccount.NoKdsRootKey' = 'There is no valid KDS Root Key in the target domain, cannot apply service accounts' # 'Invoke-DMServiceAccount.Renaming' = 'Renaming service account {0} to {1}' # $testItem.Identity, $testItem.Changed.NewValue 'Invoke-DMServiceAccount.RenamingSam' = 'Renaming SamAccountName of service account {1} to {0}' # $testItem.Identity, $testItem.ADObject.SamAccountName 'Invoke-DMServiceAccount.Updating' = 'Updating properties on service account {0}' # $testItem.Identity 'Invoke-DMServiceAccount.UpdatingPrincipal' = 'Updating principals allowed to access service account {0}' # $testItem.Identity - - 'Invoke-DMUser.User.Create' = 'Creating active directory user' # + + 'Invoke-DMUser.User.Create' = 'Creating active directory user' # 'Invoke-DMUser.User.Create.OUExistsNot' = 'Cannot create user {1} : Path does not exist: {0}' # $targetOU, $testItem.Identity - 'Invoke-DMUser.User.Delete' = 'Deleting active directory user' # + 'Invoke-DMUser.User.Delete' = 'Deleting active directory user' # 'Invoke-DMUser.User.Move' = 'Moving active directory user to {0}' # $targetOU 'Invoke-DMUser.User.MultipleOldUsers' = 'Cannot rename user to {0}: More than one user exists owning one of the previous names. Conflicting users: {1}. Please investigate and manually resolve.' # $testItem.Identity, ($testItem.ADObject.Name -join ', ') 'Invoke-DMUser.User.Rename' = 'Renaming active directory user to {0}' # (Resolve-String -Text $testItem.Configuration.SamAccountName) @@ -167,76 +168,76 @@ 'Invoke-DMUser.User.Update.Name' = 'Renaming user to {0}' # (Resolve-String -Text $testItem.Configuration.Name) 'Invoke-DMUser.User.Update.OUExistsNot' = 'Cannot move active directory group {0} - user does not exist: {1}' # $testItem.Identity, $targetOU 'Invoke-DMUser.User.Update.PasswordNeverExpires' = 'Changing user password non-expiration to: {0}' # $testItem.Configuration.PasswordNeverExpires - + 'Invoke-DMWmiFilter.Creating' = 'Creating new WMI filter: {0}' # $testItem.Identity 'Invoke-DMWmiFilter.Deleting' = 'Deleting existing WMI filter: {0}' # $testItem.Identity 'Invoke-DMWmiFilter.Updating' = 'Updating the existing WMI filter: {0}' # $testItem.Identity - + 'Remove-GroupPolicy.Deleting' = 'Deleting GPO: {0}' # $ADObject.DisplayName 'Remove-GroupPolicy.Deleting.Failed' = 'Failed to delete GPO: {0}' # $ADObject.DisplayName - + 'Resolve-ContentSearchBase.Exclude.NotFound' = 'Failed to find excluded ou/container: {0}' # $item.Name '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-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 'Resolve-PolicyRevision.Result.Success' = 'Found GPO: {0}. Last export ID: {1}. Last updated on {2}' # $Policy.DisplayName, $result.ExportID, $result.Timestamp - + 'Set-DMRedForestContext.Connection.Failed' = 'Failed to connect to {0}' # $Server - + 'Test-DMAccessRule.DefaultPermission.Failed' = 'Failed to retrieve default permissions from Schema when connecting to {0}' # $Server 'Test-DMAccessRule.NoAccess' = 'Failed to access {0}' # $resolvedPath 'Test-DMAccessRule.Parallel.Error' = 'Failed to process {0}' # $fail.ADObject - + 'Test-DMAcl.ADObjectNotFound' = 'The target object could not be found: {0}' # $resolvedPath 'Test-DMAcl.NoAccess' = 'Failed to access Acl on {0}' # $resolvedPath - + '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 - + 'Test-DMGPOwner.Filter.Error.MissingCondition' = 'Configuration error: Not all filter conditions used have been defined. Define the missing GPPermissionFilter conditions to continue. Missing conditions: {0}' # ($filterMapping.MissingCondition -join ", ") 'Test-DMGPOwner.Filter.Error.PathNotFound' = 'Unable to find OU required by the filter set. Missing path: {0}' # $filterMapping.ErrorData 'Test-DMGPOwner.Identity.NotFound' = 'Unable to resolve/find the intended owner {0} for GPO {1}' # $ownerCfg.Identity, $gpoADObject.DisplayName - + 'Test-DMGPPermission.Filter.Path.DoesNotExist.SilentlyContinue' = 'The searchbase for the filter condition {0} could not be found. This however was defined as optional and is not an error: {1}' # $Condition.Name, $searchBase 'Test-DMGPPermission.Filter.Path.DoesNotExist.Stop' = 'The searchbase {1} for the filter condition {0} could not be found. A consistent picture of the desired permission configuration is impossible, terminating!' # $searchBase 'Test-DMGPPermission.Filter.Result' = 'Resolved filter condition {0} to GPOs: {1}' # $key, ($filterToGPOMapping[$key].DisplayName -join ', ') 'Test-DMGPPermission.Identity.Resolution.Error' = 'Failed to resolve the identity of an intended privilege-holder on {0}. Cancelling the processing for this GPO, as correct access configuration is not assured.' # $adObject.DisplayName 'Test-DMGPPermission.Validate.MissingFilterConditions' = 'Critical configuration error: Not all referenced Group Policy Permission filter-conditions were defined. Undefined conditions: {0}' # ($missingConditions -join ", ") 'Test-DMGPPermission.WinRM.Failed' = 'Failed to connect to {0}' # $computerName - + 'Test-DMGPRegistrySetting.TestResult' = 'Finished testing GP Registry settings against {0}. Success: {1} | Status: {2}' # $resolvedName, $result.Success, $result.Status 'Test-DMGPRegistrySetting.WinRM.Failed' = 'Failed to connect to {0}' # $parameters.Server - + 'Test-DMGroupMembership.Assignment.Resolve.Connect' = 'Failed to resolve {2} {1} - Could not connect to {0}' # (Resolve-String -Text $assignment.Domain), (Resolve-String -Text $assignment.Name), $assignment.ItemType 'Test-DMGroupMembership.Assignment.Resolve.NotFound' = 'Successfully queried domain "{0}", but the member {1} of type {2} could not be found' # (Resolve-String -Text $assignment.Domain), (Resolve-String -Text $assignment.Name), $assignment.ItemType 'Test-DMGroupMembership.Category.Error' = 'Error resolving Object Category {0} when processing group membership of {1}. Skipping this group due to uncertain group membership.' # $assignment.Category, $assignment.Group 'Test-DMGroupMembership.Group.Access.Failed' = 'Failed to access group {0} in target domain, cannot compare its members with the configured state.' # $resolvedGroupName - + 'Test-DMGroupPolicy.ADObjectAccess.Failed' = 'Failed to access GPO active directory object for: {0}' # $managedPolicy.DistinguishedName 'Test-DMGroupPolicy.DomainData.Failed' = 'Failed to retrieve the domain-specific data for the following sources: {0}' # ($domainDataNames -join ",") 'Test-DMGroupPolicy.PolicyRevision.Lookup.Failed' = 'Failed to resolve GPO in AD: {0}' # $managedPolicies.DisplayName 'Test-DMGroupPolicy.WinRM.Failed' = 'Failed to connect to "{0}" via WinRM/PowerShell Remoting.' # $computerName - + 'Test-DMObject.ADObject.Access.Error' = 'Failed to access {0} while retrieving {1}' # $resolvedPath, ($objectDefinition.Attributes.Keys -join ",") 'Test-DMObject.ADObject.Access.Error2' = 'Failed to access {0}' # $resolvedPath - + 'Test-DMPasswordPolicy.SubjectGroup.NotFound' = 'Failed to find the group {0}, which should be granted permission to the Finegrained Password Policy {1}' # $groupName, $resolvedName - + 'Test-DMServiceAccount.Computer.NotFound' = 'Error processing service account {1}: Cannot find computer {0}, will be unable to assign this access permission to the service account.' # $name, $resolvedName 'Test-DMServiceAccount.Computer.Optional.NotFound' = 'Error processing service account {1}: Cannot find computer {0}, will be unable to assign this access permission to the service account.' # $name, $resolvedName 'Test-DMServiceAccount.Group.NotFound' = 'Error processing service account {1}: Cannot find group {0}, will be unable to assign this access permission to the service account.' # $name, $resolvedName - - 'Test-KdsRootKey.Adding' = 'Adding KDS Root Key. It is backdated by 10 hours and thus instantly available. Until this has fully replicated however, you may still be unable to reliably use any created group Managed Service Accounts. This is purely to facilitate gMSA creation.' # - 'Test-KdsRootKey.Failed' = 'Failed to add a KDS Root Key. Make sure you have sufficient permissions to complete the task.' # - + + 'Test-KdsRootKey.Adding' = 'Adding KDS Root Key. It is backdated by 10 hours and thus instantly available. Until this has fully replicated however, you may still be unable to reliably use any created group Managed Service Accounts. This is purely to facilitate gMSA creation.' # + 'Test-KdsRootKey.Failed' = 'Failed to add a KDS Root Key. Make sure you have sufficient permissions to complete the task.' # + 'Validate.DomainData.Pattern' = 'Invalid input: {0}. A domain data name must only consist of numbers, letters and underscore.' # , 'Validate.GPPermissionFilter' = 'Invalid GP Permission filter: {0}' # , 'Validate.GPPermissionFilter.InvalidIdentifiers' = 'Invalid filter elements (filter names): {1}. Filters can only consist of letters, numbers and underscore. Filter: {0}' # $_, ($invalidIdentifiers -join ', ') diff --git a/DomainManagement/functions/AccessRule/Invoke-DMAccessRule.ps1 b/DomainManagement/functions/AccessRule/Invoke-DMAccessRule.ps1 index 78b697c..a126cc4 100644 --- a/DomainManagement/functions/AccessRule/Invoke-DMAccessRule.ps1 +++ b/DomainManagement/functions/AccessRule/Invoke-DMAccessRule.ps1 @@ -2,32 +2,32 @@ <# .SYNOPSIS Applies the desired state of accessrule configuration. - + .DESCRIPTION Applies the desired state of accessrule configuration. Define the desired state with Register-DMAccessRule. Test the desired state with Test-DMAccessRule. - + .PARAMETER InputObject Test results provided by the associated test command. Only the provided changes will be executed, unless none were specified, in which ALL pending changes will be executed. - + .PARAMETER Server The server / domain to work with. - + .PARAMETER Credential The credentials to use for this operation. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. - + .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. - + .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:\> Invoke-DMAccessRule -Server contoso.com @@ -37,17 +37,17 @@ param ( [Parameter(ValueFromPipeline = $true)] $InputObject, - + [PSFComputer] $Server, - + [PSCredential] $Credential, [switch] $EnableException ) - + begin { $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential $parameters['Debug'] = $false @@ -62,13 +62,13 @@ if (-not $InputObject) { $InputObject = Test-DMAccessRule @parameters } - + foreach ($testItem in $InputObject) { # Catch invalid input - can only process test results if ($testItem.PSObject.TypeNames -notcontains 'DomainManagement.AccessRule.TestResult') { Stop-PSFFunction -String 'General.Invalid.Input' -StringValues 'Test-DMAccessRule', $testItem -Target $testItem -Continue -EnableException $EnableException } - + switch ($testItem.Type) { 'Update' { Write-PSFMessage -Level Debug -String 'Invoke-DMAccessRule.Processing.Rules' -StringValues $testItem.Identity, $testItem.Changed.Count -Target $testItem @@ -82,7 +82,7 @@ Write-PSFMessage -Level InternalComment -String 'Invoke-DMAccessRule.AccessRule.Remove' -StringValues $changeEntry.ADObject.IdentityReference, $changeEntry.ADObject.ActiveDirectoryRights, $changeEntry.ADObject.AccessControlType, $changeEntry.DistinguishedName -Target $changeEntry $aclObject.RemoveAccessRuleSpecific($changeEntry.ADObject.OriginalRule) Remove-RedundantAce -AccessControlList $aclObject -IdentityReference $changeEntry.ADObject.OriginalRule.IdentityReference - + $stillThere = $false foreach ($rule in $aclObject.GetAccessRules($true, $false, [System.Security.Principal.NTAccount])) { if (Test-AccessRuleEquality -Parameters $parameters -Rule1 $rule -Rule2 $changeEntry.ADObject.OriginalRule) { @@ -95,7 +95,7 @@ if ($stillThere -and $alternativeRemoval) { $null = $aclObject.RemoveAccessRule($changeEntry.ADObject.OriginalRule) Remove-RedundantAce -AccessControlList $aclObject -IdentityReference $changeEntry.ADObject.OriginalRule.IdentityReference - + $stillThere = $false foreach ($rule in $aclObject.GetAccessRules($true, $false, [System.Security.Principal.NTAccount])) { if (Test-AccessRuleEquality -Parameters $parameters -Rule1 $rule -Rule2 $changeEntry.ADObject.OriginalRule) { @@ -119,15 +119,26 @@ 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-Principal @parameters -Name $changeEntry.Configuration.IdentityReference), + $changeEntry.Configuration.ActiveDirectoryRights, + $changeEntry.Configuration.AccessControlType, + $changeEntry.Configuration.ObjectType, + $changeEntry.Configuration.InheritanceType, + $changeEntry.Configuration.InheritedObjectType + ) } catch { $failedCount = $failedCount + 1 Stop-PSFFunction -String 'Invoke-DMAccessRule.AccessRule.Creation.Failed' -StringValues $testItem.Identity, $changeEntry.Configuration.IdentityReference -EnableException $EnableException -Target $changeEntry -Continue -ErrorRecord $_ } $null = $aclObject.AddAccessRule($accessRule) - #TODO: Validation and remediation of success. Adding can succeed but not do anything, when accessrules are redundant. Potentially flag it for full replacement? - continue + # Validation and remediation of success. Adding can succeed but not do anything, when accessrules are redundant. Potentially flag it for full replacement? + if (-not ($aclObject.Access | Where-Object { $_ -in $accessRule })) { + $failedCount = $failedCount + 1 + Write-PSFMessage -Level Warning -String 'Invoke-DMAccessRule.AccessRule.Creation.NotApplied' -StringValues $testItem.Identity, $changeEntry.Configuration.IdentityReference -Target $changeEntry + } + continue } #endregion Add Access Rules @@ -137,14 +148,25 @@ 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-Principal @parameters -Name $changeEntry.Configuration.IdentityReference), + $changeEntry.Configuration.ActiveDirectoryRights, + $changeEntry.Configuration.AccessControlType, + $changeEntry.Configuration.ObjectType, + $changeEntry.Configuration.InheritanceType, + $changeEntry.Configuration.InheritedObjectType + ) } catch { $failedCount = $failedCount + 1 Stop-PSFFunction -String 'Invoke-DMAccessRule.AccessRule.Creation.Failed' -StringValues $testItem.Identity, $changeEntry.Configuration.IdentityReference -EnableException $EnableException -Target $changeEntry -Continue -ErrorRecord $_ } - $null = $aclObject.AddAccessRule($accessRule) - #TODO: Validation and remediation of success. Adding can succeed but not do anything, when accessrules are redundant. Potentially flag it for full replacement? + $null = $aclObject.AddAccessRule($accessRule) + # Validation and remediation of success. Adding can succeed but not do anything, when accessrules are redundant. Potentially flag it for full replacement? + if(-not ($aclObject.Access | Where-Object { $_ -in $accessRule })) { + $failedCount = $failedCount + 1 + Write-PSFMessage -Level Warning -String 'Invoke-DMAccessRule.AccessRule.Creation.NotApplied' -StringValues $testItem.Identity, $changeEntry.Configuration.IdentityReference -Target $changeEntry + } continue } #endregion Restore Default Access Rules diff --git a/DomainManagement/functions/AccessRule/Test-DMAccessRule.ps1 b/DomainManagement/functions/AccessRule/Test-DMAccessRule.ps1 index f904510..d2f5bf0 100644 --- a/DomainManagement/functions/AccessRule/Test-DMAccessRule.ps1 +++ b/DomainManagement/functions/AccessRule/Test-DMAccessRule.ps1 @@ -2,7 +2,7 @@ <# .SYNOPSIS Validates the targeted domain's Access Rule configuration. - + .DESCRIPTION Validates the targeted domain's Access Rule configuration. This is done by comparing each relevant object's non-inherited permissions with the Schema-given default permissions for its object type. @@ -19,13 +19,13 @@ - Have at least one path based rule. - Are considered as "under management", as defined using Set-DMContentMode It uses a definitive approach - any access rule not defined will be flagged for deletion! - + .PARAMETER Server The server / domain to work with. - + .PARAMETER Credential The credentials to use for this operation. - + .EXAMPLE PS C:\> Test-DMAccessRule -Server fabrikam.com @@ -39,11 +39,11 @@ param ( [PSFComputer] $Server, - + [PSCredential] $Credential ) - + begin { #region Utility Functions function Convert-AccessRule { @@ -95,6 +95,7 @@ ObjectTypeName = $objectTypeName PropagationFlags = $ruleObject.PropagationFlags Present = $ruleObject.Present + NoFixConfig = $ruleObject.NoFixConfig } } } @@ -150,7 +151,7 @@ } $adObject = Get-ADObject @parameters -Identity $resolvedPath -Properties adminCount - + if ($adObject.adminCount) { $defaultPermissions = @() $desiredPermissions = Get-AdminSDHolderRules @parameters @@ -173,30 +174,30 @@ #region Process Non-Configured AD Objects - Serial if (-not $doParallelize) { $resolvedConfiguredObjects = $script:accessRules.Keys | Resolve-String - + $foundADObjects = foreach ($searchBase in (Resolve-ContentSearchBase @parameters -NoContainer)) { Get-ADObject @parameters -LDAPFilter '(objectCategory=*)' -SearchBase $searchBase.SearchBase -SearchScope $searchBase.SearchScope -Properties adminCount } - + $resultDefaults = @{ Server = $Server ObjectType = 'AccessRule' } - + $convertCmdName = { Convert-DMSchemaGuid @parameters -OutType Name }.GetSteppablePipeline() $convertCmdName.Begin($true) $convertCmdGuid = { Convert-DMSchemaGuid @parameters -OutType Guid }.GetSteppablePipeline() $convertCmdGuid.Begin($true) - + $processed = @{ } foreach ($foundADObject in $foundADObjects) { # Prevent duplicate processing if ($processed[$foundADObject.DistinguishedName]) { continue } $processed[$foundADObject.DistinguishedName] = $true - + # Skip items that were defined in configuration, they were already processed if ($foundADObject.DistinguishedName -in $resolvedConfiguredObjects) { continue } - + $adAclObject = Get-AdsAcl @parameters -Path $foundADObject.DistinguishedName $compareParam = @{ ADRules = $adAclObject.Access | Convert-AccessRuleIdentity @parameters @@ -204,22 +205,22 @@ ConfiguredRules = Get-CategoryBasedRules -ADObject $foundADObject @parameters -ConvertNameCommand $convertCmdName -ConvertGuidCommand $convertCmdGuid ADObject = $foundADObject } - + # Protected Objects if ($foundADObject.AdminCount) { $compareParam.DefaultRules = @() $compareParam.ConfiguredRules = Get-AdminSDHolderRules @parameters } - + $compareParam += $parameters $delta = Compare-AccessRules @compareParam - + if ($delta) { New-TestResult @resultDefaults -Type Update -Changed $delta -ADObject $adAclObject -Identity $foundADObject.DistinguishedName continue } } - + $convertCmdName.End() $convertCmdGuid.End() @@ -345,7 +346,7 @@ $null = $workflow | Add-PSFRunspaceWorker @param $resolvedConfiguredObjects = $script:accessRules.Keys | Resolve-String - + $foundADObjects = foreach ($searchBase in (Resolve-ContentSearchBase @parameters -NoContainer)) { Get-ADObject @parameters -LDAPFilter '(objectCategory=*)' -SearchBase $searchBase.SearchBase -SearchScope $searchBase.SearchScope -Properties adminCount } @@ -370,7 +371,7 @@ foreach ($fail in $fails) { Write-PSFMessage -Level Warning -String 'Test-DMAccessRule.Parallel.Error' -StringValues $fail.ADObject -ErrorRecord $fail.Error -Target $fail } - + $results = Read-PSFRunspaceQueue -InputObject $workflow -Name results -All # Fix String Presentation for objects from a background runspace $results | Add-Member -MemberType ScriptMethod -Name ToString -Value { $this.Identity } -Force diff --git a/DomainManagement/functions/users/Register-DMUser.ps1 b/DomainManagement/functions/users/Register-DMUser.ps1 index 702bf2f..7323423 100644 --- a/DomainManagement/functions/users/Register-DMUser.ps1 +++ b/DomainManagement/functions/users/Register-DMUser.ps1 @@ -2,7 +2,7 @@ <# .SYNOPSIS Registers a user definition into the configuration domains are compared to. - + .DESCRIPTION Registers a user definition into the configuration domains are compared to. This configuration is then compared to the configuration in AD when using Test-ADUser. @@ -12,7 +12,7 @@ Use Register-DMNameMapping to add additional values and the placeholder they will be inserted into. Use Get-DMNameMapping to retrieve a list of available mappings. This can be used to use the same content configuration across multiple environments, accounting for local naming differences. - + .PARAMETER SamAccountName SamAccountName of the user to manage. Subject to string insertion. @@ -20,28 +20,28 @@ .PARAMETER Name Name of the user to manage. Subject to string insertion. - + .PARAMETER GivenName Given Name of the user to manage. Subject to string insertion. - + .PARAMETER Surname Surname (Family Name) of the user to manage. Subject to string insertion. - + .PARAMETER Description Description of the user account. This is required and should describe the purpose / use of the account. Subject to string insertion. - + .PARAMETER PasswordNeverExpires Whether the password should never expire. By default it WILL expire. - + .PARAMETER UserPrincipalName The user principal name the account should have. Subject to string insertion. - + .PARAMETER Path The organizational unit the user should be placed in. Subject to string insertion. @@ -53,12 +53,12 @@ .PARAMETER Optional By default, all defined user accounts must exist. By setting a user account optional, it will be tolerated if it exists, but not created if it does not. - + .PARAMETER OldNames Previous names the user object had. Will trigger a rename if a user is found under one of the old names but not the current one. Subject to string insertion. - + .PARAMETER Present Whether the user should be present. This can be used to trigger deletion of a managed account. @@ -68,7 +68,7 @@ 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:\> Get-Content .\users.json | ConvertFrom-Json | Write-Output | Register-DMUser @@ -79,35 +79,36 @@ [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $SamAccountName, - + [Parameter(ValueFromPipelineByPropertyName = $true)] [string] $Name, - + [Parameter(ValueFromPipelineByPropertyName = $true)] [string] $GivenName, - + [Parameter(ValueFromPipelineByPropertyName = $true)] [string] $Surname, - + [Parameter(ValueFromPipelineByPropertyName = $true)] [string] $Description, - + [Parameter(ValueFromPipelineByPropertyName = $true)] [switch] $PasswordNeverExpires, - + [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] + [AllowEmptyString()] [string] $UserPrincipalName, - + [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $Path, - + [Parameter(ValueFromPipelineByPropertyName = $true)] [PSFramework.Utility.TypeTransformationAttribute([string])] [DomainManagement.TriBool] @@ -116,22 +117,22 @@ [Parameter(ValueFromPipelineByPropertyName = $true)] [bool] $Optional, - + [Parameter(ValueFromPipelineByPropertyName = $true)] [string[]] $OldNames = @(), - + [Parameter(ValueFromPipelineByPropertyName = $true)] [PSFramework.Utility.TypeTransformationAttribute([string])] [DomainManagement.TriBool] $Present = 'true', - + [string] $ContextName = '' ) - + process { - + $userHash = @{ PSTypeName = 'DomainManagement.User' SamAccountName = $SamAccountName diff --git a/DomainManagement/internal/functions/acl_ace/Compare-AccessRules.ps1 b/DomainManagement/internal/functions/acl_ace/Compare-AccessRules.ps1 index bf596b5..8097c53 100644 --- a/DomainManagement/internal/functions/acl_ace/Compare-AccessRules.ps1 +++ b/DomainManagement/internal/functions/acl_ace/Compare-AccessRules.ps1 @@ -2,31 +2,31 @@ <# .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", "")] @@ -45,7 +45,7 @@ [PSFComputer] $Server, - + [PSCredential] $Credential ) @@ -142,10 +142,11 @@ :outer foreach ($configuredRule in $ConfiguredRules) { foreach ($defaultRule in $DefaultRules) { if ('True' -ne $configuredRule.Present) { break } - 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 + if (-not $configuredRule.NoFixConfig) { + Write-Result -Type FixConfig -Identity $defaultRule.IdentityReference -ADObject $defaultRule -Configuration $configuredRule -DistinguishedName $ADObject + } + continue outer } } foreach ($relevantADRule in $relevantADRules) { diff --git a/DomainManagement/internal/functions/acl_ace/Get-CategoryBasedRules.ps1 b/DomainManagement/internal/functions/acl_ace/Get-CategoryBasedRules.ps1 index 12c3bbd..dd58c51 100644 --- a/DomainManagement/internal/functions/acl_ace/Get-CategoryBasedRules.ps1 +++ b/DomainManagement/internal/functions/acl_ace/Get-CategoryBasedRules.ps1 @@ -2,25 +2,25 @@ <# .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 @@ -56,21 +56,22 @@ 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 - } + [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 + NoFixConfig = $ruleObject.NoFixConfig + } } } } \ No newline at end of file