Azure Functions, PnP PowerShell, Managed Identity and SharePoint Online
Kinga
Posted on October 14, 2022
EDIT 2002.11.13: What a time to be alive! 🙃 Since version 1.11.95-nightly, Managed Identities are both supported against SharePoint Online as well as Microsoft Graph cmdlets. 🎉 🥳 🎊
Decide how you want to authenticate in your Azure Function: By using a Managed Identity
Most of this blog post is still valid. In the profile.ps1 however, simply use
Connect-PnPOnline -ManagedIdentity
from now on.
If you followed Using PnP PowerShell in Azure Functions and now try to connect to your SPO site using
Connect-PnPOnline -ManagedIdentity
you will get The current connection holds no SharePoint context.
Access token
You can still use the managed identity though. You just need additional step, to connect to Azure services in app code:
profile.ps1
$resourceURI ="https://<yourtenant>.sharepoint.com"
$siteUrl="https://<yourtenant>.sharepoint.com/sites/<yoursite>"
if ($env:MSI_SECRET) {
$tokenAuthURI = $env:MSI_ENDPOINT + "?resource=$resourceURI&api-version=2017-09-01"
$tokenResponse = Invoke-RestMethod -Method Get -Headers @{"Secret" = "$env:MSI_SECRET" } -Uri $tokenAuthURI
$accessToken = $tokenResponse.access_token
Connect-PnPOnline -Url $siteUrl -AccessToken $accessToken
#Invoke Get-PnPSite to test
}
The $env:MSI_SECRET
and $env:IDENTITY_HEADER
return the same values. And so do $env:MSI_ENDPOINT
and $env:IDENTITY_ENDPOINT
.
run.ps1
$listTitle = "<yourlistname>"
try{
$connection = Get-PnPConnection
$list = Get-PnPList -Identity $listTitle -Connection $connection
$item = Add-PnPListItem -List $list -Values @{"Title" = "item 4" } -Connection $connection
Write-Host "Item created"
}
catch{
Write-Host "ERROR CREATING ITEM"
Get-Error
}
Minimum required permissions
And since I believe in assigning minimum required permissions, the managed identity has only Sites.Selected
API permissions for Graph API and SPO.
Setup.ps1
function Set-AzureADPermissions_SitesSelected {
param(
$tenantId,
$appDisplayName
)
Connect-AzureAD -TenantId $tenantId
$GraphAppId = "00000003-0000-0000-c000-000000000000" # Microsoft Graph
$SPOAppId = "00000003-0000-0ff1-ce00-000000000000" # SharePoint Online
#Retrieve the Azure AD Service Principal instance for the Microsoft Graph (00000003-0000-0000-c000-000000000000) or SharePoint Online (00000003-0000-0ff1-ce00-000000000000).
$servicePrincipal_Graph = Get-AzureADServicePrincipal -Filter "appId eq '$GraphAppId'"
$servicePrincipal_SPO = Get-AzureADServicePrincipal -Filter "appId eq '$SPOAppId'"
$permissionName = "Sites.Selected"
$SPN = Get-AzADServicePrincipal -Filter "displayName eq '$appDisplayName'"
Start-Sleep -Seconds 10
# Use application permissions. Delegate permissions cannot be utilized using a Managed Identity.
# $servicePrincipal_Graph.AppRole | Where-Object { $_.AllowedMemberType -eq "Application" -and $_.Value -eq "Sites.Selected"}
$appRole_Graph = $servicePrincipal_Graph.AppRoles | Where-Object { $_.AllowedMemberTypes -eq "Application" -and $_.Value -eq $permissionName }
$appRole_SPO = $servicePrincipal_SPO.AppRoles | Where-Object { $_.AllowedMemberTypes -eq "Application" -and $_.Value -eq $permissionName }
# Grant API Permissions
New-AzureAdServiceAppRoleAssignment -ObjectId $SPN.Id -PrincipalId $SPN.Id -ResourceId $servicePrincipal_Graph.ObjectId -Id $appRole_Graph.Id
New-AzureAdServiceAppRoleAssignment -ObjectId $SPN.Id -PrincipalId $SPN.Id -ResourceId $servicePrincipal_SPO.ObjectId -Id $appRole_SPO.Id
# Write-Host "Now grant access to SPO site using the following:"
# Write-Host "App Id: $($SPN.AppId)"
# Write-Host "App Name: $($SPN.DisplayName)"
return $SPN.AppId
}
function Set-PnPSiteAccess{
param(
$siteUrl,
$appId,
$appName,
$permission
)
Connect-PnPOnline -Url $siteUrl -Interactive
Grant-PnPAzureADAppSitePermission -AppId $appId -DisplayName $appName -Site $siteUrl -Permissions $permission
}
$appId= Set-APIPermissions -tenantId $tenantId -appDisplayName $appName
Set-PnPSiteAccess -siteUrl $siteUrl -appId $appId -appName $appName -permission Write
Posted on October 14, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.