Powershell – Get Permissions on folders and/or files

Sometimes it is useful to get permissions (NTFS and/or Share) on Windows systems (Server and/or Client).

The following Powershell code will generate, in the same folder in which is saved the ps1 file (once the below code is copied and saved on the system as ps1 file), a CSV file which will include all the permissions (subfolders included) set in that moment. Obviously this code can be expanded to request interactively which is the root folder from which this analysis will begin or even transform this into a function, but here we are just including the approach.

$OutFile = "$PSScriptRoot\Permissions.csv" 
$Header = "Folder Path,IdentityReference,FileSystem Rights,AccessControlType,IsInherited,InheritanceFlags,PropagationFlags"
$FileExist = Test-Path $OutFile 
If ($FileExist -eq $True) {Del $OutFile} 
Add-Content -Value $Header -Path $OutFile 
$RootPath = "C:\Users\MyProfile"
$Folders = dir $RootPath -recurse | where {$_.psiscontainer -eq $true}
    Foreach ($Folder in $Folders) {
    $ACLs = get-acl $Folder.fullname | ForEach-Object { $_.Access }
    Foreach ($ACL in $ACLs){
    $OutInfo = $Folder.Fullname + ";" + $ACL.IdentityReference + ";" + $ACL.FileSystemRights + ";" + $ACL.AccessControlType + ";" + $ACL.IsInherited + ";" + $ACL.InheritanceFlags + ";" + $ACL.PropagationFlags
    Add-Content -Value $OutInfo -Path $OutFile 
}} 

The following code instead is already a function in Powershell that is dedicated to shares in Windows environment.

There are three specified function: the first and main one is called Get-Perms, and it takes three not mandatory parameters, which meaning is included into the below code, then the GetSharedFolderNTFSPermission function, that will extract the NFTS permissions of all the Shares on the specified, or not, computer, and finally the GetSharedFolderPermission function, that will extract only the Sharing permissions (excluding the NTFS).

At the end, the code will extract the permissions into a Permissions.xlsx file.

function Get-Perms {

#requires -Version 2.0

< #
     .SYNOPSIS
        This script can be list all of shared folder permission or ntfs permission.
		
    .DESCRIPTION
        This script can be list all of shared folder permission or ntfs permission.
		
	.PARAMETER  <SharedFolderNTFSPermission>
		Lists all of ntfs permission of SharedFolder.
		
	.PARAMETER	<computername 
		Specifies the computers on which the command runs. The default is the local computer. 
		
	.PARAMETER  <credential>
		Specifies a user account that has permission to perform this action. 
		
    .EXAMPLE
        C:\PS> Get-Perms -NTFSPermission
		
		This example lists all of ntfs permission of SharedFolder on the local computer.
		
    .EXAMPLE
		C:\PS> $cre = Get-Credential
        C:\PS> Get-Perms -ComputerName "APP" -Credential $cre
		
		This example lists all of share permission of SharedFolder on the APP remote computer.
		
	.EXAMPLE
        C:\PS> Get-Perms -NTFSPermission -ComputerName "APP" | Export-Csv -Path "D:\Permission.csv" -NoTypeInformation
		
		This example will export report to csv file. If you attach the <notypeinformation> parameter with command, it will omits the type information 
		from the CSV file. By default, the first line of the CSV file contains "#TYPE " followed by the fully-qualified name of the object type.
#>

Param
(
	[Parameter(Mandatory=$false)]
	[Alias('Computer')][String[]]$ComputerName=$Env:COMPUTERNAME,

	[Parameter(Mandatory=$false)]
	[Alias('NTFS')][Switch]$NTFSPermission,
	
	[Parameter(Mandatory=$false)]
	[Alias('Cred')][System.Management.Automation.PsCredential]$Credential
)

$RecordErrorAction = $ErrorActionPreference
#change the error action temporarily
$ErrorActionPreference = "SilentlyContinue"

Function GetSharedFolderPermission($ComputerName)
{
	#test server connectivity
	$PingResult = Test-Connection -ComputerName $ComputerName -Count 1 -Quiet
	if($PingResult)
	{
		#check the credential whether trigger
		if($Credential)
		{
			$SharedFolderSecs = Get-WmiObject -Class Win32_LogicalShareSecuritySetting `
			-ComputerName $ComputerName -Credential $Credential -ErrorAction SilentlyContinue
		}
		else
		{
			$SharedFolderSecs = Get-WmiObject -Class Win32_LogicalShareSecuritySetting `
			-ComputerName $ComputerName -ErrorAction SilentlyContinue
		}
		
		foreach ($SharedFolderSec in $SharedFolderSecs) 
		{ 
		    $Objs = @() #define the empty array
			
	        $SecDescriptor = $SharedFolderSec.GetSecurityDescriptor()
	        foreach($DACL in $SecDescriptor.Descriptor.DACL)
			{  
				$DACLDomain = $DACL.Trustee.Domain
				$DACLName = $DACL.Trustee.Name
				if($DACLDomain -ne $null)
				{
	           		$UserName = "$DACLDomain\$DACLName"
				}
				else
				{
					$UserName = "$DACLName"
				}
				
				#customize the property
				$Properties = @{'ComputerName' = $ComputerName
								'ConnectionStatus' = "Success"
								'SharedFolderName' = $SharedFolderSec.Name
								'SecurityPrincipal' = $UserName
								'FileSystemRights' = [Security.AccessControl.FileSystemRights]`
								$($DACL.AccessMask -as [Security.AccessControl.FileSystemRights])
								'AccessControlType' = [Security.AccessControl.AceType]$DACL.AceType}
				$SharedACLs = New-Object -TypeName PSObject -Property $Properties
				$Objs += $SharedACLs

	        }
			$Objs|Select-Object ComputerName,ConnectionStatus,SharedFolderName,SecurityPrincipal, `
			FileSystemRights,AccessControlType
	    }  
	}
	else
	{
		$Properties = @{'ComputerName' = $ComputerName
						'ConnectionStatus' = "Fail"
						'SharedFolderName' = "Not Available"
						'SecurityPrincipal' = "Not Available"
						'FileSystemRights' = "Not Available"
						'AccessControlType' = "Not Available"}
		$SharedACLs = New-Object -TypeName PSObject -Property $Properties
		$Objs += $SharedACLs
		$Objs|Select-Object ComputerName,ConnectionStatus,SharedFolderName,SecurityPrincipal, `
		FileSystemRights,AccessControlType
	}
}

Function GetSharedFolderNTFSPermission($ComputerName)
{
	#test server connectivity
	$PingResult = Test-Connection -ComputerName $ComputerName -Count 1 -Quiet
	if($PingResult)
	{
		#check the credential whether trigger
		if($Credential)
		{
			$SharedFolders = Get-WmiObject -Class Win32_Share `
			-ComputerName $ComputerName -Credential $Credential -ErrorAction SilentlyContinue
		}
		else
		{
			$SharedFolders = Get-WmiObject -Class Win32_Share `
			-ComputerName $ComputerName -ErrorAction SilentlyContinue
		}

		foreach($SharedFolder in $SharedFolders)
		{
			$Objs = @()
			
			$SharedFolderPath = [regex]::Escape($SharedFolder.Path)
			if($Credential)
			{	
				$SharedNTFSSecs = Get-WmiObject -Class Win32_LogicalFileSecuritySetting `
				-Filter "Path='$SharedFolderPath'" -ComputerName $ComputerName  -Credential $Credential
			}
			else
			{
				$SharedNTFSSecs = Get-WmiObject -Class Win32_LogicalFileSecuritySetting `
				-Filter "Path='$SharedFolderPath'" -ComputerName $ComputerName
			}
			
			$SecDescriptor = $SharedNTFSSecs.GetSecurityDescriptor()
			foreach($DACL in $SecDescriptor.Descriptor.DACL)
			{  
				$DACLDomain = $DACL.Trustee.Domain
				$DACLName = $DACL.Trustee.Name
				if($DACLDomain -ne $null)
				{
	           		$UserName = "$DACLDomain\$DACLName"
				}
				else
				{
					$UserName = "$DACLName"
				}
				
				#customize the property
				$Properties = @{'ComputerName' = $ComputerName
								'ConnectionStatus' = "Success"
								'SharedFolderName' = $SharedFolder.Name
								'SecurityPrincipal' = $UserName
								'FileSystemRights' = [Security.AccessControl.FileSystemRights]`
								$($DACL.AccessMask -as [Security.AccessControl.FileSystemRights])
								'AccessControlType' = [Security.AccessControl.AceType]$DACL.AceType
								'AccessControlFalgs' = [Security.AccessControl.AceFlags]$DACL.AceFlags}
								
				$SharedNTFSACL = New-Object -TypeName PSObject -Property $Properties
	            $Objs += $SharedNTFSACL
	        }
			$Objs |Select-Object ComputerName,ConnectionStatus,SharedFolderName,SecurityPrincipal,FileSystemRights, `
			AccessControlType,AccessControlFalgs -Unique
		}
	}
	else
	{
		$Properties = @{'ComputerName' = $ComputerName
						'ConnectionStatus' = "Fail"
						'SharedFolderName' = "Not Available"
						'SecurityPrincipal' = "Not Available"
						'FileSystemRights' = "Not Available"
						'AccessControlType' = "Not Available"
						'AccessControlFalgs' = "Not Available"}
					
		$SharedNTFSACL = New-Object -TypeName PSObject -Property $Properties
	    $Objs += $SharedNTFSACL
		$Objs |Select-Object ComputerName,ConnectionStatus,SharedFolderName,SecurityPrincipal,FileSystemRights, `
		AccessControlType,AccessControlFalgs -Unique
	}
} 

foreach($CN in $ComputerName)
{
	
	if($NTFSPermission)
	{
		GetSharedFolderNTFSPermission -ComputerName $CN
	}
	else
	{
		GetSharedFolderPermission -ComputerName $CN
	}
}
#restore the error action
$ErrorActionPreference = $RecordErrorAction

}

$cre = Get-Credential “domain\user”
Get-Perms -ComputerName "FILE-SERVER" -Credential $cre | Export-Excel Permissions.xlsx