A simple way to programmatically create SharePoint security groups

Posted Monday, March 8, 2010 11:12 AM by CoreyRoth

When it comes to SharePoint deployments, I try to automate everything I can.  I don’t like manual steps especially when it comes to setting up security.  A common task when deploying any sites is setting up security in some manner.  Today I am going to cover how to easily store definitions your SharePoint security groups in an XML file.  We’ll use LINQ to XML to make reading the file a breeze, and then we’ll use the SharePoint object model to create the groups and add users (or AD groups).   I’ve blogged on how to create a group before, but we’re going to take this a step further by giving you code that you can easily add to a feature receiver or console application.  First let’s take a look at the XML file we’re going to use.

<?xml version="1.0" encoding="utf-8" ?>

<Groups>

  <Group Name="My Custom Read Group" Owner="SHAREPOINT\GroupOwner" Description="Readonly Permission Group" PermissionLevel="Read">

    <User Name="SHAREPOINT\TestUser1" />

    <User Name="SHAREPOINT\TestGroup1" />

    <User Name="SHAREPOINT\TestGroup2" />

  </Group>

  <Group Name="My Custom Contributors Group" Owner="SHAREPOINT\GroupOwner" Description="Contributors Permission Group" PermissionLevel="Contribute">

    <User Name="SHAREPOINT\TestGroup3" />

  </Group>

</Groups>

In this file, I am defining two SharePoint groups.  One that will have read access and one that will have contribute access.  I store the required information needed by the Add method on the SPGroupCollection object.  I then have one or more User elements with the name of my Active Directory user or group.  I tried to keep my XML schema pretty simple.  You can customize it obviously how you want, you would just have to alter your LINQ queries. 

Let’s take a look at the code we need to make this happen.  I won’t go into as much detail of the object model since I went into it pretty well on my last post.  We’ll just focus on how we use LINQ to XML to read the information we need and then have it create our groups.  My method is called CreateGroups and it takes an SPWeb object and a string with the filename of the XML document.

private void CreateGroups(SPWeb currentSite, string groupsFilename)

{

    // get the xml document from the feature folder

    XDocument groupsXml = XDocument.Load(groupsFilename);

 

    // create a new anoynmous type with the group data

    var groups = from sharePointGroup in groupsXml.Root.Elements("Group")

                select new

                {

                    Name = sharePointGroup.Attribute("Name").Value,

                    Owner = sharePointGroup.Attributes("Owner").Any() ? sharePointGroup.Attribute("Owner").Value : null,

                    Description = sharePointGroup.Attributes("Description").Any() ? sharePointGroup.Attribute("Description").Value : string.Empty,

                    PermissionLevel = sharePointGroup.Attributes("PermissionLevel").Any() ? sharePointGroup.Attribute("PermissionLevel").Value : null,

                    Users = sharePointGroup.Elements("User").Any() ? sharePointGroup.Elements("User") : null

                };

 

    // iterate through the groups and create the groups

    foreach (var sharePointGroup in groups)

    {

        // only create the group if it does not exist

        if (!ContainsGroup(currentSite.SiteGroups, sharePointGroup.Name))

        {

            // add the owner to the web site users

            currentSite.EnsureUser(sharePointGroup.Owner);

 

            // add the group

            currentSite.SiteGroups.Add(sharePointGroup.Name, currentSite.SiteUsers[sharePointGroup.Owner],

                currentSite.SiteUsers[sharePointGroup.Owner], sharePointGroup.Description);

        }

 

        // add the users to the group

        AddUsersToGroup(sharePointGroup.Name, sharePointGroup.Users, currentSite, sharePointGroup.PermissionLevel);

    }

}

This seems like kind of a big method at first, but it’s really not that bad.  To keep things simple, I haven’t included any exception handling code.  We are really just querying the XML document, iterating through each group element inside of it, creating the groups, and then adding the users to the group.  The first line of code just creates an XDocument object.  We then construct a LINQ to XML query.  What we want is to return data from each Group element in the document.  The Add method doesn’t like nulls, so we check for them and use string.Empty if the value does not exist in the file.  The one case where I don’t do this is for the Name of the group.  If that is not present, I would rather the process throw an exception.  As for the Users assigned to the group, I grab all of them and add them to our anonymous type like this.

Users = sharePointGroup.Elements("User").Any() ? sharePointGroup.Elements("User") : null

This gives us an IEnumerable<XElement> that we can pass to a method later to add each Active Directory user (or group) to the SharePoint group.  Once we execute the query, we iterate through each group element.  The first thing we have to do is make sure that the group does not exist.  Of course there is no way to do that other than using the try/catch technique.  I will usually wrap this in an extension method, but for today’s purpose, we’ll just call a method to check.

private bool ContainsGroup(SPGroupCollection groupCollection, string index)

{

    try

    {

        SPGroup testGroup = groupCollection[index];

        return true;

    }

    catch (SPException e)

    {

        return false;

    }

}

Lame I know.  I’m so happy there are ways to get around this in SharePoint 2010.  Then this starts to look like code from the previous post.  We call .EnsureUser to make sure the domain account of the group owner is registered with the site.  We then just call the Add method with the Name, Owner, default user, and description.  Again there is more info on the previous post about that method call.  Assuming the group is created, we can then add the users to the group.  We call a new method AddUsersToGroup which takes the groupName, the users element, an SPWeb, and the permission level. 

The first thing we do is query the names of the Active Directory users (or groups).  Here we are just grabbing it from the Name attribute of the User element.  I probably could have condensed this query, but at least it’s easy to read.  We then add each user (or group) from the User elements to the group.  If you are curious about the empty parameters, take a look at the previous post.  If you are going to run into an exception, it’s going to be here.  If the group failed to be created or if the user does not exist (i.e.: you typed it in the XML file wrong), this line will throw an exception.

private void AddUsersToGroup(string groupName, IEnumerable<XElement> users, SPWeb currentSite)

{

    // select the username from the xml document

    var userList = from user in users

                   select new

                   {

                       Name = user.Attribute("Name").Value

                   };

 

    // add the users to the sharepoint group

    foreach (var user in userList)

    {

        currentSite.SiteGroups[groupName].AddUser(user.Name, string.Empty, user.Name, string.Empty);

    }

}

Now, we’re almost done.  The last thing we need to do is set the permission level on the group.  This is where we specify whether the group has readonly, contribute, full control, etc access to the site.  Be sure and get the name on the permission level right otherwise you will get an exception.  I’ve also blogged about how to assign permission levels before.  Today’s post is really just a great practical use of putting together the things I have posted on before.

private void SetRoleDefinitionBinding(string groupName, SPWeb currentSite, string permissionLevel)

{

    // add the read role definition to the site group

    SPRoleAssignment roleAssignment = new SPRoleAssignment(currentSite.SiteGroups[groupName]);

    roleAssignment.RoleDefinitionBindings.Add(currentSite.RoleDefinitions[permissionLevel]);

    currentSite.RoleAssignments.Add(roleAssignment);

    currentSite.Update();

}

Effectively you create a new SPRoleAssignment by passing it a SPGroup object.  You then add a binding using the existing RoleDefinitions on the site.  You then add the assignment to the site and of course call .Update() so things get saved.

That’s really all there is to it.  This is a great use of combining information from my previous posts into something that you can use everyday to set security on your sites.  How you execute this code is up to you.  I’ve used it in a feature receiver and in a console application before.  Setting up security through the UI is very slow and painful.  Once you create it on one server, there is no way to move it to another server and that’s not a lot of fun.  This should help you with that and eliminate those nasty manual steps in your deployment process. 

Filed under: , ,

Comments

# ARB Security Solutions &raquo; A simple way to programmatically create SharePoint security groups &#8230;

Pingback from  ARB Security Solutions  &raquo; A simple way to programmatically create SharePoint security groups &#8230;

# re: A simple way to programmatically create SharePoint security groups

Tuesday, March 9, 2010 5:14 PM by Hassan

Thanks for a nice post. I have been taking similar appraoches with 2007 in the past however with 2010 we can improve it a bit further.

The challenge with developing these utilities as winform applications is maintenance, by the end of the project we would have a basket full of utulities to automate different tasks.

With 2010 I think the best approach would be creating a cmdlet for the code you have given above. I haven't played with cmdlets yet but in theory beleive it is quite possible and then we could have a powershell batch file to prepare the sharepoint enviornment and one step would be calling this custom cmdlet to create groups with xml file provided.

Hassan

# re: A simple way to programmatically create SharePoint security groups

Tuesday, March 9, 2010 5:20 PM by CoreyRoth

@Hassan - Yes, writing this as an stsadm command is a very good way to execute this code.  A feature also works as well.  Going forward with SharePoint 2010, you can write this as a powershell commandlet as well.

# Query Active Directory

Thursday, March 11, 2010 11:46 AM by Query Active Directory

Pingback from  Query Active Directory

# Sharepoint Active Directory

Thursday, March 11, 2010 12:14 PM by Sharepoint Active Directory

Pingback from  Sharepoint Active Directory

# re: A simple way to programmatically create SharePoint security groups

Monday, June 21, 2010 7:30 AM by Eliza Sahoo

SPWeb.Groups will allow you to pull out only the groups which have some / any kind of permissions defined within the site.

SPWeb.SiteGroups will pull out all the cross-site groups irrespective of any permission defined.

# Sharepoint Security Blog on: Charlie Smith: A simple way to programmatically create SharePoint security groups &#8211; Corey Roth &#8211; DotNetMafia.com &#8211; Tip of&#8230; | Social Networking &amp; Digital Collaboration news, tips,

Pingback from  Sharepoint Security Blog on: Charlie Smith: A simple way to programmatically create SharePoint security groups &#8211; Corey Roth &#8211; DotNetMafia.com &#8211; Tip of&#8230; | Social Networking &amp; Digital Collaboration news, tips, guides...

# re: A simple way to programmatically create SharePoint security groups

Monday, May 23, 2011 12:18 PM by Rich Finn

Easily converted to PowerShell - nice job Corey

# re: A simple way to programmatically create SharePoint security groups

Wednesday, July 13, 2011 6:08 AM by Dave Hunter

Great article, made some tweeks to allow the owner to be a SharePoint group and to set other attributes of the SPGroup.

Thanks

# Programmatically create SharePoint security groups using configuration &laquo; Thinking out Aloud

Pingback from  Programmatically create SharePoint security groups using configuration &laquo; Thinking out Aloud

Leave a Comment

(required)
(required)
(optional)
(required)