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

时间:2018-03-07 19:02:03

标签: powershell permissions acl

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

-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}

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

1 个答案:

答案 0 :(得分:1)

好的,让我们从顶部开始吧!很好,你实际上声明了一个参数。您可能需要考虑的是为参数设置默认值。我要做的是使用当前目录,它有一个自动变量$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:\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"
}