Довольной частой задачей, которую приходится выполнять администратору Active Directory, является формирование списка неактивных или отключенных учетных записей пользователей и/или компьютеров. Для получения списка неактивных объектов в домене Active Directory можно использовать как сохраненные LDAP запросы в консоли ADUC, так и командлеты PowerShell. В этой статье мы покажем, как использовать PowerShell для поиска неактивных учетных записей пользователей или компьютеров.
Для использование всех командлетов PowerShell, рассмотренных ниже, на компьютере должны быть установлены как минимум версия PowerShell 3.0 и набор Remote Server Administration Toolkit (RSAT), в котором должен быть включен компонент Active Directory Module for Windows PowerShell (Control Panel -> Programs-> Turn Windows Features on and off-> Remote Server Administration Tools -> Role Administration Tools -> AD DS and AD LDS Tools).
Модуль AD PowerShell также может быть включен командой:
Add-WindowsFeature RSAT-AD-PowerShell
Запустите консоль PowerShell и импортируйте модуль Active Directory в сессию:
Import-Module ActiveDirectory
Поиск старых (неактивных) компьютеров в домене
Для поиска неактивных компьютеров в домене можно использовать командлет Get-ADComputer. В качестве критерия поиска можно использовать атрибут LastLogonTimeStamp. Обратите внимание, что этот атрибут нельзя использовать для получения информации о времени последнего входа компьютера в домен в реальном времени. Однако благодаря тому, что этот атрибут реплицируется между DC раз в 9-14 дней, вы можете получить информацию о последнем входе компьютера в домен с любого контроллера домена (в отличии от атрибута LastLogonDate, который обновляется только на DC, через который выполнил вход компьютер).
Текущее значение атрибута LastLogonTimeStamp можно получить в свойствах компьютера в консоли ADUC на вкладке редактора атрибутов.
Чтобы найти в определенном OU все компьютеры, которые не использовались для входа в сеть более 180 дней, воспользуйтесь следующими командами:
$LastLogonDate= (Get-Date).AddDays(-180)
Get-ADComputer -Properties LastLogonTimeStamp -Filter {LastLogonTimeStamp -lt $LastLogonDate } -SearchBase ‘OU=Computers,OU=MSK, dc=winitpro,dc=ru’| Sort LastLogonTimeStamp| FT Name, @{N='lastlogontimestamp'; E={[DateTime]::FromFileTime($_.lastlogontimestamp)}} -AutoSize | Export-CSV c:\ps\inactive_computers.csv
Эта команда сформирует текстовый CSV файл со списком неактивных компьютеров, которые не регистрировались в сети более полугода.
Вы можете отключить найденные учетные записи компьютеров:
Get-ADComputer -Properties LastLogonTimeStamp -Filter {LastLogonTimeStamp -lt $LastLogonDate } -SearchBase ‘OU=Computers,OU=MSK,dc=winitpro,dc=ru’| Disable-ADAccount
Перенести их в отдельный OU:
Get-ADComputer ... | Move-ADObject -TargetPath “OU=Disabled Computers,DC=winitpro,DC=ru”
Или удалить:
Get-ADComputer ... | Remove-ADComputer
Поиск неактивных учетных записей пользователей в Active Directory
Для поиска учетных записей неактивных пользователей также можно использовать атрибут lastLogonTimeStamp. Для построения списка неактивных учетных записей нужно использовать именно этот атрибут, а не lastLogon (последний не реплицируется между контроллерами домена).
Следующий скрипт позволит выбрать включенные (незаблокированные) учетные записи пользователей, которые не авторизовались в домене более полугода (180 дней) с помощью командлета Get-ADUser:
$LastLogonDate= (Get-Date).AddDays(-180)
Get-ADUser -Properties LastLogonTimeStamp -Filter {LastLogonTimeStamp -lt $LastLogonDate } -SearchBase ‘OU=Users,OU=MSK,dc=winitpro,dc=ru’| ?{$_.Enabled –eq $True} | Sort LastLogonTimeStamp| FT Name, @{N='lastlogontimestamp'; E={[DateTime]::FromFileTime($_.lastlogontimestamp)}} -AutoSize | Export-CSV c:\ps\inactive_users.csv
В целях безопасности вы можете отключить учетные записи неактивных пользователей:
Get-ADUser -Properties LastLogonTimeStamp -Filter {LastLogonTimeStamp -lt $LastLogonDate } -SearchBase ‘OU=Users,OU=MSK,dc=winitpro,dc=ru’| Disable-ADAccount
Если нужно удалить неактивных пользователей, используйте пайплайн с Remove-ADUser.
Search-ADAccount: командлет для поиска неиспользуемых объектов в AD
Для поиска неактивных в объектов в AD можно использовать командлеты Get-ADUser, Get-ADComputer или Get-ADObject. Однако создание правильного фильтра для этих команд может вызывать определенные затруднения. В модуле PowerShell для ActiveDirectory есть более удобный командлет для выполнения таких задач — Search-ADAccount. Этот командлет используется для поиска объектов любого типа (как пользователей, так и компьютеров). Рассмотрим примеры использования командлета Search-ADAccount для типовых задач поиска отключенных, неактивных и заблокированных объектов в AD.
Перечислим список наиболее интересных для нас ключей командлета Search-ADAccount:
Ключ Search-ADAccount | Описание |
-AccountDisabled
| Поиск отключенных учетных записей |
-AccountExpired
| Учетные записи с истекшим сроком действия учетки |
-AccountExpiring [-DateTime DateTime] [-TimeSpan TimeSpan]
|
Учетные записи которые просрочатся в течении определенного периода (-TimeSpan) или в определенную дату(-DateTime) |
-AccountInactive [-DateTime DateTime] [-TimeSpan TimeSpan]
| Учетные записи, не регистрировавшиеся в домене начиная с определенной даты(-DateTime) или в течении определенного периода времени (-TimeSpan) |
-LockedOut
| Учетные записи, заблокированные парольной политикой |
-PasswordExpired
| Учетные записи, пароль которых просрочен |
-PasswordNeverExpires
| Учетные записи, у которых установлен атрибут PasswordNeverExpires |
К примеру, выведем список отключенных учетных записей пользователей во всем домене:
Search-ADAccount -UsersOnly –AccountDisabled
Можно ограничить область поиска определенным контейнером (OU) Active Directory так:
Search-ADAccount -UsersOnly –AccountDisabled –searchbase "OU=Admins,OU=Accounts,DC=winitpro,DC=loc"
Эти же данные можно представить в более удобном табличном виде с помощью команды:
Search-ADAccount -UsersOnly -AccountDisabled -searchbase "OU=Admins,OU=Accounts,DC=winitpro,DC=loc"|ft -AutoSize
Если вам нужно получить список отключенных пользователей, содержащий только определённые атрибуты пользователей и представить в виде графической таблицы с возможностью сортировки, выполните:
Search-ADAccount -UsersOnly -AccountDisabled |sort LastLogonDate | Select Name,LastLogonDate,DistinguishedName |out-gridview -title "Disabled Users"
Список заблокированных учетных записей пользователей:
Search-ADAccount -UsersOnly –LockedOut
Список учетных записей пользователей, неактивных в течении 60 дней:
$timespan = New-Timespan –Days 60
Search-ADAccount –UsersOnly –AccountInactive –TimeSpan $timespan | ?{$_.Enabled –eq $True}
Чтобы посчитать количество таких пользователей:
Search-ADAccount –UsersOnly –AccountInactive –TimeSpan $timespan | ?{$_.Enabled –eq $True} | Measure
Список компьютеров, которые не регистрировались в домене в течении последних 90 дней:
Search-ADAccount -AccountInactive –ComputersOnly -TimeSpan 90
Либо с определенной даты:
Search-ADAccount -AccountInactive -ComputersOnly -DateTime ‘1/1/2020’|Select Name,LastLogonDate| ft
Для выгрузки полученных данных в CSV файл воспользуйтесь командой:
Search-ADAccount -AccountDisabled -UsersOnly| Export-Csv "c:\ps\disabled_users.csv"
Search-ADAccount -AccountInactive -ComputersOnly -DateTime ‘1/1/2017’
не С такой даты, а До нее.
Это как предложение построить :). «Список компьютеров, которые не регистрировались в сети С определенной даты» = «список неактивных компьютеров ДО даты» ?
Кстати, Search-ADAccount -ComputersOnly –LockedOut выдаст перечень заблокированных хостов. Заблокированных кем?
В теории обьекты компьютер и пользователь в AD во многом похожи. Конечно, при попытке авторизации в домене компьютера с неправильном паролем (например, ПК восстановлен из старого бэкапа) не происходит его блокировка в домене, он просто теряет доверительные отношения: ошибка «Не удалось установить доверительные отношения между этой рабочей станцией и основным доменом». Чтобы восстановить членство в домене достаточно сбросить пароль компьютера так: https://winitpro.ru/index.php/2012/08/15/sbros-parolya-kompyutera-v-domene-bez-perezagruzki/
Как Ограничить область поиска «все кроме определенного контейнера»?
Как-то так (не выводить пользователей из данного OU в списке):
Search-ADAccount -UsersOnly -AccountDisabled | Where {$_.DistinguishedName -notlike "*CN=Disabled,CN=Users,DC=winitpro,DC=ru"}
Не сочетаются –TimeSpan и -Searchbase для Search-ADAccount ?
Не уверен. На мой взгляд командлеты get-aduser и get-adcomputer более универсальные и гибкие.
Добрый день.
Необходимо посмотреть когда именно было отключение учетной записи.
Если речь именно о блокировке пользователя (при неправильном n-кратном пароле), смотрите время события на DC.
Приветствую!
Интерессный факт:
При выборке Search-ADAccount -AccountInactive –ComputersOnly -TimeSpan 90,180,360
попадают компы которые реально не в сети до 30 дней! Лично тестил, как такое может быть, не стыкались с таким? Как тогда наверняка проверить?
Наверно проблема связана с тем, что Search-ADAccount выполняет поиск по атрибуту lastlogontimestamp, который по умолчанию реплицируется между DC, но только если он более на 14 дней старше чем предыдущее значение (не стоит искать компьютеры, которые были в сети менее 14 дней назад).
В теории можно проверить через Get-ADComputer
$DaysInactive = 90
$time = (Get-Date).Adddays(-($DaysInactive))
Get-ADComputer -Filter {LastLogonTimeStamp -lt $time} -resultSetSize $null -Properties Name, OperatingSystem, SamAccountName, DistinguishedName,LastLogonTimeStamp
Методом тестирования получилось что Search-ADAccount и дугие командлеты PowerShell будут показывать актуальную информацию лишь в том случае, если пк ребутаются каждый день!!! Команды смотрят на последнее обращение к контроллеру)
Добрый день. А как можно сделать выгрузку состава группы, в которой будут отражены только отключенные УЗ?
Например, я пробовал выполнять команду:
$GROUP=»имя группы»
Get-ADGroupMember -Identity $GROUP -Recursive | Get-ADUser –Filter {enabled -eq $false} –Properties * | Select DisplayName, CN, SamAccountName, EmailAddress, LastLogonDate, City, Department, PostalCode | Export-Csv «$env:HOMEPATH\GroupMembersDisabled_$GROUP.csv» -NoTypeInformation -Encoding UTF8 -Delimiter «|» -Force
но отчёт формируется из различных УЗ, которые вообще не имеют никакого отношения к некой группе; т.е. отчёт получается некорректнный/неправильный.
Внешне запрос выглядит нормально. Возможно этот эффект из-за того, что вы получаете состав пользователей из вложенных групп рекурсивно
должен быть включить компонент — включЕН
Нужен дефис перед AccountDisabled:
Search-ADAccount -UsersOnly AccountDisabled …
Каким образом лучше сообщать вам о опечатках и ошибках?
Прямо в комментах.
Спасибо, я поправил!
Нужно поправить в разделе «Список компьютеров, которые не регистрировались в домене в течении последних 90 дней», Search-ADAccount -AccountInactive –ComputersOnly -TimeSpan 90
Дату нужно взять в кавычки TimeSpan «90», иначе будет выдавать информацию за последние 14 дней.
Не забывайте, что lastlogon не реплицируется. Чтобы получить его актвальное значение, придется опросить все dc в домене:
[datetime]::FromFileTime((Get-ADDomainController -Filter * | foreach {Get-ADUser 'пользователь' -Properties LastLogon -Server $_.Name | select LastLogon} | Measure-Object -Property LastLogon -Maximum).Maximum)
А если поле LastLogonTimeStamp пустое?
ПК создали в АД, но не использовали. Что указывать в переменной $LastLogonDate ? (LastLogonTimeStamp -lt $LastLogonDate)
Если компьютер не входил в домен, то поле LastLogonTimeStamp будет пустым.
Windows Server 2012 r2
1 не работает скрипт для выведения списка отключённых юзаков. решил добавить Remove-ADUser и сразу их удалить, но тоже не сработало.
https://i.ibb.co/61vpCXt/1.png
https://i.ibb.co/xmX5nhR/2.png
Search-ADAccount -UsersOnly –LockedOut -Remove-ADUser
Search-ADAccount : Не удается найти параметр, соответствующий имени параметра "Remove-ADUser".
строка:1 знак:40
+ Search-ADAccount -UsersOnly -LockedOut -Remove-ADUser
+ ~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Search-ADAccount], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.ActiveDirectory.Management.Commands.SearchADAccountCmdl
et
https://i.ibb.co/CWvNtG3/3.png
2 по старым юзакам, код
$LastLogonDate= (Get-Date).AddDays(-180)
Get-ADUser -Properties LastLogonTimeStamp -Filter {LastLogonTimeStamp -lt $LastLogonDate } -SearchBase ‘OU=Users,OU=MSK,dc=winitpro,dc=ru’| ?{$_.Enabled –eq $True} | Sort LastLogonTimeStamp| FT Name, @{N=’lastlogontimestamp’; E={[DateTime]::FromFileTime($_.lastlogontimestamp)}} -AutoSize | Export-CSV c:\ps\inactive_users.csv
подогнал по себя: «dc=corp,dc=avtodor-eng,dc=ru»
Get-ADUser -Properties LastLogonTimeStamp -Filter {LastLogonTimeStamp -lt $LastLogonDate } -Sea
rchBase ‘OU=Users,dc=corp,dc=avtodor-eng,dc=ru’| ?{$_.Enabled -eq $True} | Sort LastLogonTimeStamp| FT Name, @{N=’lastl
ogontimestamp’; E={[DateTime]::FromFileTime($_.lastlogontimestamp)}} -AutoSize | Export-CSV c:\ps\inactive_users.csv
Get-ADUser : Объект каталога не найден
строка:1 знак:1
+ Get-ADUser -Properties LastLogonTimeStamp -Filter {LastLogonTimeStamp -lt $LastL …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (:) [Get-ADUser], ADIdentityNotFoundException
+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,M
icrosoft.ActiveDirectory.Management.Commands.GetADUser
в начале делал так, но были жалобы:
Get-ADUser -Properties LastLogonTimeStamp -Filter {LastLogonTimeStamp -lt $LastLogonDate } -Sea
rchBase ‘OU=Users,dc=corp,dc=ru’| ?{$_.Enabled -eq $True} | Sort LastLogonTimeStamp| FT Name, @{N=’lastlogontimestamp’;
E={[DateTime]::FromFileTime($_.lastlogontimestamp)}} -AutoSize | Export-CSV c:\ps\inactive_users.csv
Get-ADUser : Указанное различающееся имя должно принадлежать одному из следующих разделов: «DC=corp,DC=avtodor-eng,DC=r
u , CN=Configuration,DC=corp,DC=avtodor-eng,DC=ru , CN=Schema,CN=Configuration,DC=corp,DC=avtodor-eng,DC=ru , DC=Domain
DnsZones,DC=corp,DC=avtodor-eng,DC=ru , DC=ForestDnsZones,DC=corp,DC=avtodor-eng,DC=ru».
строка:1 знак:1
+ Get-ADUser -Properties LastLogonTimeStamp -Filter {LastLogonTimeStamp -lt $LastL …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-ADUser], ArgumentException
+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:System.ArgumentException,Microsoft.ActiveDirectory.Management.Comm
ands.GetADUser
как должно быть написано, чтобы отрабатывал код?
Search-ADAccount -AccountDisabled -UsersOnly | remove-aduser
вот так надо было писать
а перемещение не работает:
Search-ADAccount -AccountDisabled -UsersOnly | Move-ADObject -TargetPath “OU=Blocked_accounts,DC=corp,DC=avtodor-eng,DC=ru”
ответ:
Move-ADObject : Эта операция не может быть выполнена, т.к. родитель объекта либо не подтвержден, либо удален
строка:1 знак:48
+ Search-ADAccount -AccountDisabled -UsersOnly | Move-ADObject -TargetPath «OU=Blo …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (CN=Филимонов Ал…todor-eng,DC=ru:ADAccount) [Move-ADObject], ADException
+ FullyQualifiedErrorId : ActiveDirectoryServer:8329,Microsoft.ActiveDirectory.Management.Commands.MoveADObject
как быть?
Проверьте, что DN целевого OU указан правильно:
$TargetOU = "OU=Blocked_accounts,DC=corp,DC=avtodor-eng,DC=ru"
Get-AdObject $targetOU
Либо другой вариант — вы пытаетесь переместить учетные записи которые уже в целевом контейнере надо его исключить:
$OUTransfer = "OU=Blocked_accounts,DC=corp,DC=avtodor-eng,DC=ru"
Search-ADAccount -AccountDisabled -UsersOnly | Where-Object DistinguishedName -notlike "*$OUTransfer" |Move-ADObject -TargetPath $OUTransfer
Существует проблема. Учетная запись AD была создана, но пользователь использует её только для доступа к почте Exchange или только для работы с корпоративным порталом (LDAP авторизация).
Соответственно атрибут lastLogonTimeStamp не обновляется. Можно ли в таком случае как-то выявлять реально неактивных пользователей, а не тех кто не логинился с ПК?
Здесь вам поможет выгрузка времени последнего доступа к ящику exchange и сравнение двух списков:
Get-MailboxStatistics -Server Exch19 | Sort LastLogonTime -Descending
Получается, что
$timespan = New-Timespan –Days 30
(Search-ADAccount –UsersOnly –AccountInactive –TimeSpan $timespan | select SamAccountName).count
и
$Days = 30
$Time = (Get-Date).Adddays( - ($Days))
(Get-ADUser -Filter { LastLogonTimeStamp -lt $Time } -Properties * | select SamAccountName).count
Тают разные результаты. Перевес в пользу Search-ADAccount
Тут наверно дело в том, что используются разные атрибуты для выборки: LastLogonTimeStamp и LastLogon
Отличия в том, что LastLogon обновляется только на DC, где выполен вход.
Возможно Search-ADAccount как-то собирает/парсит данные с нескольких DC. не разбирался дотошно с этим
Search-ADAccount
показывает пользователей, которые никогда не логинились, аGet-ADUser
— нет.