Script Repository


User permissions for shares, shared files and folders on server

January 11, 2017
1376

The script generates and emails a report on permissions granted to a user to access shares and all shared folders and files on a specific server. Using the script, you can, for example, create a Custom Command to generate such a report on demand. To add the script to your Custom Command, use the Run a program or PowerShell script action.

Parameters:

  • $computerName - specifies the fully qualified domain name (FQDN) of the server;
  • $allowPermissionMarker - specifies an HTML marker for Allow permissions. You need to specify how an HTML table cell for Allow permissions will look like using HTML code;
  • $denyPermissionMarker - specifies an HTML marker for Deny permissions. You need to specify how an HTML table cell for Deny permissions will look like using HTML code;
  • $to - specifies a semicolon-spearated list of recipients of the report. You can use value references for a recipient. For example, if you specify %adm-InitiatorEmail%, reports will be sent to the email address of the user who executes the Custom Command;
  • $subject - specifies the email message subject;
  • $reportHeader - specifies an HTML-formatted header of the report;
  • $reportFooter - specifies an HTML-formatted footer of the report.
    You can use value references in the subject, header and footer. For example, if you specify %name%, the report will include the full name of the user on which the script is executed.
Edit Remove
PowerShell
$computerName = "server.domain.com" # TODO: modify me
$allowPermissionMarker = "<td bgcolor='Green'></td>" # TODO: modify me
$denyPermissionMarker = "<td bgcolor='Red'></td>" # TODO: modify me

# E-Mail settings
$to = "recipient@domain.com;%adm-InitiatorEmail%" # TODO: modify me
$subject = "%name%'s permissions for shares on computer '$computerName'" # TODO: modify me
$reportHeader = "<b>%name%'s permissions for shares on computer '$computerName'</b><br/><br/>"
$reportFooter = "<hr /><p><i>Please do not reply to this e-mail, it has been sent to you for notification purposes only.</i></p>" # TODO: modify me

function GetColumnNumber($column)
{
    if ($columns.ContainsKey($column))
    {
        return $columns[$column]
    }
    
    $columnNumber = $columns.Count
    $columns.Add($column, $columnNumber)
    return $columnNumber
}

# Test connection
if (!(Test-Connection $computerName -Quiet))
{
    $Context.LogMessage("Unable to connect to computer '$computerName'", "Warning")
    return
}

# Get user SID
$trustee = New-Object "System.Collections.Generic.HashSet[System.String]"
$sidByte = $Context.TargetObject.Get("objectSid")
$userSid = New-Object "Softerra.Adaxes.Adsi.Sid" @($sidByte, 0)
[void]$trustee.Add($userSid)

# Get SIDs of groups user belongs to
try
{
    $groupGuidsBytes = $Context.TargetObject.GetEx("adm-MemberOfGuid")
}
catch
{
    $groupGuidsBytes = $NULL
}

if ($groupGuidsBytes)
{
    # Build filter to find all groups
    $filter = New-Object "System.Text.StringBuilder"
    [void]$filter.Append("(|")
    foreach ($guidBytes in $groupGuidsBytes)
    {
        [void]$filter.Append([Softerra.Adaxes.Ldap.FilterBuilder]::Create("objectGuid", $guidBytes))
    }
    [void]$filter.Append(")")
    
    $searcher = $Context.BindToObject("Adaxes://rootDSE")
    $searcher.SearchFilter = $filter.ToString()
    $searcher.SearchScope = "ADS_SCOPE_SUBTREE"
    $searcher.PageSize = 500
    $searcher.ReferralChasing = "ADS_CHASE_REFERRALS_NEVER"
    $searcher.SetPropertiesToLoad(@("objectSid"))
    $searcher.VirtualRoot = $True
    
    try
    {
        $searchResultIterator = $searcher.ExecuteSearch()
        $searchResults = $searchResultIterator.FetchAll()
        
        # Get group SID
        foreach ($searchResult in $searchResults)
        {
            $sidBytes = $searchResult.Properties["objectSid"].Value
            if ($sidBytes -eq $NULL)
            {
                continue
            }
            $sid = New-Object "Softerra.Adaxes.Adsi.Sid" @($sidBytes, 0)
            [void]$trustee.Add($sid)
        }
    }
    finally
    {
        # Release resources used by the search
        $searchResultIterator.Dispose()
    }
}

# Get all shares on the server
$shares = Get-WmiObject -Class Win32_Share -Computer $computerName | WHere {$_.Type -eq 0}
$columns = @{}
$objectsInfo = @{}
foreach ($share in $shares)
{
    $sharePath = "\\$computerName\" + $share.Name
    if (!(Test-Path $sharePath))
    {
        $Context.LogMessage("Cannot verify user permissions for share '$sharePath' probably because of insufficient access rights", "Information")
        continue
    }
    
    # Get permissions for the share
    $aclObjects = @()
    try
    {
        $shareAclObject = Get-Acl $sharePath -ErrorAction Stop
        $aclObjects += $shareAclObject
    }
    catch
    {
        $Context.LogMessage("Unable to get permissions for share '$sharePath'. Error: " + $_.Exception.Message, "Warning")
    }
    
    # Get permissions for child objects
    $childObjects = Get-ChildItem -Path $sharePath -Recurse -ErrorAction SilentlyContinue
    if ($childObjects -ne $NULL)
    {
        foreach ($object in $childObjects)
        {
            try
            {
                $acl = $object | Get-Acl -ErrorAction Stop
            }
            catch
            {
                $objectPath = $object.FullName
                $Context.LogMessage("Unable to get permissions for file or folder '$objectPath'. Error: " + $_.Exception.Message, "Warning")
                
            }
            $aclObjects += $acl
        }
    }
    
    # Get user permissions
    foreach ($aclObject in $aclObjects)
    {
        # Get object path
        $objectPath = Convert-Path $aclObject.PSPath
        
        # Get access rules
        $rules = $aclObject.GetAccessRules($true, $true, [System.Security.Principal.SecurityIdentifier])
        foreach ($rule in $rules)
        {
            if (!($trustee.Contains($rule.IdentityReference.Value)))
            {
                continue
            }
            
            # Add object info
            if (!($objectsInfo.ContainsKey($objectPath)))
            {
                $objectsInfo.Add($objectPath, @{})
            }
            $permissions = $objectsInfo[$objectPath]
            
            # Get File system rights
            $fileSystemRights = $rule.FileSystemRights -split ","
            foreach ($value in $fileSystemRights)
            {
                # Get column number in report
                $columnNumber = GetColumnNumber $value
                
                # Get access control mask
                if ($rule.AccessControlType -eq [System.Security.AccessControl.AccessControlType]::Allow)
                {
                    $type = $allowPermissionMarker
                }
                else
                {
                    $type = $denyPermissionMarker
                }
                
                # Update object info
                if ($permissions.ContainsKey($columnNumber) -and $permissions[$columnNumber] -eq $type)
                {
                    continue
                }
                elseif ($permissions.ContainsKey($columnNumber) -and ($type -eq $denyPermissionMarker))
                {
                    $permissions[$columnNumber] = $type
                }
                elseif (!($permissions.ContainsKey($columnNumber)))
                {
                    $permissions.Add($columnNumber, $type)
                }
            }
        }
    }
}
if ($columns.Count -eq 0)
{
    return
}

# Build report
$htmlTable = "<table border='1' width=100%%><tr><th>Object path</th>"
$columns.GetEnumerator() | Sort-Object Value | %%{$htmlTable += "<th>$($_.Name)</th>"}
$htmlTable += "</tr>"
$objectsInfoSorted = $objectsInfo.GetEnumerator() | Sort-Object Key

foreach ($objectInfo in $objectsInfoSorted)
{
    # Add user permissions to the report
    $objectPath = $objectInfo.Name
    $permissions = $objectInfo.Value
    $recordParts = @("<td></td>") * $columns.Count
    foreach ($columnNumber in $permissions.Keys)
    {
        $type = $permissions[$columnNumber]
        $recordParts[$columnNumber] = $type
    }
    $htmlTable += "<tr><td>$objectPath</td>" + ($recordParts -join "") + "</tr>"
}
$htmlTable += "</table>"

# Send Mail
$html = $reportHeader + $htmlTable + $reportFooter
$Context.SendMail($to, $subject, $NULL, $html)

Comments ( 0 )
No results found.
Leave a comment