Три безопасных PowerShell-скрипта для Active Directory: приём, увольнение и аудит учётных записей
Для небольшого домена хватает трёх PowerShell-сценариев: создать пользователя из CSV отключённым, уволить со снимком групп и переносом в карантинную OU, раз в неделю выгружать неактивные записи в отчёт. Ниже — готовые скрипты, защита от ошибок, откат и разбор внедрения в студии на 10 рабочих мест.
Что автоматизировать в Active Directory через PowerShell, а что оставить человеку
Я начинаю не со скрипта, а с границ автоматизации. В небольшой компании не нужен комбайн на тысячи строк. Нужны три предсказуемые операции: подготовить нового пользователя, закрыть доступ уволенному сотруднику и показать забытые учётные записи. Эти действия повторяются, состоят из одинаковых шагов и хорошо проверяются. Именно с них я начинаю, когда делаем аудит Active Directory у небольших клиентов. Автоматизировать переименование домена, массовое удаление объектов или «исправление всего AD» я бы не стал: выполняются они редко, а цена ошибки слишком высока.
Мой принцип простой: скрипт может подготовить изменение, проверить данные и выполнить понятную последовательность команд. Решение об увольнении или блокировке принимает человек. Поэтому приём и увольнение запускаются вручную по заявке, а по расписанию работает только отчёт. Я сознательно не делаю автоматическое отключение по дате последнего входа. Для бизнеса на десять-пятьдесят мест выигрыш составит пару минут, а ошибочно заблокированный директор или бухгалтер остановит работу на полдня.
У каждого изменяющего сценария должны быть WhatIf, остановка при первой ошибке и журнал исходного состояния. Ещё важнее идемпотентность: повторный запуск не должен создавать второго пользователя или повторно менять уже обработанную запись. Полной транзакции у набора команд AD нет. Если создание пользователя прошло, а добавление в группу завершилось ошибкой, объект останется в каталоге. Поэтому я создаю его отключённым и включаю только после финальной проверки.
- Создание пользователя — отключённая запись, проверенные группы, без пароля в CSV.
- Активация — отдельная команда и пароль, введённый как SecureString.
- Увольнение — сначала блокировка, затем удаление из групп и перенос в карантинную OU.
- Аудит — только CSV-отчёт, без автоматического изменения каталога.
Как подготовить рабочее место: RSAT, права, политика выполнения
В 2026 году модуль ActiveDirectory остаётся штатным средством управления AD DS в Windows Server 2025, 2022, 2019 и 2016. Для проекта ниже я выбрал Windows PowerShell 5.1 на отдельном компьютере администратора. PowerShell 7 тоже работает с модулем на актуальных версиях Windows с установленным RSAT, но переходить на него ради десятка локальных пользователей я смысла не вижу. Чем скучнее административный контур, тем он надёжнее.
Запускать сценарии непосредственно на контроллере домена не требуется. Я ставлю RSAT на сервер управления или выделенный компьютер администратора. Для Windows Server и Windows 11 Pro/Enterprise команды различаются:
# Windows Server
Install-WindowsFeature -Name RSAT-AD-Tools -IncludeAllSubFeature
# Windows 11 Pro или Enterprise
Add-WindowsCapability -Online `
-Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0
Import-Module ActiveDirectory
Get-Command -Module ActiveDirectory | Select-Object -First 5Рабочая учётная запись не должна постоянно состоять в Domain Admins. Я делегирую ей создание и изменение пользователей только в рабочей OU, перенос объектов в OU отключённых сотрудников и изменение состава конкретных ролевых групп. Первичная настройка делегирования потребует повышенных прав, ежедневные операции — нет. Папку со скриптами разрешаю изменять только локальным администраторам и SYSTEM: иначе пользователь с доступом на запись сможет подменить файл, который позже запустит привилегированная задача.
Политику выполнения я задаю централизованно как RemoteSigned или, если уже развёрнута внутренняя PKI и процесс подписи, AllSigned. Политика выполнения контролирует условия запуска файлов, но не заменяет права NTFS, делегирование и аудит. Постоянный Bypass в задаче планировщика — плохая привычка. Сначала проверяю эффективные настройки командой Get-ExecutionPolicy -List, потому что доменная Group Policy имеет приоритет над локальным Set-ExecutionPolicy.
Отдельно про журнал. Каждый изменяющий сценарий я запускаю внутри Start-Transcript с файлом в защищённой папке журналов и закрываю Stop-Transcript в блоке finally. Транскрипт не заменяет аудит на контроллере домена, но показывает, что именно видел и подтверждал администратор. Для студии на десять мест этого хватает с запасом: когда через месяц спрашивают, кто и зачем убрал человека из группы, ответ находится в одном текстовом файле.
Разбор из практики: танцевальная студия «Ритм тела», 10 рабочих мест
Танцевальная студия «Ритм тела», 10 рабочих мест: два администратора ресепшн, бухгалтер, управляющий, менеджер по маркетингу и общий компьютер в тренерской, через который тренеры смотрят расписание и отмечают занятия. Особенность студии — текучка: тренеры и администраторы приходят на сезон, часть работает по совместительству. Приём и увольнение здесь случаются почти каждый месяц, и именно на этих операциях ручная работа давала сбои. Домен — Windows Server 2022, функциональный уровень Windows Server 2016, два контроллера: DC01 — виртуальная машина на основном хосте рядом с файловым сервером, DC02 — на отдельном небольшом сервере. Рабочие станции — Windows 11 Pro 24H2. В примерах настоящий суффикс заменён на зарезервированный ritm.example.
В каталоге нашлись 14 пользовательских объектов: 9 личных активных записей, 2 сервисные и 3 записи бывших сотрудников. Одна из трёх старых записей оставалась включённой — тренер, ушедший полгода назад, всё ещё мог зайти на общий компьютер в тренерской. У четырёх действующих пользователей не был заполнен отдел. Пять разрешений на файловом сервере были выданы напрямую пользователям, хотя ролевые группы уже существовали. Ручное оформление новичка занимало от 14 до 21 минуты и зависело от памяти того, кто оформлял.
Я привёл структуру к четырём OU: OU=Employees, OU=Service Accounts, OU=Computers и OU=Disabled Users внутри OU=Ritm,DC=ritm,DC=example. Пользователей включали только в глобальные группы ролей с префиксом GG- (GG-Admins, GG-Trainers, GG-Accounting), а те входили в локальные группы ресурсов DL-. Затем прогнали импорт с -WhatIf, создали одного тестового пользователя, проверили вход, применение GPO и доступ к общей папке. Только после этого обработали действующие записи. Вся подготовка заняла два рабочих дня, из них большая часть — разговор с управляющим о том, кому какой доступ на самом деле нужен.
За первые три месяца через сценарии провели пять приёмов и четыре увольнения — сезон набора групп. Среднее время подготовки новичка снизилось с 17 до 4 минут, отключения сотрудника — примерно с 15 до 3 минут. Аудит нашёл двух кандидатов на отключение, но одного мы не тронули: тренер была в декретном отпуске и собиралась вернуться. Именно поэтому отчёт остался отчётом. Через три месяца у всех действующих записей были заполнены отдел и должность, бывшие сотрудники лежали в карантинной OU, а новых прямых назначений на папки больше не появлялось.
- DC01 и DC02 — Windows Server 2022 Standard, на разных физических серверах
- 10 рабочих мест — Windows 11 Pro 24H2
- 14 пользовательских объектов до очистки, из них 3 — бывшие сотрудники, 1 из них включён
- Проверка результата — вход, GPO, группы, файловые разрешения и журнал сценария
Скрипт 1: как создать пользователя AD из CSV через PowerShell
CSV хранит только кадровые атрибуты и имена ролевых групп. Пароля в нём нет. Для одного-двух новых сотрудников это может показаться излишним, зато исчезают опечатки и становится видно, кто запросил доступ. Файл сохраняем в UTF-8 с разделителем ;. В поле Groups перечисляем только подготовленные глобальные группы ролей:
GivenName;Surname;SamAccountName;Department;Title;Groups
Анна;Соколова;a.sokolova;Ресепшн;Администратор;GG-Admins
Илья;Орлов;i.orlov;Тренеры;Тренер;GG-TrainersСкрипт проверяет формат логина, наличие пользователя и существование каждой группы до записи в каталог. Все операции закреплены за одним контроллером домена, чтобы следующий шаг не упёрся в задержку репликации. Существующую запись сценарий не «чинит» автоматически — пропускает с предупреждением. Я считаю это правильным: совпавший логин может принадлежать другому человеку.
#Requires -Version 5.1
#Requires -Modules ActiveDirectory
[CmdletBinding(SupportsShouldProcess)]
param(
[Parameter(Mandatory)] [string]$CsvPath,
[string]$Server = 'dc01.ritm.example',
[string]$TargetOU = 'OU=Employees,OU=Ritm,DC=ritm,DC=example'
)
$ErrorActionPreference = 'Stop'
Import-Module ActiveDirectory
$rows = Import-Csv -Path $CsvPath -Delimiter ';' -Encoding UTF8
foreach ($row in $rows) {
$sam = $row.SamAccountName.Trim().ToLowerInvariant()
if ($sam -notmatch '^[a-z][a-z0-9._-]{2,19}$') {
throw "Недопустимый SamAccountName: $sam"
}
$existing = Get-ADUser -LDAPFilter "(sAMAccountName=$sam)" `
-Server $Server -ErrorAction SilentlyContinue
if ($existing) {
Write-Warning "$sam уже существует — строка пропущена"
continue
}
$groupNames = @(($row.Groups -split ',') |
ForEach-Object { $_.Trim() } | Where-Object { $_ })
$groups = foreach ($groupName in $groupNames) {
if ($groupName -notlike 'GG-*') {
throw "Группа $groupName не является ролевой GG-группой"
}
Get-ADGroup -Identity $groupName -Server $Server
}
$displayName = "$($row.GivenName.Trim()) $($row.Surname.Trim())"
$params = @{
Name = $sam
GivenName = $row.GivenName.Trim()
Surname = $row.Surname.Trim()
DisplayName = $displayName
SamAccountName = $sam
UserPrincipalName = "$sam@ritm.example"
Path = $TargetOU
Enabled = $false
}
if ($row.Department) { $params.Department = $row.Department.Trim() }
if ($row.Title) { $params.Title = $row.Title.Trim() }
if ($PSCmdlet.ShouldProcess($sam, 'Создать отключённого пользователя')) {
New-ADUser @params -Server $Server
if ($groups.Count -gt 0) {
Add-ADPrincipalGroupMembership -Identity $sam `
-MemberOf $groups -Server $Server
}
Write-Information "Создан отключённый пользователь $sam" -InformationAction Continue
}
}Первый запуск выглядит так: New-RitmUser.ps1 -CsvPath .\new-users.csv -WhatIf. Затем убираем -WhatIf, сверяем свойства пользователя и только после этого задаём пароль. Я ввожу его интерактивно как SecureString; открытый текст не попадает в CSV, историю команд или наш журнал:
$user = Get-ADUser -Identity 'a.sokolova' -Server 'dc01.ritm.example'
$password = Read-Host 'Временный пароль' -AsSecureString
Set-ADAccountPassword -Identity $user -Reset `
-NewPassword $password -Server 'dc01.ritm.example'
Set-ADUser -Identity $user -ChangePasswordAtLogon $true `
-Server 'dc01.ritm.example'
Enable-ADAccount -Identity $user -Server 'dc01.ritm.example'Ещё одна деталь, которую легко пропустить: все команды сценария явно работают с одним контроллером через параметр -Server. Если создать пользователя на DC01, а добавлять в группы через DC02, между шагами может не успеть пройти репликация, и вторая команда не найдёт только что созданный объект. В домене из двух контроллеров на одной площадке это секунды, но именно такие секунды превращаются в плавающую ошибку, которую потом невозможно воспроизвести.
Самая частая поломка здесь — не синтаксис, а грязный CSV: пробел после логина, несуществующая группа или кириллическая буква в латинском имени. Вторая ошибка — сразу создавать Enabled = $true. Если добавление в группы затем упадёт, сотрудник получит рабочий пароль, но неполный доступ. В моей схеме частично созданная запись остаётся отключённой. Это безопасный и заметный сбой.
Скрипт 2: как уволить сотрудника в AD без удаления учётной записи
При увольнении первым действием я отключаю учётную запись. Не переименовываю, не очищаю атрибуты и тем более не удаляю. Затем сохраняю снимок прямого членства в группах, убираю эти группы, записываю номер заявки и переношу объект в карантинную OU. Снимок позволяет понять прежний доступ или восстановить запись, если кадровая заявка оказалась ошибочной.
Сценарий намеренно требует подтверждаемого ручного запуска. Параметр SupportsShouldProcess даёт -WhatIf, а ConfirmImpact='High' напоминает, что операция влияет на доступ. Поле MemberOf содержит прямое членство; основная группа вроде Domain Users туда обычно не входит и этим кодом не удаляется.
#Requires -Version 5.1
#Requires -Modules ActiveDirectory
[CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')]
param(
[Parameter(Mandatory)] [string]$SamAccountName,
[Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$Ticket,
[string]$Server = 'dc01.ritm.example',
[string]$DisabledOU = 'OU=Disabled Users,OU=Ritm,DC=ritm,DC=example',
[string]$SnapshotPath = 'C:\AD-Automation\Snapshots'
)
$ErrorActionPreference = 'Stop'
Import-Module ActiveDirectory
$user = Get-ADUser -Identity $SamAccountName -Server $Server `
-Properties MemberOf,Department,Title,Description
$groups = @(foreach ($groupDN in $user.MemberOf) {
Get-ADGroup -Identity $groupDN -Server $Server
})
if ($PSCmdlet.ShouldProcess($user.SamAccountName, 'Отключить и поместить в карантин')) {
New-Item -Path $SnapshotPath -ItemType Directory -Force | Out-Null
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
[ordered]@{
SamAccountName = $user.SamAccountName
DistinguishedName = $user.DistinguishedName
Department = $user.Department
Title = $user.Title
MemberOf = @($user.MemberOf)
Ticket = $Ticket
CapturedAt = (Get-Date).ToString('o')
} | ConvertTo-Json -Depth 3 |
Set-Content -Path "$SnapshotPath\$($user.SamAccountName)-$stamp.json" -Encoding UTF8
Disable-ADAccount -Identity $user -Server $Server
if ($groups.Count -gt 0) {
Remove-ADPrincipalGroupMembership -Identity $user `
-MemberOf $groups -Server $Server -Confirm:$false
}
Set-ADUser -Identity $user -Clear manager `
-Description "Disabled $(Get-Date -Format 'yyyy-MM-dd'); ticket $Ticket" `
-Server $Server
Move-ADObject -Identity $user.DistinguishedName `
-TargetPath $DisabledOU -Server $Server
}AD — только один слой доступа. Следом я закрываю облачную почту, VPN, CRM, онлайн-кассу и систему записи клиентов, телефонию и внешние кабинеты. Проверяю активные SMB-сеансы на файловом сервере и при необходимости завершаю конкретный сеанс. Автоматически закрывать все соединения пользователя по одному совпавшему имени опасно: можно оборвать копирование данных или задеть одноимённую локальную запись. Удаление объекта я рассматриваю отдельно после согласованного срока хранения, обычно не в день увольнения.
- Проверить номер и время кадровой заявки.
- Запустить сценарий с `-WhatIf`, затем без него.
- Закрыть облачные приложения, VPN и внешние сервисы.
- Проверить активные сеансы и сохранность рабочих данных.
- Через установленный срок отдельно решить вопрос удаления объекта.
Скрипт 3: как найти неактивные учётные записи AD и запустить отчёт по расписанию
Для поиска я использую Search-ADAccount -AccountInactive, но отношусь к результату как к подсказке. Свойство LastLogonDate строится на реплицируемом lastLogonTimestamp. Этот атрибут обновляется не при каждом входе: стандартная логика предусматривает интервал и случайный сдвиг, исторически дающий окно примерно 9–14 дней. Кроме того, сервисные сценарии Kerberos и неверное время на контроллере могут искажать картину. Поэтому беру порог 90 дней, исключаю свежесозданные записи и всё равно запрашиваю подтверждение руководителя. Подробно про разницу между lastLogon на разных контроллерах и реплицируемым lastLogonTimestamp я писал в статье про аудит последнего входа в Active Directory — здесь нужен только грубый фильтр.
Отчёт ограничен рабочей OU, не захватывает сервисные записи и ничего не блокирует. Пустой LastLogonDate тоже важен: это может быть забытая заготовка или сотрудник, который так и не вышел на работу.
#Requires -Version 5.1
#Requires -Modules ActiveDirectory
$Server = 'dc01.ritm.example'
$SearchBase = 'OU=Employees,OU=Ritm,DC=ritm,DC=example'
$ReportDir = 'C:\ProgramData\AD-Automation\Reports'
$cutoff = (Get-Date).AddDays(-90)
New-Item -Path $ReportDir -ItemType Directory -Force | Out-Null
$report = foreach ($account in (Search-ADAccount -UsersOnly -AccountInactive `
-TimeSpan '90.00:00:00' -SearchBase $SearchBase -Server $Server)) {
$user = Get-ADUser -Identity $account -Server $Server `
-Properties LastLogonDate,whenCreated,Enabled,Department
if ($user.Enabled -and $user.whenCreated -lt $cutoff) {
[pscustomobject]@{
SamAccountName = $user.SamAccountName
Name = $user.Name
Department = $user.Department
LastLogonDate = $user.LastLogonDate
Created = $user.whenCreated
}
}
}
$file = Join-Path $ReportDir "inactive-$(Get-Date -Format 'yyyyMMdd').csv"
$report | Sort-Object LastLogonDate |
Export-Csv -Path $file -NoTypeInformation -Encoding UTF8
Write-Output "Кандидатов: $($report.Count). Отчёт: $file"Такой read-only сценарий можно запускать от SYSTEM на присоединённом к домену сервере: машинной записи обычно хватает стандартных прав чтения каталога, а пароль хранить не приходится. Я назначаю еженедельный запуск и отдельно защищаю каталог со скриптом от изменения обычными пользователями:
$action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument `
'-NoProfile -NonInteractive -ExecutionPolicy RemoteSigned -File "C:\AD-Automation\Audit-AD.ps1"'
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Monday -At '07:00'
$principal = New-ScheduledTaskPrincipal -UserId 'SYSTEM' `
-LogonType ServiceAccount -RunLevel Highest
Register-ScheduledTask -TaskName 'AD inactive users audit' `
-Action $action -Trigger $trigger -Principal $principal `
-Description 'Еженедельный отчёт, без изменений в AD'Если задаче действительно нужно менять AD по расписанию, я выбираю gMSA, а не обычную сервисную запись с бессрочным паролем. Но для студии на 10 мест это оправдано только при уже подготовленном KDS и делегировании: нужны функциональные уровни домена и леса не ниже Windows Server 2012, корневой ключ KDS и разрешённый узел получения управляемого пароля. Для трёх редких кадровых операций проще и прозрачнее оставить ручной подтверждаемый запуск. В первую очередь внедрите отключение и аудит. Красивую панель, уведомления в мессенджер и универсальный модуль можно спокойно отложить. Общие приёмы работы с планировщиком — триггеры, журнал, перезапуск при сбое — собраны в материале про автоматизацию задач через Task Scheduler.
- Еженедельно формировать отчёт за 90 дней.
- Сверять кандидатов с кадровыми данными и руководителем.
- Отдельно контролировать сервисные и общие записи.
- Раз в квартал проверять права на папку сценариев и журнал задач.
- Не превращать отчёт в автоматическую блокировку без отдельного процесса согласования.
Что делать, если скрипт ошибся: откат по снимку и корзина AD
Ошибки случаются даже с проверенными сценариями: кадровик перепутал фамилии, в заявке указали не того тренера, администратор запустил увольнение по старой заявке. Ради этого сценарий увольнения и сохраняет JSON-снимок прямого членства в группах до изменений. Откат занимает минуту: вернуть объект в рабочую OU, восстановить группы из снимка и включить запись. Я держу этот откат отдельным маленьким скриптом рядом с основным, чтобы в стрессовой ситуации не писать код с нуля.
#Requires -Modules ActiveDirectory
param(
[Parameter(Mandatory)] [string]$SnapshotFile,
[string]$Server = 'dc01.ritm.example',
[string]$TargetOU = 'OU=Employees,OU=Ritm,DC=ritm,DC=example'
)
$ErrorActionPreference = 'Stop'
$snap = Get-Content -Path $SnapshotFile -Raw -Encoding UTF8 | ConvertFrom-Json
$user = Get-ADUser -Identity $snap.SamAccountName -Server $Server
Move-ADObject -Identity $user.DistinguishedName -TargetPath $TargetOU -Server $Server
if (@($snap.MemberOf).Count -gt 0) {
Add-ADPrincipalGroupMembership -Identity $snap.SamAccountName `
-MemberOf @($snap.MemberOf) -Server $Server
}
Enable-ADAccount -Identity $snap.SamAccountName -Server $ServerХуже, когда объект удалили руками, не дождавшись срока хранения. Здесь спасает только заранее включённая корзина Active Directory: без неё удалённый пользователь теряет членство в группах и большинство атрибутов, и восстанавливать придётся из резервной копии состояния системы. Корзина включается один раз на лес командой Enable-ADOptionalFeature и выключить её потом нельзя — как это сделать и как восстанавливать объекты, я разбирал в статье про Active Directory Recycle Bin. В «Ритме тела» мы включили её в первый же день, до любых скриптов.
И последнее. Любой сценарий, который меняет каталог, я держу в одном месте с понятной историей изменений — хотя бы в папке с датами в именах файлов, лучше в git. Через полгода вопрос «почему у Анны нет доступа к папке расписаний» решается за пять минут, если видно, какой версией скрипта и по какой заявке её оформляли. Для малого офиса этого достаточно; журнал в SIEM и согласование через тикет-систему нужны уже при большем масштабе. А если однажды захочется расширить набор — отчёты по группам, сброс паролей, инвентаризацию компьютеров, — добавляйте новые сценарии по тем же правилам: WhatIf, остановка при ошибке, снимок до изменений и отдельный тест на пробной OU.
- Снимок членства в группах сохраняется до любых изменений
- Откат: перенос в рабочую OU, группы из снимка, включение записи
- Корзина AD включается заранее, до первой ошибки
- Скрипты и их версии — в одном месте с историей изменений
Частые вопросы
Можно ли запускать эти скрипты с контроллера домена?
Технически можно, но я использую отдельный сервер управления или защищённый компьютер с RSAT. Для работы cmdlet достаточно сетевого доступа к контроллеру и делегированных прав.
Нужна ли учётная запись Domain Admin?
Для ежедневного создания и отключения пользователей — нет. Делегируйте минимальные права на рабочие OU и конкретные группы. Повышенные права понадобятся администратору при первоначальной настройке.
Почему сценарий создания не генерирует пароль автоматически?
Чтобы пароль не оказался в CSV, журнале или консольном выводе. Для малого количества приёмов безопаснее отдельно ввести временный пароль как SecureString и включить обязательную смену при первом входе.
Можно ли автоматически блокировать пользователей после 90 дней без входа?
Я не советую. lastLogonTimestamp обновляется с задержкой и имеет дополнительные ограничения. Формируйте отчёт, сверяйте его с кадровыми данными и только потом отключайте подтверждённые записи.
Что делать, если добавление в группу завершилось ошибкой?
Пользователь останется отключённым. Исправьте имя или права группы, проверьте объект вручную и завершите назначение доступа. Не включайте запись, пока вся проверка не пройдена.
Как откатить ошибочное увольнение?
Сценарий увольнения сохраняет JSON-снимок прямого членства в группах. По нему объект возвращают в рабочую OU, восстанавливают группы через Add-ADPrincipalGroupMembership и включают запись Enable-ADAccount. Если объект уже удалён, поможет только заранее включённая корзина AD или резервная копия.
Источники
- Microsoft Learn — New-ADUser — Синтаксис, параметры AccountPassword, Enabled, Path и пример импорта CSV, Windows Server 2025 PowerShell: https://learn.microsoft.com/en-us/powershell/module/activedirectory/new-aduser?view=windowsserver2025-ps
- Microsoft Learn — Search-ADAccount — Раздел AccountInactive, параметры UsersOnly, SearchBase и TimeSpan, Windows Server 2025 PowerShell: https://learn.microsoft.com/en-us/powershell/module/activedirectory/search-adaccount?view=windowsserver2025-ps
- Microsoft Learn — Last-Logon-Timestamp attribute — Условия обновления lastLogonTimestamp и интервал репликации атрибута: https://learn.microsoft.com/en-us/windows/win32/adschema/a-lastlogontimestamp
- Microsoft Learn — Install and Manage RSAT — Требования и установка RSAT-AD-Tools на Windows Server и Rsat.ActiveDirectory.DS-LDS.Tools на Windows Client: https://learn.microsoft.com/en-us/windows-server/administration/install-remote-server-administration-tools
- Microsoft Learn — about_Execution_Policies — Области политик выполнения, RemoteSigned, AllSigned и приоритет Group Policy, PowerShell 7.6: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.6
- Microsoft Learn — Manage Group Managed Service Accounts — Разделы Prerequisites, Install a gMSA и поддержка Task Scheduler; требования к KDS и функциональным уровням: https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/group-managed-service-accounts/group-managed-service-accounts/manage-group-managed-service-accounts



