代码之家  ›  专栏  ›  技术社区  ›  ArcticWFox

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

  •  0
  • ArcticWFox  · 技术社区  · 6 年前

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

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

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

    2 回复  |  直到 6 年前
        1
  •  1
  •   TheMadTechnician    6 年前

    好吧,让我们从头开始!很好,您实际上声明了一个参数。您可能需要考虑的是为参数设置默认值。我要做的是使用当前目录,它方便地有一个自动变量 $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 语句,并且还添加了一个检查,以查看它是否是允许规则(因为在其中包含拒绝规则只会让人困惑)。我用过 ? 这是的别名 哪里 以及 % 这是的别名 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"
    }
    
        2
  •  0
  •   Paul Machin    3 年前

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

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

    $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 似乎对我不起作用

    这有意义吗?