Группы Active Directory используются для множества разных целей, будь то фильтрация групповой политики или назначение определенных привилегий пользователям. Достаточно гибкая структура позволяет разграничивать объекты пользователей и компьютеров наиболее удобным для нас образом.
Но в то же время это приводит к образованию иерархии групп, состоящей из нескольких уровней (что, в общем то, нормально), тем самым затрудняя определение, в какие же именно группы входит определенный пользователь.
Для поиска подобной информации мы можем использовать командлеты модуля ActiveDirectory.
Group
Для получения объекта группы мы используем командлет Get-ADGroup.
Get-ADGroup -Identity somegroup
Для получения непосредственно входящих в нее объектов, будь то пользователь, компьютер или группа — командлет Get-ADGroupMember.
Get-ADGroupMember -Identity somegroup
Для того, чтобы получить список как непосредственных участников группы, так и тех, кто является членом всех вложенных групп, мы можем воспользоваться параметром -Recursive.
Стоит сказать, что использование этого параметра изменяет вывод таким образом, что присутствовать в нем будут только объекты, не имеющие дочерних объектов. То есть информация о вложенных группах среди результатов вывода будет отсутствовать.
Например:
Get-ADGroupMember -Identity somegroup -Recursive
Кроме того, получить список участников группы мы можем, запросив значение атрибута Member:
Get-ADGroup somegroup -Properties Member | Select-Object -ExpandProperty Member
Стоит сказать, что командлет Get-ADGroup добавляет еще один атрибут — Members — равнозначный по содержанию атрибуту Member. Таким образом, если для выполнения запросов к Active Directory вы используете командлеты одноименного модуля, вы можете обращаться к любому из этих двух атрибутов.
Get-ADGroup somegroup -Properties Members | Select-Object -ExpandProperty Members
При использовании других способов, например ADSI, нам будет доступен только атрибут Member.
[ADSI]"LDAP://CN=somegroup,OU=groups,DC=domain,DC=com" | Select-Object -ExpandProperty Member
Также мы можем использовать вид запроса с использованием свойства AttributeScopeQuery объекта DirectorySearcher:
$adsisearcher = New-Object -TypeName System.DirectoryServices.DirectorySearcher $adsisearcher.SearchRoot = "LDAP://CN=somegroup,OU=groups,DC=domain,DC=com" $adsisearcher.Filter = "(objectCategory=person)" $adsisearcher.AttributeScopeQuery = 'Member' $adsisearcher.FindAll()
Начиная с Windows Server 2012 R2, мы можем получить список всех членов группы, как непосредственных, так и входящих во вложенные группы, обратившись к атрибуту типа constructed — msds-MemberTransitive.
Стоит упомянтуь, что использовать для этого командлет Get-ADGroup не получится. Вместо этого нам понадобится командлет Get-ADObject.
Get-ADObject -Identity "CN=somegroup,OU=groups,DC=domain,DC=com" -Properties msds-MemberTransitive | Select-Object -ExpandProperty msds-MemberTransitive
В этом случае результат запроса будет содержать все входящие в группы объекты — как пользователей и компьютеров, так и других групп.
При помощи ADSI мы можем запросить значение атрибута msds-MemberTransitive следующим образом:
$adsisearcher = New-Object -TypeName System.DirectoryServices.DirectorySearcher $adsisearcher.SearchRoot = "LDAP://CN=somegroup,OU=groups,DC=domain,DC=com" $adsisearcher.SearchScope = "Base" $adsisearcher.PropertiesToLoad.Add("msds-MemberTransitive") $result = $adsisearcher.FindAll() $result[0].Properties.'msds-MemberTransitive'
В данном случае нам пришлось явно указать нужную группу в качестве значения свойства SearchRoot, потому что получение значений большинства constructed-атрибутов (кроме таких, как createTimestamp, modifyTimestamp, structuralObjectClass и objectClasses) через ADSI возможно только при SearchScope в значении ‘Base’.
Еще одним способом получения списка всех членов группы, явных или неявных, является использование оператора -RecursiveMatch. Например, так:
Get-ADUser -Filter {MemberOf -RecursiveMatch "CN=somegroup,OU=groups,DC=domain,dc=com"} Get-ADComputer -Filter {MemberOf -RecursiveMatch "CN=somegroup,OU=groups,DC=domain,dc=com"} Get-ADObject -Filter {MemberOf -RecursiveMatch "CN=somegroup,OU=groups,DC=domain,dc=com"}
Если же нас интересует только, например, входит ли определенный пользователь в определенную группу, мы можем поступить следующим образом:
Get-ADUser -Filter {MemberOf -RecursiveMatch "CN=somegroup,OU=groups,DC=domain,dc=int"} -SearchBase "CN=someuser,CN=Users,DC=domain,DC=com"
При использовании LDAP, синтаксис немного изменится:
Get-ADUser -LDAPFilter '(MemberOf:1.2.840.113556.1.4.1941:=CN=somegroup,OU=groups,DC=domain,dc=com)' Get-ADUser -LDAPFilter '(MemberOf:1.2.840.113556.1.4.1941:=CN=somegroup,OU=groups,DC=domain,dc=com)' -SearchBase "CN=someuser,CN=Users,DC=domain,DC=com"
Где 1.2.840.113556.1.4.1941 — это Object ID правила LDAP_MATCHING_RULE_IN_CHAIN, что является LDAP-аналогом оператора -RecursiveMatch.
При использовании ADSI запросы будут выглядеть следующим образом:
$adsisearcher = New-Object -TypeName System.DirectoryServices.DirectorySearcher $adsisearcher.Filter = "(&(objectCategory=person)(MemberOf:1.2.840.113556.1.4.1941:=CN=TopLevelGroup,OU=groups,DC=domain,dc=int))" $adsisearcher.FindAll() $adsisearcher = New-Object -TypeName System.DirectoryServices.DirectorySearcher $adsisearcher.Filter = "(&(objectCategory=person)(MemberOf:1.2.840.113556.1.4.1941:=CN=TopLevelGroup,OU=groups,DC=domain,dc=int))" $adsisearcher.SearchRoot = "LDAP://CN=Ivanov Ivan,OU=allusers,DC=domain,DC=int" $adsisearcher.FindAll()
User
Перейдем теперь к объектам пользователей.
Чтобы получить список групп, в которые непосредственно входит пользователь, мы можем поступить следующим образом:
Get-ADPrincipalGroupMembership -Identity someuser
Если же нам понадобится узнать все группы, в которые он входит посредством вложенных групп, мы можем воспользоваться командлетом Get-ADAccountAuthorizationGroup:
Get-ADAccountAuthorizationGroup -Identity someuser
В данном случае среди результатов будут присутствовать не только созданные вами группы, в которые явно или неявно входит определенный пользователь, но и системные группы, такие, например, как Authenticated Users и This Organization.
По сути, командлет Get-ADAccountAuthorizationGroup выводит все группы, SID которых будет присутствовать в токене безопасности данного пользователя.
Если же нас интересуют только действительно существующие группы, то есть те, членством в которых мы можем управлять явным образом, мы можем отфильтровать результаты по существованию значения атрибута objectClass, поскольку у групп, не присутствующих в Active Directory в виде объектов, оно будет отсутствовать:
Get-ADAccountAuthorizationGroup -Identity someuser | Where-Object objectClass
Точно так же, как и в случае с группами, мы можем обратиться к атрибутам объекта пользователя, чтобы получить информацию о том, членом каких групп он является.
Для получения групп, в которые пользователь входит явным образом, мы можем запросить значение атрибута MemberOf.
Это backlink-атрибут, то есть он не присутствует в ActiveDirectory явно, а является отражением значений других атрибутов — в данном случае атрибута Member.
Get-ADUser -Identity someuser -Properties MemberOf | Select-Object -ExpandProperty MemberOf
На что тут стоит обратить внимание, так это на то, что среди вывода будет отсутствовать одна группа — та, что значится как Primary Group. Обычно это Domain Users для пользователей и Domain Computers для компьютеров.
Текущая primary group объекта определяется значением атрибута primaryGroupID, но об этом отдельно.
Также значение атрибута MemberOf мы можем получить следующими способами:
[ADSI]"LDAP://CN=someuser,CN=Users,DC=domain,DC=com" | Select-Object -ExpandProperty Memberof
или:
$adsisearcher = New-Object -TypeName System.DirectoryServices.DirectorySearcher $adsisearcher.SearchRoot = "LDAP://CN=someuser,CN=Users,DC=domain,DC=com" $adsisearcher.Filter = "(objectCategory=group)" $adsisearcher.AttributeScopeQuery = 'MemberOf' $adsisearcher.FindAll()
Как и в случае групп, для объектов пользователей и компьютеров, начиная с Windows Server 2012 R2, доступен атрибут типа constructed — msds-MemberOfTransitive.
Его значение содержит все группы, в которые явно или неявно входит объект — но опять же за исключением primary group.
Для получения значения атрибута msds-MemberOfTransitive нам снова понадобится командлет Get-ADObject:
Get-ADObject -Identity "CN=someuser,CN=Users,DC=domain,DC=com" -Properties msds-MemberOfTransitive | Select-Object -ExpandProperty msds-MemberOfTransitive
Еще одним способом будет использование объекта DirectorySearcher:
$adsisearcher = New-Object -TypeName System.DirectoryServices.DirectorySearcher $adsisearcher.SearchRoot = "LDAP://CN=someuser,CN=Users,DC=domain,DC=com" $adsisearcher.SearchScope = "Base" $adsisearcher.PropertiesToLoad.Add("msds-MemberOfTransitive") $result = $adsisearcher.FindAll() $result[0].Properties.'msds-memberoftransitive'
Страницы в социальных сетях:
Twitter: https://twitter.com/vsseth
Facebook: https://fb.com/inpowershell
VKontakte: https://vk.com/inpowershell