en-US/about_Invoke-FvAdOuAceRemediation.help.txt

TOPIC
    about_Invoke-FvAdOuAceRemediation

SHORT DESCRIPTION
    Assesses, reports on, remediates and rolls back over-permissive explicit Everyone/GenericAll
    ACEs on Active Directory Organizational Units.

LONG DESCRIPTION
    Six functions are provided:

      Get-FvAdOuAce - read-only assessment of a supplied OU's ACEs
      Get-FvAdOuAceReport - opt-in, explicit domain-wide reporting sweep
      Backup-FvAdOuAcl - pre-change security-descriptor backup (DACL only)
      Reset-FvAdOuAce - remediation: removes the offending explicit ACE(s)
      Restore-FvAdOuAcl - rollback: restores a DACL from a Backup-FvAdOuAcl manifest
      Invoke-FvAdOuAceRemediation - single entry point, dispatches to the above by mutually
                                      exclusive parameter set (-Assess/-Report/-Remediate/
                                      -Rollback); default is read-only assessment.

    DESIGN CHOICES

    - The security descriptor is read and written via the nTSecurityDescriptor attribute
      (Get-ADObject -Properties nTSecurityDescriptor / Set-ADObject -Replace), never via
      Get-Acl/Set-Acl against the AD:\ provider drive. The AD:\ drive's behaviour under
      PowerShell 7 is unreliable; nTSecurityDescriptor is the underlying LDAP attribute and
      gives predictable, object-based read/write.

    - ACEs are enumerated via '$securityDescriptor.GetAccessRules($true, $true,
      [System.Security.Principal.SecurityIdentifier])', never via the '.Access' property. This
      was verified against a live, non-production OU read during this build: '.Access' returned
      only 1 of 33 real ACEs on the same object (it appears to omit inherited rules by default),
      which would have silently under-reported findings and under-remediated targets.

    - A right "matches the watchlist" when the ACE's rights fully contain at least one
      watchlisted right's bit pattern, not merely when any bit overlaps. GenericAll's numeric
      value (983551 / 0xF01FF) is a combination of many lower-privilege bits (including
      ReadProperty), so a naive combined-mask "any bit overlaps" test would flag an ordinary
      ReadProperty-only ACE as a GenericAll match purely by bit coincidence - confirmed during
      this build. Testing full containment per watchlisted right avoids that.

    - Backup and restore are scoped to the DACL only (AccessControlSections.Access). Owner,
      primary group and the SACL are deliberately left untouched throughout this module -
      restoring or altering them is out of scope.

    - ACE matching is performed exclusively on resolved SecurityIdentifier values. There is no
      comparison anywhere against a display-name string such as "Everyone".

    - Only explicit (IsInherited -eq $false) Allow ACEs are ever removed. Inherited ACEs are
      reported, never remediated - an inherited over-permissive ACE must be fixed at its source
      (a parent container), which this module does not touch.

    UNVERIFIED ASSUMPTION

    Writing nTSecurityDescriptor back via 'Set-ADObject -Identity <dn> -Replace
    @{ ntSecurityDescriptor = $securityDescriptor }' (where $securityDescriptor is the
    System.DirectoryServices.ActiveDirectorySecurity instance returned by
    'Get-ADObject -Properties nTSecurityDescriptor') is a long-standing, widely used community
    pattern. The current Microsoft Learn reference page for Set-ADObject documents -Replace
    generically as a Hashtable of LDAP attribute names to values and does not carry a worked
    nTSecurityDescriptor example, so this specific usage could NOT be confirmed against a
    current Microsoft-authored code sample during this build. Test this write path against a
    non-production OU before relying on it in change control.

    OTHER STATED ASSUMPTIONS

    - "Restore the default permissions" is implemented as two distinct, non-equivalent modes
      (RestoreMode parameter on Reset-FvAdOuAce). RemoveAce (default) removes only the offending
      explicit ACE(s) and is the minimal, reversible reading. SchemaDefaultDacl rebuilds the
      OU's DACL from the live organizationalUnit classSchema object's defaultSecurityDescriptor
      and discards ALL custom delegations on the OU, not just the offending ACE - it must be
      deliberately selected, never assumed.
    - A live OU's effective DACL is the schema default merged with inheritable ACEs from its
      parents; SchemaDefaultDacl mode does not reproduce a pristine OU exactly, and says so at
      runtime via Write-Warning.
    - No change-record/ticket-ID parameter is included; none was requested.
    - Backup manifests are written wherever the caller points -BackupPath, with no automatic
      retention or pruning.
    - Execution identity is assumed to hold WriteDacl on each target OU and read access to the
      schema naming context. This is not enforced by the module - a failed write surfaces as a
      per-OU 'Failed' result, per the per-OU error isolation design.

    NON-GOALS (deliberately out of scope)

    - Group Policy objects, Conditional Access policies, tenant settings, domain-root ACLs.
    - Inherited ACEs, inheritance flags, SE_DACL_PROTECTED, object ownership, the SACL.
    - A GUI, an HTML dashboard beyond Get-FvAdOuAceReport's own export, or a scheduled task.

COMMANDS
    Get-FvAdOuAce
    Get-FvAdOuAceReport
    Backup-FvAdOuAcl
    Reset-FvAdOuAce
    Restore-FvAdOuAcl
    Invoke-FvAdOuAceRemediation

EXAMPLES
    # Read-only assessment of one OU (the default mode)
    Invoke-FvAdOuAceRemediation -OrganizationalUnit 'OU=Example,DC=contoso,DC=local'

    # Domain-wide reporting sweep, exported as CSV and HTML
    Invoke-FvAdOuAceRemediation -Report -SearchBase 'DC=contoso,DC=local' `
        -OutputPath 'C:\Reports' -OutputFormat Csv, Html

    # Preview remediation with no changes made
    Invoke-FvAdOuAceRemediation -Remediate -OrganizationalUnit 'OU=Example,DC=contoso,DC=local' `
        -BackupPath 'C:\Backups' -WhatIf

    # Remediate, then roll back from the manifest Backup-FvAdOuAcl wrote
    $result = Invoke-FvAdOuAceRemediation -Remediate -OrganizationalUnit 'OU=Example,DC=contoso,DC=local' `
        -BackupPath 'C:\Backups' -Confirm:$false
    Invoke-FvAdOuAceRemediation -Rollback -ManifestPath $result.BackupManifestPath -Confirm:$false

NOTES
    This module requires PowerShell 7.0 or later and the ActiveDirectory RSAT module
    (Windows-only). Modifying an OU's discretionary ACL is a Tier-0-adjacent change: Reset-FvAdOuAce
    and Restore-FvAdOuAcl both require WriteDacl on the target OU, declare
    SupportsShouldProcess with ConfirmImpact 'High', and Reset-FvAdOuAce always takes a
    Backup-FvAdOuAcl snapshot before writing and aborts the OU if that backup fails.

SEE ALSO
    Get-Help Get-FvAdOuAce -Full
    Get-Help Invoke-FvAdOuAceRemediation -Full