Как эффективно использовать параметр `-Filter` в командлетах Active Directory?

Слишком часто я вижу следующий тип кода на этом сайте, специфичный для командлетов AD:

Get-ADUser -Filter * | Where-Object { $_.EmailAddress -eq $email }

Проблема в том, что вы возвращаете каждый отдельный пользовательский объект в Active Directory, а затем обрабатываете его во второй раз. Как мы можем улучшить это, не только чтобы сократить время, необходимое для запуска сценария, но также и снять ненужную нагрузку с Active Directory и, возможно, сети?

1 ответ

Решение

Что в этом плохого -Filter *?

Вы фактически выбираете и возвращаете каждый объект, который существует в AD, в зависимости от используемого командлета (например, Get-ADUser, Get-ADComputer, Get-ADGroup родовой Get-ADObject и т. д.) - это дорогая вещь, особенно в больших средах AD. Это нормально, если вам по закону нужно работать с каждым возможным объектом, но в большинстве случаев вам не нужно возвращать все. Кроме того, ваш сценарий будет обрабатывать гораздо больше данных, чем нужно, увеличивая время выполнения и время обработки, когда это просто не нужно.

-Filter Параметр может сделать больше, чем просто сопоставить все, что эффективно -Filter * делает. Filter Строка очень похожа на синтаксис Powershell (не совсем, но в большинстве случаев). Вы можете использовать большинство тех же логических операторов, которые поддерживает Powershell, и они работают так же, как и операторы Powershell. Этот ответ призван прояснить это и объяснить, как использовать этот неуловимый параметр. Эти примеры будут использовать Get-ADUser командлеты, но это также распространяется на другие Get-ADObject командлеты, которые также используют фильтры.

Синтаксис

Синтаксис для Filter строка выглядит следующим образом: "PropertyName -comparisonoperator 'somevalue'" хотя вы можете связать несколько условий вместе с логическими операторами, такими как -and а также -or, Обратите внимание, что операторы сопоставления регулярных выражений, такие как -match а также -notmatch не работают, но -like а также -notlike работать так, как вы ожидаете.

Соответствие на имущество

Чтобы использовать пример в вопросе, давайте найдем пользователя, который соответствует адресу электронной почты, но без указания Where-Object (безумно верно???):

$email = 'box@domain.tld'
Get-ADUser -Filter "EmailAddress -eq '${email}'"

Готово. Get-ADUser вернет все учетные записи, в которых свойство EmailAddress равно значению $email переменная есть.

Что если мы хотим найти все учетные записи пользователей, которые не были зарегистрированы в течение последних 30 дней? Но строка даты является более сложной, чем электронная почта! Кому интересно, все таки довольно просто!

# Get the date from 30 days ago
$notUsedSince = ( Get-Date ).AddDays( -30 )
Get-ADUser -Filter "LastLogonDate -lt '${notUsedSince}'"

Это возвращает всех пользователей, которые не вошли в систему в течение последних 30 дней.

Совпадение по нескольким свойствам

Совпадение по нескольким свойствам не сильно отличается, но лучше заключить каждое условие в скобки (), Вот пример, давайте найдем учетные записи администратора домена (если мы знаем это по номенклатуре имени пользователя) *-da), которые не имеют адрес электронной почты, связанный с ними.

Get-ADUser -Filter "(samaccountname -notlike '*-da') -and (EmailAddress -notlike '*')"

Это немного сложнее, потому что мы не можем передать пустое значение для правой части условия в -Filter как в случае для EmailAddress, Но '*' соответствует любому непустому значению, поэтому мы можем использовать это поведение с -notlike оператор сравнения, чтобы найти пустые значения для EmailAddress, Чтобы сломать фильтр, убедитесь, что все учетные записи, оканчивающиеся на -da не сопоставляются фильтром, а также сопоставляются только те учетные записи, которые не имеют EmailAddress значение.

Вещи, чтобы избежать

  1. Не пытайтесь использовать { ScriptBlock } для ваших параметров фильтра. Да, нам все удобнее писать ScriptBlock чем беспокоиться о создании string и убедившись, что он избежал правильно. Их использование определенно привлекает. Я видел так много ответов, используя ScriptBlock как -Filter аргумент, или люди, имеющие проблемы (включая меня), пытающиеся сделать что-то подобное, и СЮРПРИЗ!!! Ничто не возвращается

    Import-Csv C:\userInfoWithEmails.csv | Foreach-Object { Get-ADUser -Filter { EmailAddress -eq $_.Email } }

    -Filter не поддерживает ScriptBlocks, но они вид работы иногда ™, потому что они получают ToString'd до оценки. Технически они будут работать, если вы используете простое расширение переменной, например $_ или же $emailAddress, но это в конечном итоге вызовет у вас головную боль, особенно если вы попытаетесь получить доступ к свойству объекта (как выше), потому что оно просто не будет работать. Каждый раз используйте строковый фильтр, а если вам нужно использовать свойство объекта в качестве параметра фильтра, используйте подстановку переменных или подстановку команд.

  2. Вам не нужно указывать дополнительные -Properties если вы заботитесь только о свойстве для фильтрации по нему. Командлеты AD могут оценивать все свойства в пределах Filter параметр без необходимости передавать их по конвейеру.

  3. И пока я на это, никогда не использую -Properties * Исключая, может быть, если по какой-то причине вы проверяете все свойства возвращаемого объекта. Укажите свойства, которые нужно обработать, только после того, как объект AD был возвращен. Для этого есть причина - некоторые свойства особенно дороги для получения значений. Лучшая практика - перенаправлять только те свойства, которые вам нужны для обработки по конвейеру. Немного не связанный с этим вопросом, но все же очень важная деталь, о которой нужно помнить.

В итоге

Эти методы с использованием -Filter Параметр с помощью командлетов AD сэкономит вам дорогостоящее время обработки при переборе в больших средах AD и повысит производительность ваших операций Powershell AD. Я надеюсь, что это поможет объяснить некоторые из неуловимых поведений командлетов AD -Filter параметр.

Другие вопросы по тегам