Link to home
Start Free TrialLog in
Avatar of Albert Widjaja
Albert WidjajaFlag for Australia

asked on

PowerShell script to list which specific folder a user does not have access to?

People,

I need some help in modifying the below PowerShell script so that it can be used to check which folder, the specified user account does not have access to.

Get-ServerShares -ServerName PRDFS01-VM -Type NTFS

<#
.SYNOPSIS
    get-servershares generates a report an individual or all servers in AD and its shares access permissions or a shares NTFS permissions of its local path
    using WMI instead of relying on WinRM access.
 
.DESCRIPTION
    Get-SharePerm will either query a singular server or all windows servers in Active Directory, and all local shares presented.  This does not include
    admin or remote shares (aka C$, D$ etc...) It will include SYSVOL shares.  if you are using a windows server as a print server, it will exclude all 
    shares that include -ptr- You are welcome to change this. A CSV will be created in C:\ called Shares_Share_Permissionscsv or Shares_NTFS_Permissions.
 
.PARAMETER UserName
    ServerName
        Defines the server that will queried.
        If blank, every windows server on the domain will be queried. 
    
    Type
        This defines the type of permissions being queried.  
        
        Share 
            will generate all access given at the share level
        NTFS 
            will give all NTFS permissions against the local path of a share. 
.EXAMPLE
    get-servershares -ComputerName Example-FP -Type Share
        This will generate a report in C:\ that contains all share level accesses for the particular server defined
        If you re-run as with a different server name, the report will compund on the exsisting document.  Makes reporting specific servers easier.
 
.EXAMPLE
    get-servershares -ComputerName Example-FP -Type NTFS
        This will generate a report in C:\ that contains all NTFS level accesses for the particular server defined
        If you re-run as with a different server name, the report will compund on the exsisting document.  Makes reporting specific servers easier.
 
.EXAMPLE
    get-servershares -Type Share
        This will generate a report in C:\ that contains all share level accesses for the particular for every windows server reachable on the domain
 
.EXAMPLE
    get-servershares -Type NTFS
        This will generate a report in C:\ that contains all NTFS level accesses for the particular for every windows server reachable on the domain
.NOTES
    Created by: David Dubuque
    Date: 27-Sep-2016
    Works with: Windows Server 2008R and 2012R
#>

function get-servershares
{
	Param (
		[string]$ServerName,
		[string]$Type
	)
	
	if ($ServerName -eq "")
	{
		write-host "Server not defined gathering server list"
		write-host ""
		$Servers = Get-ADComputer -Filter { operatingsystem -like "*server*" } | Select-Object Name | Sort-Object Name
		
		if ($Type -eq "NTFS")
		{
			$csvexport = "C:\Shares_$($Type)_Permissions.csv"
			
			
			foreach ($server in $Servers)
			{
				$serverName = $server.Name
				$shares = Get-WmiObject Win32_Share -ComputerName "$serverName" | Where-Object{ $_.Name -notlike "*$" -AND $_.Name -notlike "*-ptr-*" } | Select-Object PSComputerName, Name, Path
				
				
				foreach ($item in $shares)
				{
					$Path = $item.Path
					$RawPath = $item.Path
					$Server = $item.PSComputerName
					$ShareName = $item.Name
					$Path = $Path -replace ":", "$"
					$LocalPath = "\\$Server\$Path"
					
					
					$ACLS = Get-ACL "$LocalPath" | ForEach-Object { $_.Access }
					foreach ($ACL in $ACLS)
					{
						$hash = @{
							"Server"	    = $Server
							"ShareName"	    = $ShareName
							"LocalPath"	    = $RawPath
							"Permissions"   = $ACL.FileSystemRights
							"AccessControlType" = $ACL.AccessControlType
							"IdentityReference" = $ACL.IdentityReference
							"Inheritance"   = $ACL.IsInherited
							"InheritanceFlags" = $ACL.InheritanceFlags
							"PropagationFlags" = $ACL.PropagationFlags
						}
						$newRow = New-Object PsObject -Property $hash
						$InheritFlag = $newRow | Select-Object InheritanceFlags
						$PropFlag = $newRow | Select-Object PropagationFlags
						
						
						
						if ($PropFlag.PropagationFlags -like "none" -AND $InheritFlag.InheritanceFlags -eq "none")
						{
							$AppliesToValue = "folder only"
						}
						elseif ($PropFlag.PropagationFlags -eq "none" -AND $InheritFlag.InheritanceFlags -eq "ContainerInherit, ObjectInherit")
						{
							$AppliesToValue = "folder, sub-folders and files"
						}
						elseif ($PropFlag.PropagationFlags -eq "none" -AND $InheritFlag.InheritanceFlags -eq "ContainerInherit")
						{
							$AppliesToValue = "folder and sub-folders"
						}
						elseif ($PropFlag.PropagationFlags -eq "none" -AND $InheritFlag.InheritanceFlags -eq "ObjectInherit")
						{
							$AppliesToValue = "folder and files"
						}
						elseif ($PropFlag.PropagationFlags -eq "InheritOnly" -AND $InheritFlag.InheritanceFlags -eq "ContainerInherit, ObjectInherit")
						{
							$AppliesToValue = "sub-folders and files"
						}
						elseif ($PropFlag.PropagationFlags -eq "InheritOnly" -AND $InheritFlag.InheritanceFlags -eq "ContainerInherit")
						{
							$AppliesToValue = "sub-folders"
						}
						elseif ($PropFlag.PropagationFlags -eq "InheritOnly" -AND $InheritFlag.InheritanceFlags -eq "ObjectInherit")
						{
							$AppliesToValue = "files"
						}
						else
						{
							$AppliesToValue = "Cannot determine"
						}
						
						$newhash = @{ "AppliesTo" = $AppliesToValue }
						$newRow2 = New-Object PsObject -Property $newhash
						$output = [pscustomobject] @{
							Server   = $newRow.Server
							ShareName = $newRow.ShareName
							LocalPath = $newRow.LocalPath
							Permissions = $newRow.Permissions
							AccessControlType = $newRow.AccessControlType
							IdentityReference = $newRow.IdentityReference
							Inheritance = $newRow.Inheritance
							InheritanceFlags = $newRow.InheritanceFlags
							PropagationFlags = $newRow.PropagationFlags
							AppliesTo = $newRow2.AppliesTo
						}
						
						
						write-host " Server: $serverName | Share: $ShareName "
						Export-Csv $csvexport -inputobject $output -append -Force -NoTypeInformation
						
					}
				}
			}
		}
		Elseif ($Type -eq "Share")
		{
			foreach ($server in $Servers)
			{
				$serverName = $server.Name
				$csvexport = "C:\Shares_$($Type)_Permissions.csv"
				$shares = Get-WmiObject win32_LogicalShareSecuritySetting -ComputerName "$serverName" | Where-Object{ $_.Name -notlike "*$" -AND $_.Name -notlike "*-ptr-*" }
				foreach ($share in $shares)
				{
					$ACLs = $share.GetSecurityDescriptor().Descriptor.DACL
					foreach ($ACL in $ACLs)
					{
						$Name = $ACL.Trustee.Name
						$Perm = $null
						switch ($ACL.AccessMask)
						{
							268435456   { $Perm = "FullControl (Sub Only)" }
							2032127     { $Perm = "Full Control" }
							1245631     { $Perm = "Change" }
							1180095     { $Perm = "ReadAndExecute, Write" }
							1180063     { $Perm = "Read, Write" }
							1179817     { $Perm = "Read" }
							1179817     { $Perm = "ReadAndExecute" }
							1179785     { $Perm = "Read" }
							-1610612736 { $Perm = "ReadAndExecuteExtended" }
							default { $Perm = $ACL.AccessMask }
						}
						$ACL | Select-Object -Property @{ n = 'Server'; e = { $serverName } },
											 @{ n = 'Name'; e = { $Share.Name } },
											 @{ n = 'Principal'; e = { $Name } },
											 @{ n = 'Permission'; e = { $Perm } } |
						Export-Csv -Path $csvexport -NoTypeInformation -Append
						$ACL | Select-Object -Property @{ n = 'Server'; e = { $serverName } },
											 @{ n = 'Name'; e = { $Share.Name } },
											 @{ n = 'Principal'; e = { $Name } },
											 @{ n = 'Permission'; e = { $Perm } }
					}
				}
				
				
				Switch ($DACL.AccessMask)
				{
					2032127 { $AccessMask = "FullControl" }
					1179785 { $AccessMask = "Read" }
					1180063 { $AccessMask = "Read, Write" }
					1179817 { $AccessMask = "ReadAndExecute" }
					-1610612736 { $AccessMask = "ReadAndExecuteExtended" }
					1245631 { $AccessMask = "ReadAndExecute, Modify, Write" }
					1180095 { $AccessMask = "ReadAndExecute, Write" }
					268435456 { $AccessMask = "FullControl (Sub Only)" }
					default { $AccessMask = $DACL.AccessMask }
				}
				
				Switch ($DACL.AceType)
				{
					0 { $AceType = "Allow" }
					1 { $AceType = "Deny" }
					2 { $AceType = "Audit" }
				}
			}
			
		}
		Else
		{
			Write-Host "You did not define the type paramater. Please type Share or NTFS" -BackgroundColor Red -ForegroundColor White
			Write-Host""
			Write-Host "Use -Type Share or -Type NTFS. Also include -ServerName if you want to query a specific server" -BackgroundColor Red -ForegroundColor White
			Write-Host""
		}
	}
	else
	{
		$Servers = $ServerName
		if ($Type -eq "NTFS")
		{
			$csvexport = "C:\Shares_$($Type)_Permissions.csv"
			
			
			foreach ($server in $Servers)
			{
				$shares = Get-WmiObject Win32_Share -ComputerName "$serverName" | Where-Object{ $_.Name -notlike "*$" -AND $_.Name -notlike "*-ptr-*" } | Select-Object PSComputerName, Name, Path
				
				
				foreach ($item in $shares)
				{
					$Path = $item.Path
					$RawPath = $item.Path
					$Server = $item.PSComputerName
					$ShareName = $item.Name
					$Path = $Path -replace ":", "$"
					$LocalPath = "\\$Server\$Path"
					
					
					$ACLS = Get-ACL "$LocalPath" | ForEach-Object { $_.Access }
					foreach ($ACL in $ACLS)
					{
						$hash = @{
							"Server"	    = $Server
							"ShareName"	    = $ShareName
							"LocalPath"	    = $RawPath
							"Permissions"   = $ACL.FileSystemRights
							"AccessControlType" = $ACL.AccessControlType
							"IdentityReference" = $ACL.IdentityReference
							"Inheritance"   = $ACL.IsInherited
							"InheritanceFlags" = $ACL.InheritanceFlags
							"PropagationFlags" = $ACL.PropagationFlags
						}
						$newRow = New-Object PsObject -Property $hash
						$InheritFlag = $newRow | Select-Object InheritanceFlags
						
						$PropFlag = $newRow | Select-Object PropagationFlags
						
						
						
						if ($PropFlag.PropagationFlags -like "none" -AND $InheritFlag.InheritanceFlags -eq "none")
						{
							$AppliesToValue = "folder only"
						}
						elseif ($PropFlag.PropagationFlags -eq "none" -AND $InheritFlag.InheritanceFlags -eq "ContainerInherit, ObjectInherit")
						{
							$AppliesToValue = "folder, sub-folders and files"
						}
						elseif ($PropFlag.PropagationFlags -eq "none" -AND $InheritFlag.InheritanceFlags -eq "ContainerInherit")
						{
							$AppliesToValue = "folder and sub-folders"
						}
						elseif ($PropFlag.PropagationFlags -eq "none" -AND $InheritFlag.InheritanceFlags -eq "ObjectInherit")
						{
							$AppliesToValue = "folder and files"
						}
						elseif ($PropFlag.PropagationFlags -eq "InheritOnly" -AND $InheritFlag.InheritanceFlags -eq "ContainerInherit, ObjectInherit")
						{
							$AppliesToValue = "sub-folders and files"
						}
						elseif ($PropFlag.PropagationFlags -eq "InheritOnly" -AND $InheritFlag.InheritanceFlags -eq "ContainerInherit")
						{
							$AppliesToValue = "sub-folders"
						}
						elseif ($PropFlag.PropagationFlags -eq "InheritOnly" -AND $InheritFlag.InheritanceFlags -eq "ObjectInherit")
						{
							$AppliesToValue = "files"
						}
						else
						{
							$AppliesToValue = "Cannot determine"
						}
						
						$newhash = @{ "AppliesTo" = $AppliesToValue }
						$newRow2 = New-Object PsObject -Property $newhash
						$output = [pscustomobject] @{
							Server   = $newRow.Server
							ShareName = $newRow.ShareName
							LocalPath = $newRow.LocalPath
							Permissions = $newRow.Permissions
							AccessControlType = $newRow.AccessControlType
							IdentityReference = $newRow.IdentityReference
							Inheritance = $newRow.Inheritance
							InheritanceFlags = $newRow.InheritanceFlags
							PropagationFlags = $newRow.PropagationFlags
							AppliesTo = $newRow2.AppliesTo
						}
						
						
						write-host " Server: $serverName | Share: $ShareName "
						Export-Csv $csvexport -inputobject $output -append -Force -NoTypeInformation
						
					}
				}
			}
		}
		Elseif ($Type -eq "Share")
		{
			foreach ($server in $Servers)
			{
				if ($ServerName -eq "")
				{
					$serverName = $server.Name
					$serverName
				}
				else
				{
					$serverName = $server
					$serverName
				}
				$csvexport = "C:\Shares_$($Type)_Permissions.csv"
				$shares = Get-WmiObject win32_LogicalShareSecuritySetting -ComputerName "$serverName" | Where-Object{ $_.Name -notlike "*$" -AND $_.Name -notlike "*-ptr-*" }
				foreach ($share in $shares)
				{
					$ACLs = $share.GetSecurityDescriptor().Descriptor.DACL
					foreach ($ACL in $ACLs)
					{
						$Name = $ACL.Trustee.Name
						$Perm = $null
						switch ($ACL.AccessMask)
						{
							268435456   { $Perm = "FullControl (Sub Only)" }
							2032127     { $Perm = "Full Control" }
							1245631     { $Perm = "Change" }
							1180095     { $Perm = "ReadAndExecute, Write" }
							1180063     { $Perm = "Read, Write" }
							1179817     { $Perm = "Read" }
							1179817     { $Perm = "ReadAndExecute" }
							1179785     { $Perm = "Read" }
							-1610612736 { $Perm = "ReadAndExecuteExtended" }
							default { $Perm = $ACL.AccessMask }
						}
						$ACL | Select-Object -Property @{ n = 'Server'; e = { $serverName } },
													   @{ n = 'Name'; e = { $Share.Name } },
													   @{ n = 'Principal'; e = { $Name } },
													   @{ n = 'Permission'; e = { $Perm } } |
						Export-Csv -Path $csvexport -NoTypeInformation -Append
						$ACL | Select-Object -Property @{ n = 'Server'; e = { $serverName } },
													   @{ n = 'Name'; e = { $Share.Name } },
													   @{ n = 'Principal'; e = { $Name } },
													   @{ n = 'Permission'; e = { $Perm } }
					}
				}
				
				
				Switch ($DACL.AccessMask)
				{
					2032127 { $AccessMask = "FullControl" }
					1179785 { $AccessMask = "Read" }
					1180063 { $AccessMask = "Read, Write" }
					1179817 { $AccessMask = "ReadAndExecute" }
					-1610612736 { $AccessMask = "ReadAndExecuteExtended" }
					1245631 { $AccessMask = "ReadAndExecute, Modify, Write" }
					1180095 { $AccessMask = "ReadAndExecute, Write" }
					268435456 { $AccessMask = "FullControl (Sub Only)" }
					default { $AccessMask = $DACL.AccessMask }
				}
				
				Switch ($DACL.AceType)
				{
					0 { $AceType = "Allow" }
					1 { $AceType = "Deny" }
					2 { $AceType = "Audit" }
				}
			}
			
		}
		Else
		{
			Write-Host "You did not define the type paramater. Please type Share or NTFS" -BackgroundColor Red -ForegroundColor White
			Write-Host""
			Write-Host "Use -Type Share or -Type NTFS. Also include -ServerName if you want to query a specific server" -BackgroundColor Red -ForegroundColor White
			Write-Host""
		}
	}
}

Open in new window


The above script will be only dumping the list of Shared Folder only to .CSV

I wanted to get to know which user DOMAIN\John.Smith does not have access under the Shared Folder \\FileServer\HomeDrives$ then export it as .CSV

Any other solution outside of the PowerShell script will also be appreciated.

Thanks,
Avatar of Fibertron
Fibertron
Flag of United States of America image

Netwrix makes a tool to accomplish your needs:

https://www.netwrix.com/netwrix_effective_permissions_reporting_tool.html

AccessEnum also audits access but isn't quite as eloquent as the Netwrix tool:

https://docs.microsoft.com/en-us/sysinternals/downloads/accessenum

Hope that helps!
Avatar of David Favor
You asked, "PowerShell script to list which specific folder a user does not have access to?"

There is no way to do this.

If a specific user is denied access to a folder, they won't be able to list it's contents.

This is by design.

Maybe you're asking something else. Add a clarifying comment about what you're trying to accomplish.
ASKER CERTIFIED SOLUTION
Avatar of Qlemo
Qlemo
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Back to the original topic, checking if a user has access is more difficult than it sounds.
As stated above, the checking account needs to have enough privilieges to check permissions.
Then you need to check which groups the user is in - and as groups can be nested, this is a recursive/iterative task.
Only then you can check the ACLs for that particular user.
Avatar of Albert Widjaja

ASKER

Qlemo,

thanks for the update in this thread. yes, that does make sense.

@Fibertron, yes, but it requires some amount of fee to generate the report.
thanks guys !