获取 ACL 文件夹和子文件夹 + 用户使用 Powershell



是否可以获取文件夹及其子文件夹的权限,然后显示与该组关联的路径、组和用户?所以,看起来像这样。或者它必须一次是一个文件夹。

-Folder1

-Line separator
-Group
-Line separator
-List of users

-Folder2

-Line separator
-Group
-Line separator
-List of users

到目前为止,我想出的脚本被警告我对powershell的经验很少。(别担心我的老板知道。

Param([string]$filePath)
$Version=$PSVersionTable.PSVersion
if ($Version.Major -lt 3) {Throw "Powershell version out of date. Please update powershell." }
Get-ChildItem $filePath -Recurse | Get-Acl | where { $_.Access | where { $_.IsInherited -eq $false } } | select -exp Access | select IdentityReference -Unique | Out-File .Groups.txt
$Rspaces=(Get-Content .Groups.txt) -replace 'JAC.*?\|','' |
Where-Object {$_ -notmatch 'BUILTIN|NT AUTHORITY|CREATOR|-----|Identity'} | ForEach-Object {$_.TrimEnd()}
$Rspaces | Out-File .Groups.txt
$ErrorActionPreference= 'SilentlyContinue'
$Groups=Get-Content .Groups.txt
ForEach ($Group in $Groups)
{Write-Host"";$Group;Write-Host --------------
;Get-ADGroupMember -Identity $Group -Recursive | Get-ADUser -Property DisplayName | Select Name}

这仅显示组和用户,而不显示路径。

好的,让我们从顶部开始!太好了,您实际上声明了一个参数。您可能需要考虑的是设置参数的默认值。我要做的是使用当前目录,它方便地有一个自动变量$PWD(我相信这是PowerShell工作目录的缩写)。

Param([string]$filePath = $PWD)

现在,如果提供了路径,它将使用该路径,但是如果没有提供路径,则仅使用当前文件夹作为默认值。

版本检查很好。我很确定有更优雅的方法可以做到这一点,但老实说,我从未做过任何版本检查。

现在,您正在为找到的每个组和用户查询 AD(经过一些筛选,授予)。我建议我们跟踪组和成员,这样我们只需要为每个组和成员查询一次 AD。它可能不会节省很多时间,但如果多次使用任何组,则会节省一些时间。因此,为此,我们将创建一个空的哈希表来跟踪组及其成员。

$ADGroups = @{}

现在开始了一个不好的趋势...写入文件,然后重新读回这些文件。可以输出到文件,或者保存配置,或者在当前 PowerShell 会话之外再次需要的东西,但写入文件只是为了将其读回当前会话只是浪费。相反,您应该将结果保存到变量中,或直接使用它们。因此,与其获取文件夹列表,将其直接管道到Get-Acl,然后丢失路径,我们将对文件夹进行ForEach循环。请注意,我添加了-Directory开关,因此它只会查看文件夹而忽略文件。这发生在提供程序级别,因此您将以这种方式获得更快的结果Get-ChildItem

ForEach($Folder in (Get-ChildItem $filePath -Recurse -Directory)){

现在,您想要输出文件夹的路径和一行。现在这很容易,因为我们没有放弃文件夹对象:

$Folder.FullName
'-'*$Folder.FullName.Length

接下来,我们获取当前文件夹的 ACL:

$ACLs = Get-Acl -Path $Folder.FullName

这就是事情变得复杂的地方。我从 ACL 中获取组名,但我合并了您的几个Where语句,并添加了一个检查以查看它是否是允许规则(因为在此中包含拒绝规则只会令人困惑)。我使用了?,它是Where的别名,%ForEach-Object的别名。你可以在管道后有一个自然的线刹车,所以我这样做是为了便于阅读。我在每一行都包含了我正在做的事情的评论,但如果其中有任何令人困惑的地方,请告诉我您需要澄清的内容。

$Groups = $ACLs.Access | #Expand the Access property
?{ $_.IsInherited -eq $false -and $_.AccessControlType -eq 'Allow' -and $_.IdentityReference -notmatch 'BUILTIN|NT AUTHORITY|CREATOR|-----|Identity'} | #Only instances that allow access, are not inherited, and aren't a local group or special case
%{$_.IdentityReference -replace 'JAC.*?\'} | #Expand the IdentityReference property, and replace anything that starts with JAC all the way to the first backslash (likely domain name trimming)
Select -Unique #Select only unique values

现在我们将遍历组,首先输出组名称和一行。

ForEach ($Group in $Groups){
$Group
'-'*$Group.Length

对于每个组,我将通过检查哈希表上的键列表来查看我们是否已经知道谁在其中。如果我们在那里找不到组,我们将查询 AD 并将组添加为键,并将成员添加为关联值。

If($ADGroups.Keys -notcontains $Group){
$Members = Get-ADGroupMember $Group -Recursive -ErrorAction Ignore | % Name
$ADGroups.Add($Group,$Members)
}

现在我们确定我们有了组成员,我们将显示它们。

$ADGroups[$Group]

我们可以关闭与组相关的ForEach循环,由于这是当前文件夹循环的结束,我们将在输出中添加一个空行,并关闭该循环

}
"`n"
}

所以我写了这个,然后对我的 C:\temp 文件夹运行它。它确实告诉我我需要清理该文件夹,但更重要的是,它向我展示了大多数文件夹没有任何非继承的权限,因此它只会给我带有下划线、空行的路径,然后移动到下一个文件夹,所以我有很多东西,比如:

C:TempFolderA
---------------
C:TempFolderB
---------------
C:TempFolderC
---------------

这对我来说似乎没有用。如果是给你的,那么使用上面的行,因为我有它们。就个人而言,我选择获取ACL,检查组,然后如果没有组移动到下一个文件夹。以下是它的产物。

Param([string]$filePath = $PWD)
$Version=$PSVersionTable.PSVersion
if ($Version.Major -lt 3) {Throw "Powershell version out of date. Please update powershell." }
#Create an empty hashtable to track groups
$ADGroups = @{}
#Get a recursive list of folders and loop through them
ForEach($Folder in (Get-ChildItem $filePath -Recurse -Directory)){
# Get ACLs for the folder
$ACLs = Get-Acl -Path $Folder.FullName
#Do a bunch of filtering to just get AD groups
$Groups = $ACLs | 
% Access | #Expand the Access property
where { $_.IsInherited -eq $false -and $_.AccessControlType -eq 'Allow' -and $_.IdentityReference -notmatch 'BUILTIN|NT AUTHORITY|CREATOR|-----|Identity'} | #Only instances that allow access, are not inherited, and aren't a local group or special case
%{$_.IdentityReference -replace 'JAC.*?\'} | #Expand the IdentityReference property, and replace anything that starts with JAC all the way to the first backslash (likely domain name trimming)
Select -Unique #Select only unique values
#If there are no groups to display for this folder move to the next folder
If($Groups.Count -eq 0){Continue}
#Display Folder Path
$Folder.FullName
#Put a dashed line under the folder path (using the length of the folder path for the length of the line, just to look nice)
'-'*$Folder.FullName.Length
#Loop through each group and display its name and users
ForEach ($Group in $Groups){
#Display the group name
$Group
#Add a line under the group name
'-'*$Group.Length
#Check if we already have this group, and if not get the group from AD
If($ADGroups.Keys -notcontains $Group){
$Members = Get-ADGroupMember $Group -Recursive -ErrorAction Ignore | % Name
$ADGroups.Add($Group,$Members)
}
#Display the group members
$ADGroups[$Group]
}
#output a blank line, for some seperation between folders
"`n"
}

我已经设法让它为我工作。

我编辑了以下部分以显示用户的名称和用户名。

$Members = Get-ADGroupMember $Group -Recursive -ErrorAction Ignore | % Name | Get-ADUser -Property DisplayName | Select-Object DisplayName,Name | Sort-Object DisplayName

这真的很有效,但是如果它在文件夹结构中重复,是否有办法让它停止列出相同的组访问权限?

例如,"\example1\example2"被分配了一个名为"group1"的组,我们有以下文件夹结构:

\example1example2folder1 
\example1example2folder2
\example1example2folder1randomfolder
\example1example2folder2anotherrandomfolder

所有文件夹都分配有组"group1",当前代码将列出每个目录的组和用户,即使它们是相同的。如果沿着目录结构重复,是否可以让它只列出一次组和用户?

-notcontains似乎对我不起作用

如果这有意义?

相关内容

最新更新