Качественно
сделанная сложная задача приносит удовлетворение, вызывает чувство гордости.
Это один из мощнейших мотиваторов. Если вы, конечно, внесли в нее значительный
вклад.
Скрипт
делает удаленную выборку событий журналов Eventlog security на предмет последних
интерактивных входов пользователей в ОС Windows.
Скрипт
решает несколько задач:
- Автоматическое
определение версии и локализации ОС, Get-Wmi-Object вследствие выполняются четыре
различные функции
- Ввод
компьютеров с консоли пользователя либо опрос файла со списком компьютеров
с которых нужно собрать информацию
- Сбор
информации из Eventlog Security за несколько последних дней. История входа
пользователей.
- Сбор данных о пользователях из Active Directory
Get-Aduser mail, telephonenumber
- Вывод
требуемой информации в файл формата CSV для последующей обработке
в Excel со столбцами
Скачать мой
скрипт можно отсюда:
Спасибо
человеку с Github - Craig Meinschein https://github.com/pfaffle за предоставленную наработку. Его скрипт был взят за основу и дописан мною
под требования заказчика.
А задача
была следующая:
Определение
для виртуальных Windows-машин неизвестного назначения 5-ти последних профилей
пользователей AD, которые регистрировались в операционной системе. Далее,
опираясь на эту информацию, подготовить таблицу следующего содержания:
-
Пользователь AD (по профилю);
- Список ОС
виртуальных машин, на которых он регистрировался;
- Контакты
пользователя из AD (email, телефон)
*** одна
строка: 1 пользователь, 1 ВМ на которой он логинился, контакты пользователя в
каждой строке. (для последующей сортировки в Excel)
Мне много
пришлось потрудиться. Я потратил на скрипт неприличное количество часов и даже
купил книжку по powershell.
Мне очень
понравилась задумка с функциями, которые предназначены для разных ОС учитывая
разные номера EventID. Функции выполняются на основе выбора
оператором ветвления If() .. else if ().. и определению типа
операционной системы Windows Server 2003 или Windows Server 2008.
Коды event ID с выходом Windows Server 2008
изменились. Коды событий взяты из замечательных справочников :
Давайте разберем понятия интерактивных входов в систему консоль entrytype=2 entrytype=10
Следует
понимать, где следует собирать информацию о входах. Существует ошибочное мнение
тех, кто готовился к экзаменам по сертификации МС, что информацию о входах пользователей надо искать на контроллерах домена.
Но там будут только события сетевых входов entrytype=3. Это данные аутентификации пользователя в домене.
Что мы понимаем под логином пользователя? сетевой вход, обращение к сетевой папке, вход компьютера, запрос билета керберос. Я провел тесты и обнаруживаю, что интересующие нас интерактивные входы контроллер не регистрирует. А значит их следует искать в локальных файлах журналов Eventlog Security куда непосредсвенно входил пользовтель по RDP entrytype=10 и в консоль entrytype=2 (по нажатию ctrl + alt + delete).
Что мы понимаем под логином пользователя? сетевой вход, обращение к сетевой папке, вход компьютера, запрос билета керберос. Я провел тесты и обнаруживаю, что интересующие нас интерактивные входы контроллер не регистрирует. А значит их следует искать в локальных файлах журналов Eventlog Security куда непосредсвенно входил пользовтель по RDP entrytype=10 и в консоль entrytype=2 (по нажатию ctrl + alt + delete).
Еntry type=2 — Interactive. Успешный
вход пользователя на компьютер.
Entry type=10 —
RemoteInteractive. Пользователь выполнил удаленный вход на этот компьютер,
используя Terminal Services или Remote Desktop.
Информация
по типам входа есть тут:
Более того,
события в журнал пишутся на языке локализации ОС. Это значит, что будут разные
записи в журнале смысл которых одинаков, а парсинг надо написать для каждого
языка свой.
Пример:
"Entry type" =
"Тип входа"
Для русской
локазизации ОС пришлось написать еще две функции.
Что
требовалось написать:
1. Основной запрос
$logons = Get-EventLog Security -AsBaseObject -InstanceId 4624,4647 |
Where-Object { ($_.InstanceId -eq 4647) `
-or
(($_.InstanceId -eq 4624) -and ($_.Message
-match "Logon
Type:\s+2")) `
-or
(($_.InstanceId -eq 4624) -and ($_.Message
-match "Logon
Type:\s+10")) }
Переделан в более простой, дело в
том что, опрос удаленных компьютеров происходил с подвисанием сессии. Упрощен на вариант:
Get-EventLog Security -computername $_
-AsBaseObject -InstanceId 4624 -after $date |
Where-Object { ($_.Message -match "Logon Type:\s+2") `
-or ($_.Message
-match "Logon
Type:\s+10") }
2. Поиск выражений в тексте
#
Determine user.
if ($event.message -match "New Logon:\s*Security ID:\s*.*\s*Account
Name:\s*(\w+)"
Имена без дефисов типа
"mdanilov" доставались успешно, а ts-mdanilov читался как
"ts-". Пришлось изменить фильтр по регулярным выражениям.
-match "New
Logon:\s*Security ID:\s*.*\s*Account Name:\s*(\w+\S\w+\S\w+)"
3. Добавлен новый фильтр по тексту
для определения домена.
# Determine Account Domain (Определение
домена пользователя).
if
($event.message -match "Account Domain:\s*(\w+\S\w+\S\w+)") {
$UserDomain = $matches[1]
}
else {
$index = $event.index
Write-Warning "Unable to parse Security
log Event. Malformed entry?
Index: $index"
4. А это самая важная часть. В тело каждой функции содержит команедлеты
для составления таблицы. Добавлен поиск пользователей в AD и вынимание
атрибутов для коллекции $user
# As long as we managed to parse the Event, print
output (После разбора лога фомируем наконец вывод).
if
($user) {
$aduser = Get-ADuser $user -Properties name, samaccountname, mail,telephonenumber | Select-Object name, samaccountname, mail, telephonenumber
$timeStamp = Get-Date $event.TimeGenerated
$output = New-Object -Type
PSCustomObject
Add-Member -MemberType NoteProperty -Name 'TimeStamp' -Value $timeStamp -InputObject $output
Add-Member -MemberType NoteProperty -Name 'UserName' -Value $user -InputObject $output
Add-Member -MemberType NoteProperty -Name 'User Domain' -Value $UserDomain -InputObject $output
Add-Member -MemberType NoteProperty -Name 'ComputerName' -Value $Event.MachineName -InputObject $output
Add-Member -MemberType NoteProperty -Name 'Action' -Value $action -InputObject $output
Add-Member -MemberType NoteProperty -Name 'LogonType' -Value $logonType -InputObject $output
Add-Member -MemberType NoteProperty -Name 'Mail' -Value $aduser.Mail -InputObject $output
Add-Member -MemberType NoteProperty -Name 'Telephonenumber' -Value $aduser.telephoneNumber -InputObject $output
Write-Output $output | FT
$output | ConvertTo-Html | Add-Content C:\script\UserProperties.html
$output | Export-Csv -Append -Path C:\script\getuser.csv -Encoding 'UTF8' -force
}
}
} else {
Write-Host "No recent logon/logoff events ( Не обнаружено свежих записей о событиях входа в журнале )."
}
5. Вывод информации в файл. Тут я
ломал голову долго. Дело в том, что командлет Export-Csv в цикле обработки
всегда перезаписывает конечный файл. Информация в нем будет только о последнем
пользовтеле вынутом из коллекции $user
Export-Csv -Path C:\script\getuser.csv -Encoding 'UTF8' -force
Правильным решением стало добавить
параметр -Append который доступен только в версии Powershell 3.0 Тем самым
усложнив требования под среду выполнения. Но зато новые записи просто
добавляется в файл, не перезаписывая его.
$output | Export-Csv -Append -Path C:\script\getuser.csv -Encoding 'UTF8' -force
6. Тело самой программы начинается с
импорта модуля ActiveDirectory для работы с командлетами AD. Далее операторы
ветвления для определения версии ОС и ее локализации. Дальше я работал над
составлением четырех функций для требуемых ОС:
·
Windows Server 2003 RUS Get-Win2003LogonHistory-rus
·
Windows Server 2003 EN Get-Win2003LogonHistory-en
·
Windows Server 2008 RUS Get-Win2008LogonHistory-rus
·
Windows Server 2008 EN Get-Win2008LogonHistory-en
Import-Module ActiveDirectory
$Date = $null
$Day = $null
$Day = Read-Host "Enter count of several last days for parse log ( Введите количество дней за которые надо собрать информацию из лога )"
$Date = (Get-Date).AddDays(-$Day)
$ComputerName = $Null
$ComputerName = Read-Host "Enter computer name for analysis ( Введите имя компьютера для анализа )"
#$ComputerName = (Import-Csv -Path C:\script\computers.csv).name
$ComputerName | ForEach-Object {
$OSversion = (Get-WmiObject -computername $_ -Query 'SELECT version FROM Win32_OperatingSystem').version
$OSLanguage = (Get-WmiObject -computername $_ -Query 'SELECT oslanguage FROM Win32_OperatingSystem').oslanguage
if (($OSversion -ge 6) -and ($OSLanguage -eq 1049))
{ "Сбор событий журнала Security на компьютере $_
(Windows 2008 RU)"
Get-Win2008LogonHistory-rus
} else {
if (($OSversion -ge 6) -and ($OSLanguage -eq 1033)) {
"Сбор событий журнала Security на компьютере $_ (Windows 2008
EN)"
Get-Win2008LogonHistory-en
} elseif ($OSLanguage -ge 1049) {
"Сбор событий журнала Security на компьютере $_ (Windows 2003
RU)"
Get-Win2003LogonHistory-rus
}
else {
"Сбор событий журнала Security на
компьютере $_ (Windows 2003 EN)"
Get-Win2003LogonHistory-en
}
}
}
Полную
версию файла скрипта можно скачать тут
Системные
требования
- Операционная
система – Windows Server 2008 R2
- Платформа Dot net 4.5.1
- Подключение
к контроллеру домена Windows Server 2008 R2 или к Windows Server 2003 R2 c установленной службой AD Gateway Service (AD Web Services)
- PowerShell
3.0
- Скрипт
содержит Командлеты версии Powershell 3.0. По умолчанию в ОС Windows Server 2008 R2 содержится устаревший
компонент Powershell 2.0 с которым данный
скрипт будет работать неправильно.
Подготовка ПО
На
компьютере с windows Server 2008 R2 создаем
папку C:\script помещаем в
нее скрипт Get-logonhistory.ps1
- Установить RSAT – ADDS & LDS Tools вместе с dot NET Framework 3.5.1
- Перезагрузить компьютер
- Устанавливаем Dot Net 4.5.1 http://www.microsoft.com/en-us/download/details.aspx?id=40779
- Устанавливаем Windows6.1-KB2506143-x64 http://www.microsoft.com/en-us/download/details.aspx?id=34595
Для
подключения к AD в среде контроллеров Windows Server 2003 необходимо поставить службу на
сам контроллер домена
Установка ADWS:
- Установить Kb969429 http://support.microsoft.com/kb/969429/ru
- Установка dot net 3.5.1 http://www.microsoft.com/en-us/download/details.aspx?id=25150
- Установка dot net 3.5.1 kb969166 http://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=20556
- Установка kb Windows5.2-kb968934 http://www.microsoft.com/en-us/download/details.aspx?id=2852
Подготовка
к запуску скрипта
Создаем
папку C:\script
Все файлы
скрипта будут формироваться в этой папке.
! Важно при
запуске скрипта от имени другого пользователя, важно указать его в разрешениях
на папку C:\script
Открываем
скрипт в Powershell ISE с правами чтения журналов на
удаленных компьютерах в домене.
Вводим имя
компьютера
Если нужно обработать список, то комментируем строку и снимаем знак комментария со строки
Если нужно обработать список, то комментируем строку и снимаем знак комментария со строки
На вид:
Формирование
списка компьютеров (произвольного)
v
Выполняем скрипт.
Время выполнения скрипта зависит от $day которые мы ввели. Примерно по 1-5 мин на один хост
Пример выполнения
В результате выполнения на выходе получаем два файла, для наглядности сделаны СSV и
еще HTML
Задача решена! Вот такой красивый файл у нас получается.
Комментариев нет:
Отправить комментарий