DEV Community

Kinga
Kinga

Posted on β€’ Edited on

3

Azure Functions, PnP PowerShell, Managed Identity and SharePoint Online

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
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

Sentry image

See why 4M developers consider Sentry, β€œnot bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

πŸ‘‹ Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay