Wednesday, August 12, 2015

SharePoint 2013: PowerShell automation of user and group reconfigurations


Introduction

This is a collection of PowerShell methods to automate SharePoint user and group reconfigurations. Topics in this posting include:

  • Remove a SharePoint web user group's permission level
  • Cleanup Usernames after migration
  • Configure primary and secondary site collection administrators
  • Add additional Site Collection Administrators
  • Add an Active Directory user group as a site collection administrator
  • Remove all users from SharePoint web's user group

Remove a SharePoint web user group's permission level

To interact with SharePoint users and groups and their permission levels for a specific web in your web application, you need to work with four objects:
  • SPWeb: this is the object that contains all of the members associated with a specific web in your web application.
  • RoleDefinitions: this a property of the SPWeb object and contains a collection of permission levels, such Full Control, Design, Contribute and Read, that you have defined for the web application.
  • RoleAssignments: this is a property of the SPWeb object and contains a collection of SharePoint users and groups that have been assigned a permission level to the web.
  • RoleDefinitionBindings: this  is a property of the RoleAssignments object and contains a collection of the actual associations, or bindings, between a role definition and an SPWeb user or group member.
These four objects are all that you need to get started. First, get an instance of the web object:
$Web = Get-SPWeb "htp://contoso.com/web1"
Interrogate the web object to see all of that web's current role assignments:
$Web.RoleAssignments
If this web was created using default settings, it would include these assignments: Web1 Owners (Full Control), Web1 Members (Contribute), and Web1 Visitors (Read). Let's say, for example, that the role assignment that needs to be modified is the third in this collection, or Web1 Visitors.  Then, to do this, we need to get an instance of that assignment, which you can do via its index in the collection:
$ra= $Web.RoleAssignments["2"]
You could execute this by itself to see what's included in this object. So, executing:
$Web.RoleAssignments["2"]
gets you something like this:
Member RoleDefinitionBindings       Parent ParentSecurableObject
Web1 Visitors       {Read}       Web1       Web1
Now, an instance of a group within a web can have multiple permission levels, or Role Assignments. Therefore, we need to get an instance of the group's particular permission level, or Role Definition, that needs to be removed.  This aspect of the group is actually a property that is a member of the group's parent in this instance, or Web1.  So:
$rd = $ra.Parent.RoleDefinitions["Read"]
We now have an instance of the group's assignment, $ra, as it exists within Web1, and we have an instance of that group's permission level definition, $rd, as it exists within Web1.  We can now remove the instance of the particular permission level, or role definition, that we want to remove from the group's role assignments.    This is done like so:
$ra.RoleDefinitionBindings.Remove($rd)
The next step is to update the group with this change:
$ra.Update()
And now you're done. It really is that easy.  Here's what the total script would look like for removing the Read permission from the Web1 Visitors group:

1.$web = get-SPWeb "[root site collection url]\web1"
2.$group = $web.SiteGroups["Web1 Visitors"]
3.$ra = $group.ParentWeb.RoleAssignments.GetAssignmentByPrincipal($group)
4.$rd = $group.ParentWeb.RoleDefinitions["Read"]
5.$ra.RoleDefinitionBindings.Remove($rd)
6.$ra.Update()
7.$group.Update()
8.$web.Dispose()

Note that since this is the only permission that this group is configured with, this effectively removes Web1 Visitors from the list of SharePoint groups configured for this web.  This is in fact how you remove a SharePoint user group from a web.

Now take the more general case, where a web's user group, call it Web1 Members, has previously been assigned a number of different permission levels, say Design, Manage Hierarchy and Approve, in addition to its standard permission level of Contribute.  You want to remove all the non-standard permission levels to get this user group back to what it should be.  The script for this would be:

01.$web = get-SPWeb "[root site collection url]/web1"
02.$group = $web.SiteGroups["Web1 Members"]
03.$ra = $group.ParentWeb.RoleAssignments.GetAssignmentByPrincipal($group)
04.$rd = $group.ParentWeb.RoleDefinitions["Design"]
05.$ra.RoleDefinitionBindings.Remove($rd)
06.$rd = $group.ParentWeb.RoleDefinitions["Manage Hierarchy"]
07.$ra.RoleDefinitionBindings.Remove($rd)
08.$rd = $group.ParentWeb.RoleDefinitions["Approve"]
09.$ra.RoleDefinitionBindings.Remove($rd)
10.$ra.Update()
11.$group.Update()
12.$web.Dispose()

Cleanup Usernames after migration

I use this script to clean up usernames after migrating the content database to 2013 and upgrading to claims.  These usernames had a variety of special characters and domain prefixes that needed to be removed.  This script doesn't do the mapping of these usernames to Active Directory.  All it does is interrogate the SiteUsers collection of usernames and modify the DisplayName property of each one.  This script works with these two SharePoint objects:
  • SPWeb
  • SPUser
It also employs regular expressions to simplify the code.  It works by first interrogating the SPWeb object and then getting an instance of the SiteUsers collection.  It then works through each member of this collection, using that member to get an instance of the SPUser object.  Once the SPUser object instance is obtained, it performs various string operations on the SPUser object's DisplayName property.  Along the way, some record keeping is performed.  Thanks to The Johnson Blog for the regular expression used in this script.

01.If ((Get-PSSnapin -Name "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null ){Add-PsSnapin Microsoft.SharePoint.PowerShell}
02.$Web=Get-SPWeb http://[URL]
03.$SiteUsers=$web.SiteUsers | Where {($_.UserLogin.Contains("DOMAINPREFIX1")) -or ($_.UserLogin.Contains("DOMAINPREFIX2"))} | Sort-Object DisplayName
04.$web.dispose()
05.$Count=1
06.Write-Host ""
07.Write-Host "02 - Cleaning SharePoint User Display Names..."
08.Write-Host "=============================================="
09.ForEach ($User in $SiteUsers)
10.  {
11.    $CandidateUser=Get-SPUser -Identity $User.UserLogin -Web "http://[URL]"
12.    $DisplayName = $CandidateUser.DisplayName
13.    $OldDisplayName = $DisplayName
14.    $DisplayName = $DisplayName.Replace("DOMAINPREFIX1:","")
15.    $DisplayName = $DisplayName.Replace("DOMAINPREFIX2:","")
16.    $DisplayName = $DisplayName.Replace("í","i")
17.    $DisplayName = $DisplayName.Replace("á","a")
18.    $DisplayName = $DisplayName.Replace("ê","e")
19.    $DisplayName = ([Regex]::Replace($DisplayName, '\b(\w)', { param($m) $m.Value.ToUpper() })).Replace(".", " ")
20.    Set-SPUser -Identity $CandidateUser -Web "http://[URL]" -DisplayName $DisplayName
21.    Write-Host $Count, ": updating ", $OldDisplayname, " to ", $DisplayName -ForegroundColor Green
22.    $Count=$count + 1
23.  }

Configure primary and secondary site collection administrators

I use this script to automate configuration of the primary and secondary site collection administrators.  I developed this script to automate the migration of a SharePoint Server 2007 Enterprise farm, employing Active Directory Lightweight Directory Services (AD LDS) authentication to SharePoint Server 2013 employing standard AD authentication.  This script uses a single SharePoint object; SPUser, specifically configuring the -Owner and -SecondaryContact properties of the object.

01.If ((Get-PSSnapin -Name "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null ){Add-PsSnapin Microsoft.SharePoint.PowerShell}
02. 
03.Write-Host ""
04.Write-Host "Configuring Site Collection Administrators"
05.Write-Host "=========================================="
06. 
07.Function UpdateSiteCollectionAdmins
08.    {
09.        Write-Host ""
10.        Write-Host "Updating Site Collection Administrators (farm level)..."
11.        Write-Host ""
12.        Try
13.            {
14.                $CurrentOwner = Get-SPSite "http://[URL]" | Select Owner
15.                Write-Host "  Current primary site collection administrator: ", $CurrentOwner -BackgroundColor DarkGray
16.                Write-Host "  Modifying this to: i:0#.w|DOMAIN\spadmin..." -BackgroundColor DarkGray
17.                Set-SpSite "http://[URL]" -owneralias "i:0#.w|DOMAIN\spadmin"
18.                $CurrentOwner = Get-SPSite "http://[URL]" | Select Owner
19.                Write-Host "    New primary site collection administrator set to", $CurrentOwner -ForegroundColor Green
20.            }
21.        Catch
22.            {
23.                Write-Host "   Problem encountered trying to modify primary site collection administrator." -ForegroundColor red
24.                Write-host "   Skipping to next SP task" -ForegroundColor red
25.            }
26.        Finally {}
27.        Try
28.            {
29.                $SecondaryContact = Get-SPSite "http://[URL]" | Select SecondaryContact
30.                Write-Host "  Current secondary site collection administrator: ", $SecondaryContact -BackgroundColor DarkGray
31.                Write-Host "  Modifying this to: i:0#.w|DOMAIN\First.Last..." -BackgroundColor DarkGray
32.                Set-SpSite "http://[URL]" -SecondaryOwnerAlias "i:0#.w|DOMAIN\First.Last"
33.                $CurrentOwner = Get-SPSite "http://[URL]" | Select SecondaryContact
34.                Write-Host "    New secondary site collection administrator set to", $SecondaryContact -ForegroundColor Green
35.            }
36.        Catch
37.            {
38.                Write-Host "   Problem encountered trying to modify secondary site collection administrator." -ForegroundColor red
39.                Write-host "   Skipping to next SP task" -ForegroundColor red
40.            }
41.        Finally {}
42.    }
43. 
44.UpdateSiteCollectionAdmins

Add additional Site Collection Administrators

The following script adds additional site collection administrators (SCA).  These are the SCAs that you would normally add by using the Site Settings capabilities of the site collection (go: Settings > Site Settings > Go to top level site settings > User and Permissions > Site collection administrators).  These can also be added by setting the SPUser object's IsSiteAdmin property, which the following script presents.  Note the claims authentication formatting.

1.Write-Host "    Now adding i:0#.w|DOMAIN\spadmin to site collection administrators..."  -BackgroundColor DarkGray
2.$User = Get-SPUser -Web "[URL]" -Identity "i:0#.w|DOMAIN\spadmin"
3.$user.IsSiteAdmin = $true
4.$user.Update()
5.Write-Host "      Added"  -ForegroundColor Green

Add an Active Directory user group as a site collection administrator

 One thing I found useful in administration was to move from assigning site collection administrator privileges individually to assigning this permission to a user group.  You can of course do this using the Site Settings capabilities.  You can also do this via PowerShell and again using the site collection's SPUser object.  However, there is one caveat: you need to use the AD group's SID, not its display name.  For example, consider a user group containing system administrators., DOMAIN\SysAdmins, with SID s-1-2-34-1234567890-1234567890-1234567890-1234. Then, accounting for claims authentication, its SharePoint identity would be
 c:0+.w|s-1-2-34-1234567890-1234567890-1234567890-1234
 and the script would be:

1.Write-Host "    Now adding DOMAIN\SysAdmins to site collection administrators..."  -BackgroundColor DarkGray
2.New-SPUser -UserAlias "c:0+.w|s-1-2-34-1234567890-1234567890-1234567890-1234" -DisplayName "DOMAIN\SysAdmins" -Web "[URL]"
3.$User = Get-SPUser -Web "[URL]" -Identity "c:0+.w|s-1-2-34-1234567890-1234567890-1234567890-1234"
4.$user.IsSiteAdmin = $true
5.$user.Update()
6.Write-Host "      Added"  -ForegroundColor Green

Remove all users from SharePoint web's user group

Consider that you have particular user group in a web, call it Web1, and a user group, Web1 Members, containing a number of SharePoint users, and that you would like to completely empty Web1 Members of all users so as to replace them with a single Active Directory group, DOMAIN\Web1-Users. This was the challenge I faced when migrating a legacy 2007 farm and wanting to implement this in an automated way so as to ensure maximum repeatability.  The below script does this.

It employs just two key SharePoint objects: SPWeb and SPUser. To remove all users from a group, the script first obtains an instance of the particular group from the SPWeb's group collection, SiteGroups. Each member of this collection in turn contains a collection of its users that you can access via the group's Users collection. After obtaining an instance of a user in this group, the group's RemoveUser method is used to remove the user from the group.  Once all the SharePoint users have been removed from this group, it remains to add a single AD group to complete the migration to a full AD user group approach.

Adding an Active Directory user group to a SharePoint user group requires the use of a single object, SPWeb, and a method that you may not be familiar with, EnsureUser, which get's an instance of the user.
The EnsureUser method get's an instance of the user among the web's user collection or it add's the AD user to the web's user collection.  Contrast this with Get-SPUser, which requires that the user already be a member of the farm's user collection or otherwise it fails.  Note that in this case, the EnsureUser method engages an Active Directory group the same as an Active Directory user.
This script first gets an instance of the SharePoint web group that you want to work on.  It then creates an instance of the Active Directory "user" (in this case, group) that you want to add.  I then uses the group instance's AddUser method to add the "user" to the SharePoint group.  Note how the method is named.  Here's the complete script:

01.Function UpdateWeb1Security
02.    {
03.        Try
04.            {
05.                Write-Host "Web1 Members: removing all users" -BackgroundColor DarkGray
06.                $web = Get-SPWeb "http://[URL]"
07.                $SPGroup = $web.SiteGroups["Web1 Members"]
08.                $Users = $SPGroup.Users
09.                ForEach ($User in $Users)
10.                    {
11.                        $SPGroup.RemoveUser($User)
12.                        Write-Host " Successfully removed: ", $User.Name  -ForegroundColor Green  
13.                    }
14.            }
15.        Catch
16.            {
17.                Write-Host " Problem encountered trying to remove member. Skipping to next SP group" -ForegroundColor red
18.            }
19.        Finally {}
20.        Try
21.            {
22.                $web = Get-SPWeb "http://[URL]"
23.                $SPGroup = $web.SiteGroups["Web1 Members"]
24.                $ADGroup = $web.Site.RootWeb.EnsureUser(“DOMAIN\Web1-Users”)
25.                Write-Host $SPGroup.Name, ": adding AD group", $ADGroup.Name -BackgroundColor DarkGray
26.                $SPGroup.AddUser($ADGroup)
27.                Write-Host -ForegroundColor green " Successfully added"
28.                $Web.Dispose()
29.            }
30.        Catch
31.            {
32.                Write-Host -ForegroundColor Red "DOMAIN\Web1-Users: User not added"
33.            }
34.        Finally {}
35.    }

References

Notes

  • These methods were discovered through trial and error and exploring the SharePoint object model (OM) using Get-Member.

No comments: