Azure Functions, PnP PowerShell, Managed Identity and SharePoint Online

kkazala

Kinga

Posted on October 14, 2022

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
💖 💪 🙅 🚩
kkazala
Kinga

Posted on October 14, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related