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

Get ACL Folder & Subfolder + Users Using 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 Working Directory 的缩写)。

Param([string]$filePath = $PWD)

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

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

现在您正在为找到的每个组和用户查询 AD(经过一些过滤后,g运行ted)。我建议我们跟踪组和成员,这样我们只需为每个组和成员查询一次 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 文件夹。它确实告诉我我需要清理那个文件夹,但更重要的是它告诉我大多数文件夹没有任何 non-inherited 权限,所以它只会给我带下划线的路径,一个空白行,然后移动到下一个文件夹,所以我有很多东西,比如:

C:\Temp\FolderA
---------------

C:\Temp\FolderB
---------------

C:\Temp\FolderC
---------------

这对我来说似乎没有用。如果适合您,请使用上面的行,因为我有它们。我个人选择获取 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”的组,我们有以下文件夹结构:

\example1\example2\folder1 
\example1\example2\folder2
\example1\example2\folder1\randomfolder
\example1\example2\folder2\anotherrandomfolder

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

-notcontains 似乎对我不起作用

如果这有意义?