Introduction

Trying out the new way to Provision via PnP PowerShell V4 and Azure Functions V3 was a little challenging at first. There are some of the difference and issues that I encountered which I could not get to work correctly. I happen to be one of the early ones that need to do this because Azure had made a change to their interface which prevented using PnP PowerShell V3 and the Microsoft documentation was not updated. Since that time and now Microsoft has updated their online documentation with examples of the exact steps. I’ve decided to post the process I used to get everything working but I still suggest reading the official Microsoft article as well.

Install PnP.PowerShell

  1. Open PowerShell 7 (if not installed, please install from here – https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-core-on-windows?view=powershell-7.1)
  2. Run the following cmdlet to install the PnP.PowerShell module

Install-Module -Name "PnP.PowerShell" -RequiredVersion "1.5.0"

Set up app-only access to your tenant

  1. Open PowerShell 7 and run the following cmdlets to register an Azure App

Select the appropriate tenant name before running.

Register-PnPAzureADApp -ApplicationName "PnPProvisioningDemo" -Tenant "<tenant-name>.onmicrosoft.com" -DeviceLogin -OutPath .

Follow the instructions to complete the Azure AD App registration. You will need to open a browser and enter the url above and supply the code. You will also be asked to log in.

This will now take 60 seconds to create the certificate in the out path that was specified in the above command

  • After the cmdlet is executed. It will create a PFX file. Keep this file saved, as we will have to upload it to Azure function.
  • Login to https://aad.portal.azure.com/
  • Click -> Azure Active Directory -> App Registration
  • Search for ‘PnPProvisioningDemo’ and the select the App Registration which got created. Copy the Application (client) ID from here.
  • Click API Permission
  • Click API Permissions, and Grant admin consent for {tenant}
  • In the small popup click Yes to approve this app those permissions.

Create the Azure function

  • Type in ‘Function’ and select ‘Function App’
  • In the Project Details, click on Create New, for the Resource Group
  • Type in ‘PnPProvisioningDemo’ for the resource group name, click OK

  • Enter in a Function App name – this will need to be unique, Runtime Stack, Version and select a Region in which you want the resources inr its created, navigate to your new function App
  • From the dropdown menu, select host.json file and add the following entry and save it.
  • Click ‘Review + create’
  • Click ‘Create’

After a few moments all of the assets will be created.

  • Click ‘Go To Resource’
  • Next click on ‘App Files’
  • I typically bump the timeout to 10 mins for the Azure Function from the default 5 minutes.
  • In the App Files > host.json, add this line. Make sure to use a ‘,’ on the previous line
"functionTimeout": "00:10:00"
  • Click Save to lock in the changes
  • Click on the dropdown and select requirements.psd1
  • You can remove the ‘Az’ = ‘5.*’ as it won’t be used
  • Click Save to lock in the changes
  • Create a new Azure Function Functions > Add:
  • Create a new HTTP Trigger function, by selecting the options as shown below
  • Scroll down, name the function InvokePnPSiteTemplate
  • Set Authorization level, Anonymous
  • Click Save

Upload the code for your Azure Function

  • Go to the Function App main screen and select Advanced Tools
  • Click “Go”, this will open Kudu
  • Select “PowerShell” from the Debug Console menu at the top.
  • Navigate to site\wwwroot\InvokePnPSiteTemplate

This is where it gets complicated. Hold on to your hats.

Extract the AzureFunCode.zip file provided as a sample.

  • Add your PnP template into the pnp-template.xml file
  • Update run.ps1
    • set $filePath to the correct drive [C or D] that you see in the azure portal
  • set $AzAppId to match your Azure App Id
    • set $certFileName to match your exported certificate
    • set $tenant to match your tenant prefix
  • Drag & drop the files to the site\wwwroot\InvokePnPSiteTemplate directory

NOTE: If you want to use a different version of PnP PowerShell then you can generate the PnP.PowerShell files for upload from the command line. Use the folder that is exported to upload.

Create a new folder and then execute the following commands

Save-Module PnP.PowerShell . 
  1. After the code is updated. Navigate back to Function screen on Azure portal and click on ‘Get Function Url’ and copy the URL

Create the Flow

  1. Go to the Power Automate site, sign in, and choose Create -> Automated Cloud Flow
  2. Click Skip at this screen
  1. Click ‘untitled’ and give the Flow a name, PnPProvisioningDemo
  1. Search for Request, and select Request – When a HTTP Request is received.
  1. Enter the following JSON as your request body:
{
    "type": "object",
    "properties": {
        "webUrl": {
            "type": "string"
        },
        "parameters": {
            "type": "object",
            "properties": {
                "event": {
                    "type": "string"
                },
                "product": {
                    "type": "string"
                }
            }
        }
    }
}
  • Select + New Step and choose Add an action.
  • In the search box type ‘http’ and click HTTP
  • Configure the properties as shown below.
  • You also need the Azure Function, HTTP endpoint. This is in the Azure Function, Overview screen, click Get Function Url
  • Copy this http endpoint to then paste into the flow
  • Choose Save Flow. This will generate the URL that you will copy in the next step.
  • Back in the Flow, Paste the URI in this box
  • Save the Flow
  • Once save is completed, click back on the first step and copy the Flow HTTP Post Url. Save this for later

Create the Site Design

In this section we are going to create a SharePoint Site Design, based on a Team Site template.

  1. Open SharePoint Online Management Shell and connect to your tenant using Connect-SPOService
Connect-SPOService -Url https://[yourtenant]-admin.sharepoint.com
  • Update the URL property in the code below. Set the url property to the value you copied when you created the flow
{
  "$schema": "schema.json",
  "actions": [
   {
      "verb": "triggerFlow",
      "url": "{UPDATE THE FLOW URL HERE}",
      "name": "Apply PnP Template",
      "parameters": {}
    }
  ],
  "bindata": {},
  "version": 1
}
  • Select the JSON again and copy it, this will put it on your ‘clipboard
  • Open PowerShell and enter the following to copy the script into a variable and create the site script:
$script = Get-Clipboard -Raw
#before the next step verify you have data in $script by typing this
$script
#if that is empty try the copy and run the first line again.
Add-SPOSiteScript -Title "Contoso Team Config" -Content $script
Get-SPOSiteScript
  • You will see a list of one or more site scripts, including the site script you just created. Select the ID of the site script that you created and copy it to the clipboard.
  • Use the following command to create the site design:
Add-SPOSiteDesign -Title "Contoso Team" -SiteScripts {Paste the ID of the Site Script here} -WebTemplate "64"

Conclusion

That completes all the necessary steps to get the basics up and running. Hope this was helpful walkthrough to make your first time getting started a little easier. The screens are constantly changing in Office 365 but the basics steps should remain the same. Leave a comment below if you get stuck or have a suggestion.

About the Author

Developer, Designer, Thinker, Problem Solver, Office Servers and Services MVP, & Collaboration Director @ SoHo Dragon.

View Articles