Get-FolderPermissions.ps1

<#PSScriptInfo
 
.VERSION 1.0
 
.GUID 1069276e-50b4-414a-ae8c-b8801445ae7e
 
.AUTHOR Juan Granados
 
.COPYRIGHT 2021 Juan Granados
 
.TAGS Folder Permission Report HTML CSV email mail
 
.LICENSEURI https://raw.githubusercontent.com/juangranados/powershell-scripts/main/LICENSE
 
.PROJECTURI https://github.com/juangranados/powershell-scripts/tree/main/Email%20Report%20of%20File%20Permissions%20on%20HTML%20and%20CSV
 
.RELEASENOTES
    Initial release
#>


<#
.SYNOPSIS
    Generate a folders permissions report.
.DESCRIPTION
    Starting with a root folder, it generates a folders permissions report. Number of subfolders examined depends on FolderDeep parameter.
    Report is generated in CSV format and can be send attached via mail with a html report in the body.
.PARAMETER OutFile
    Path to store CSV file.
    Default .\Permissions.csv
.PARAMETER RootPath
    Folder to start checking permissions.
.PARAMETER FolderDeep
    Number of subfolders levels to check.
    Default 99.
.PARAMETER ObjectsIgnored
    Users or groups to ignore in report.
    Default NT AUTHORITY\SYSTEM,BUILTIN\Administrator
.PARAMETER InspectGroups
    List only users in report.
    Default $False
.PARAMETER SMTPServer
    Sets smtp server in order to sent an email with backup result. If leave blank, no email will be send.
.PARAMETER SMTPRecipient
    List of emails addresses which will receive the backup result separated by commas.
.PARAMETER SMTPSender
    Email address which will send the backup result.
.PARAMETER SMTPUser
    Username in case of smtp server requires authentication.
.PARAMETER SMTPPassword
    Password in case of smtp server requires authentication.
.PARAMETER SMTPSSL
    Use of SSL in case of smtp server requires SSL.
    Default: $False
.PARAMETER SMTPPort
    Port to connect to smtp server.
    Default: 25
.EXAMPLE
    Get-FoldersPermissions -RootPath "D:\Data\Departments" -FolderDeep 2 -SMTPServer "mail.server.com" -SMTPRecipient "megaboss@server.com","support@server.com" -SMTPSender "reports@server.com"
.LINK
    https://github.com/juangranados/powershell-scripts/tree/main/Email%20Report%20of%20File%20Permissions%20on%20HTML%20and%20CSV
.NOTES
    Author: Juan Granados
#>

[cmdletbinding()]

param(
    [parameter(Position=0,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Path to store CSV file')][string]$OutFile = ".\$(Get-Date -format "yyyyMMdd_hhmmss")-Permissions.csv",
    [parameter(Position=1,Mandatory=$true,ValueFromPipeline=$false,HelpMessage='Folder to start checking permissions')][string]$RootPath,
    [parameter(Position=2,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Number of subfolders levels to check')][string]$FolderDeep = 99,
    [parameter(Position=3,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Users or groups to ignore in report')][string[]]$ObjectsIgnored = @("NT AUTHORITY\SYSTEM","BUILTIN\Administrator"),
    [parameter(Position=4,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Inspect users in groups ($True/$False)')][bool]$InspectGroups=$false,
    [parameter(Position=5,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Mail From')][string]$SMTPSender,
    [parameter(Position=6,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Mail To')]$SMTPRecipient,
    [parameter(Position=7,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Mail Server')][string]$SMTPServer,
    [parameter(Position=8,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Mail User')][string]$SMTPUser,
    [parameter(Position=9,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Mail Password')][string]$SMTPPassword,
    [parameter(Position=10,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Mail Port')][string]$SMTPPort=25,
    [parameter(Position=11,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Use SSL in mail sending ($True/$False)')][bool]$SMTPSSL=$False,
    [parameter(Position=12,Mandatory=$false,ValueFromPipeline=$false,HelpMessage='Mail Subject')][string]$SMTPSubject="Permission report on server $($env:computername) on directory $($RootPath) with $($FolderDeep) level deep"
)
Function Get-FolderPermissions($Folder,[int]$Deep = 0){
    # Write current folder name
    Write-Host "Examining folder $($Folder.FullName)"
    
    # Get folder ACLs
    $ACLs = get-acl $Folder.fullname | ForEach-Object {$_.Access}
    # Examining folder ACLs
    Foreach ($ACL in $ACLs){
        # If current ACL contains one of object ignored list, skip ACL
        if (-not ($ObjectsIgnored.Contains($ACL.IdentityReference.value.toString()))){
            # Delete commas in folder name and ACL InheritanceFlags, FileSystemRights
            $FolderName = $($Folder.Fullname -replace ',','.')
            $ACLInheritanceFlags = $($ACL.InheritanceFlags -replace ',',' &')
            $ACLFileSystemRights = $($ACL.FileSystemRights -replace ',',' &')
            # If inspect groups is true, list group users.
            if ($InspectGroups){
                # Check if ACL identity reference is a group
                if (-not ($ACL.IdentityReference.value -like "BUILTIN\*") -and ($ACL.IdentityReference.Value.LastIndexOf('\') -ne -1)){
                    # Get group users
                    $ADGroup = Get-ADGroup -LDAPFilter "(SAMAccountName=$($ACL.IdentityReference.Value.Substring($ACL.IdentityReference.Value.LastIndexOf('\')+1)))" -ErrorAction SilentlyContinue
                    # If group has users
                    if ($ADGroup){
                        # Get group users
                        $users = Get-ADGroupMember -identity $ADGroup -Recursive | Get-ADUser -Property DisplayName
                        # Store users ACL information
                        ForEach($User in $users){
                            # Store user info in csv file
                            $OutInfo = $FolderName + "," + $User.UserPrincipalName  + "," + $ACL.AccessControlType + "," + $ACLFileSystemRights + "," + $ACL.IsInherited + "," + $ACLInheritanceFlags + "," + $ACL.PropagationFlags
                            Add-Content -Value $OutInfo -Path $OutFile
                            # Store user info in table
                            $Rows+="<tr><td>" + $Folder.Fullname + "</td>" + "<td>" + $User.UserPrincipalName + "</td>" + "<td>" + $ACL.AccessControlType + "</td>" + "<td>" + $ACL.FileSystemRights + "</td>" + "<td>" + $ACL.IsInherited + "</td>" + "<td>" + $ACL.InheritanceFlags + "</td>" + "<td>" + $ACL.PropagationFlags + "</td></tr>`r"
                        }
                        # Next loop
                        continue
                    }
                }
            }
        # Inspect groups is false or ACL identity reference is a group but users could not be retrieved
        # Store object info in csv file
        $OutInfo = $FolderName + "," + $ACL.IdentityReference  + "," + $ACL.AccessControlType + "," + $ACLFileSystemRights + "," + $ACL.IsInherited + "," + $ACLInheritanceFlags + "," + $ACL.PropagationFlags
        Add-Content -Value $OutInfo -Path $OutFile
        # Store object info in table
        $Rows+="<tr><td>" + $Folder.Fullname + "</td>" + "<td>" + $ACL.IdentityReference + "</td>" + "<td>" + $ACL.AccessControlType + "</td>" + "<td>" + $ACL.FileSystemRights + "</td>" + "<td>" + $ACL.IsInherited + "</td>" + "<td>" + $ACL.InheritanceFlags + "</td>" + "<td>" + $ACL.PropagationFlags + "</td></tr>`r"

        }
    }
    # Get subfolders
    $Folders = Get-ChildItem $Folder.FullName -dir -ErrorAction SilentlyContinue
    # If there any folders and we want to inspect more folders
    If ($Folders -and $Deep){
        # Examining new folders
        ForEach ($F in $Folders){
            # Add results to table
            $Rows +=  $(Get-FolderPermissions $F $($Deep - 1) )
        }
    }
    # Return table
    return $Rows
}

# Variable initialization
# Set csv header
$Header = "Folder Path,Identity Reference,Access Control Type,File System Rights,Is Inherited,Inheritance Flags,Propagation Flags"
# Delete csv file
Del $OutFile -ErrorAction "SilentlyContinue"
# Add header to csv
Add-Content -Value $Header -Path $OutFile 
# Clear html table variable
if ([boolean](get-variable "Rows" -ErrorAction SilentlyContinue))
    {Clear-Variable -Name "Rows" -Scope Global}

#Generate table and csv
$Table = Get-FolderPermissions $(Get-Item $RootPath) $FolderDeep

#Create HTML body
$HTMLFile = @"
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
<style>TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
    TH{border-width: 2px;padding: 5px;border-style: solid;border-color: black;background-color:#99CCFF}
    TD{border-width: 2px;padding: 5px;border-style: solid;border-color: black;background-color:#E0F5FF}
</style>
</head>
<body>
<H1>$SMTPSubject</H1>
<table>
    <tr>
        <th>Folder Path</th>
        <th>Identity Reference</th>
        <th>Access Control Type</th>
         <th>File System Rights</th>
        <th>Is Inherited</th>
        <th>Inheritance Flags</th>
        <th>Propagation Flags</th>
    </tr>
        $Table
</table>
</body>
</html>
"@

#Send mail
If ($SMTPServer)
{
    # Set smpt password
    $SecureSMTPPassword = ConvertTo-SecureString $SMTPPassword -AsPlainText -Force
    $SMTPCredential = New-Object System.Management.Automation.PSCredential($SMTPUser,$SecureSMTPPassword)
    Write-Host "Sending Email"
    if ($SMTPSSL){
        Send-MailMessage -To $SMTPRecipient -From $SMTPSender -Attachments $OutFile -SmtpServer $SMTPServer -Subject $SMTPSubject -UseSsl -Port $SMTPPort -Credential $SMTPCredential -BodyAsHtml -Body $HTMLFile -Encoding ([System.Text.Encoding]::utf8)
    }
    else{
        Send-MailMessage -To $SMTPRecipient -From $SMTPSender -Attachments $OutFile -SmtpServer $SMTPServer -Subject $SMTPSubject -Port $SMTPPort -Credential $SMTPCredential -BodyAsHtml -Body $HTMLFile -Encoding ([System.Text.Encoding]::utf8)
    }
}