Monday, January 5, 2015

SharePoint 2013 User Permission Analysis & Reporting using PowerShell

Analysing SharePoint permissions for a particular user is often a common task in SharePoint administration. Generally, How do we check what permissions a user has on SharePoint content? By getting into site or list settings page and check permissions for the particular user, isn't it? Well, You may want to analyze the particular user's permissions for your entire SharePoint environment.  How about that? Each and every SharePoint site, list, library, folder and list items may have unique permissions. It can even go more challenging when you have multiple SharePoint farms.

Well, PowerShell is the life saver! Here is my permission reporting solution to scan and provide a report to view a user's permission on the SharePoint web application. With this script, you can analyze and track the security effectively! Check what permissions on an account has been granted in all places in SharePoint. This PowerShell script scans below areas to retrieve a specific user's access rights:

  • Farm administrator's group
  • Central administration web application policies
  • Site collection administrators 
  • Scans all site collections and sub-sites with unique permissions in which user has access.
  • Scans all lists and libraries with unique permissions in which user has access.
  • Scans all folders and list Items which has permissions in the site in which user has access.
Just change the Input variables section and provide parameters for User Id, Web Application and Report path variables and run the script in PowerShell.

After generating a SharePoint permissions report, this script generates a CSV file, which can be export as excel file to allows the further research and analyze outside of a SharePoint environment. It gets data such as:  Object, Title, URL, Permission Type, Permissions as in the below screenshot.
PowerShell Script to Generate User Permission Report in SharePoint 2010/2013

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

#Function to retrieve Permission data
Function Get-PermissionInfo([String]$UserID, [Microsoft.SharePoint.SPSecurableObject]$Object)
{
 #Object Array to hold Permission data
    $PermissionDataCollection = @()

 #Determine the given Object type and Get URL of it
    switch($Object.GetType().FullName)
 {
  "Microsoft.SharePoint.SPWeb"  { $ObjectType = "Site" ; $ObjectURL = $Object.URL }
  "Microsoft.SharePoint.SPListItem" 
  { 
   if($Object.Folder -ne $null)
   {
     $ObjectType = "Folder" ; $ObjectURL = "$($Object.Web.Url)/$($Object.Url)" 
   }
   else
   {
    $ObjectType = "List Item"; $ObjectURL = "$($Object.Web.Url)/$($Object.Url)" 
   }
  }
  #Microsoft.SharePoint.SPList, Microsoft.SharePoint.SPDocumentLibrary, "Microsoft.SharePoint.SPPictureLibrary",etc
  default { $ObjectType = "List/Library"; $ObjectURL = "$($Object.ParentWeb.Url)/$($Object.RootFolder.URL)" }
 }
 
 #Get Permissions of the user on given object - Such as: Web, List, Folder, ListItem
 $UserPermissionInfo = $Object.GetUserEffectivePermissionInfo($UserID)
 #Iterate through each permission and get the details
 foreach($UserRoleAssignment in $UserPermissionInfo.RoleAssignments)
 {
  #Get all permission levels assigned to User account directly or via SharePOint Group
  $UserPermissions=@()
        foreach ($UserRoleDefinition in $UserRoleAssignment.RoleDefinitionBindings)
        {
   #Exclude "Limited Accesses"
   if($UserRoleDefinition.Name -ne "Limited Access")
   {
          $UserPermissions += $UserRoleDefinition.Name
   }
        }
 
  #Determine Permissions granted directly or through SharePoint Group
  if($UserPermissions)
  {
   if($UserRoleAssignment.Member -is [Microsoft.SharePoint.SPGroup])   
   {
     $PermissionType = "Member of SharePoint Group: " + $UserRoleAssignment.Member.Name     
   }
   else
   {
    $PermissionType = "Direct Permission"
   }
   $UserPermissions = $UserPermissions -join ";"  
 
   #Create an object to hold storage data
         $PermissionData = New-Object PSObject
         $PermissionData | Add-Member -type NoteProperty -name "Object" -value $ObjectType
   $PermissionData | Add-Member -type NoteProperty -name "Title" -value $Object.Title
         $PermissionData | Add-Member -type NoteProperty -name "URL" -value $ObjectURL  
   $PermissionData | Add-Member -type NoteProperty -name "Permission Type" -value $PermissionType
   $PermissionData | Add-Member -type NoteProperty -name "Permissions" -value $UserPermissions
   $PermissionDataCollection += $PermissionData
  }   
 } 
 Return $PermissionDataCollection
}

#Function to Generate Permission Report
Function Generate-PermissionReport($UserID, $WebAppURL, $ReportPath)
{
    #Output Report location, delete the file, If already exist!
    if (Test-Path $ReportPath)
     {
        Remove-Item $ReportPath
     }
  
   #Write Output Report CSV File Headers
  "Object, Title, URL, Permission Type, Permissions" | out-file $ReportPath

 ###Check Whether the Search Users is a Farm Administrator ###
 Write-host "Scanning Farm Administrators..." 
   #Get the SharePoint Central Administration site
   $AdminWebApp = Get-SPwebapplication -includecentraladministration | where {$_.IsAdministrationWebApplication}
    $AdminSite = Get-SPWeb $AdminWebApp.Url
    $AdminGroupName = $AdminSite.AssociatedOwnerGroup
    $FarmAdminGroup = $AdminSite.SiteGroups[$AdminGroupName]
 
 #enumerate in farm adminidtrators groups
    foreach ($user in $FarmAdminGroup.users)
    {
     if($user.LoginName.Endswith($UserID,1)) #1 to Ignore Case
     {
       "Farm, $($AdminSite.Title), $($AdminWebApp.URL), Farm Administrators Group, Farm Administrator" | Out-File $ReportPath -Append
     }     
    }
 
 ### Check Web Application User Policies ###
 Write-host "Scanning Web Application Policies..." 
  $WebApp = Get-SPWebApplication $WebAppURL
 
  foreach ($Policy in $WebApp.Policies)
  {
      #Check if the search users is member of the group
     if($Policy.UserName.EndsWith($UserID,1))
       {
       #Write-Host $Policy.UserName
        $PolicyRoles=@()
       foreach($Role in $Policy.PolicyRoleBindings)
       {
        $PolicyRoles+= $Role.Name +";"
       }
   #Send Data to CSV File
      "Web Application, $($WebApp.Name), $($WebApp.URL), Web Application Policy, $($PolicyRoles)" | Out-File $ReportPath -Append
   }
  }

 #Convert UserID Into Claims format - If WebApp is claims based! Domain\User to i:0#.w|Domain\User
    if($WebApp.UseClaimsAuthentication)
    {
        $ClaimsUserID = (New-SPClaimsPrincipal -identity $UserID -identitytype 1).ToEncodedString()
    }
 
 #Get all Site collections of given web app
 $SiteCollections = Get-SPSite -WebApplication $WebAppURL -Limit All

 #Loop through all site collections 
    foreach($Site in $SiteCollections)
    {
     Write-host "Scanning Site Collection:" $site.Url
  ###Check Whether the User is a Site Collection Administrator
     foreach($SiteCollAdmin in $Site.RootWeb.SiteAdministrators)
        {
      if($SiteCollAdmin.LoginName.EndsWith($ClaimsUserID,1))
      {
       "Site Collection, $($Site.RootWeb.Title), $($Site.RootWeb.Url), Site Collection Administrators Group, Site Collection Administrator" | Out-File $ReportPath -Append
      }     
    }
  
  #Get all webs
  $WebsCollection = $Site.AllWebs
  #Loop throuh each Site (web)
  foreach($Web in $WebsCollection)
  {
       if($Web.HasUniqueRoleAssignments -eq $True)
             {
     Write-host "Scanning Site:" $Web.Url
    
     #Get Permissions of the user on Web
     $WebPermissions = Get-PermissionInfo $ClaimsUserID $Web
     
     #Export Web permission data to CSV file - Append
     $WebPermissions |  Export-csv $ReportPath  -notypeinformation -Append 
    } 
    
    #Check Lists with Unique Permissions
    Write-host "Scanning Lists on $($web.url)..."
    foreach($List in $web.Lists)
    {
              if($List.HasUniqueRoleAssignments -eq $True -and ($List.Hidden -eq $false))
                 {
      #Get Permissions of the user on list
                        $ListPermissions = Get-PermissionInfo $ClaimsUserID $List
      
      #Export Web permission data to CSV file - Append
      $ListPermissions |  Export-csv $ReportPath -notypeinformation -Append       
     }
    
     #Check Folders with Unique Permissions
     $UniqueFolders = $List.Folders | where { $_.HasUniqueRoleAssignments -eq $True }                    
                    #Get Folder permissions
                    foreach($folder in $UniqueFolders)
        {
                        $FolderPermissions = Get-PermissionInfo $ClaimsUserID $folder
    
      #Export Folder permission data to CSV file - Append
      $FolderPermissions |  Export-csv $ReportPath -notypeinformation -Append    
                    }
    
     #Check List Items with Unique Permissions
     $UniqueItems = $List.Items | where { $_.HasUniqueRoleAssignments -eq $True }
                    #Get Item level permissions
                    foreach($item in $UniqueItems)
        {
                        $ItemPermissions = Get-PermissionInfo $ClaimsUserID $Item
      
      #Export List Items permission data to CSV file - Append
      $ItemPermissions |  Export-csv $ReportPath -notypeinformation -Append    
                    }
    }
  }
 }
 Write-Host Permission Report Generated successfully!
}

#Input Variables
$WebAppURL = "http://intranet.crescent.com"
$Userid ="Crescent\Salaudeen" 
$ReportPath = "D:\Reports\PermissionRpt.csv"

#Call the function to generate user access report
Generate-PermissionReport $Userid $WebAppURL $ReportPath
You can also download the script from Technet gallery: SharePoint Permission Report: Check Access Rights for a Specific User

This script is broken into two functions. So that you can use the first function: Get-PermissionInfo to get permissions data scoped to a site collection permission report/site. Above script scoped at a particular web application. You can call the same function on all your web application to get the entire SharePoint permissions reports.

PowerShell Scripts to generate SharePoint Permission Reports:
Here is my list of PowerShell scripts to create various reports for SharePoint permission auditing.

3rd Party Tools:
There are many tools in the market to analyze, audit SharePoint user permissions (and more features naturally!). Here are some:



You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Check out these SharePoint products:

13 comments :

  1. Instead of finding all the sites a specific user has access to, I need to find all the sites that 'everyone' has access to. Is it possible to modify your script to do this?

    ReplyDelete
    Replies
    1. You mean get permission report for "All Users" instead of one specific user? Well, Just remove IF blocks from the script. Such as:
      If($user.LoginName.Endswith($UserID,1)),
      If($Policy.UserName.EndsWith($UserID,1))
      If($SiteCollAdmin.LoginName.EndsWith($ClaimsUserID,1))

      Delete
    2. i commented the 3 IF loop you mentioned. How do i call the function to list all users ?

      like this ?
      generate-permissionreport $WebappUrl $ReportPath$

      Delete
    3. This script enumerates through all users who has permission on particular object such as Farm, Web App Policy, Site collection, List, etc. These IF condition checks whether the given user account matches while enumerating. Removing IF gets you all users who has access.

      Delete
  2. I attempted really hard to reverse engineer this script to find out why it keeps failing for me, but I can't figure out why. I'm even attempting to run this with the SharePoint 2010 Management shell with the full out sharepoint farm admin account and all I get is this constantly:

    You cannot call a method on a null-valued expression.
    At C:\temp\UserAccessReport.ps1:135 char:49
    + if($SiteCollAdmin.LoginName.EndsWith <<<< ($ClaimsUserID,1))
    + CategoryInfo : InvalidOperation: (EndsWith:String) [], RuntimeE
    xception
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Generate-PermissionReport : Exception has been thrown by the target of an invoc
    ation.
    At C:\temp\UserAccessReport.ps1:203 char:26
    + Generate-PermissionReport <<<< $Userid $WebAppURL $ReportPath
    + CategoryInfo : NotSpecified: (:) [Generate-PermissionReport], T
    argetInvocationException
    + FullyQualifiedErrorId : System.Reflection.TargetInvocationException,Gene
    rate-PermissionReport

    Thoughts?

    ReplyDelete
  3. Is this for On-Prem only?

    ReplyDelete
    Replies
    1. Yes! Its written for On-Prem. However, its possible to make one for O365 by leaving Farm & Web App sections.

      Delete
  4. Is it possible to skip some groups like Style Resource Readers?

    Can I change this script to only show direct permissions and not permssions given via an ad group?

    ReplyDelete
    Replies
    1. Yes! Add your group name in Line#38: if($UserRoleDefinition.Name -ne "Limited Access")

      This script doesn't count permissions granted via AD Groups!

      Delete
  5. Hi Salaudeen..

    You have written a great script for SharePoint admins. I have exactly same requirements but it’s for all users including folder permissions if it’s unique folder permissions.

    I have seen comments that other user are looking for the same i.e. for all users.
    Function Get-PermissionInfo([String]$UserID, [Microsoft.SharePoint.SPSecurableObject]$Object)

    requires userID and I tried to use this function that accepts only the $Object but not able to managed all users using your script.

    Any pointer would be greatly appreciated.

    ReplyDelete
    Replies
    1. Hi Aroh, I've published a new script which generates complete permission reporting at: SharePoint Site Collection Permission Report using PowerShell

      Delete
    2. Thanks a lot Salaudeen ...its great help. Thanks Again! :)

      Delete
  6. Hi, is this script going to work on MOSS 2007?

    ReplyDelete

Please Login and comment to get your questions answered!

You might also like:

Related Posts Plugin for WordPress, Blogger...