SharePoint Limited Access Permission – Careful when using BreakInheritance

This post is for SharePoint Developer or Admin who deals with SharePoint APIs (PowerShell or C#)

I have recently discovered a killing command from SharePoint that could kill your SharePoint Day. At times, you will need to configure a Unique permission to document/file for Content Sharing purposes. Typical feature which your end user will ask is to Share a certain document or folder to only certain group of people. Although it is recommend to Share using SharePoint Group which more manageable when it comes to a big Content management system, sometime you prefer to make a easier way out by just assigning to the Individual Users. (Less group to manage and you CAN Afford to loss the permission when things go wrong… and yes, this post will tell you why and how it goes wrong)

With much user friendly SharePoint “Share With” feature, you could break inheritance, grant new user permission so on and so forth. You can’t stop user from doing it, cause it is so apparent nowadays in SharePoint 2013

break and grant permission

Or you can run PowerShell script to Get the ListItem (or to be precise, SPSecurableObject Base Type object), subsequently execute  $object.BreakInheritance($false) and start adding SPRoleAssignment object.

If you have noticed this API

void ISecurableObject.BreakRoleInheritance(bool copyRoleAssignments)

 

This command allows you to quickly remove all existing RoleAssignment (from inheriting parent object permission) and so you can start adding Custom permission that you desired.

Important! This is Extremely Dangerous. Why? Because if you carefully loop into the $object.RoleAssignments (SPRoleAssignmentCollection) property, you will discover that some role definition bindings are named “Limited Access”. In SharePoint 2010, you can easily notice this definition through the permission setting page whereas in SharePoint 2013, it is hidden by default (which is more scarier cause you didn’t even know its existence).

Why is this Limited Access permission? There are many articles out there telling you why and why. I’m not gonna cover that here.

But if you really intend to so-called Cleanse the messy permission list that you have already added, the advice is Don’t.

Let me give you an example of how this BreakInheritance way of breaking parent permission can cause you problem.

By executing BreakInheritance(False), you are technically removing ALL Role Assignments from this object, which include the Limited Access permission granted automatically by SharePoint. You will usually see a lot of limited access for Document library and Web, cause the children within it are likely to be requested (by user) to have unique custom permission.

reset and break with false

 

For Example

  • Web 1 
    • Document Library A
      • Folder a (Break inheritance)
        • File
      • Folder b 

Assuming you have a “Folder a” with broken inheritance permission for UniqueUserA. Upon granting this unique permission, SharePoint automatically creates a Role Assignment for UniqueUserA with “Limited Access” permission to Web1 because Document Library A is inheriting permission from Web1 and hence it is added into Web1 instead.

Somehow or other, you need to change/script to change the permission for Web 1 object up there (the one with Limited Access), by purging the limited access granted to UniqueUserA. the permission that you granted previously to “Folder a” will be DELETED automatically! Yes, Automatically, seamlessly, without-your-knowingly.

And what is going to happen after that? Your lovely user UniqueUserA will send email you, telling you that he has no permission to access files or folder a. Not to mention if you have many Unique permission granted for sub folders within that document library.

Now, the Task you need to ask yourself is – How to still be able to remove existing permission while preserving the Unique configured child permission.

I came out with a simple PowerShell script that allows me to clear the permission. I think it can be easily translated into C# for code behind implementation.

[sourcecode language=”powershell”]

#############################################################################
# Clearing Permission while keeping Limited Access user – Important #
#############################################################################
function ClearPermission
{
Param([Microsoft.SharePoint.SPSecurableObject]$obj)

$roleAssignments = $obj.RoleAssignments;
$count = $roleAssignments.Count;
for($i = 0; $i -lt $count ; $i++)
{
$roleAssignment = $roleAssignments[$i];
$bindingCount = $roleAssignment.RoleDefinitionBindings.Count
$clearCounter = 0;
for($j = 0; $j -lt $bindingCount ; $j++)
{
$roleBinding = $roleAssignment.RoleDefinitionBindings[$clearCounter];
if($roleBinding.Name -ne "Limited Access")
{
$roleAssignment.RoleDefinitionBindings.Remove($clearCounter);
}
else
{
$clearCounter++;
}
}
}
$obj.Update();
}

[/sourcecode]

What it simply does is to loop through the Role Assignment Collection and delete only Binding with definition of Limited Access. Note that I do not loop via ForEach loop as when you looping the collection, you cannot delete the object within the collection. You can try and you will end up seeing error.

How to use:

[sourcecode language=”powershell”]

Add-PSSnapin Microsoft.SharePoint.PowerShell

$w = Get-SPWeb https://yoursite

ClearPermission $w;

#add your unique permission here.

#additional code to add role assignement (permission)

$user = $w.EnsureUser("domainX\LoginNameY");

$roleAssignment = New-Object Microsoft.SharePoint.SPRoleAssignment($user);

$roleDefinition = $w.RoleDefinitions["Full Control"]

$roleAssignment.RoleDefinitionBindings.Add($roleDefinition)

$w.Update();

[/sourcecode]

Hope it helps

4 thoughts on “SharePoint Limited Access Permission – Careful when using BreakInheritance

  1. Hi,

    thanks for shring your your code. I think, you missed a $roleAssignment.Update() in your outer loop. In C# it’s necessary or else the removing of the roledefinitionbinding is not persistated.

    Greetings

    1. Hi Ricky, In PowerShell it does not required to have the Update, it’s automatically committed when your run Bindings.Remove().

      But thanks for noting the Key Difference between C# and PowerShell!

  2. I may just be confused but this line:
    if($roleBinding.Name -ne “Limited Access”)
    {
    $roleAssignment.RoleDefinitionBindings.Remove($clearCounter);
    }
    and this part of the explanation do not seem to add up:
    “…delete only Binding with definition of Limited Access”

    If the first one ($j=0 & $clearCounter = 0) is not a “Limited Access” it gets removed?

    Then again why the usage of the $clearCounter in the first place?
    for($j = $bindingCount-1; $j -gt -1 ; $j–)
    {
    if($roleBinding.Name -eq “Limited Access”)
    { $roleAssignment.RoleDefinitionBindings.Remove($j);
    }
    }

    Well, still helped me with the overall concept, thanks.

    1. H Nooby,
      Glad it gives the overall concept, the idea of having ClearCount is because we want to keep the $j loop continue running for the entire Binding Count
      When we do a $roleAssignment.RoleDefinitionBindings.Remove($clearCounter); the index of $roleAssignment.RoleDefinitionBindings will actually be shifted 1 index ahead.
      e.g.
      if we have a indexes of [0, 1, 2, 3], when we remove [1], it actually shifted to be come [0, 2 , 3] where it then the index of 2 onward will replace 1.
      Hence if we are doing removing, we do not increment $ClearCount, cause the next loop will be the NEXT instance that we are checking.

Leave a Reply

Your email address will not be published. Required fields are marked *