我正在尝试制作一个 PS 脚本,它将列出所有 Active Directory 用户组成员身份(递归)。
我已经有了工作脚本:
import-module activedirectory
$users = get-aduser -Filter {Name -Like "*"} -Searchbase "ou=Users, dc=Domain" | Where-Object { $_.Enabled -eq 'True' }
$targetFile = "D:\users.csv"
rm $targetFile
Add-Content $targetFile "User;Group"
foreach ($user in $users)
{
$groups = Get-ADPrincipalGroupMembership $user
foreach ($group in $groups)
{
$username = $user.samaccountname
$groupname = $group.name
$line = "$username;$groupname"
Add-Content $targetFile $line
}
}
但是脚本不会递归地列出组,即,如果输出文件中列出的组是另一个组的一部分。
示例:
组1:用户
组2:组3:用户
脚本仅显示 Group1 和 3,但不显示 2。
我应该在第一个以递归方式写入组成员身份的脚本中添加什么?
抱歉,我正在发布 3 年前问题的答案,但如果有人会看到它,它会有所帮助。
归功于:
如何使用Powershell或其他工具(递归)获取所有AD用户组?
您可以使用 LDAP_MATCHING_RULE_IN_CHAIN:
Get-ADGroup -LDAPFilter "(member:1.2.840.113556.1.4.1941:=CN=User,CN=USers,DC=x)"
您可以在任何可以使用 LDAP 过滤器的地方使用它。
示例:
$username = 'myUsername'
$dn = (Get-ADUser $username).DistinguishedName
Get-ADGroup -LDAPFilter ("(member:1.2.840.113556.1.4.1941:={0})" -f $dn) | select -expand Name | sort Name
修复您的脚本:
import-module activedirectory
$users = get-aduser -Filter {Name -Like "*"} -Searchbase "ou=Users, dc=Domain" | Where-Object { $_.Enabled -eq 'True' }
$targetFile = "D:\users.csv"
rm $targetFile
Add-Content $targetFile "User;Group"
foreach ($user in $users)
{
$dn = $user.DistinguishedName
$groups = Get-ADGroup -LDAPFilter ("(member:1.2.840.113556.1.4.1941:={0})" -f $dn) | select -expand Name | sort Name
foreach ($group in $groups)
{
$username = $user.samaccountname
$groupname = $group.name
$line = "$username;$groupname"
Add-Content $targetFile $line
}
}
如果将其设为函数,则可以递归调用它。看看这个,我想你会对结果感到满意:
Function Get-ADGroupsRecursive{
Param([String[]]$Groups)
Begin{
$Results = @()
}
Process{
ForEach($Group in $Groups){
$Results+=$Group
ForEach($Object in (Get-ADGroupMember $Group|?{$_.objectClass -eq "Group"})){
$Results += Get-ADGroupsRecursive $Object
}
}
}
End{
$Results | Select -Unique
}
}
将其放在脚本的顶部,然后为每个用户调用它。比如:
import-module activedirectory
$users = get-aduser -Filter {Name -Like "*"} -Searchbase "ou=Users, dc=Domain" -Properties MemberOf | Where-Object { $_.Enabled -eq 'True' }
$targetFile = "D:\users.csv"
rm $targetFile
Add-Content $targetFile "User;Group"
foreach ($user in $users)
{
$Groups = $User.MemberOf
$Groups += $Groups | %{Get-ADGroupsRecursive $_}
$Groups | %{New-Object PSObject -Property @{User=$User;Group=$_}}|Export-CSV $targetfile -notype -append
}
现在,根据您的广告结构的大小,这可能需要相当长的时间,但它会给您带来您想要的东西。
较新版本的 PowerShell(AD 模块)确实有 -Recursive 开关。因此您可以轻松使用Get-ADGroupMember。
示例:Get-ADGroupMember -Identity My_Group -Recursive
这很容易。只需使用Active Directory 的 ActiveRoles Management Shell。带有参数 Indirect 的 Cmdlet Get-QADMemberOf 就是您要寻找的。示例:
Get-QADMemberOf john.smith -Indirect
返回的 Quest 对象已在属性中包含所有递归组(和第一级用户)
$_.AllMembers
Add-PSSnapin Quest.ActiveRoles.ADManagement
$UsersFirstLevel = ($Members | Get-QADObject -Type Group -DontUseDefaultIncludedProperties | Get-QADGroupMember -DontUseDefaultIncludedProperties | ?{$_.type -eq 'user'})
$UsersSubGroup = ($Members | Get-QADObject -Type Group -DontUseDefaultIncludedProperties | Get-QADGroupMember -DontUseDefaultIncludedProperties | ?{$_.type -eq 'group'}).Allmembers | Get-QADObject -DontUseDefaultIncludedProperties | ?{$_.type -eq 'user'}
$RecursiveUsers = $UsersFirstLevel
$RecursiveUsers += $UsersSubGroup
$RecursiveUsers = $RecursiveUsers | Sort-Object -Unique
我有一些对我有用的东西要补充。不太漂亮,但完成了工作,输入组的 txt 文件进行检查。如果有很多组,可以以更有用的方式导出。
$groups = Get-Content -Path 'C:\Export\groups.txt'
function CheckAccount($accountinquestion) {
if($accountinquestion.objectClass -like 'group'){
$members = get-adgroupmember $member.name | select name, objectClass
foreach($member in $members){
if($member.objectClass -like 'group'){
CheckAccount($member.name)
}
else{write-host $member.name $member.objectClass}
}
}
}
foreach($group in $groups){
$members = get-adgroupmember $group | select name, objectClass
write-host "--------------------"
write-host $group
write-host "--------------------"
foreach($member in $members){
if($member.objectClass -like 'group'){
CheckAccount($member.name)
}
else{write-host $member.name $member.objectClass}
}
}