Вики IT-KB

Пошаговые руководства, шпаргалки, полезные ссылки...

Инструменты пользователя

Инструменты сайта


powershell:active-directory:powershell-script-to-compare-permissions-of-two-organizational-units-ous-in-active-directory

PowerShell скрипт сравнения разрешений двух подразделений (OU) в Active Directory

Приводим пример PowerShell скрипта, который сравнивает разрешения двух организационных подразделений (OU) в службе каталогов Active Directory и выдаёт информацию о расхождениях, то есть показывает уникальные разрешения для OU:

Compare-OUPermissions.ps1
<#
.SYNOPSIS
    Compares permissions between two OUs in Active Directory.
.DESCRIPTION
    This script compares ACLs of two specified OUs and shows differences.
    Output is in Russian.
#>
 
param(
    [Parameter(Mandatory=$true)]
    [string]$FirstOU,
 
    [Parameter(Mandatory=$true)]
    [string]$SecondOU
)
 
# Set UTF-8 encoding for output
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8
 
# Check ActiveDirectory module
if (-not (Get-Module -Name ActiveDirectory -ErrorAction SilentlyContinue)) {
    try {
        Import-Module ActiveDirectory -ErrorAction Stop
    }
    catch {
        Write-Error "Failed to load ActiveDirectory module. Ensure RSAT is installed."
        exit 1
    }
}
 
function Get-OUPermissionDifferences {
    param(
        [System.DirectoryServices.ActiveDirectorySecurity]$Acl1,
        [System.DirectoryServices.ActiveDirectorySecurity]$Acl2,
        [string]$Acl1Name,
        [string]$Acl2Name
    )
 
    $differences = @()
 
    # Collect all unique SIDs from both ACLs
    $allSids = @()
    $Acl1.Access | ForEach-Object { $allSids += $_.IdentityReference }
    $Acl2.Access | ForEach-Object { $allSids += $_.IdentityReference }
    $uniqueSids = $allSids | Select-Object -Unique
 
    foreach ($sid in $uniqueSids) {
        $acl1Entries = $Acl1.Access | Where-Object { $_.IdentityReference -eq $sid }
        $acl2Entries = $Acl2.Access | Where-Object { $_.IdentityReference -eq $sid }
 
        # If SID exists in first ACL but not in second
        if ($acl1Entries -and -not $acl2Entries) {
            foreach ($entry in $acl1Entries) {
                $differences += [PSCustomObject]@{
                    Identity = $sid
                    Rights = $entry.ActiveDirectoryRights
                    Inheritance = $entry.InheritanceType
                    AccessType = $entry.AccessControlType
                    Source = $Acl1Name
                    Status = "Missing in $Acl2Name"
                }
            }
        }
        # If SID exists in second ACL but not in first
        elseif ($acl2Entries -and -not $acl1Entries) {
            foreach ($entry in $acl2Entries) {
                $differences += [PSCustomObject]@{
                    Identity = $sid
                    Rights = $entry.ActiveDirectoryRights
                    Inheritance = $entry.InheritanceType
                    AccessType = $entry.AccessControlType
                    Source = $Acl2Name
                    Status = "Missing in $Acl1Name"
                }
            }
        }
        # If SID exists in both ACLs, compare permissions
        else {
            foreach ($entry1 in $acl1Entries) {
                $found = $false
                foreach ($entry2 in $acl2Entries) {
                    if ($entry1.ActiveDirectoryRights -eq $entry2.ActiveDirectoryRights -and
                        $entry1.InheritanceType -eq $entry2.InheritanceType -and
                        $entry1.AccessControlType -eq $entry2.AccessControlType) {
                        $found = $true
                        break
                    }
                }
                if (-not $found) {
                    $differences += [PSCustomObject]@{
                        Identity = $sid
                        Rights = $entry1.ActiveDirectoryRights
                        Inheritance = $entry1.InheritanceType
                        AccessType = $entry1.AccessControlType
                        Source = $Acl1Name
                        Status = "Different in $Acl2Name"
                    }
                }
            }
        }
    }
 
    return $differences
}
 
try {
    # Get ACLs for both OUs
    Write-Host "[INFO] Получение разрешений для первого OU: $FirstOU" -ForegroundColor Cyan
    $ou1 = Get-ADOrganizationalUnit -Identity $FirstOU
    $acl1 = Get-Acl -Path "AD:\$FirstOU"
 
    Write-Host "[INFO] Получение разрешений для второго OU: $SecondOU" -ForegroundColor Cyan
    $ou2 = Get-ADOrganizationalUnit -Identity $SecondOU
    $acl2 = Get-Acl -Path "AD:\$SecondOU"
 
    # Compare permissions
    $differences = Get-OUPermissionDifferences -Acl1 $acl1 -Acl2 $acl2 -Acl1Name $ou1.Name -Acl2Name $ou2.Name
 
    # Display results
    if ($differences.Count -eq 0) {
        Write-Host "[RESULT] Разрешения идентичны для обоих OU." -ForegroundColor Green
    }
    else {
        Write-Host "[RESULT] Найдены различия в разрешениях:" -ForegroundColor Yellow
 
        # Prepare Russian column names
        $output = $differences | Select-Object @{
            Name="Пользователь/Группа"; Expression={$_.Identity}
        }, @{
            Name="Разрешения"; Expression={$_.Rights}
        }, @{
            Name="Наследование"; Expression={$_.Inheritance}
        }, @{
            Name="Тип доступа"; Expression={$_.AccessType}
        }, @{
            Name="Источник"; Expression={$_.Source}
        }, @{
            Name="Статус"; Expression={$_.Status -replace "Missing in","Отсутствует в" -replace "Different in","Отличается в"}
        }
 
        $output | Format-Table -AutoSize -Wrap
 
        # Optional: export to CSV
        $exportPath = "OUPermissionsComparison_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"
        $output | Export-Csv -Path $exportPath -NoTypeInformation -Encoding UTF8
        Write-Host "[EXPORT] Результаты сохранены в $exportPath" -ForegroundColor Cyan
    }
}
catch {
    Write-Error "[ERROR] Ошибка выполнения: $_"
    exit 1
}

Инструкция по использованию:

  1. Скопируйте скрипт в файл с расширением .ps1 (например, Compare-OUPermissions.ps1) в кодировке UTF-8
  2. Запустите PowerShell от имени администратора
  3. Выполните скрипт, указав DistinguishedName двух OU для сравнения:
.\Compare-OUPermissions.ps1 -FirstOU "OU=Sales,DC=domain,DC=com" -SecondOU "OU=Marketing,DC=domain,DC=com"

Особенности скрипта:

  • Показывает различия в разрешениях, типах наследования и контроле доступа
  • Форматирует вывод в удобочитаемую таблицу
  • Поддерживает экспорт результатов в CSV файл
  • Требует PS-модуль ActiveDirectory (часть RSAT)

Для работы скрипта необходимо иметь права на чтение разрешений в сравниваемых OU.


Проверено на следующих конфигурациях:

Версия ОС Версия Powershell
Microsoft Windows 11 Pro 24H2 10.0.26100 PowerShell 5.1.26100.2161

Автор первичной редакции:
Алексей Максимов
Время публикации: 22.05.2025 14:50

Обсуждение

Ваш комментарий:
 
powershell/active-directory/powershell-script-to-compare-permissions-of-two-organizational-units-ous-in-active-directory.txt · Последнее изменение: Алексей Максимов

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki