This post is going to discuss how to determine where a user has been granted access to your SharePoint environment. The script I provide is scoped to an individual web application and searches for all users based on their domain. I'll explain why I did that below. Both of these elements could easily be modified to suit your purposes – such as searching for a single user account across all web applications in the farm.
I was recently working with a customer who had discovered a configuration issue in their farm. The environment has two domains. In their particular case, a two-way trust was required and had been enabled. Only users from one specific domain were intended to have access to the SharePoint environment. Two elements of oversight resulted in users of the other domain having access to the site. The first oversight is that the people picker had not been scoped to only one domain. This can be configured using the following article: Peoplepicker-searchadforests: Stsadm property (Office SharePoint Server). I do realize that the documentation specifies SharePoint 2007, however it is also applicable for SharePoint 2010, as indicated in this article: People Picker overview (SharePoint Server 2010). The next issue is that people had also been granting access to 'NT Authority\Authenticated User', which includes users authenticated to both domains.
The approach I'm taking is a series of enumerations. Permissions are applied at the web, list, and object level, so we need to find a way to get all the way down there. First we need to enumerate all site collections, and all webs in those site collections, then all lists in those webs, finally we could enumerate all list items in those lists as well.
For the purposes of this sample script and this blog post, I've chosen to go only as far as the individual lists. The approach you would take to report on individual list items would be effectively the same, including one additional enumeration for all list items in each list.
Once we have a list of all these webs and lists, we need to find a way to find out who has been granted access to the item, and how they have been granted access to that item.
Now that we know the approach, the solution is pretty simple. The first thing that you have to do is enumerate through site collections. Getting a list of all site collections can be accomplished using Get-SPSite.
As I said, we're going to be enumerating through them and performing some additional actions. For that, I've chosen to create some ForEach-Object loops.
User security is applied not at the site level, but at the web level. Which means we actually need to get a list of all webs in all sites. This can be placed inside the first ForEach loop. What we'll be doing is using the SPSite object's AllWebs property.
If a web is not using unique security, then it will be inheriting from the parent. This means we don't need to check roles on that object. But first we need to find out how to do that for each web. PowerShell again makes this very simple, because every web has a HasUniqueRoleAssignments property. This property will tell us if the site uses unique permissions or not.
Once we've determined if the web has unique role assignments, we can start looking for what those role assignments are. There are two places to look for. Users who have been assigned permissions directly, and users who have been added to SharePoint groups. PowerShell again makes gives us a break. To discover each user who has been assigned permission directly, use the RoleAssignments property of the Web object.
In order to discover users who have been granted permission through groups, this is a little more difficult – but not much. From the RoleAssignments from the web, we have a list of users and a list of SharePoint groups. We can enumerate the members of all group objects by calling the users property of the members property of the RoleAssignments property for the web. This may be getting a little complicated, but I've included a screenshot below. In this screenshot, we can see that two accounts have been granted full control because they are members of the SharePoint Owners group.
This has gotten us as far as enumerating all webs where unique permissions have been applied. So how do we do this for lists? It's effectively exactly the same. Each Web object has a Lists property.
Another great thing about PowerShell in SharePoint, every single list object has a RoleAssignments property, just like webs.
In order to return users who have been explicitly granted access, or who have been granted access via a SharePoint group, you would use the same script as you did for the web object.
As I mentioned, the sample script I'm providing currently looks for users from a particular domain. It would take very little effort to transform this script and search for specific user accounts. If I get any requests for it, I may just add it as a secondary download from this blog post.
Download SecurityReport.ps1 (zipped)
There are three variables which need to be altered before running this script. Failing to alter them may result in the script not running, or producing useless data. One is the web application URL, one is the unwanted domain prefix, and one is the log file directory where the output will be generated.
As always, if you have any questions or feedback, let me know. If you have any ideas to optimize the script, I'd like to hear that too. Thanks for reading!
You can also follow me on Twitter: