Заметки · 22.05.2026

Юзеры на две ставки

Все посты про группы безопасности Active Directory можно найти по этому тегу.

Этот пятничный вечер планирую посвятить отчёту о пользователях и их количестве, которые состоят одновременно в нескольких группах безопасности. В качестве инструмента разработки буду использовать всемогущий PowerShell, а на выходе должна получиться html-страничка.

Наименования необходимых групп буду трамбовать в массив $groups:

$groups = @("Группа 1", 
            "Группа 2")

Важно, чтобы скрипт умел работать с любым количеством групп в массиве $groups, поэтому необходимо написать функцию, которая бы возвращала перечень пользователей, состоящих во всех указанных группах безопасности:

function Get-FilteredUsersByGroups {
    param (
        [string[]]$groups
    )

    # Получаем всех пользователей из Active Directory
    $allUsers = Get-ADUser -Filter * -Properties Name, MemberOf, EmailAddress, Enabled

    # Фильтруем пользователей
    $filteredUsers = $allUsers | Where-Object {
        # Получаем группы пользователя
        $userGroups = $_.MemberOf

        # Проверяем наличие всех групп
        $hasAllGroups = $true

        # Проверяем на членство в указанных группах
        foreach ($group in $groups) {
            if (-not ($userGroups -match $group)) {
                $hasAllGroups = $false
                break
            }
        }

        # Возвращаем список пользователей из конвейера
        $hasAllGroups
    }

    # Возвращаем отфильтрованных пользователей из функции
    return $filteredUsers
}

Если усложнить задачу и затребовать у функции только тех пользователей, у которых есть электронная почта можно отредактировать возврат из конвейера:

$hasAllGroups -and ($_.EmailAddress)

Таким образом переменная $filteredUsers будет содержать только пользователей, у которых есть адрес электронного почтового ящика.

Ну, или наоборот ящика нет вовсе:

$hasAllGroups -and (-not $_.EmailAddress)

Так можно фильтровать пользователей по любой прихоти и менять возврат функции под любые потребности.

Остаётся только вызвать функцию Get-FilteredUsersByGroups и обработать данные, которые она вернёт:

# Вызываем функцию
$filteredUsers = Get-FilteredUsersByGroups -groups $groups

# Создаем объект с необходимыми данными для отчета
$reportData = $filteredUsers | Select-Object Name, SamAccountName, EmailAddress, Enabled | Sort-Object -Property Name

# Получаем текущее время для добавления в отчет
$reportDate = Get-Date -Format "dd-MM-yyyy"
$groupNames = $groups -join ', '

# Преобразуем данные в HTML
$htmlReport = $reportData | ConvertTo-Html -Property Name, SamAccountName, EmailAddress, Enabled -Head "<style>
    h2 { font-size: 24px; color: #333; }
    h3 { text-align: right; font-size: 20px; color: #333; }
    table { border-collapse: collapse; width: 100%; }
    th, td { border: 1px solid black; padding: 8px; text-align: left; }
    th { background-color: #f2f2f2; font-weight: bold; }
    .header { text-align: center; font-size: 24px; margin-bottom: 20px; }
    .subheader { font-size: 20px; margin-bottom: 10px; text-align: center; }
    .footer { font-size: 20px; margin-bottom: 10px; text-align: right; }
</style>" -Title "Отчет по пользователям AD" `
    -PreContent "<h2 class='header'>Дата создания отчета: $reportDate</h2><h3 class='subheader'>Группы отбора: $groupNames</h3>" `
    -PostContent "<h3 class='footer'>Количество пользователей: $($filteredUsers.Count)</h3>"

# Сохраняем HTML-отчет в файл
$outputFile = "$PSScriptRoot\AD_Users_InGroups.html"
$htmlReport | Out-File -FilePath $outputFile -Encoding utf8

Собранный воедино скрипт выглядит так:

# Установите названия ваших групп
$groups = @("Группа 1", 
            "Группа 2")

# Функция для получения пользователей
function Get-FilteredUsersByGroups {
    param (
        [string[]]$groups
    )

    # Получаем всех пользователей из Active Directory
    $allUsers = Get-ADUser -Filter * -Properties Name, MemberOf, EmailAddress, Enabled

    # Фильтруем пользователей
    $filteredUsers = $allUsers | Where-Object {
        # Получаем группы пользователя
        $userGroups = $_.MemberOf

        # Проверяем наличие всех групп
        $hasAllGroups = $true

        # Проверяем на членство в указанных группах
        foreach ($group in $groups) {
            if (-not ($userGroups -match $group)) {
                $hasAllGroups = $false
                break
            }
        }

        # Возвращаем список пользователей из конвейера
        $hasAllGroups
    }

    # Возвращаем отфильтрованных пользователей из функции
    return $filteredUsers
}

# Вызываем функцию
$filteredUsers = Get-FilteredUsersByGroups -groups $groups

# Создаем объект с необходимыми данными для отчета
$reportData = $filteredUsers | Select-Object Name, SamAccountName, EmailAddress, Enabled | Sort-Object -Property Name

# Получаем текущее время для добавления в отчет
$reportDate = Get-Date -Format "dd-MM-yyyy"
$groupNames = $groups -join ', '

# Преобразуем данные в HTML
$htmlReport = $reportData | ConvertTo-Html -Property Name, SamAccountName, EmailAddress, Enabled -Head "<style>
    h2 { font-size: 24px; color: #333; }
    h3 { text-align: right; font-size: 20px; color: #333; }
    table { border-collapse: collapse; width: 100%; }
    th, td { border: 1px solid black; padding: 8px; text-align: left; }
    th { background-color: #f2f2f2; font-weight: bold; }
    .header { text-align: center; font-size: 24px; margin-bottom: 20px; }
    .subheader { font-size: 20px; margin-bottom: 10px; text-align: center; }
    .footer { font-size: 20px; margin-bottom: 10px; text-align: right; }
</style>" -Title "Отчет по пользователям AD" `
    -PreContent "<h2 class='header'>Дата создания отчета: $reportDate</h2><h3 class='subheader'>Группы отбора: $groupNames</h3>" `
    -PostContent "<h3 class='footer'>Количество пользователей: $($filteredUsers.Count)</h3>"

# Сохраняем HTML-отчет в файл
$outputFile = "$PSScriptRoot\AD_Users_InGroups.html"
$htmlReport | Out-File -FilePath $outputFile -Encoding utf8

Если Вы ввели корректные имена групп безопасности на выходе получите файл отчёта AD_Users_InGroups.html в папке со скриптом.