Рассмотрим на примерах процесс создания простой системы оповещения администартора о добавлении нового пользователя в группу безопасности Active Directory. К примеру, мы хотим отслеживать изменение группы администраторов домена, и в случае добавления в нее нового пользователя получать соответствующее уведомление (письмом или всплывающим окошком).
Есть два варианта организации такого решения:
- Можно включить аудит событий на контроллерах домена и отслеживание появление события добавления пользователя в группу безопасности (EventID 4728)
- Хранить локальный текстовый файл со списком пользователей в определенной группе и периодически сравнивать его с текущими членами доменной группы
Аудит добавления пользователя в группу на контроллере домена
В том случае, если у вас в GPO включена политика аудита Computer Configuration -> Windows Settings -> Security Settings -> Advanced Audit Configuration -> Account Management -> Audit Security Group Management, то при добавлении пользователя в группу Active Directory в журнале Security появляется событие EventId 4728 (A member was added to a security-enabled global group).
С помощью PowerShell можно отследить появление этого события в журнале безопасности. К примеру, выведем все события с этим кодом EventID за 24 часа на котроллере домена. Для удобства мы будем выводить имя группы AD, которая изменилась, какая учетная запись была добавлена и кто из администраторов добавил пользователя в группу (скрипт по примеру из статьи Получение списка пользователей AD, созданных за 24 часа).
$time = (get-date) - (new-timespan -hour 24)
Get-WinEvent -FilterHashtable @{LogName="Security";ID=4728;StartTime=$Time}| Foreach {
$event = [xml]$_.ToXml()
if($event)
{
$Time = Get-Date $_.TimeCreated -UFormat "%Y-%m-%d %H:%M:%S"
$NewUser = $event.Event.EventData.Data[0]."#text"
$ADGroup = $event.Event.EventData.Data[2]."#text"
$AdminUser = $event.Event.EventData.Data[6]."#text"
$dc = $event.Event.System.computer
$dc + “|” + $Time + “|” + “|” + $ADGroup + “|” + $NewUser + “|” + $AdminUser
}
}
Теперь на контроллере домена нужно создать новое задание планировщика и привязать его запуск к появлению события 4728. При появления данного события нужно отправить пользователю письмо (как привязать скрипт к событию описано в статьях Триггеры событий Windows и Запуск PowerShell скрипта при возникновении события, не буду повторяться).
Однако проблема в том, что проверяется журнал только одного DC. Если добавление пользователя в группу выполнялось на другой контроллере домена, вы не увидите это событие. Можно, конечно создать подписку на события с нескольких DC или перебирать все контроллеры скриптом, но в том случае, если в домене большое количество DC, все это не очень удобно.
$time = (get-date) - (new-timespan -hour 124)
$DCs = Get-ADDomainController -Filter *
foreach ($DC in $DCs){
Get-WinEvent -ComputerName $DC -FilterHashtable @{LogName="Security";ID=4728;StartTime=$Time}| Foreach {
$event = [xml]$_.ToXml()
if($event)
{
$Time = Get-Date $_.TimeCreated -UFormat "%Y-%m-%d %H:%M:%S"
$NewUser = $event.Event.EventData.Data[0]."#text"
$ADGroup = $event.Event.EventData.Data[2]."#text"
$AdminUser = $event.Event.EventData.Data[6]."#text"
$dc = $event.Event.System.computer
$dc + “|” + $Time + “|” + “|” + $ADGroup + “|” + $NewUser + “|” + $AdminUser
}
}
}
Рассмотрим другой подход.
Сравнение текущего состава доменной группы с шаблоном
С помощью командлета Get-ADGroupMember выведем список пользователей в группе Domain Admin и сохраним полученный список в текстовый файл (строим рекурсивный список пользователей, с учетом вложенных групп).
(Get-ADGroupMember -Identity "Domain Admins" -recursive).Name | Out-File C:\PS\DomainAdmins.txt
Теперь добавим в группу Domain Admins нового пользователя и еще раз сохраним список пользователей, но уже во второй файл.
(Get-ADGroupMember -Identity "Domain Admins" -recursive).Name | Out-File C:\PS\DomainAdminsCurrent.txt
Теперь сравним два файла и выведем на экран отличия в списках:
$oldadm=GC C:\PS\DomainAdmins.txt
$newadm=GC C:\PS\DomainAdminsCurrent.txt
$diff=Compare-Object -ReferenceObject $oldadm -DifferenceObject $newadm | Select-Object -ExpandProperty InputObject
write-host $diff
На экран вывелась учетная запись, которого добавили в группу AD.
Можно вывести сообщение в консоль:
$result=(Compare-Object -ReferenceObject $oldadm -DifferenceObject $diff | Where-Object {$_.SideIndicator -eq "=>"} | Select-Object -ExpandProperty InputObject) -join ", "
If ($result)
{msg * "В группу Domain Admins добавлен пользователь: $result"}
Или отправить письмо с помощью командлета Send-MailMessage:
If ($result)
{Send-MailMessage -SmtpServer msg01 -From [email protected] -To [email protected] -Subject "В группу Domain Admins добавлен пользователь: $result " -Body "Сообщение создано $date" -Priority High}
Данный скрипт можно сохранить в файл admins_group_changes.ps1 и запускать регулярно с помощью планировщика (как создать задание планировщика с помощью PowerShell). Создадим новое задание планировщика, которое раз в сутки запускает наш PowerShell скрипт, коорый выполняет сверку состава группы доменных администраторов с локально сохраненным списком.
$Trigger= New-ScheduledTaskTrigger -At 10:00am -Daily
$User= "NT AUTHORITY\SYSTEM"
$Action= New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "C:\PS\admins_group_changes.ps1 "
Register-ScheduledTask -TaskName "Check Admins Group" -Trigger $Trigger -User $User -Action $Action -RunLevel Highest –Force
Таким образом состав группы администраторов будет проверяться один раз в день и в случае наличия изменений администартор будет получать уведомление (всплывающим сообщением или письмом).
Не добавляется задача для отправки по почте, здесь видео
Это у меня одного или у всех так?
Отправка писем через задание планировщика является устаревшей функцией (deprecated) и не поддерживается, если я не ошибаюсь, начиная с Windows Server 2012. Для отправки писем нужно запускать внешний скрипт. Проще всего через PoSh командлет Send-MailMessage, как указано в статье.
Спасибо!
Спасибо за статью. В альтернативу хочу добавить, что описываемую задачу успешно решает связка Scom + Acl Services. С выгрузки всех событий безопасности DC&RODC в отчёты web формы sql report service.
Да, конечно SCOM/MOM в этом плане более удобные инструменты. Но для небольшой задачи мониторинга групп вполне можно обойтись и такими скриптами.
Насчет скрипта, удобнее сделать бесконечный do while и слать письмо изнутри цикла ну и там же sleep c желаемой задержкой хоть минуту хоть день. А таск запускать on startup
В общем-то да, можно и в цикле постоянно проверять. В итоге можно придти к системному PoSh сервису, который постоянно отслеживает изменения в группах AD. 🙂
В моем случае оповещения раз в день было достаточно.
Подскажите, можно ли вариант «Сравнение текущего состава доменной группы с шаблоном» сделать так, чтобы запланированное задание запускалось от имени gMSA. У меня при запуске задания от имени gMSA появляется ошибка планировщика 0x1. Как мне кажется gMSA не хватает каких то прав.
Попробуйте создавать задание планровщика для аккаунта gMSA так. Сначала создаете и настройте новое задание через графический интерфейс Task Scheduler от имени просто пользователя, а потом меняете акканунт на gMSA командой
schtasks /change /TN \TaskName /RU DOMAIN\gMSA_account$ /RP
На запрос пароля оставляете его пустым.
подскажите пожалуйста, как создать запрос по нескольким событиям сразу, например ID=4720 (Создание пользователя) и ID=4726 (Удаление пользователя)
перечисляйте ID событий через запятую:
Get-WinEvent -ComputerName $DC -FilterHashtable @{LogName="Security";ID=4720,4726 ;StartTime=$Time}
Подскажите пожалуйста, В первом варианте скрипт нацелен на все группы в домене, а как бы првильно нацелить его только на определённую группу, допустим Domain admins.