通过嵌套的 AD 组查找用户和 AD 组关系 [英] Find user and AD group relation via nested AD groups

查看:95
本文介绍了通过嵌套的 AD 组查找用户和 AD 组关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上,在我们的环境中,我们有大量的安全组.嵌套在其他组等中的安全组.因此,找出为什么将设置应用于用户的原因是一个真正的 PITA,因为其中一个嵌套组可能是也可能不是

Basically, in our environment, we have a ton of security groups. Security groups that are nested within other groups etc. So it is a real PITA to find out why a setting is applying to a user, because of one of the nested groups they may or may not be a part of

例如如果您将用户添加到 X 组,他们会突然在 Citrix 中拥有一个已发布的应用程序.Citrix 针对安全组 Y 进行了配置.尝试查找 X 和 Y 之间的链接非常耗时,但可以自动化.

For e.g. If you add a user to group X, they suddenly have a published application in Citrix. Citrix is configured for security group Y. Attempting to find the link between X and Y is very time consuming but can be automated.

我想创建一个脚本,在其中输入用户和最终安全组(上面的 Y 组),脚本输出将用户连接到最终组的中间组.如果这有意义吗?

I want to create a script where, you enter a user and the end security group (group Y from above), and the script outputs the intermediary groups that connects the user to the final group. If this makes sense?

像这样:

function get-grouprelationship($username, $knownsecuritygroup)
{
    $getallgroups = get-adgroupmember $knownsecuritygroup | where-object {$_.ObjectClass -eq "Group" | select-object SamAccountName | foreach-object {get-adgroupmember $_.SamAccountName}
}

(上面的变量获取你的组,并循环遍历该组的所有成员,打印他们的成员)

(The above variable takes your group, and loops through all members of that group, printing their members)

$usergroups = (get-aduser -identity $username -Properties memberof | select-object memberof).memberof

(以上获取用户所在的所有组)

(The above gets all groups that a user is in)

$usergroups1 = $usergroups.split(",")
$usergroups2 = $usergroups1[0]
$usergroups3 = $usergroups2.substring(3)

(上面的文字格式很好)

(the above formats the text nicely)

if ($usergroups3 -contains $groupname){write-host "$username is directly in $groupname}

从这里开始,我陷入了困境,因为我基本上需要嵌套多个 for 循环,具体取决于每个组中有多少组.然后做一个条件检查

From here, I am quite stuck as I basically need to nest multiple for loops, depending on how many groups are in each group. Then do a condition check that

if ($groupname -eq $currentgroup){write-host "connected by $groupname and $currentgroup}

我也坚持使用 $getallgroups 变量,因为它只检查 1 个级别.然后它需要另一个 foreach 循环在里面,这将需要另一个循环等等.

I'm also stuck with the $getallgroups variable, because it only checks 1 level down. It would then need another foreach loop inside that, which would need another one inside that etc.

之前没有编码经验,我真的很难找到一种简单的方法来实现我的目标.

Having no prior coding experience, I am really struggling to get my head around an easy way to achieve my goal.

我在这里找到了这个脚本 - 脚本.下面基本上有效,除了它是冗长的方式:

I found this script here - script. Below basically works, except it is way to verbose:

import-module activedirectory
$username = read-host "What's their username?"
Function RecurseUsersInGroup {
    Param ([string]$object = "", [int]$level = 0)
    $indent = "-" * $level

    $x = Get-ADObject -Identity $object -Properties SamAccountName

    if ($x.ObjectClass -eq "group") {
        Write-Host "# $($x.SamAccountName)"

        $y = Get-ADGroup -Identity $object -Properties Members

        $y.Members | %{
            $o = Get-ADObject -Identity $_ -Properties SamAccountName

            if ($o.ObjectClass -eq "user" -and $o.SamAccountName -eq $username) {
                Write-Host "-> $($o.SamAccountName)"
            } elseif ($o.ObjectClass -eq "group") {
                RecurseUsersInGroup $o.DistinguishedName ($level + 1)
            }
        }
    } else {
        Write-Host "$($object) is not a group, it is a $($x.ObjectClass)"
    }
}
$thegroup = read-host "What's the Group?"
RecurseUsersInGroup (get-adgroup $thegroup).DistinguishedName

这工作正常,但似乎输出每个安全组,反对连接的组.不过,这无疑是朝着正确方向迈出的一步!如果我找到来源,我也会发布信用.

That works fine, but appears to output every security group, oppose to the connecting ones. Certainly a step in the right direction though! If I find the source I will post the credit as well.

推荐答案

以下版本不那么冗长(可能会写得更简洁,但我希望脚本至少是半可读的),但是它会搜索组并返回沿找到该组的分支的每个组的 Active Directory 组对象.

The following version is not less verbose (could probably be written a lot more terse, but I'm hoping the script is at least semi-readable), but it does a search for the group and returns the Active Directory group objects for each group along the branch in which the group was found.

function Get-GroupConnection
{
    [CmdletBinding()]
    PARAM (
        $Username,
        $GroupName
    )

    $User = Get-AdUser -Identity $Username -Properties MemberOf
    if (-Not ($User))
    {
        return;
    }

    $SearchedGroups = @()

    function Find-GroupBranches
    {
        [CmdletBinding()]
        PARAM (
            $GroupNameList,
            $SearchForGroupName
        )

        $ADGroups = $GroupNameList | Foreach { Get-ADGroup -Identity $_ -Properties MemberOf }

        foreach($group in $ADGroups)
        {
            Write-Verbose "Testing if either '$($Group.SamAccountName)' or '$($Group.DistinguishedName)' are equal to '$SearchForGroupName'"
            if ($Group.SamAccountName -eq $SearchForGroupName -OR $Group.DistinguishedName -eq $SearchForGroupName)
            {
                Write-Verbose "Found $($Group.DistinguishedName)"
                Write-Output $Group
                return
            }
        }

        Write-Verbose "No match in current collection, checking children"
        foreach ($currentGroup in $ADGroups)
        {
            if ($SearchedGroups -Contains $currentGroup.DistinguishedName)
            {
                Write-Verbose "Already checked children of '$($currentGroup.DistinguishedName)', ignoring it to avoid endless loops"
                continue
            }
            $SearchedGroups += $currentGroup.DistinguishedName

            if ($currentGroup.MemberOf)
            {
                Write-Verbose "Checking groups which $($currentGroup.DistinguishedName) is member of"

                $foundGroupInTree = Find-GroupBranches -GroupNameList $currentGroup.MemberOf -SearchForGroupName $SearchForGroupName
                if ($foundGroupInTree)
                {
                    Write-Output $currentGroup
                    Write-Output $foundGroupInTree
                    break
                }
            }
            else
            {
                Write-Verbose "$($currentGroup.DistinguishedName) is not member of any group, branch ignored"
            }
        }
    }

    Write-Verbose "Searching immediate group membership"
    Find-GroupBranches -GroupNameList $User.MemberOf -SearchForGroupName $GroupName
}

Get-GroupConnection -Username MyUser -GroupName SubSubGroup -Verbose

其搜索方式的描述如下.

A description of how it searches follows.

鉴于以下 Active Directory 结构:

Given the following Active Directory structure:

MyUser
    Domain Admins
        AnotherSubGroup
    Other Group
    DirectMemberGroup
        Domain Admins (same group as MyUser is direct member of, above)
            AnotherSubGroup (which is of course the same as above too)
        SubGroup
            SubSubGroup
    Some Other Group

如果我们搜索 MyUser 和SubSubGroup"之间的连接,脚本将首先搜索 MyUser 用户的直接成员身份,即域管理员"、其他组"、DirectMemberGroup"和其他组".这些都与我们搜索的SubSubGroup"不匹配,因此它开始检查child"组.

If we search for the connection between MyUser and 'SubSubGroup' the script would search first the direct membership of the MyUser user, i.e. 'Domain Admins', 'Other Group', 'DirectMemberGroup' and 'Some Other Group'. None of these match the 'SubSubGroup' we search for, so it starts checking 'child'groups.

域管理员"是AnotherSubGroup"的成员,但与SubSubGroup"不匹配.'AnotherSubGroup' 不是任何组的成员,因此该分支将被忽略.

'Domain Admins' is member of 'AnotherSubGroup', but that does not match 'SubSubGroup'. 'AnotherSubGroup' is not member of any group, so that branch is ignored.

'Other Group' 不是任何组的成员,因此该分支将被忽略.

'Other Group' is not member of any group, so that branch are ignored.

'DirectMemberGroup' 是其他组的成员,因此它遍历这些组.它已经为孩子检查了域管理员",因此跳过该组以避免陷入循环搜索.因此它检查子组".

'DirectMemberGroup' is member of other groups, so it iterates through those groups. It has already checked 'Domain Admins' for children, so that group is skipped to avoid getting stuck in a circular search. Therefore it check 'SubGroup'.

'SubGroup' 与 'SubSubGroup' 不匹配,因此它检查 'SubGroup' 所属的组.'SubGroup' 是 'SubSubGroup' 的成员,因此它会检查该组.

'SubGroup' does not match 'SubSubGroup' so it check the groups which 'SubGroup' is member of. 'SubGroup' is member of 'SubSubGroup', so it checks that group.

SubSubGroup"确实与SubSubGroup"匹配,因此将被选为匹配项.

'SubSubGroup' does match 'SubSubGroup' and will therefore be chosen as a match.

在上面的示例中,输出组对象将是指向SubSubGroup"组的分支,顺序如下:

In the above example, the output group object will be branches which lead to the 'SubSubGroup' group, in the following order:

DirectMemberGroup
SubGroup
SubSubGroup

观察该方法将返回它在用户和组之间找到的第一个连接.例如,如果Some Other Group"组也是SubSubGroup"的成员,这将不会改变输出,也不会改变上面提到的搜索过程.

Observe that this method will return the first connection it finds between the user and the group. If, for example, the 'Some Other Group' group would also be a member of 'SubSubGroup' this would not change the output, nor the search process, mentioned above.

这篇关于通过嵌套的 AD 组查找用户和 AD 组关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆