Reporting on Windows File Server Shares and NTFS Permissions with PowerShell

I recently had a requirement to audit the Share and NTFS permissions of a Windows File Server. PowerShell contains the Get-ACL cmdlet which makes retreving the NTFS permissions fairly straightforward, but for the Share permissions it is not so easy, but we can make use of WMI and the Win32_LogicalShareSecuritySetting class.

The below forum post details some discussion around using this class to find the Share permissions and unsurprisingly the legendary Shay Levy provides the solution.

http://groups.google.com/group/powershell-users/browse_thread/thread/43f06ce172e68c38?pli=1

The following script makes use of this code and adds some parameters depending on your requirements.


<# .SYNOPSIS Retrieve report of share permissions

.DESCRIPTION Retrieve report of share permissions

.PARAMETER  ComputerName Computer name to retrieve share permissions from

.PARAMETER  Share Name of the share to retrieve permissions from (optional)

.PARAMETER  OutputFile Name of the file to output the report to (optional)

.EXAMPLE PS C:\\> Get-SharePermissions.ps1 -ComputerName Server01 -Share Share01 -OutputFile C:\\Scripts\\SharePermissions.csv

.EXAMPLE PS C:\\> Get-SharePermissions.ps1 -ComputerName Server01

.NOTES Author: Jonathan Medd Date: 06/12/2011 Version: 0.1

#>

\[CmdletBinding()\] param(

\[Parameter(Position=0)\] \[System.String\] $ComputerName = '.',

\[Parameter(Position=1)\] \[System.String\] $Share,

\[Parameter(Position=2)\] \[System.String\] $OutputFile )

function Translate-AccessMask($val){ Switch ($val) { 2032127 {"FullControl"; break} 1179785 {"Read"; break} 1180063 {"Read, Write"; break} 1179817 {"ReadAndExecute"; break} -1610612736 {"ReadAndExecuteExtended"; break} 1245631 {"ReadAndExecute, Modify, Write"; break} 1180095 {"ReadAndExecute, Write"; break} 268435456 {"FullControl (Sub Only)"; break} default {$AccessMask = $val; break} } }

function Translate-AceType($val){ Switch ($val) { 0 {"Allow"; break} 1 {"Deny"; break} 2 {"Audit"; break} } }

\# Create calculated properties $ShareProperty = @{n="Share";e={$ShareName}} $AccessMask = @{n="AccessMask";e={Translate-AccessMask $\_.AccessMask}} $AceType = @{n="AceType";e={Translate-AceType $\_.AceType}} $Trustee = @{n="Trustee";e={$\_.Trustee.Name}}

if ($Share){

$filter="name='$Share'"

$WMIQuery = Get-WmiObject -Class Win32\_LogicalShareSecuritySetting -ComputerName $ComputerName -filter $filter | ForEach-Object { $ShareName = $\_.name $\_.GetSecurityDescriptor().Descriptor.DACL | Select-Object $Shareproperty,$AccessMask,$AceType,$Trustee} }

else { $WMIQuery = Get-WmiObject -Class Win32\_LogicalShareSecuritySetting -ComputerName $ComputerName | ForEach-Object { $ShareName = $\_.name $\_.GetSecurityDescriptor().Descriptor.DACL | Select-Object $Share,$AccessMask,$AceType,$Trustee } }

if ($OutputFile){ $WMIQuery | Export-Csv $OutputFile -NoTypeInformation }

else { $WMIQuery | Format-Table -AutoSize }

 

For NTFS permissions Jeff Hicks has a very useful post for creating NTFS ACL reports.

http://jdhitsolutions.com/blog/2011/06/creating-acl-reports/

The following is a script based off some of the ideas in that post which you can use for generating a report depending on your requirements.


<# .SYNOPSIS Retrieve report of NTFS permissions

.DESCRIPTION Retrieve report of NTFS permissions

.PARAMETER  ComputerName Computer name to retrieve NTFS permissions from

.PARAMETER  Folder Name of the NTFS path to retrieve permissions from

.PARAMETER  Recurse Retrieve permissions from subfolders and files

.PARAMETER  OutputFile Name of the file to output the report to (optional)

.EXAMPLE PS C:\\> Get-NTFSPermissions.ps1 -ComputerName Server01 -Folder D$\\Home -OutputFile C:\\Scripts\\NTFSPermissions.csv

.EXAMPLE PS C:\\> Get-NTFSPermissions.ps1 -Folder D:\\Home -Recurse

.NOTES Author: Jonathan Medd Date: 07/12/2011 Version: 0.1

#>

\[CmdletBinding()\] param(

\[Parameter(Position=0)\] \[System.String\] $ComputerName = '.',

\[Parameter(Position=1,Mandatory=$true,HelpMessage="Name of the NTFS path to retrieve permissions from")\] \[System.String\] $Folder,

\[Parameter(Position=2)\] \[Switch\] $Recurse,

\[Parameter(Position=3)\] \[System.String\] $OutputFile )

\# Set the Path variable dependent on whether its for a remote machine if ($ComputerName -eq '.'){ $Path = $Folder }

else { $Path = "\\\\$ComputerName\\$Folder" }

if ($OutputFile){ Get-Childitem $Path -Recurse:$Recurse | ForEach-Object {Get-Acl $\_.FullName} | Select-Object @{Name="Path";Expression={$\_.PSPath.Substring($\_.PSPath.IndexOf(":")+2) }},@{Name="Type";Expression={$\_.GetType()}},Owner -ExpandProperty Access | Export-CSV $OutputFile -NoTypeInformation }

else { Get-Childitem $Path -Recurse:$Recurse | ForEach-Object {Get-Acl $\_.FullName} | Select-Object @{Name="Path";Expression={$\_.PSPath.Substring($\_.PSPath.IndexOf(":")+2) }},@{Name="Type";Expression={$\_.GetType()}},Owner -ExpandProperty Access | Format-Table -AutoSize } ```