Create Sharepoint Site with Azure Function using PowerShell

Business Case
Create SharePoint site based on user requirement without SharePoint Admin manually performing the task.

Design
A SharePoint List is created and shared with designated users to enter the desired SharePoint site criteria. Using an Azure function with PnP PowerShell module (compatible with PowerShell core in Azure function) to periodically check if any new entry in the SharePoint List and create SharePoint site based on the user entered criteria.



Create a SharePoint List
Create a new SharePoint List. In this example, it is named as NewSiteList.


Create necessary fields/columns to capture new SharePoint site criteria.


Create an account to access SharePoint List
Create an account in Azure AD which would be used by the Azure function to access the SharePoint List. Similar account is also used to create SharePoint site.

Grant account permission
Grant the account read (and write access in needed to update the list) access to the list. 


Check the setting where user can create site or set site creation permission accordingly.


Create Azure function
Select code and PowerShell Core as runtime stack with PowerShell 7.0


Store user credential in Azure Key Vault
Azure Key Vault is used to store the credential safely. In order for Azure function to access the Secret in the Key vault, an identity is created for Azure function, and the identity is used for granting access permission in Key vault.

Under identity, on System assigned tab, create system managed identity by selecting On for the status. Copy the Object ID for later use.


Create Key Vault.


Create a Secret each for user and password


Copy the secret identifier for user and password


Grant Get access to Secret for the Azure function system managed identity created earlier


Create new application settings each for the user and password in the Azure function.
Back to Azure function, under Configuration, create new application setting with a name and the secret identifier created previously.

The format of the value is 
@Microsoft.KeyVault(SecretUri=<secret identifier>)

More information in this article,
https://docs.microsoft.com/en-us/azure/app-service/app-service-key-vault-references#reference-syntax


Configure PnP PowerShell Shell permission
Admin permission is required to grant permission to PnP PowerShell shell to execute Microsoft Graph API on behalf of the user. 

To grant permission, execute the following command locally with an Azure AD admin account (with Application Admin role), it would prompt to grant admin permission the first time.

Connect-PnPOnline -Url https://test.sharepoint.com/sites/test -Interactive

Admin consent can be also granted through Azure AD enterprise application.


Setup PnP PowerShell Module in Azure function
Option 1, use dependency requirement specified in the requirement.psd1 file


Option 2, via Kudu, create a Modules folder under site/wwwroot. Copy (drag and drop) the PnP.PowerShell module (downloaded to PC) to the Modules folder.



Azure function code
Add new function. Select Time Trigger to periodically trigger every 5 minutes.


Azure function code



##If using the option 2, import the module with the path
Import-Module -Name C:\home\site\wwwroot\Modules\PnP.PowerShell

##Retrieve user credential from application setting where the source is from the secrets stored in key vault.
$user = $env:spfunctionuser
$pw = $env:spfunctionpw | ConvertTo-SecureString -AsPlainText
$cred = New-Object System.Management.Automation.PSCredential($user, $pw)

##Connect to SharePoint site where the SharePoint list is hosted 
Connect-PnPOnline -Url https://test.sharepoint.com/sites/test -Credentials $cred -ErrorAction Stop

##Only get the entries where SiteCreated is 'No' using CAML filter query
$sites = Get-PnPListItem -List lists/newsitelist -Query "<View><Query><Where><Eq><FieldRef Name='SiteCreated'/><Value Type='Integer'>0</Value></Eq></Where></Query></View>"

##Loop through the entries and create the site based on the criteria provided, and update the SiteCreated field of the entry.
if ($sites) {
    $sites | ForEach-Object { 
        New-PnPSite -Title $_.FieldValues.Title `
            -Type $_.FieldValues.SiteType `
            -Url $("https://test.sharepoint.com/sites/$($_.FieldValues.Title)") `
            -ShareByEmailEnabled:$_.FieldValues.ShareByEmailEnabled `
            -SiteDesign $_.FieldValues.SiteDesign `
            -Owner $_.FieldValues.SiteOwner.Email

        if ($?) {
            Write-Output "site created"
            Set-PnPListItem -List lists/newsitelist -Identity $_.Id -Values @{"SiteCreated" = 1}
        }
    }
}


Once the Azure function schedule trigger the execution, new SharePoint Site is created accordingly. Success!


Instead of executing Azure function with a schedule, potential improvement is to leverage SharePoint webhooks to notify, for example via Azure queue to invoke Azure function when there is new entry in the SharePoint List.

No comments:

Post a Comment