SOLVED

Microsoft Graph PowerShell SDK Module OneDrive Folder Permissions Assignment

Copper Contributor

As an M365 Global Admin, I have been tasked with creating a new folder in other users OneDrive root folder (Documents) we can call that folder 'myFolder', then I need to assign a Microsoft Azure Security group ('myGroup') to that folder with read/write permissions. I have a list of users (taking input from txt file of UPNs), and am able to loop through the users and create the folder, so step one is possible, but where I am failing is the assignment of the permissions, am using PowerShell 7 and the MS Graph PowerShell Mod, actually for the folder creation I used the API and invoke-method, but I am running into problems since OneDrive is on top of SharePoint, I am not sure how to accomplish this task. Any help would be greatly appreciated!

11 Replies
best response confirmed by ShaneGibson (Copper Contributor)
Solution

It would be helpful if you posted some code snippets for the Graph request.

I am not sure if you are stuck with Microsoft Graph PowerShell, but I was able to do what you needed to do with PnP PowerShell:

$url = "<ONEDRIVEURL>"
Connect-PnPOnline -Url $url -Interactive
$oneDriveDefaultListName = "Documents"
$folderToCreate = "myFolder"
$securityGroupToAdd = "Group1"
$permission = "Contribute"
Add-PnPFolder -Name $folderToCreate -Folder $oneDriveDefaultListName
Set-PnPFolderPermission -List $oneDriveDefaultListName -Identity "$oneDriveDefaultListName/$folderToCreate" -User $securityGroupToAdd -AddRole $permission

If you are stuck with Graph API (and Azure Security Groups), maybe take a look at these links:

 

Send an invite to access an item - Microsoft Graph v1.0 | Microsoft Learn


https://learn.microsoft.com/en-us/graph/api/resources/driverecipient?view=graph-rest-1.0#properties

@Tristan999 

Thank you for your reply, I greatly appreciate it! 

 

I will have to check into PnP I guess but here is what I have so far it is failing exactly at the invoke call as you pointed out, in your url for invite, that is where I have made it too!

These are the permissions that the connection has in Azure App:
GENERIC APP REG Permissions (Application)
TeamSettings.ReadWrite.All
Mail.ReadWrite
User.ReadWrite.All
Directory.ReadWrite.All
TeamsActivity.Send
Team.Create
Group.ReadWrite.All
User.Invite.All
Files.ReadWrite.All
TeamMember.ReadWrite.All
ServicePrincipalEndpoint.ReadWrite.All
Team.ReadBasic.All
Calendars.ReadWrite
Mail.Send
RoleManagement.ReadWrite.Directory
GroupMember.ReadWrite.All
Sites.FullControl.All
TeamsTab.ReadWriteForTeam.All

The file "myFolder" already exists in this test scenario, here is my code:

Import-Module Microsoft.Graph.Files

Connect-MgGraph `
	-ClientId "{Some long GUID from when you created the Azure App}" # Get in Registered App Settings in Azure Portal `
	-TenantId "{Some long GUID of your Microsoft 365 Tenant}" # Can get in Azure Portal or in Registered App Settings in Azure Portal `
	-CertificateThumbprint "{Some long passphrase of letters and numbers}" Get when you created the Registered Azure App

#The Admin user that needs access to migrate files over from on-prem 2013 to online OneDrive4B
$adminUserUPN = "email address removed for privacy reasons"
$adminUser = Get-MgUser -Filter "UserPrincipalName eq '$adminUserUPN'"
$adminUserId = $adminUser.Id

#User selected for the test run
$userUPN = "email address removed for privacy reasons"
$user = Get-MgUser -Filter "UserPrincipalName eq '$userUPN'"
$userId = $user.Id

$userOneDrive = Get-MgUserDrive -UserId $userId
$userDriveId = $userOneDrive.Id
$userDriveItems = Get-MgUserDriveListItem -DriveId $userDriveId  -UserId $userId
$userFolder = Get-MgUserDriveListItem -DriveId $userDriveId -UserId $userId -Search "Documents" | Where-Object { $_.WebUrl -like "*myFolder*" }
$userFolderId = $userFolder.Id

$params = @{
	recipients = @(
		@{
			email = $userUPN
		}
	)
	message = "it worked"
	requireSignIn = $true
	sendInvitation = $true
	retainInheritedPermissions = $true
	roles = @(
		"write"
	)
}

Invoke-MgInviteDriveItem -DriveId $userDriveId -DriveItemId $userFolderId  -UserId $userId -BodyParameter $params

#I have also tried these and fail, I wonder given the error at times if the DriveItemId is correct or not
#New-MgUserDriveItemPermission -DriveId $userDriveId -DriveItemId $userFolderId  -UserId $userId -BodyParameter $params
#Grant-MgUserDriveItemPermission -DriveId $userDriveId -DriveItemId $userFolderId  -UserId $userId -BodyParameter $params

@ShaneGibson 

 

Can you post the error that you get from running the command?

Invoke-MgInviteDriveItem

 Also, your original post talked about using a Security Group. Is it a mail-enabled group? 

 

I posted the link for the drive recipient just in case it is not a mail-enabled group. In which case, you may want to use something like the alias or objectid instead of email:

 

Tristan999_0-1696869416959.png

 

Tristan999_1-1696869565129.png

 

 

$params = @{
recipients = @(
@{
alias = $userAlias
}
)
message = "it worked"
requireSignIn = $true
sendInvitation = $true
retainInheritedPermissions = $true
roles = @(
"write"
)
}

 

Here are some additional resources, you may want to look at 

 

Graph Explorer | Try Microsoft Graph APIs - Microsoft Graph

 

I'll take a look at your code later and test it out on my end. 

 

Just to confirm the PnP Powershell does work, I would still like to get it done in Graph, but wanted to say that my test with PnP Powershell with your post worked properly! I did have to add myself as a site collection admin on the onedrive site though. I will post error and answer questions for MS Graph after my meeting but thank you again for the help, greatly appreciate it!
No problem! PnP is just a wrapper, in the backend it's probably using Graph/CSOM. Yes, I forgot to mention that you will have to add two additional lines to add yourself to the site collection admin for one drive that you do not own and then remove yourself.

@Tristan999 Again, can't thank you enough for the help, greatly appreciated it! Right now I am just trying to get it to work with a single user via email (Which is the same as the UPN in our case) trying to keep it simple! But yeah I was thinking ObjectId would be the best for the security group once I got that far as it is NOT an Microsoft 365 group (Or email enabled group) but a classic "Security" group object in Azure AD portal. The error I get for Invoke-MgInviteDriveItem command is the following:

 

PS C:\> Invoke-MgInviteDriveItem -DriveId $userDriveId -DriveItemId $userFolderId  -BodyParameter $params

Invoke-MgInviteDriveItem_Invite: The resource could not be found.

Status: 404 (NotFound)
ErrorCode: itemNotFound
Date: 2023-10-09T17:35:29

Headers:
Cache-Control                 : no-store, no-cache
Transfer-Encoding             : chunked
Vary                          : Accept-Encoding
Strict-Transport-Security     : max-age=31536000
request-id                    : b7639245-1f38-4e2c-abbb-0d0a1c7967ea
client-request-id             : 800ea0c0-950b-44a5-a08a-032da706caf5
x-ms-ags-diagnostic           : {"ServerInfo":{"DataCenter":"North Central US","Slice":"E","Ring":"3","ScaleUnit":"000","RoleInstance":"CH01EPF0000D3FC"}}
Link                          : <https://developer.microsoft-tst.com/en-us/graph/changes?$filterby=v1.0,Removal&from=2021-09-01&to=2021-10-01>;rel="deprecation";type="text/html",<https://developer.microsoft-tst.com/en-us/graph/changes?$filterby=v1.0,Removal&from=2021-09-01&to=2021-10-01>;rel="deprecation";type="text/html"
Deprecation                   : Fri, 03 Sep 2021 23:59:59 GMT
Sunset                        : Sun, 01 Oct 2023 23:59:59 GMT
Date                          : Mon, 09 Oct 2023 17:35:28 GMT


When I run it and put in the eTag id instead of the driveItemId

PS C:\> $userFolder

CreatedDateTime      Description ETag                                     Id LastModifiedDateTime Name WebUrl
---------------      ----------- ----                                     -- -------------------- ---- ------
10/2/2023 6:26:05 PM             "f2c5a1f9-06f8-****-****-de18****8bc4,4" 1  10/9/2023 4:26:15 PM      https://tenant-my.sharepoint.com/personal/john_smith_tenant_onmicrosoft_com/Documents/myFolder

Just the GUID part I end up with this outcome, but the user does not end up added when looking at the permissions

PS C:\> Invoke-MgInviteDriveItem -DriveId $userDriveId -DriveItemId f2c5a1f9-****-****-9840-de********c4  -BodyParameter $params

Id                                                                     ExpirationDateTime HasPassword Roles   ShareId
--                                                                     ------------------ ----------- -----   -------
aTo*********WJlcnNoaX**********ZW5lc2lzQDB3bHNnLm9**********2Z0L**vbQ                                {write}


The  expected outcome for the script when it runs and does not error out is to see the user listed on the folder permissions which doesn't happen, still shows the old permissions of only the owner listed for the folder

I thought Grant-MgUserDriveItemPermission might be the golden ticket since I am running under an AppOnly Application Connection and not delegate it might need the MgUser piece in the command as we are trying to manipulate another OneDrive users Drive and not our own, but it ends for me at the "PermissionId" because I am not sure what that is meaning, i.e. is that the id assigned to the contribute permision object itself for the site collection, and if so how I get that from graph, I do not know!:

PS C:\> Grant-MgUserDriveItemPermission -DriveId $userDriveId -DriveItemId f2c5a1f9-****-****-9840-de********c4 -UserId $userId -BodyParameter $params

cmdlet Grant-MgUserDriveItemPermission at command pipeline position 1
Supply values for the following parameters:
PermissionId:


Of course that could just be a wild goose chase too! Thanks again for the help on this!
SG.




 

@ShaneGibson 

 

So, I found a few things when using the Graph and your code:

 

#1:

 

$userDriveItems = Get-MgUserDriveListItem -DriveId $userDriveId -UserId $userId
 
** Much like the PnP solution, if you do not have access to the User's OneDrive, this request will return null. So, you'll have to take a look at the following:
 
  • Check/Add your access to the site collection admin.
  • Remove after the request is done. For my test, I just added/removed it through the OneDrive UI. 

 

#2:

 

The drive item id is not what you would expect it to be, i.e., it's not the list item id from SharePoint. I wanted to timebox the amount of time I spent. So, I cheated by using the Graph Explorer site and got the id from there (It looks like you will have to do some investigation using the command Get-MgDriveItemChild:(

 

Tristan999_0-1696885005671.png

 

#3:

 

I was getting an error with the -UserId param, so I just removed it and replaced the drive item id I got from graph explorer:

 

Invoke-MgInviteDriveItem -DriveId $userDriveId -DriveItemId "01TWBMQNWPEDAAW7ZE25EYOD5TZPWGX3EF" -BodyParameter $params

 

I did get an email. However, when I click the link I get an access denied. You will have to take a look at that issue (perhaps try to play around your params OR check this link Change sharing permissions - Microsoft Graph v1.0 | Microsoft Learn)

 

Tristan999_1-1696885450147.png

 

Hopefully, this helps you a lot :) 

 

 

The issue for the access denied was $retainInheritedPermissions = $true. You will need to set this to false as it would prevent the permission from being modified.

You'll need to replace:

 

$userDriveItems = Get-MgUserDriveListItem -DriveId $userDriveId  -UserId $userId
$userFolder = Get-MgUserDriveListItem -DriveId $userDriveId -UserId $userId -Search "Documents" | Where-Object { $_.WebUrl -like "*myFolder*" }
$userFolderId = $userFolder.Id

 

To get the actual drive item id for your folder, you will need to use the following commands:

1. $rootDriveId = (Get-MgDriveRoot -DriveId $userDriveId).Id
2. $myFolderDriveItemId = (Get-MgDriveItemChild -DriveId $userDriveId -DriveItemId $rootDriveId | ? {$_.Name -eq "myFolder"}).Id

 

If you execute the commands directly, you should see something like this 

 

Tristan999_0-1696894651488.png

 

Please like and mark as best response if this helped you :)

In the PnP Online code example, I had a question for the $securityGroupToAdd = "Group1" parameter, was this an AzureAD classic security group, a Microsoft 365 security group, or a SharePoint Site Collection Security Group?

I used the script above for one project they are wanting to adapt it to add an AzureAD classic security group that has no email, so just curious if you got that to work or not because my attempts fail and there is no -group attribute on Set-PnPFolderPermission function.

Thanks again for all your help!

Group1 is an Azure AD Security Group (in all the examples). The Set-PnPFolderPermission User parameter does not distinguish between an Azure Security Group and a user (email address removed for privacy reasons). I haven't tried using a SharePoint group with that command, but according to the documentation here https://pnp.github.io/powershell/cmdlets/Set-PnPFolderPermission.html, the -Group parameter seems to be used if you want assign permissions to a SharePoint group.

FYI. In the case, of the Graph example, even though the group was not mail-enabled, the group members still received emails since those accounts have emails tied to them.

Hopefully that helps!
1 best response

Accepted Solutions
best response confirmed by ShaneGibson (Copper Contributor)
Solution

It would be helpful if you posted some code snippets for the Graph request.

I am not sure if you are stuck with Microsoft Graph PowerShell, but I was able to do what you needed to do with PnP PowerShell:

$url = "<ONEDRIVEURL>"
Connect-PnPOnline -Url $url -Interactive
$oneDriveDefaultListName = "Documents"
$folderToCreate = "myFolder"
$securityGroupToAdd = "Group1"
$permission = "Contribute"
Add-PnPFolder -Name $folderToCreate -Folder $oneDriveDefaultListName
Set-PnPFolderPermission -List $oneDriveDefaultListName -Identity "$oneDriveDefaultListName/$folderToCreate" -User $securityGroupToAdd -AddRole $permission

If you are stuck with Graph API (and Azure Security Groups), maybe take a look at these links:

 

Send an invite to access an item - Microsoft Graph v1.0 | Microsoft Learn


https://learn.microsoft.com/en-us/graph/api/resources/driverecipient?view=graph-rest-1.0#properties

View solution in original post