Be cloudy and secure...

Security


Cloud Security Authors: Elizabeth White, Yeshim Deniz, Shelly Palmer, Rick Popko, Jackie Kahle

Related Topics: Intel XML, XML Magazine, Mixed Network Integration, SharePoint Archiving Journal, Security

Cloud Security: Blog Feed Post

A Simple Way to Programmatically Create SharePoint Security Groups

I don’t like manual steps especially when it comes to setting up security

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="Readonly">

<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 readonly 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.

Read the original blog entry...

More Stories By Corey Roth

Corey Roth, a SharePoint Server MVP, is a consultant at Hitachi Consulting specializing in SharePoint and Office 365 for clients in the energy sector. He has more than ten years of experience delivering solutions in the energy, travel, advertising and consumer electronics verticals.

Corey specializes in delivering ECM and search solutions to clients using SharePoint. Corey has always focused on rapid adoption of new Microsoft technologies including Visual Studio 2013, Office 365, and SharePoint.

He is a member of the .NET Mafia (www.dotnetmafia.com) where he blogs about the latest technology and SharePoint. He is dedicated to the community and speaks regularly at user groups and SharePoint Saturdays.