SharePoint Item Level Permissions using PowerShell and CSOM

I generally try to avoid using item level permissions, but I had a specific scenario where these were needed. Had I been using an on-premise solution I would have built a timer job to manage the permissions, however as Office 365 was being used I decided to build a PowerShell script using the Client Side Object Model – the script is executed every night.

  • The script iterates through a couple of lists each night a performs a couple of actions:
    Checks for new items
  •  Based on the list item data, find the column ‘EmployeeId’ and query active directory to find the User Principle Name (UPN) (EmployeID is stored against each user in AD).
  • If the above action finds a user from AD the script removes all permissions on the list item and sets unique permissions so only the employee and a management group have access to that list item.

The following code snippets assume a connection to SharePoint is open (ClientContext), and the current web is loaded into context.

To find the SharePoint group the following was used:

# Load in list of groups on the current web.
$groups = $web.SiteGroups

# Find the group called HR. Note - using GetGroupByName was not working, therefore I had to iterate through the groups.

foreach($group in $groups)

if($group.Title -eq "hr")
$hrGrp = $group.Id

# Get the group and load into context to be used.
$spGrp = $groups.GetById($hrGrp)

To set item level permission on each list item:

# Get the list by Title and load.
$list = $web.Lists.GetByTitle("MyList")
$listTitle = $list.Title

# Simple query - purely used to ensure all data is returned.
$camlQuery = New-Object microsoft.SharePoint.Client.CamlQuery
$camlQuery.ViewXml = "10000"
# Load in the items.
$collListItem = $list.GetItems($camlQuery)

# Iterate through each item.
foreach ($item in $collListItem)
	# reset variable to ensure no false positives.
	$upn = $null
	$user = $null
	$roleAssignment = $null	
	$continue = $false

	# Set a couple of variable, get the user from AD based on employee number.
	$recordId = $item.Id
	$upn = Get-Upn -eid $item["EmployeeID"]
	$continue = $false

	if($upn -ne $null)
		$continue = $true
		Add-LogMessage "ERROR: Missing employee number on record '$recordId' "

		# Break inheritance on the list item and remove existing permissons.
		$item.BreakRoleInheritance($false, $true)

		# Get the permissions role for 'Read' and 'Edit'.
		$reader = $web.RoleDefinitions.GetByName("Read");
		$Editor = $web.RoleDefinitions.GetByName("Edit");
		# Create a role assignment and apply the 'read' role.
		$roleAssignment = New-Object microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx)
		# Create a role assignment for editors - applying the 'edit' role.
		$roleAssignmentEditor = New-Object microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx)

		# Ensure the user exists on the site level, using EnsureUser.
		$user = $ctx.Site.RootWeb.EnsureUser($upn)

		# Apply the two permission roles to the list item.
		# $user is a SharePoint user.
		$ctx.Load($item.RoleAssignments.Add($user, $roleAssignment))    
		# spGrp is the HR group returned in the above snippet.
		$ctx.Load($item.RoleAssignments.Add($spGrp, $roleAssignmentEditor))

		# Update field on the list item to show it has ben processed.
		$item["A001"] = "PROCESSED"

	# Execute changes.

One thought on “SharePoint Item Level Permissions using PowerShell and CSOM

  1. Awesome David… This is exactly what i was looking for.. I was breaking my head until i found this… Thanks a lot !!!!!!!!!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s