Thursday, 17 February 2011

Add a SharePoint or AD group/user to all sites in a site collection using PowerShell

I have written this script based on some feedback I received in this article, which has become one of the more popular posts on the site. I was asked if there was any way of assigning group permissions for all sites in a site collection, bearing in mind that some sites will have unique permissions set on them whereas others will inherit their permissions from a parent site.

The function below provides this functionality, as well as a few other features:

  • Skips sites where permissions are being inherited from a parent site
  • Adds not only SharePoint groups to sites, but also Active Directory users and groups
  • Provides the option to skip the root site of the site collection, should you only wish to set permissions on all sub-sites
  • Will add a new SharePoint group to the site collection, if it doesn’t exist already. The script will allow you to add a description for the group, and it will automatically assign the user running the script as group owner and member

Before you can start assigning permissions to sites using the script, you have to run the function first in a PowerShell console with the SharePoint cmdlets loaded (e.g., the SharePoint 2010 Management Shell). I have annotated portions of the script so that you can hopefully follow what it is doing:

function AddAccountToAllSites ($siteURL, $accountName, $permLevel, [switch]$skipRootSite, $newGroupDescription)
{
    #Get Site Collection
    $site = Get-SPSite $siteURL
   
    #Check if the accountName variable contains a slash - if so, it is an AD account
    #If not, it is a SharePoint Group
    $rootWeb = $site.RootWeb
    if ($accountName.Contains("\")) { $account = $rootWeb.EnsureUser($accountName) }
    else {
        #If the SharePoint Group does not exist, create it with the name and description specified
        if (!$rootWeb.SiteGroups[$accountName])
        {
            $rootWeb.SiteGroups.Add($accountName, $rootWeb.CurrentUser, $rootWeb.CurrentUser, $newGroupDescription)
        }
        $account = $rootWeb.SiteGroups[$accountName]
    }
    $rootWeb.Dispose()
   
    #Step through each site in the site collection
    $site | Get-SPWeb -limit all | ForEach-Object {
       
        #Check if the user has chosen to skip the root site - if so, do not change permissions on it
        if (($skipRootSite) -and ($site.Url -eq $_.Url)) { write-host "Root site" $_.Url "will be bypassed" }
        else {
            #Check if the current site is inheriting permissions from its parent
            #If not, set permissions on current site
            if ($_.HasUniqueRoleAssignments) {

                $assignment = New-Object Microsoft.SharePoint.SPRoleAssignment($account)
                $role = $_.RoleDefinitions[$permLevel]
                $assignment.RoleDefinitionBindings.Add($role)
                $_.RoleAssignments.Add($assignment)
       
                write-host "Account" $accountName "added to site" $_.Url "with" $permLevel "permissions."
            }
            else {
                write-host "Site" $_.Url "will not be modified as it inherits permissions from a parent site."
            }
        }
    }
    #Display completion message and dispose of site object
    write-host "Operation Complete."
    $site.Dispose()
}

Once the script has been run, you can use it to assign permissions to your site collection by calling the function. Here are some scenarios:

  • Add the Active Directory user PACDOMAIN\Phil to all sites except the root site and assign Read permissions to them:

AddAccountToAllSites -siteURL "http://portal" -accountName "PACDOMAIN\Phil" -permLevel "Read" -skipRootSite

  • Add the Active Directory user PACDOMAIN\Phil to all sites including the root site and assign Read permissions to them:

AddAccountToAllSites -siteURL "http://portal" -accountName "PACDOMAIN\Phil" -permLevel "Read"

  • Add the Active Directory group PACDOMAIN\Portal Users to all sites including the root site and assign Read permissions to it:

AddAccountToAllSites -siteURL "http://portal" -accountName "PACDOMAIN\Portal Users" -permLevel "Read"

  • Add the SharePoint group “Test Group” to all sites except the root site and assign Full Control permissions to it. I am also assuming that this group has already been created in the site collection:

AddAccountToAllSites -siteURL "http://portal" -accountName "Test Group" -permLevel "Full Control" -skipRootSite

  • Add the SharePoint group “Test New Group” to all sites except the root site and assign Contribute permissions to it. This time I would like to create the group in the site collection as it doesn’t currently exist, and so I am also specifying the group description to be used during creation:

AddAccountToAllSites -siteURL "http://portal" -accountName "Test New Group" -permLevel "Contribute" -skipRootSite -newGroupDescription "This is a test group"

The screenshot below shows the affect of running these commands on one of the sites configured with unique permissions. All sites inheriting permissions will not be changed, although they will inherit these changes if their parent site has been affected by them.

image

I have posted a follow up article demonstrating how users and group assignments can be removed from sites in a similar way.

22 comments:

  1. Will this script also work in Sharepoint MOSS 2007?

    ReplyDelete
  2. Yes, with a few tweaks:

    http://get-spscripts.com/2011/03/using-powershell-scripts-with-wss-30.html

    ReplyDelete
  3. This is a potentially awesome solution to what I'm trying to accomplish, but it simply stops without executing anything for me. Just blanks.

    I'm trying to tweak this code a bit and hopefully I can get it to work.

    ReplyDelete
  4. Scratch that. I see what I was doing wrong. I actually ended up adding this function to another script and running it from the new script. Thanks!

    ReplyDelete
    Replies
    1. Hi, I have the same problem. Shall I insert the scenario end the end of the first script?

      Thanks

      Delete
  5. Hi Phil
    Great post!
    I need to update the permissions for a particular site and subsites with in a site collection. i.e. we have 1 site collection which contains all of our departments, i only need to update the permissions for 1 department. Is this possible with this script?
    Many thanks!
    Tomas

    ReplyDelete
  6. Tomas - You can use elements of this script to do it just not the script as it is written here. You may also want to look at this one for inspiration: http://get-spscripts.com/2010/07/adding-groups-with-permission-levels-to.html

    ReplyDelete
  7. I've improved upon the script a bit, just a few minor changes. If you're interested, email me - "john at dumb dot org" or email my gmail id in my comments.

    ReplyDelete
  8. Wonderful blog! I found it while searching on Yahoo News. Do you have any tips on how to get listed in Yahoo News? I’ve been trying for a while but I never seem to get there! Many thanks.sbo

    ReplyDelete
  9. Hello Phil,
    Very useful script. Is there a way to use it to add a user when using claims-based authentication? If I just add the user name they show up in the site's permissions list, but don't actually have any permissions. When added through the GUI the username is prefaced with 'i:0#.w'.

    ReplyDelete
    Replies
    1. OK solved it - needed to put a pipe so "i:0#.w|domain\user"

      Delete
  10. Hi Phil,

    Just an off the topic question taht I'm looking for an answer... I'm writing a program to grant user permission to a folder. this is for Sharepoint 2007 and I'm using c# managed code. (not powershell) However I am unable to add user permissions to a folder in a document library unless the user is added to the site permissions. Am I missing something here? or is this a known issue in MOSS and if so is there a workaround available?

    ReplyDelete
  11. Is's great!
    Exist any like this for adding permission for all non-inherited content objects(libraries, lists, folders, documents, ...) in specified site?

    Thank you
    Josef

    ReplyDelete
  12. I have 300 folders under a site. There is a subfolder that has to have unique permissions under each of these 300 folders. Anyway to run a script to add unique permissions to the subfolder without having to break the inheritance manually and change the permissions?

    ReplyDelete
  13. Thanks a lot for the script... You saved my day!!!

    ReplyDelete
  14. Trying to use this script but getting errors:

    Exception calling "Add" with "1" argument(s): "Object reference not set to an i
    nstance of an object."

    + $assignment.RoleDefinitionBindings.Add <<<< ($role)
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    Exception calling "Add" with "1" argument(s): "Cannot add a role assignment wit
    h empty role definition binding collection."


    + $_.RoleAssignments.Add <<<< ($assignment)
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    ReplyDelete
    Replies
    1. Found what caused the error, had to use the Swedish term for "Full Control" because Sharepoint site is in Swedish.

      Delete