Azure Logic Apps and SharePoint Permission management

Matthew Barben
Driver Lane
Published in
10 min readJun 30, 2020

--

For a while, I have been playing in SharePoint land. While there, I have been making good use of Power Automate and Azure Logic Apps.

Primarily I have been using Azure Logic Apps as a means of integration and orchestration using it to overcome limitations of a customer-specific workflow engine as well as a means of integration with on-premise applications.

Whilst the environment does come with a bunch of pre-canned SharePoint actions and triggers there are times where you need to go beyond standard steps and make use of the SharePoint REST API.

One of those use cases is definitely permission management — in this, I want to cover off an example use case:

  • Create a folder in a document library
  • Apply permissions based on a group name
  • Then remove permissions for that group from the created folder

Like my other article where I cover setting up an Azure WebApp, I found it frustrating that there is no one place that attempts to take you end-to-end through the process — so the hope here is that I can take you end-to-end.

What tools are available

Before we start, let’s at least call out the alternative approaches that exist.

PowerShell

If you are:

  • Happy to develop your own PowerShell Scripts
  • Have a server to run said scripts
  • And have Tenent based administrator rights

Then PowerShell might be a good alternative to Logic Apps.

Other Logic App / Power Automate actions

The marketplace for actions and triggers is growing — and some provide a bunch of the functionality already. An example of one would be Plum Sail.

It is a subscription service, you will need to add another subscription. And for some that might be a deal-breaker — especially when you can do some actions with your existing tooling.

The Setup

So let’s set some things up. Before we start I am going to set up the scenario — for this we are creating the following:

A Target Folder that we will use for our examples

Folder Structure we will use for our tutorial

And a Temp Group

Create a Sample Group

This is very standard SharePoint to set up so I won't dwell long

Finally, we will set up the base permission on our folder (this should inherit down)

Base Permissions

Create an Azure Logic App

Now there are several ways to get your logic app running, you can set it to trigger on a SharePoint list item being created, or a message hitting a message queue — but for illustrative purposes, we are just creating one logic app that will use an HTTP request.

Note: If you are using HTTP requests you will need to secure this request by limiting the IP address that can access this endpoint, alternatives can also include using the Azure API Management.

The Logic App will perform the following actions (depending on the mode selected):

  • Create a Folder
  • Add Permissions to that Folder (for a Specific Group)
  • Remove Permissions to that Folder

We will use a combination of standard SharePoint actions as well as the API SharePoint action to show how you can leverage the existing SharePoint Rest API in a Logic App

To start create your Azure Logic App resource from the Azure Portal, and create a blank Logic App

Select Request Trigger

Select the Request Trigger

Blank HTTP Request

Next, click on the ‘Use sample payload to generate schema’ link and enter the schema. To begin we are just using a simple message to get us underway.

{
"mode":"createfolder",
"name": "sampleFolder"
}

As we progress we will update this.

Using a Sample JSON payload to configure the Schema

Enter the sample JSON message and click Done and you will be left with a schema that you can use to start building a flow.

HTTP Request Schema

Finally, click save and this will give you an HTTP endpoint that we can use to develop against.

Create A Folder

Logic Apps requires you to declare your variables upfront. For this action, we will need the declare the following:

  • BaseFolder — which is the base folder in the Document Library where we are creating our folders
  • FolderName — the name of the folder

Both variables will be strings

Initialize Folder variables

Next, we will create a switch statement — we will use this to switch to the different operations

Select the Switch Action

For the switch action, we will be switching on the mode

Switch based on Mode

Next, we add a case for the createfolder mode.

In this case, we will create our logic to create a folder using the standard actions the are provided making sure to set the FolderName variable on the way through.

Save this, and when we run this using a client Postman we get a response.

Postman client creating folder via Logic App endpoint
The folder is now created

Apply permissions based on a group name

Now things get a little interesting. For this case, we will extend the existing Logic App and add the ability to pass in a group name and have that used to grant access to the folder.

To get started we need to add another property to the HTTP Request call.

{ "properties": {
"mode": {
"type": "string"
},
"name": {
"type": "string"
},
"groupname": {
"type": "string"
}
},
"type": "object"
}
Update HTTP Request

Next, add another case to the switch statement.

Grant access switch case

Next, we need to get the ID of the folder for this SharePoint has an action called Get folder metadata. But first, we set the variable name up

Set Variable for FolderName

Next, we can get the folder metadata.

Get Folder Metadata

With the ID — we can now Grant access to the folder — however in this case it is the itemid that you need. Now, this is a pretty good call as you can just add the Group Name in Text and it will apply for the permissions.

Grant Access to an item or a folder

Add an HTTP request to respond (forgot to do this initially, but I also added a path to capture errors granting access).

And now we are ready to test using PostMan.

Testing grant access with PostMan

And all things going right — you are now able to see that Temporary Permission Group has access to our folder.

Permissions Granted

Remove Permissions

Now comes the fun part. For this we are going to need to perform the following actions:

  • Accept the Group Name and fetch the group ID
  • Get the Permissions on the Folder
  • From the permissions, determine the ID of the permission that relate to the group's permission
  • Update Permissions on the folder

Now, there may be a more efficient way to do this — this way you get to see each step on the way through.

To start we will need to add a couple more variables to the logic app to handle this scenario. The first is removepermissions — an array-based variable. And the second is groupid — an integer-based variable. Add these above the switch statement.

Additional variables for removing access scenario

Then we will need to add a new condition to our switch statement

Remove access switch case

Like the other scenarios, we will set our folder name variable.

Set Folder Name

Next, we need to get the Group ID of the SharePoint Group. For this will need to make an API call to Sharepoint. From the SharePoint actions select Send an HTTP Request to SharePoint

Get Group ID using the SharePoint Send HTTP Request to SharePoint Call

Because we are using the Send an HTTP request to SharePoint call, the Logic App is not going to know the shape of the data coming back. To overcome this we will use the Parse JSON step.

{
"properties": {
"d": {
"properties": {
"AllowMembersEditMembership": {
"type": "boolean"
},
"AllowRequestToJoinLeave": {
"type": "boolean"
},
"AutoAcceptRequestToJoinLeave": {
"type": "boolean"
},
"Description": {
"type": "string"
},
"Id": {
"type": "integer"
},
"IsHiddenInUI": {
"type": "boolean"
},
"LoginName": {
"type": "string"
},
"OnlyAllowMembersViewMembership": {
"type": "boolean"
},
"OwnerTitle": {
"type": "string"
},
"PrincipalType": {
"type": "integer"
},
"RequestToJoinLeaveEmailSetting": {},
"Title": {
"type": "string"
}
},
"type": "object"
}
},
"type": "object"
}

This is a large object to get back in response, and most of it we will not need. So to streamline things a little I adjust this back so that I just get the elements of the response I need.

{
"properties": {
"d": {
"properties": {
"Id": {
"type": "integer"
}
},
"type": "object"
}
},
"type": "object"
}
Simplified Parse JSON step

With our group id returned, we will need to set the groupid variable.

Set the Group ID variable

The next step we need the get the permissions on the folder. We will use the Send an HTTP Request to SharePointaction again. But this time we will use the Role Assignments API. For this will hit the following endpoint:

_api/web/getFolderByServerRelativeUrl(‘/Shared Documents/@{variables(‘BaseFolder’)}@{variables(‘FolderName’)}/’)/ListItemAllFields/RoleAssignments?$expand=RoleDefinitionBindings`
Get the Permissions API call.

Note: I am using a Document Library at the root of my SharePoint site for illustrative purposes. If you are using sites, you may need to adjust the path that you use when using this call.

As with the group id API call we will get back a large object. For our purposes, I have trimmed the object back to the bare essentials.

{
"properties": {
"d": {
"properties": {
"results": {
"items": {
"properties": {
"PrincipalId": {
"type": "integer"
},
"RoleDefinitionBindings": {
"type": "object"
}
},
"required": [
"RoleDefinitionBindings",
"PrincipalId"
],
"type": "object"
},
"type": "array"
}
},
"type": "object"
}
},
"type": "object"
}

This will bring back an array of elements, from this we will need to match the PrincipalID with the group id. For this:

  • Create a For Each loop
  • Check if the PrincipleID is equal to the groupid
  • If PrincipleIDand groupidvariable are equal; append the Current Item to the removepermission array-based variable.
Populate the removepermission array

With the removepermissionarray populated, we now need to use this to make the API call to remove the SharePoint permissions.

Create a For Each step and use the removepermissionvariable.

Next — for each object in that array we will need to map out the ID of the permissions. For this, we use a Parse JSON step again.

Parse removepermission object in array

For this step, we are using the following schema

{
"type": "object",
"properties": {
"RoleDefinitionBindings": {
"type": "object",
"properties": {
"results": {
"type": "array",
"items": {
"type": "object",
"properties": {
"Id": {
"type": "integer"
}
},
"required": [
"Id"
]
}
}
}
},
"PrincipalId": {
"type": "integer"
}
}
}

Note: This Parse JSON step can be combined with the one above — however, you will end up with two nodes called results (!!) which will make it hard to determine which one to use (again — we are aiming for obvious)

Within the same For Each look, create a new For Each loop that will process the array of permissions.

And within the for each loop we will make our remove permission API call using the groupidvariable, the role definition ID from our previous API call.

_api/web/getFolderByServerRelativeUrl('/Shared Documents/@{variables('BaseFolder')}@{variables('FolderName')}/')/ListItemAllFields/RoleAssignments/removeroleassignment(principalid=@{variables('groupid')},roleDefId=@{items('Remove_Access:_Go_through_each_to_remove_permission')?['Id']})

Finish this off with a response, and we are done.

Remove Access Potion of Logic App

Finally, we do a little test to ensure everything is working.

PostMan test to confirm the removal of permissions
Permission Removed

Wrap Up Time

Beyond the next level silliness involved in removing the permissions of a user — this was a straight forward process. Given the low code and flexible nature of the Azure Logic App / Power Automate environment means that you can do a lot without laying down a lot of code.

There are traps here that I have not covered here:

  • Scale, especially when you start to get into extremely large Azure Logic App — As you scale you might want to look at splitting off functions.
  • And security — this ties into the above point. Once you start passing off data to other Logic App you might want to look at implementing API management or other mechanisms to limit the access

Matthew Barben is a co-founder, EIM consultant at Driver Lane. You can follow Driver Lane on Twitter, and LinkedIn, or directly on our website.

--

--