Ever wanted to know what shares are on all your Servers
I have been scripting using VBScript for some time now, and only on occasion have I had the motivation and\or reason to write a script using Powershell, but I have decided in the last 9 months to make a concerted effort to utilise the Power of Powershell as my main scripting technology. In this time period I have produced a number of scripts and I will be adding them to my blog in case anybody finds them useful.
So my first offering is something I wrote for a colleague of mine, that queries all the Windows Servers in your domain and gathers their Shares, the permissions set on the shares and the permissions set on the NTFS file system at the share level (not lower). All this is output to 2 CSV files in the same folder that the script is run from. There are no Parameters for the script, and I hadn't written it to specifically search in specific OU structures or to read from text file based list of computers. I have since written another script that I will be posting here, that has this functionality, so if you need it that functionality it can be done.
The script requires that you have the necessary Rights on all the Servers you will be querying to get back all the information.
Below is a listing of the script, but I have attached the code in a text file as well (obviously remove the txt extension to use)..
<#
#####################################################################
SCRIPT GetPermissions.ps1
SYNOPSIS
Gets all Servers from the domain from which the script is run in
(i.e. the domain you are logged in to).
Then uses the server list to query each servers Share permissions
and the NTFS permissions of each share root folder.
The Script creates 2 files in the same location the script is
run from (sharereport.csv and ntfsreport.csv).
NOTE
Script requires no parameters or arguments
I recommend you have the relevant permissions in the domain and
on the servers being queried for optimal results.
Myself or my employer do not warrantee this script in any way and
use of it is entirely at the users own risk.
The working functions of this script are taken from examples found
at Microsoft Script Center web site and are written by Boe Prox.
AUTHOR
Carl Harrison
The script utilises 2 functions written by Boe Prox and publically
available at Microsoft Script Center. They have been altered slightly
to work with this script.
VERSION: 1.0 - First cut
1.1 - Sorted FQDN Ping instead of netbios ping
#####################################################################
#>
function Get-SharePermissions{
<#
.SYNOPSIS
Retrieves share permissions. This function was extracted from a
Powershell Module written by Boe Prox named FileSharePermissions.psm1
.DESCRIPTION
Retrieves share permissions.
.PARAMETER computer
Name of server to test.
.EXAMPLE
Get-SharePermissions -computer Test
#>
[cmdletbinding(
DefaultParameterSetName = 'computer',
ConfirmImpact = 'low'
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'computer',
ValueFromPipeline = $True)]
[array]$computer
)
Begin
{
#Process Share report
$sharereport = @()
}
Process
{
#Iterate through comptuers
ForEach ($c in $computer)
{
Try
{
#Write-Verbose "Computer: $($c)"
#Retrieve share information from comptuer
$ShareSec = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -ComputerName $c -ea stop
ForEach ($Shares in $sharesec)
{
#Write-Verbose "Share: $($Shares.name)"
#Try to get the security descriptor
$SecurityDescriptor = $ShareS.GetSecurityDescriptor()
#Iterate through each descriptor
ForEach ($DACL in $SecurityDescriptor.Descriptor.DACL)
{
$arrshare = New-Object PSObject
$arrshare | Add-Member NoteProperty Computer $c
$arrshare | Add-Member NoteProperty Name $Shares.Name
$arrshare | Add-Member NoteProperty ID $DACL.Trustee.Name
#Convert the current output into something more readable
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}
}
$arrshare | Add-Member NoteProperty AccessMask $AccessMask
#Convert the current output into something more readable
Switch ($DACL.AceType)
{
0 {$AceType = "Allow"}
1 {$AceType = "Deny"}
2 {$AceType = "Audit"}
}
$arrshare | Add-Member NoteProperty AceType $AceType
#Add to existing array
$sharereport += $arrshare
}
}
}
#Catch any errors
Catch
{
$arrshare = New-Object PSObject
$arrshare | Add-Member NoteProperty Computer $c
$arrshare | Add-Member NoteProperty Name "NA"
$arrshare | Add-Member NoteProperty ID "NA"
$arrshare | Add-Member NoteProperty AccessMask "NA"
#Add to existing array
$sharereport += $arrshare
}
Finally
{
#Do Nothing Currently
}
}
}
End {
#Display report
#$ShareReport
#$ShareReport | Export-Csv -notypeinformation "sharereport.csv"
return $sharereport
}
}
function Get-ShareNTFSPermissions{
<#
.SYNOPSIS
Retrieves NTFS permissions on a share. This function was extracted from a
Powershell Module written by Boe Prox named FileSharePermissions.psm1
.DESCRIPTION
Retrieves NTFS permissions on a share.
.PARAMETER computer
Name of server to test.
.EXAMPLE
Get-ShareNTFSPermissions -computer Test
#>
[cmdletbinding(
DefaultParameterSetName = 'computer',
ConfirmImpact = 'low'
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'computer',
ValueFromPipeline = $True)]
[array]$computer
)
Begin
{
#Process NTFS Share report
$ntfsreport = @()
}
Process
{
#Iterate through each computer
ForEach ($c in $computer)
{
Try
{
Write-Verbose "Computer: $($c)"
#Gather share information
$shares = Gwmi -comp $c Win32_Share -ea stop | ? {$_.Name -ne 'ADMIN$'-AND $_.Name -ne 'C$' -AND $_.Name -ne 'IPC$'} | Select Name,Path
ForEach ($share in $shares)
{
#Iterate through shares
Write-Verbose "Share: $($share.name)"
If ($share.path -ne "")
{
#Retrieve ACL information from Share
$remoteshare = $share.path -replace ":","$"
Try
{
#Gather NTFS security information from each share
$acls = Get-ACL "\\$computer\$remoteshare"
#iterate through each ACL
ForEach ($acl in $acls.access)
{
If ($acl.FileSystemRights -match "\d")
{
Switch ($acl.FileSystemRights)
{
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 = "Unknown"}
}
}
Else
{
$AccessMask = $acl.FileSystemRights
}
$arrntfs = New-Object PSObject
#Process NTFS Report
$arrntfs | Add-Member NoteProperty Computer $c
$arrntfs | Add-Member NoteProperty ShareName $Share.name
$arrntfs | Add-Member NoteProperty Path $share.path
$arrntfs | Add-Member NoteProperty NTFS_User $acl.IdentityReference
$arrntfs | Add-Member NoteProperty NTFS_Rights $AccessMask
$ntfsreport += $arrntfs
}
}
Catch
{
$arrntfs = New-Object PSObject
#Process NTFS Report
$arrntfs | Add-Member NoteProperty Computer $c
$arrntfs | Add-Member NoteProperty ShareName "NA"
$arrntfs | Add-Member NoteProperty Path "NA"
$arrntfs | Add-Member NoteProperty NTFS_User "NA"
$arrntfs | Add-Member NoteProperty NTFS_Rights "NA"
#Add to existing array
$ntfsreport += $arrntfs
}
Finally
{
#Do nothing currently
}
}
}
}
Catch
{
$arrntfs = New-Object PSObject
$arrntfs | Add-Member NoteProperty Computer $c
$arrntfs | Add-Member NoteProperty ShareName "NA"
$arrntfs | Add-Member NoteProperty Path "NA"
$arrntfs | Add-Member NoteProperty NTFS_User "NA"
$arrntfs | Add-Member NoteProperty NTFS_Rights "NA"
#Add to existing array
$ntfsreport += $arrntfs
}
Finally
{
#Do Nothing Currently
}
}
}
End
{
#Display report
#$ntfsreport
#$ntfsreport | Export-Csv -notypeinformation "ntfsreport.csv"
return $ntfsreport
}
}
#THIS IS THE START OF THE SCRIPT
#Define Some variables and Arrays
$strOperatingSystem = "*Server*"
$Servers = @()
$ServersShareReport = @()
$ServersNTFSReport = @()
#Set up the Directory Search parameters
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.Filter = ("OperatingSystem=$strOperatingSystem")
$objSearcher.PageSize = 1000
#Define the Attributes we need from the search
$colProplist = "name","dnshostname","operatingsystemversion"
#Do the Search
foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}
$colResults = $objSearcher.FindAll()
$Ping = New-Object System.Net.NetworkInformation.Ping
ForEach ($objResult in $colResults)
{
$Server = $objResult.Properties.name
$ServerDNS = $objResult.Properties.dnshostname
Write-Host "Pinging $ServerDNS"
$errorActionPreference="SilentlyContinue"
$Pingy = $ping.send($ServerDNS,5000)
$ServerShareOutput = $Null
$ServerNTFSOutput = $Null
Try
{
#This is where we go get the information
If ($Pingy.status.tostring() –eq “Success”)
{
#Cool we can get to the server now lets gather some information
write-host “$Server Available”
$errorActionPreference="Continue"
$ServerShareOutput = Get-SharePermissions -computer $ServerDNS
$ServerNTFSOutput = Get-ShareNTFSPermissions -computer $ServerDNS
$ServersShareReport += $ServerShareOutput
$ServersNTFSReport += $ServerNTFSOutput
}
else
{
#oh-oh either WMI is restricted or we cannot get to the current server
write-host “$Server Not Available"
$FailedShareServer = New-Object PSObject
$FailedShareServer | Add-Member NoteProperty Computer "$Server"
$FailedShareServer | Add-Member NoteProperty Name "Server No Available"
$ServersShareReport += $FailedShareServer
$FailedNTFSServer = New-Object PSObject
$FailedNTFSServer | Add-Member NoteProperty Computer "$Server"
$FailedNTFSServer | Add-Member NoteProperty ShareName "Server No Available"
$ServersNTFSReport += $FailedNTFSServer
}
}
Catch
{
#And this just catches any weird error events
write-host “$Server Not Available"
$FailedShareServer = New-Object PSObject
$FailedShareServer | Add-Member NoteProperty Computer "$Server"
$FailedShareServer | Add-Member NoteProperty Name "Server Not Available"
$ServersShareReport += $FailedShareServer
$FailedNTFSServer = New-Object PSObject
$FailedNTFSServer | Add-Member NoteProperty Computer "$Server"
$FailedNTFSServer | Add-Member NoteProperty ShareName "Server Not Available"
$ServersNTFSReport += $FailedNTFSServer
}
Finally
{
$errorActionPreference="Continue"
$pingy = $null
$Server = $Null
}
}
#Now we have the data let's save it to file - in the same location the script is run from
$ServersShareReport | Export-Csv -notypeinformation ".\sharereport.csv"
$ServersShareReport = @()
$ServersNTFSReport | Export-Csv -notypeinformation ".\ntfsreport.csv"
$ServersNTFSReport = @()