Powershell, чтобы запутать пользователя AD, который был отключен за последние 6 месяцев?

Я хотел знать, какую команду или сценарий можно использовать или настроить для поиска учетной записи пользователя AD, которая была отключена за последние 6 месяцев?

Сценарий 1: Не знаю, как настроить этот сценарий ниже, так как он довольно сложный.

# When an account is disabled, the userAccountControl attribute is set to 514. 
# Therefore, with Get-ADReplicationAttributeMetadata to find out when that attribute was the last set

$disabledUsers = Get-ADObject -Filter "ObjectClass -eq 'User' -and userAccountControl -eq '514'"

foreach ($disabledUser in $disabledUsers)
{
    Get-ADReplicationAttributeMetadata $disabledUser -Server localhost |
    Where-Object { $_.AttributeName -eq 'UserAccountControl' } | Select Object, LastOriginatingChangeTime |
    Where-Object { $_.LastOriginatingChangeTime -gt (Get-Date).AddDays(-180) }
}

Сценарий 2: я смог использовать этот сценарий и получить все необходимые столбцы и фильтры, однако он не показывает учетную запись AD, которая была отключена за последние 6 месяцев?

Import-Module ActiveDirectory
$domainDN = (Get-ADDomain).DistinguishedName

$excludeOUs = @(
    'OU=Shared Mailbox'
    'OU=Company Leaver'
) | ForEach-Object { $_ + ',' + $domainDN }

$Past = -180
$Days = (Get-Date).AddDays($Past)
$ResultPath = "C:\TEMP\ADLastLogonPast_$($Past)_Days.csv"
$properties = @('Name', 'mail', 'physicalDeliveryOfficeName', 'DisplayName', 'title', 'SamAccountName', 'CanonicalName', 'lastlogondate')
$filter = { (LastLogonDate -notlike '*' -or LastLogonDate -le $Days) -and (passwordLastSet -le $Days) -and (enabled -eq $True) -and (PasswordNeverExpires -eq $false) -and (whenCreated -le $Days) }

Get-ADUser -properties $properties -Filter $filter -SearchBase $domainDN |
Select-Object DisplayName,
              Title,
              PhysicalDeliveryOfficeName,
              UserPrincipalName,
              LastLogonDate,
              @{ n = 'LastLogonDaysAgo'; e = { [int]((Get-Date) - $_.LastLogonDate).TotalDays } },
              @{ n = 'CN'; e = { Split-Path $_.CanonicalName -Parent } },
              @{ n = 'ParentContainer'; e = { $_.DistinguishedName -replace '^CN=.*?(?=CN|OU)' } } | Where-Object {
                  ($_.SamAccountName -notmatch '^(Calendar|Room|Account|Fax|Team|Office|Test|User|SM_|HealthMailbox|SVC)$') -and
                  ($excludeOUs -notcontains $_.ParentContainer)
              } |
Export-Csv -NoTypeInformation -Path $ResultPath

person Senior Systems Engineer    schedule 01.05.2020    source источник
comment
Разве это не должно быть LastOriginatingChangeTime -gt $180DaysAgo, а не -lt?   -  person Mathias R. Jessen    schedule 01.05.2020
comment
Да, вы правы, но как-то как показать Имя, CN и отметку даты-времени в формате dd/MM/YYYY   -  person Senior Systems Engineer    schedule 01.05.2020
comment
Если все дело в форматировании LastLogonDate, попробуйте: @{Name = 'LastLogonDate'; Expression = {'{0:dd/MM/yyyy' -f $_.LastLogonDate}}   -  person Theo    schedule 01.05.2020
comment
Ваш второй блок кода не имеет смысла. Вы говорите, что фильтр правильный, но он ищет активные учетные записи с датой входа в систему после заданного времени. Я думал, вам нужны учетные записи, которые были отключены в течение последних 6 месяцев?   -  person Bacon Bits    schedule 01.05.2020
comment
По сути, это дубликат вашего предыдущего вопроса: Powershell для отключения пользователя AD за последние 6 месяцев?   -  person halfer    schedule 05.05.2020


Ответы (2)


Предполагая, что вы хотите найти учетные записи, которые были изменены с включенных на отключенные в течение последних 6 месяцев, ваш второй скрипт не скажет вам об этом. Вы просто находите аккаунты, которые отключены и не использовались более 6 месяцев. Или, в лучшем случае, вы можете изменить это, чтобы предоставить вам учетные записи, которые отключены и последний раз обновлялись за последние 6 месяцев. Но некоторые из них могли быть отключены более 6 месяцев назад.

Первый сценарий даст вам то, что вы хотите, поскольку с помощью Get-ADReplicationAttributeMetadata< /a> позволяет узнать, когда был изменен конкретный атрибут. Таким образом, вы можете узнать, когда был изменен атрибут userAccountControl. Но он нуждается в некоторой модификации.

Во-первых, это:

# When an account is disabled, the userAccountControl attribute is set to 514.

Это не обязательно правда. Атрибут userAccountControl представляет собой битовый флаг, означающий, что каждый бит в двоичном значении — это флаг, который означает что-то другое (1 = включено, 0 = выключено). Так что десятичное значение на самом деле не имеет никакого значения. Чтобы узнать, отключена ли учетная запись, вам нужно посмотреть на второй бит. Для этого вы используете побитовый оператор -band.

Этот сценарий также указывает на localhost, что означает, что вам придется запускать его на контроллере домена. Но вы можете легко изменить это, чтобы найти контроллер домена, на который можно указать.

Я также добавил условие в Get-ADObject, чтобы найти только учетные записи, которые были изменены за последние 6 месяцев, поскольку, если учетная запись была отключена менее 6 месяцев назад, это, безусловно, означает, что она была изменена менее 6 месяцев назад. Это уменьшает количество учетных записей, для которых вы должны вызывать Get-ADReplicationAttributeMetadata, уменьшая количество времени, которое потребуется для запуска этого скрипта. (Обратите внимание на одинарные кавычки вокруг фильтра, это важно из-за того, как PowerShell обрабатывает дату.)

$sixMonthsAgo = (Get-Date).AddDays(-180)

$disabledUsers = Get-ADObject -Filter 'ObjectClass -eq "User" -and whenChanged -ge $sixMonthsAgo -and UserAccountControl -band 2'

$server = Get-ADDomainController

foreach ($disabledUser in $disabledUsers)
{
    Get-ADReplicationAttributeMetadata $disabledUser -Server $server -Properties UserAccountControl |
    Where-Object { $_.AttributeName -eq 'UserAccountControl' } | Select Object, LastOriginatingChangeTime |
    Where-Object { $_.LastOriginatingChangeTime -gt $sixMonthsAgo }
}

(По какой-то причине я обнаружил, что Get-ADReplicationAttributeMetadata не дает мне никаких данных, когда я запускаю этот скрипт в PowerShell ISE, но он отлично работает, когда я копирую/вставляю в обычное окно PowerShell. Не знаю почему, но стоит упомянуть )

Технически это все еще не может точно определить, когда учетная запись была отключена, поскольку она ищет любое изменение в userAccountControl. Возможно, что, например, кто-то установил для учетной записи «неограниченный срок действия пароля» после того, как учетная запись была отключена, что также изменит атрибут userAccountControl, и этот скрипт будет искать дату «неограниченный срок действия пароля». "изменить, а не отключить дату. Но в большинстве случаев такого не происходит.

person Gabriel Luci    schedule 01.05.2020
comment
Я согласен с оговоркой в ​​вашем последнем абзаце. Это стоит повторить. - person Bacon Bits; 01.05.2020
comment
@Gabriel, скрипт выдает ошибку, например: Get-ADObject: ошибка синтаксического анализа запроса: «ObjectClass -eq 'User» -and whenChanged -ge 06.11.2019 13:30:28 -and UserAccountControl -band 2 'Сообщение об ошибке: ' Оператор Не поддерживается: ' в позиции: '47'. В строке:3 символа:18 - person Senior Systems Engineer; 04.05.2020
comment
Вот почему я упомянул о важности одинарных кавычек вокруг фильтра :) Вам нужно оставить кавычки, как я их поставил. Вся строка фильтра должна быть заключена в одинарные кавычки, а "User" — в двойные кавычки. Если вы измените его на двойные кавычки, PowerShell заменит переменную $sixMonthsAgo значением этой переменной, а затем решит, что / в дате является математическим оператором, с которым он не знает, что делать. Если вы оставите его в одинарных кавычках, PowerShell не расширит переменную, а командлет Get-ADObject интерпретирует переменную даты (это то, что вам нужно). - person Gabriel Luci; 04.05.2020
comment
Подробнее здесь: О правилах цитирования - person Gabriel Luci; 04.05.2020
comment
Это здорово, большое спасибо, Габриэль. - person Senior Systems Engineer; 05.05.2020

Я бы сделал это так:

# Midnight 180 days ago
$CutoffDate = [DateTime]::Today.AddDays(-180)

$UsersDisabledAfterCutoff = Search-ADAccount -AccountDisabled -UsersOnly |
    Get-ADReplicationAttributeMetadata -Server $DomainController -Properties UserAccountControl |
    Where-Object LastOriginatingChangeTime -ge $CutoffDate |
    Select-Object -Property Object, LastOriginatingChangeTime

Команда Search-ADAccount позволяет легко находить категории учетных записей, не заморачиваясь с битовыми масками. Вам определенно стоит взглянуть на документация для будущего использования, потому что она обрабатывает огромный объем работы для такого рода вещей.

Команда Get-ADReplicationAttributeMetadata позволяет указать нужные свойства, что снижает объем работы для всех. В этой команде тоже есть параметр -Filter, но я считаю, что его производительность иногда ужасна.

person Bacon Bits    schedule 01.05.2020
comment
Круто, спасибо вам, сэр Бэкон :-) - person Senior Systems Engineer; 05.05.2020