In "Inventorying SharePoint Using PowerShell," I discussed how to use Windows PowerShell to inventory top-level SharePoint objects. In "Windows PowerShell Scripts for SharePoint: Info on Files, Pages, Web Parts," I discussed how to use PowerShell scripts to get information out of SharePoint about lists, libraries, files, and pages. In this article, I'll concentrate on users, groups, and security queries.

With the PowerShell commands and scripts presented here, you'll be able to inventory users, groups, group members, site owners, and site collection administrators. You'll also be able to find all users and groups with access to a specific file, folder, or list item. In addition, you'll be able to find all sites, libraries, folders, and documents that have unique permissions (i.e., broken inheritance).

Before Getting Started

Before getting started, there are a few details I need to cover:

  • Just because you can use PowerShell doesn't mean that you can ignore SharePoint security. In "Inventorying SharePoint Using PowerShell," I describe the basic security requirements. In a nutshell, you need to have at least read permissions to the content you want to explore and be a member of the SharePoint_Shell_Access role for the databases containing that content. You can add the account you're using to run PowerShell as a site collection administrator to every site collection. Alternatively, you can use SharePoint Central Administration user policies to give your account Full Read permissions in each application. (To do so, select Central Administration, choose Application Management, select an application, and click User Policy.)
  • The PowerShell scripts are for on-premises installs of SharePoint. They won't work with Office 365 or SharePoint Online.
  • Running the PowerShell scripts can put quite a load on a server, so you might want to run these scripts during nonbusiness hours.

Finally, before you get started, you need to know the difference between SharePoint users and groups. A SharePoint user is a person (e.g., domain\mike) or an Active Directory (AD) group/role (or another authentication group/role). A SharePoint group is a collection of SharePoint users. Both SharePoint users and SharePoint groups are associated with a site collection. For example, you might have a Sales Managers group in the HR site collection and a Sales Managers group in the Sales site collection. The Sales Managers group in the HR site collection isn't necessarily the same collection of users found in the Sales Managers group in the Sales site collection.

With this information in mind, let's look at how you can:

  • Access information about a user.
  • Find AD groups
  • List all the SharePoint groups in a site collection
  • List all the users in a SharePoint group
  • List all the SharePoint groups to which a user belongs
  • List all the users in a site collection
  • List all site owners
  • List all site collection administrators
  • List all the users, AD groups, and SharePoint groups with access to a file, folder, or list item
  • Find all sites, libraries, folders, and documents with unique permissions
  • List AD group members
     

Accessing Information About a User

Sometimes you need to access information about a single user. You can use the Get-SPUser cmdlet with the -Identity parameter for this:

Get-SPUser -web http://server/sites/yoursite
  -Identity "yourdomain\mike" |
  Select ID, UserLogin, DisplayName

Note that the -Identity parameter might not work as expected in SharePoint 2013 because the UserLogin property might display a simple login (domain\mike) or a more complex login that includes Claims Provider information (i:0#.w|domain\mike).

To find a user when using Claims-Based Authentication, you need to do a little filtering:

Get-SPUser -Web http://server/sites/yoursite |
  Where { $_.UserLogin -LIKE "*|yourdomain\mike" } |
  Select ID, UserLogin, DisplayName

You can also find users by filtering by the SPUser object's DisplayName property:

Get-SPUser -Web http://server/sites/yoursite |
  Where { $_.DisplayName -LIKE "*Conklin*" } |
  Select ID, UserLogin, DisplayName

In the results, you'll see an ID field. This is unique to the user, but only in the current site collection. For example, the user domain\mike might have an ID of 117 in the HR site collection and an ID of 12 in the Sales site collection.

The SPUser object exposes many properties in addition to DisplayName. I'll use a few of them in the scripts that follow. For a list of all the properties, see the SPUser properties web page.

You can also query User Profile Services to retrieve additional information about each user. The following command retrieves a custom property named hobbies for a user named sam. The site specified can be any site collection in a web application that's using User Profile Services.

$aSiteCollection = "http://yourdomain/sites/yoursite";
$serviceContext = Get-SPServiceContext($aSiteCollection);
$profileManager = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($serviceContext);
$profileManager.GetUserProfile("yourdomain\sam").GetProfileValueCollection("hobbies")

For more examples, you can search the Internet using the phrase PowerShell UserProfileManager.

Finding AD Groups

In SharePoint, an AD (or another authentication method) group is a special kind of user. To find AD groups, you can filter the list of users using the SPUser object's IsDomainGroup property:

Get-SPUser -Web http://server/sites/yoursite |
  Where { $_.IsDomainGroup }

Listing All the SharePoint Groups in a Site Collection

SharePoint groups are scoped, or unique, to a site collection. For example, the Sales Managers group in the Sales site collection isn't the same group as the Sales Managers group in the Training site collection. When listing groups from all site collections, you need to include the URL or the site collection name.

To get information about the SharePoint groups in a single site collection, you can use the Get-SPSite cmdlet in a command such as:

Get-SPSite http://server/sites/yoursite |
  Select -ExpandProperty RootWeb |
  Select -ExpandProperty Groups |
  Select {$_.ParentWeb.Url}, Name

Note that instead of using Get-SPSite, you can use the Get-SPSiteAdministration cmdlet to obtain a subset of site collection data, which might contain data about site collections to which you don't have access.

To get information about the SharePoint groups in all site collections in a farm, you can run the command:

Get-SPSite -Limit All |
  Select -ExpandProperty RootWeb |
  Select -ExpandProperty Groups |
  Select {$_.ParentWeb.Url}, Name

Listing All the Users in a SharePoint Group

You can get a list of users in a group by using the Get-SPUser cmdlet or by using any property that returns SPGroup objects. For example, here's a command that does the latter:

Get-SPSite http://server/sites/yoursite |
  Select -ExpandProperty RootWeb |
  Select -ExpandProperty Groups |
  Where {$_.Name -EQ "your group name here"} |
  Select -ExpandProperty Users |
  Select Name, Email

Listing All the SharePoint Groups to Which a User Belongs

To list all the SharePoint groups to which a user belongs, you first need to find that user's SPUser object:

$user = Get-SPUser -Web http://server/sites/yoursite |
  Where {$_.LoginName -LIKE "*|DOMAIN\SAMC"}

Once you have this object, you can scan all the site collections in the farm and find all the groups to which the user belongs:

Get-SPSite -Limit All |
  Select -ExpandProperty RootWeb |
  Select -ExpandProperty SiteUsers |
  Where { $user.UserLogin -EQ $_.LoginName } |
  Select -ExpandProperty Groups |
  Select Name, {$_.ParentWeb.Url}

Listing All the Users in a Site Collection

To list all the users in a site collection, you can use the Get-SPUser cmdlet and set the -Web attribute. Because the output will include both people and AD groups, you might want to include the IsDomainGroup property value in the output or filter by that property. (However, AD group members who have never visited the site will not be listed.) For example, the following command includes the IsDomainGroup property value as well as the UserLogin and DisplayName property values in the output:

Get-SPUser -Web http://server/sites/yoursite |
Select UserLogin, DisplayName, IsDomainGroup

Figure 1 shows sample results. In Figure 1, notice the ID for the system account. This is a fixed value that will be the same for all site collections. Also note the Claims Provider prefix on each of the UserLogin property values.

Figure 1: Listing All the Users in a Site Collection

Listing All Site Owners

Before you list all the site owners, you need to know the definition of a site owner. Although you might think a site owner is anyone who has Full Control permission, there's a formal group of site owners. This group can be retrieved from the SPWeb.AssociatedOwnerGroup property. For more about the three associated group properties—AssociatedOwnerGroup, AssociatedMemberGroup and AssociatedVisitorGroup—see my blog post "When is Full Control not Full Control."

To list all the site owners in a single site, you can run the command:

$web = Get-SPWeb http://server/sites/yoursite
$web.AssociatedOwnerGroup.Users

To list all the site owner groups in a farm, you can use the command:

Get-SPSite -Limit All | Get-SPWeb -Limit All |
  Where { $_.AssociatedOwnerGroup -Ne $null } |
  Select Url, AssociatedOwnerGroup

To list all the site owners in a farm, you can run the command:

Get-SPSite -Limit All | Get-SPWeb -Limit All |
  Where { $_.AssociatedOwnerGroup -Ne $null } |
  Select Url, {$_.AssociatedOwnerGroup.Users}

Listing All Site Collection Administrators

There are three kinds of site collection administrators: primary site collection administrator (SPSite.Owner), secondary site collection administrator (SPSite.SecondaryContact) and everyone else who has the SPUser.IsSiteAdmin property set to True. If you're unfamiliar with these three types of site collection administrators, see my blog post "Fun and Games with Site Collection Administrators." You might be surprised how they get assigned and changed.

To list the primary and secondary site collection administrators for all the site collections, you can use the command:

Get-SPSite -Limit All | Select Url, Owner, SecondaryContact

To list all the site collection administrators and their roles, you can run the command:

Get-SPSite -Limit All |
foreach {$Url = $_.Url; $site=$_; $_.RootWeb} |
Select -ExpandProperty SiteUsers |
Where { $_.IsSiteAdmin } |
Select {$Url}, Name,
{$(If($_.UserLogin -Eq $site.Owner.UserLogin) {"Primary Contact"}
  Else {
    If($_.UserLogin -Eq $site.SecondaryContact.UserLogin) {"Secondary Contact"}
      Else {"Other"}
  })
}

Figure 2 shows sample results.

Figure 2: Listing All the Site Collection Administrators and Their Roles

If you want more user-friendly column headings, you can add custom columns using @{ label=""; expression={} }, as shown here:

Get-SPSite -Limit All |
foreach {$Url = $_.Url; $site=$_; $_.RootWeb} |
Select -ExpandProperty SiteUsers |
Where {$_.IsSiteAdmin} |
Select @{label="Url"; expression={$Url}},
  Name,
  @{ label="Admin Role"; expression={
    $(If($_.UserLogin -Eq $site.Owner.UserLogin) {"Primary Contact"}
      Else {
        If($_.UserLogin -Eq $site.SecondaryContact.UserLogin) {"Secondary Contact"}
        Else {"Other"}
      })
  } }

Figure 3 shows the results with the new column headings.

Figure 3: Using User-Friendly Column Headings When Listing All the Site Collection Administrators and Their Roles

Listing All the Users, AD Groups, and SharePoint Groups with Access to a Specific File, Folder, or List Item

To list all the users, AD groups, and SharePoint groups with access to a file or folder, you can run this script:

$web = Get-SPWeb http://server/sites/yoursite
$web.GetFile("Shared Documents/Training Schedule.docx") |
  Select -ExpandProperty ListItemAllFields  |
  Select -ExpandProperty RoleAssignments |
  Select {$_.Member.DisplayName}, {$_.Member.LoginName}, RoleDefinitionBindings

As you can see, the output includes the RoleDefinitionBindings property, which contains the SharePoint permission levels assigned to the user or group. As the sample results in Figure 4 show, this command doesn't expand the AD groups or SharePoint groups to list the group members.

Figure 4: Listing All the Users, AD Groups, and SharePoint Groups with Access to a File or Folder

The script to list all the users, AD groups, and SharePoint groups with access to a list item is similar to the script just presented, except it specifies a single list item. To specify the list item, you can use a script such as:

$web = Get-SPWeb http://server/sites/yoursite
$web.lists["Bikes"].items[0] | Select -ExpandProperty RoleAssignments |
Select {$_.Member.DisplayName}, {$_.Member.LoginName}, RoleDefinitionBindings

You can select the "nth" item as this script does (.items[0]) or add a Where-Object filter to select the list item.

Finding All Sites, Libraries, Folders, and Documents with Unique Permissions

SharePoint has only a few types of securable objects: sites, lists, libraries, folders, list items, and library items. To see whether a securable object has unique permissions, you can check the HasUniquePerm property for sites and the HasUniqueRoleAssignments property for all the other types of securable objects. For sites, you also need to check to see if the site is a top-level site because top-level sites always have unique permissions and should be excluded from a "broken inheritance" list. The Where statement to exclude top-level sites looks like this:

Where { $_.HasUniquePerm -AND $_.ParentWeb -NE $Null }

For lists and libraries, you might also want to exclude hidden lists. In this case, the Where statement looks like this:

Where { $_.HasUniqueRoleAssignments -AND -NOT $_.Hidden }

The command to check the different types of securable objects is relatively straightforward. To find all the sites with broken inheritance in a site collection, you can run the command:

Get-SPSite http://yourSiteUrl |
Get-SPWeb -Limit All |
Where { $_.HasUniquePerm -AND $_.ParentWeb -NE $Null } |
Select ServerRelativeUrl

To find all the lists and libraries with broken inheritance in a site collection, you can use the command:

Get-SPSite http://yourSiteUrl |
Get-SPWeb -Limit All |
Select -ExpandProperty Lists |
Where { $_.HasUniqueRoleAssignments -AND -NOT $_.Hidden } |
Select Title, ParentWebUrl

To find all the folders with broken inheritance in a site collection, you can run the command:

Get-SPSite http://yourSiteUrl |
Get-SPWeb -Limit All |
Select -ExpandProperty Lists |
Select -ExpandProperty Folders |
Where { $_.HasUniqueRoleAssignments } |
Select {$_.ParentList.ParentWebUrl + "/" + $_.ParentList.Title + "/" +$_.DisplayName}

To find all the list and library items with broken inheritance in a site collection, you can use the command:

Get-SPSite http://yourSiteUrl |
Get-SPWeb -Limit All |
Select -ExpandProperty Lists |
Select -ExpandProperty Items |
Where { $_.HasUniqueRoleAssignments } |
Select Name, {$_.ParentList.ParentWebUrl + "/" + $_.ParentList.Title}

Note that this command might put a heavy load on the server. Thus, you might want to run it during low load times.

If you would like to merge these commands into a single script so that the results are output in a single report, you need to deal with the different columns and data types, then sort the results. Although you could build an array to hold all the content and then sort the array, the array could get very large. A better plan is to take advantage of PowerShell 3.0's Export-CSV cmdlet to merge each collection of data into a single file, then read back that file and sort its contents.

The script in Listing 1 is a bit long and complex, but if you break it down into its parts, you'll see the four commands just given along with custom columns ( @{Label="…"; Expression={…}} ) used to generate a compatible output for each list of objects. The script also modifies the output of each command to produce compatible columns (i.e., Securable, Item, and Parent). You can download the script in Listing 1 by clicking the Download the Code button near the top of the page.

Listing AD Group Members

As I mentioned previously, a SharePoint user is either a person (domain\mike) or an AD group. Up to this point, the commands just listed AD groups and didn't expand them to list the members of the AD groups. A single AD group can have thousands of members. The SharePoint PowerShell module doesn't include cmdlets for managing AD users and groups, but there's an AD module. For more information about it, see the Active Directory Administration with Windows PowerShell web page.

In PowerShell 2.0, you need to load the AD module using the command:

Import-Module -Name activedirectory

PowerShell 3.0 will find the AD module if it's on your server. As a test, you might try the following two commands, which find AD groups and find users in an AD group, respectively:

Get-ADGroup -Filter * | Select Name
Get-ADGroupMember -Identity Sales | Select Name

Listing 2 shows a script that expands an AD group to show its members. Up to this point, most of the script snippets I presented use a single-line command style based on PowerShell pipes. This script uses a programming style that includes foreach and if/else statements. You can download the script in Listing 2 by clicking the Download the Code button near the top of the page. Although you could copy this script into a PowerShell shell, it's easiest to work with in the PowerShell Integrated Scripting Environment (ISE) or a third-party PowerShell editor.

Figure 5 shows sample results. In this case, the SharePoint group named Demo3 Members has three users: one AD group named Sales and two users named Robert and Sam. The AD group named Sales has three members named Stella, Richard, and Susan. So, by expanding the AD group, you can see that the site actually has a total of five people in the Demo3 Members group.

Figure 5: Expanding an AD Group to Show Its Members

From Inventory to Content to Security

In "Inventorying SharePoint Using PowerShell," I showed you how to start inventorying core SharePoint objects, such as site collections and websites. In "Windows PowerShell Scripts for SharePoint: Info on Files, Pages, Web Parts," I showed you how to work with content, such as finding all documents of a certain type (e.g., .docx) or over a certain size, listing all libraries (including their file counts and total file size), and finding all libraries that use a specific content type. In this article, I showed you how to get information about users, groups, site owners, and site collection administrators. I also showed you how to run security queries to find out which files, folders, and list items that users, AD groups, and SharePoint groups have access to. I even showed you how to use PowerShell to find out if you have any sites, libraries, folders, and documents with broken inheritance. What would you like to see next?