PowerShell — пользователи AD из основной группы плюс любая из двух дополнительных групп

Скрипт здесь:

https://gallery.technet.microsoft.com/scriptcenter/Powershell-Get-users-who-b0420fe1

вернет результаты для пользователей, которые существуют в основной группе, а также в любой из двух дополнительных групп (спасибо OP zperryz за код). Ниже моя версия этого скрипта на данный момент.

Я хотел бы добавить условия для пользователей с ограниченными возможностями и пользователей, которые находятся в определенной организационной единице "удержания". В другом скрипте я смог сделать это так (очевидно, фрагмент, а не весь скрипт):

| where {$_.Enabled -ne $False} `
| where {$_.DistinguishedName -notlike "*HOLD OU*"} `

Я просто не уверен, куда «вставить» их в сценарий ниже. (Будущая модификация будет возвращать больше информации, например DisplayName, Enabled и DistinguishedName, а не только вход в систему.)

Если у кого-то есть совет, буду очень признателен! Вот сценарий в его нынешнем виде:

$ADgroup1 = "VPN Front Door"
$ADgroup2 = "VPN Full Access"
$ADgroup3 = "VPN Restricted Access"

get-adgroupmember $ADgroup1 `
  | ForEach-Object {if(((GET-ADUSER –Identity $_.SamAccountName –Properties MemberOf `
  | Select-Object MemberOf).MemberOf -replace '^CN=([^,]+).+$','$1') -eq "$ADgroup2" -or "$ADgroup3"){$_.SamAccountName `
  | Out-File -append -filepath C:\Users\3Jake\Desktop\VPN_Users.txt}}

Благодарю вас!

ФИНАЛЬНАЯ ВЕРСИЯ, полностью дополненная комментариями:

Как есть, он предназначен для работы в консоли, но его должно быть легко обновить, чтобы при необходимости выдать файл.

#  Define Variables
$ADgroup1 = "VPN Front Door"
$ADgroup2 = "VPN Full Access"
$ADgroup3 = "VPN Restricted Access"
$vpnGroups = $ADgroup2, $ADgroup3

#  Collect users in $ADgroup1
#  Also pass user properties forward
$UsersFound = (
  Get-ADGroupMember $ADgroup1 |
  Get-ADUser -Properties MemberOf, Name, SamAccountName, Company |

  #  Ignore disabled users & those in the "On HOLD" OU
  Where {
    $_.Enabled -ne $False -and
    $_.DistinguishedName -notlike '*HOLD OU*'
  } |

  #  Compare users in $ADgroup1 to the ones in $ADgroup2 and $ADgroup3
  select Name, SamAccountName, Company,
         @{n='Groups';e={$_.MemberOf | Get-ADGroup | select -Expand Name}} |
  Where { $groups = @($_.Groups); $vpnGroups | Where { $groups -contains $_ } }
  )

  #  Display count
Write-Host "Total = " $UsersFound.Count

  #  Prompt to show user info
$YN = Read-Host "Show Users? (Y/N)"
if ($YN -eq 'Y')
{
$UsersFound |
select Name, SamAccountName, Company | 
Sort-Object name, company | 
Out-GridView
}
else {exit}

person 3Jake    schedule 23.06.2015    source источник


Ответы (1)


Во-первых, вы должны распутать это запутанное утверждение if. Что-то вроде этого было бы гораздо более читабельным (и гораздо более удобным для обслуживания):

$vpnGroups = $ADgroup2, $ADgroup3

Get-ADGroupMember $ADgroup1 | ForEach-Object {
  Get-ADUser -Identity $_.SamAccountName -Properties MemberOf |
    select SamAccountName,
           @{n='Groups';e={$_.MemberOf | Get-ADGroup | select -Expand Name}} |
    ? { $groups = @($_.Groups); $vpnGroups | ? { $groups -contains $_ } } |
    select -Expand SamAccountName |
    Out-File -Append -Filepath 'C:\Users\3Jake\Desktop\VPN_Users.txt'
}

Вам даже не нужен цикл ForEach-Object, потому что Get-ADUser может читать прямо из конвейера:

$vpnGroups = $ADgroup2, $ADgroup3

Get-ADGroupMember $ADgroup1 |
  Get-ADUser -Properties MemberOf |
  select SamAccountName,
         @{n='Groups';e={$_.MemberOf | Get-ADGroup | select -Expand Name}} |
  ? { $groups = @($_.Groups); $vpnGroups | ? { $groups -contains $_ } } |
  select -Expand SamAccountName |
  Out-File -Filepath 'C:\Users\3Jake\Desktop\VPN_Users.txt'

При этом вы можете просто вставить дополнительные фильтры после Get-ADUser:

Get-ADGroupMember $ADgroup1 |
  Get-ADUser -Properties MemberOf |
  ? {
    $_.Enabled -ne $False -and
    $_.DistinguishedName -notlike '*HOLD OU*'
  } |
  select SamAccountName,
         @{n='Groups';e={$_.MemberOf | Get-ADGroup | select -Expand Name}} |
  ? { $groups = @($_.Groups); $vpnGroups | ? { $groups -contains $_ } } |
  select -Expand SamAccountName |
  Out-File -Filepath 'C:\Users\3Jake\Desktop\VPN_Users.txt'
person Ansgar Wiechers    schedule 23.06.2015
comment
Круто, спасибо @AnsgarWiechers - я за распутывание исходного кода! Это НАМНОГО более читабельно. - person 3Jake; 25.06.2015
comment
@ AnsgarWiechers Я обязательно это сделаю - прямо сейчас я получаю некоторые ошибки с этим и задаюсь вопросом, есть ли у меня где-то опечатка. Я постараюсь опубликовать код и ошибки в комментариях ниже: - person 3Jake; 25.06.2015
comment
хорошо, спасибо, теперь я обновил его в исходном вопросе - там он выглядит намного лучше! :) - person 3Jake; 25.06.2015
comment
@3Jake А, моя ошибка. Перед e= отсутствует ;. Смотрите обновленный ответ. - person Ansgar Wiechers; 25.06.2015
comment
Спасибо! Я добавил ; а еще пришлось убрать запятую из строчки выше - у меня в консоли ИСЕ работает, но в файл не выводит. Похоже, что в последних двух строках ему все равно; Я попытался переместить их в последний набор фигурных скобок, но пока без радости. Он выведет на экран, а затем создаст пустой .txt. Но, честно говоря, мне все равно, это намного дальше, чем я был раньше!! В любом случае, я мог бы получить его для подсчета результатов? Поместите все это в переменную ($Total), а затем используйте Write-Host $Total.count? - person 3Jake; 25.06.2015
comment
С чего вы взяли, что вам нужно убрать запятую? Верните его туда, где он был. Удаление его отключает трубопровод. Пустой ввод во вторую половину, конечно, производит пустой вывод. - person Ansgar Wiechers; 26.06.2015
comment
Да, у меня были проблемы, и я пытался понять это самостоятельно - безусловно, имеет смысл, что если я отключу конвейер, то, очевидно, я не получу никакого вывода после этой точки :) Спасибо, что указали на мою ошибку. Моя проблема в том, что когда я запускаю код из моего обновления выше, С запятой и точкой с запятой на месте, я не получаю никаких результатов. Ничего в окне консоли и пустой .txt. Не должно быть пользователей, которые одновременно отключены и находятся в подразделении удержания, поэтому я также попытался изменить -и на -или (и обратно), но без разницы. - person 3Jake; 26.06.2015
comment
@3Jake Замените все после первого select на Format-List (чтобы ваше утверждение заканчивалось на ... | selcect SamAccountName, @{n='Groups';e={...}} | Format-List *) и проверьте, действительно ли списки групп содержат одну из групп VPN. - person Ansgar Wiechers; 26.06.2015
comment
Еще раз спасибо @AnsgarWiechers - изменив строку на @{n='Groups';e={$_.MemberOf | Get-ADGroup | select -Expand Name}} | format-list *, в полученном списке пользователей будет указана одна или несколько групп VPN. Просто пытаясь обдумать это, я затем вернул эту строку и переместил список форматов вниз к следующей строке: ? { $vpnGroups | ? { @($_.Groups) -contains $_ } } | format-list *, после чего никаких результатов не было возвращено. Означает ли это, что сценарий считает, что в основной группе нет пользователей, которые также существуют в одной из дополнительных групп? - person 3Jake; 26.06.2015
comment
@3Jake Я идиот. Текущая переменная объекта во вложенном конвейере (внутри блока сценария Where-Object) — это не объект пользователя, а имя текущей группы VPN, которая, конечно же, не имеет свойства Groups, поэтому вы никогда не получите совпадения. *бьет себя* См. обновленный ответ. - person Ansgar Wiechers; 26.06.2015
comment
Ааа, спасибо за объяснение! Обновленный код идеален - на тестовом пользователе, если у меня есть только основная группа, он не отображается. Если у меня есть первичный и любой из вторичных, это так. Если я затем перемещаю его в Hold OU, он не работает, и если я перемещаю его обратно, но отключаю, он также не работает. Идеальный! Отметив это как ответ. - person 3Jake; 30.06.2015
comment
Вы уже многим помогли, но я хотел бы сообщить и другую информацию — есть ли способ показать имя и компанию? Я пытался добавить их в операторы get и select, чтобы передать их, но не уверен, как это сделать в select -Expand. Также работаю над подсчетом, заключая всю энчиладу в скобки и присваивая переменной ($ Result), а затем используя $ Result.count, который ДЕЙСТВИТЕЛЬНО работает, но на данный момент я получаю ТОЛЬКО подсчет, а не список пользователей :) Если у вас остались какие-либо советы для этого проекта, я был бы признателен, если нет, еще раз спасибо за все ваши замечательные советы! - person 3Jake; 30.06.2015
comment
@ 3Jake Скорее всего, есть способ, но вы должны задать его как новый вопрос. - person Ansgar Wiechers; 30.06.2015