Tuesday 2 October 2012

SharePoint User Profile Service and PowerShell

The Goal is To Make Life Easier

PowerShell is amazing – more precisely it is an amazing tool.
Within the confines of the PowerShell environment are all of the working essentials for producing incredibly sophisticated scripts for operations, maintenance, management, development, and more. The structure of the system is designed for ease of use, understandability, quick access to assistance, and the ability to add to the PowerShell ecosystem.  It is based on the .Net framework which gives it an incredible depth and breadth for performing management tasks in Windows. It is mandated as the standard for Windows management, it continues to grow unabated.
All is well and good, except that there are some circumstances where this standard has not held up. My interaction with a cmdlet while working with the User Profile Service in SharePoint is a primary illustration. I spent the better part of a morning trying to understand the nuance in the cmdlet. Documentation that was clear would have easily taken care of this situation, and I would have been off and running in minutes instead of hours. However this was not the script for the affairs of the morning (pun intended).
 

Get-Help Get-UserProfilePowerShellAssistance

Let me begin at the beginning. I was tasked with looking through and pulling together some sample cmdlets for use in training.  PowerShell cmdlets were chosen to illustrate how easy it is to manage most of the SharePoint environment with the stock cmdlets. It was supposed to be an OOB experience without going into the object model or into some rabbit hole. Clear and succinct use of SharePoint PowerShell cmdlets. 
All worked as expected until I turned my attention to the User Profile Service – then expectations and reality began to diverge.
My choice of demonstration were the two cmdlets Get-SPProfileServiceApplicationSecurity and Set-SPProfileServiceApplicationSecurity. I thought these would both be good for demonstrating how personalization features could be managed through the command line. I did the usual background investigation to get up to speed – read the help and look at examples. Go to TechNet and see if there are any updates. 
My adventure started with Get-Help Set-SPProfileServiceApplicationSecurity – Full. This gave me the name of the cmdlet and Syntax, nothing more. OK. Let’s do the same for Get-SPProfileServiceApplicationSecurity. Better. At least the parameters are defined, but the example is pretty weak.
Off to TechNet to review the state of these two cmdlets. Much better, but still not as straight forward as I would expect.
 

Set-SPProfileServiceApplicationSecurity

The read on this cmdlet is pretty quick. The gist of the cmdlet’s purpose is quoted below from TechNet:
Use the Set-SPProfileServiceApplictionSecurity cmdlet to set permission and identity information for the following User Profile objects:
- Read individual My Sites
- Use Personal Features
- Use Social Features
- Create Personal Site
Sound straightforward. Let’s look at the parameters so that we can really under stand how this works. The main parameters are:
Identity – SPObjectSecurity
ProfileServiceApplicationProxy – The GUID for the service application proxy
Type - Specifies the type of object to display. The type is any one of the following values: MySiteReaderACL or UserACL
Huh. We have a SPObjectSecurity which is undefined, a GUID, and a Type of MySiteReaderACL or UserACL. And no example.
So the question is – how do these three parameters translate into an operation for assigning permissions to the profile service objects identified above. I will play the spoiler by saying that an answer was recently published. I found it after a bit of grappling with the cmdlets. However, before I stumbled across the MSDN blog, I did some background research looking at the object returned by the Get-SPProfileServiceApplicationSecurity.
 

To Work with Security We Must First Set Security

I start with a try at getting the security for the User Profile store objects identified above. First get a reference to the service application proxy (SAP) and then make a call to see what is present for security:
PS C:\> $SAP=Get-SPServiceApplicationProxy | where {$_.DisplayName -like "User*"}
PS C:\> Get-SPProfileServiceApplicationSecurity –ProfileServiceApplicationProxy $SAP.Id –Type UserACL | Format-List
Not what I expected:
SharePoint2010.png


No User Profile Application – or I don’t have access to it. Hmmm. I obviously have access to run PowerShell, and the service application is running – you’ll just have to trust me on that. Why the error?
A quick look at permissions on the user profile service application shows that I (the desktop user running PowerShell) do not have permission to the service application. I add my user identity to the permissions and then, bingo, I get a response.
 

Looking into the Elements of the Profile Security Command

The following output from my Get-SPProfileServiceApplicationSecurity command above:
NamedAccessRights : {Use Personal Features, Create Personal Site, Use Social Features}
AccessRules : {nt authority\authenticated users, c:0(.s|true}
Now things seem to make a bit more sense. However, two questions:
  1. How do the NamedAccessRights related to the AccessRules? In other words how do I apply one (the access rule) to a user for a specific object (NamedAccessRights).
  2. Remember the Type parameter – how does this relate to the output? Note that my previous command was executed with the UserACL Type. I want to now look at the MySiteReaderACL.
To explore further:
PS C:\> Get-SPProfileServiceApplicationSecurity –ProfileServiceApplicationProxy $SAP.Id –Type MySiteReaderACL | Format-List
NamedAccessRights : {Read}
AccessRules : {c:0!.s|windows, c:0(.s|true}
So this is where the structure of the output stands:

Structure.jpg

SPObjectSecurity – Need I Say More!

Now that there is some understanding of the relationship between the Type parameter and the securable objects that it relates to, there might be some understanding as to how this is applied with the Set-SPProfileServiceApplicationSecurity cmdlet. But we are still missing a couple of essential ingredients. For instance, the Identity is just thrown into the command with nary a definition, except that it is a SPObjectSecurity.
On closer look, the Identity parameter is really the core of the whole process related to assigning permissions. The use of the Set-SPProfilesApplicationSecurity is just the final step in the assignment of permissions. The core of the assignment is done with the Identity parameter, which is of type SPObjectSecurity.
It turns out the SPObjectSecurity is the item returned from the Get-SPProfileServiceApplicationSecurity command, which makes sense. But how does PowerShell work with these objects. Through the following cmdlets -
  • Grant-SPObjectSecurity
  • Revoke-SPObjectSecurity

I have to take a moment to say here that things just get more complicated.  This blog was entitled with the word rant for a reason. This is down the trail I went before discovering a blog which essentially gave away the secret to using the profile service security cmdlets. However, this is the point – it could have been much easier with an explanation in the actual cmdlet help or article.

So here is how this goes:
  1. Get a reference to a SPObjectSecurity object.
  2. Create a principal based upon a user or group.
  3. Apply the grant or revoke permission to the object based upon a predefined right.
Everything seems pretty straight forward, except for item 2. I need to get a cmdlet to create a new user identity – it happens to be New-SPClaimsPrincipal. Note that you cannot use New-SPUser – because service application security works off of claims identities. To see the extensive list of SPClaims types, just type Get-Help New-SPClaimsPrincipal – Examples.
So maybe we can actually do something here now.
 

Stitching It All Together

The road has been a bit of a wind. But the way this narrative has proceeded is based upon the research that I was doing prior to actually finding the answer on an MSDN blog. 
At the start this looked like a pretty easy task. The more I dug, the more dependencies arose, and the more complex it became. And here is the kicker, the solution is straight forward, but requires quite a bit of reference to information beyond just the Set or Get SPProfileServiceApplicationSecurity cmdlets. If the example had been provided, then extending and using these cmdlets effectively would have been a morning cup or coffee.
So here it is:
#Get the reference to the SPObjectSecurity
PS C:\> $SAP=Get-SPServiceApplicationProxy | where {$_.DisplayName -like "User*"}
PS C:\> $Identity=Get-SPProfileServiceApplicationSecurity –ProfileServiceApplicationProxy $SAP.Id –Type UserACL
#Create a claims identity
PS C:\> $Principal = New-SPClaimsPrincipal -Identity "synergy\domain users" -IdentityType WindowsSecurityGroupName
#Grant Permission To the Principal to a Defined Right
Grant-SPObjectSecurity –Identity $Identity –Principal $Principal –Rights “Use Social Features”
#Set the permission on the user profile service FINALLY
Set-SPProfileServiceApplicationSecurity –ProfileServiceApplicationProxy $SAP.Id –Type UserACL –Identity $Principal –Confirm:$false
 Done!

And so, to look at the Set-SPProfileServiceApplicationSecurity cmdlet in TechNet, one could say that it is a bit shy on support. This cmdlet is worthless without a whole host of other cmdlets that provide essential services

No comments:

Post a Comment