How to use PnP PowerShell on Azure Functions with application permissions

How to use PnP PowerShell on Azure Functions with application permissions

Last updated on November 3, 2024

Whenever I’ve previously instructed other developers on how to use the PnP.PowerShell module on Azure function apps with application permissions, I’ve often found myself referencing a subsection of an article I’ve previously written with some modifications. After doing it a few times, I figured the instructions would be easier to follow if I included only the required steps in a separate article. So, here we are. In addition, the steps detailed in this article are more generalized instead of focusing on the original specific scenario.

In this article, I’ll present you two ways of authenticating to SharePoint Online with PnP PowerShell using application permissions:

  1. Using the Azure function system-managed identity (recommended)
  2. Using a self-signed certificate

Table of Contents

  1. Create an Azure Function App
  2. Add PnP.PowerShell to the required modules to load
  3. Enable the Function App’s Managed Identity
  4. Authenticating with the Azure Function managed identity
    1. Grant the managed identity permissions to SharePoint Online
    2. Add the script to the function app
  5. Authenticating with a self-signed certificate
    1. Create a self-signed certificate
    2. Create and configure an Entra ID application registration
    3. Create and configure an Azure Key Vault
    4. Add the certificate to the vault
    5. Finalize the Function App configurations
    6. Add the script to the function app

Create an Azure Function App

Let’s start by going to Azure Portal and creating a resource group and a function app. I’m assuming you have an Azure subscription set up at this point (hence I won’t give you instructions for creating one).

First, let’s create the resource group.

  1. Create a new resource group in your subscription with a descriptive name (adhere to your company’s naming conventions) and a region near you.
  2. You can optionally add tags. Otherwise, click Review + create.

After the resource group has been deployed, navigate to it and click the big blue Create a resource button.

  1. Search for Function App on the Marketplace. When you find it, click on Create.
  2. Ensure the correct subscription and the resource group you created earlier are selected.
  3. Give your function app a name (according to your organization’s naming conventions). This will also function as the URL prefix.
  4. Choose to publish your solution as Code.
  5. Select PowerShell Core as the runtime stack, and the latest version.
  6. Change the Region to the same one you chose when creating the resource group.
  7. Leave the Operating system to Windows and Plan type to Consumption.
  8. Go to the Hosting tab, click on Create new and rename the storage account according to your organization’s naming conventions.
  9. Go to the Monitoring tab, click on Create new and rename the application insights resource (and a new workspace) according to your organization’s naming conventions.
  10. You may optionally tag the resource. Otherwise, click Review + create.

Add PnP.PowerShell to the required modules to load

We’ll also be using the version 2 of PnP PowerShell Core which supports the managed identity authentication to SharePoint Online. If your script is still using version 1, I highly recommend updating your script to use the version 2 instead.

  1. Go to the Function App resource in Azure Portal.
  2. Open the App files blade.
  3. Select requirements.psd1 from the dropdown.
  4. Add a reference to the PnP.PowerShell module. The managed identity authentication requires version 2 of PnP.PowerShell while authentication with a certificate is also possible in version 1.
  5. Managed identity authentication also requires Azure modules, namely the Az.Accounts and Az.ManagedServiceIdentity modules. I recommend installing these two Azure PowerShell modules (and other possible Az modules required by your script) explicitly instead of installing the entire Az module collection because the latter takes a really long time and results in a lot of hassle when it comes to installing the dependencies for the first time (namely, the function timeouts on a consumption plan). The file should now look something like the one below.
  6. Remember to Save the changes.

If you are going to be authenticating with a certificate and do NOT need to use any Azure modules in your function script, you need to do the following; otherwise, your script will produce an error.

  1. Still on the App files blade, select profile.ps1 from the dropdown.
  2. Comment out the four lines of code. After that, there should not be executable code present in the file.

  3. Remember to Save the changes.

Enable the Function App’s Managed Identity

Now, we need to enable the function app’s system managed identity. We can either use this identity directly for authentication, or alternatively use it to fetch the certificate for authentication from an Azure Key Vault. Either way, the managed identity always needs to be enabled.

  1. Open the Identity blade
  2. Change the system assigned managed identity Status to On.
  3. Click on Save and Yes when prompted
  4. Copy the Object ID that appears upon saving to, e.g., Notepad. You’ll need this later.

Authenticating with the Azure Function managed identity

Today, PnP.PowerShell supports authenticating to SharePoint Online with Azure managed identities. I highly recommend you use this approach whenever possible instead of setting up a certificate. Configuring certificate authentication requires additional effort and the method is not as secure as using a managed identity because it is always possible that the certificate may get leaked.

Grant the managed identity permissions to SharePoint Online

Run the script below to assign the managed identity the minimum permissions required by the operation(s) you wish to execute on the SharePoint Online API. The user executing the script needs to have either Application administrator, Cloud application administrator or Global administrator role. Note: you may need to assign other permissions depending on what you want to do via PnP.PowerShell. This is just an example.

Add the script to the function app

After deploying the function app resource, click Go to resource and perform the following configurations.

  1. Open the Functions blade.
  2. Create a new function:
    • Leave Development environment to its default value (Develop in portal).
    • Select the type of trigger you want to use.
    • Give your function a descriptive name.
    • Configure the rest of the available settings (depending on the selected trigger type).
    • Click on Create.
  3. Click on Code + test in the navigation.
  4. Finally, include the following lines in your PowerShell script to implement authentication using the certificate, and click on Save.

Authenticating with a self-signed certificate

As I mentioned at the beginning of this article, it is also possible to authenticate to PnP PowerShell with a certificate (which we will create in just a moment). We’ll store that certificate in an Azure Key Vault (which we will also create in just a second). Our function app will to fetch that certificate from the key vault with the previously enabled managed identity.

In the past, authenticating with a certificate was the only way; it was not possible to authenticate with a managed identity. Today, I highly recommend you to authenticate with the managed identity directly as setting up a certificate this way just requires additional effort and it is not as secure as the managed identity because it is always possible that the certificate may get leaked. However, I’ll leave these previously written instructions here just in case there is ever a bug or some other scenario which might require you to resort to authenticating with a certificate instead.

Create a self-signed certificate

We must generate a self-signed certificate for our PowerShell script to authenticate to SharePoint Online. This happens by executing the following script (after you’ve adjusted the $commonName and $password variable values). The certificate files will appear in the same directory where you execute the script.

Before running the script below, you must have the PnP.PowerShell module installed. Also, if you install PnP.PowerShell version 2.0.0 or higher, you need to run the script using PowerShell 7. You can find instructions for installing PowerShell 7 on Microsoft documentation.

Create and configure an Entra ID application registration

To be able to authenticate, we need to create a new application registration on Entra ID.

  1. On Azure Portal, click on Microsoft Entra ID on the left-hand side navigation. Then, select App registrations.
  2. Click on New registration
  3. Name the app registration after your function app. Otherwise, you can leave the settings to their default values and click on Register.

After creating the application registration, we must configure it with permissions and a certificate.

  1. In the application registration settings, as the first thing while you are still on the Overview blade, please copy the Application (client) ID to, e.g., Notepad. You’ll need it later!
  2. Then, go to the API permissions blade, and do the following. Note: you may need to assign other permissions depending on what you want to do via PnP.PowerShell. This is just an example.
    1. Click on Add a permission.
    2. Select SharePoint.
    3. Select Application permissions.
    4. Select Sites.FullControl.All.
    5. Click on Add permissions.
    6. Click on Grant admin consent for organization. You may need to ask your global admin to perform this step if you do not have the required permissions.
  3. Then, go to the Certificates & secrets blade.
    1. Open the Certificates tab.
    2. Click on Upload certificate.
    3. Select the .cer file we generated with the PowerShell script above. You may also optionally enter a description to explain what the certificate is for.

That’s it; all configurations for the application registration are now done!

Create and configure an Azure Key Vault

Azure Key Vault offers a secure place to store the certificate so that our function app can access it during runtime. On Azure Portal, go back to the root of the resource group. Then, click the button to create a new resource and search for Key Vault on the Marketplace. Then, create one with the following settings.

  1. Select the same subscription and resource group as before.
  2. Give the key vault a name according to your organization’s naming conventions.
  3. Select the same region as you’ve done before.
  4. Leave the pricing tier to Standard
  5. You may wish to enable purge protection.
  6. Open the Access policy tab and click on the Add access policy link.
    1. Select Get permission from the Secret dropdown.
    2. Click on the None selected link. In the search field, paste the function app managed identity GUID you copied into Notepad (or similar) earlier. Add the function app as the principal.
  7. Again, you may tag the resource. Otherwise, click on Review + create

Add the certificate to the vault

When the Key Vault resource has been provisioned, go to it.

  1. Navigate to the Certificates blade.
  2. Click on the Generate/Import button at the top.
  3. Select Import from the Method of Certificate Creation dropdown.
  4. Give a descriptive name for the vault certificate.
  5. Upload the .pfx certificate file you generated earlier.
  6. Provide the same password as what you used when generating the certificate.

To reference the certificate in your function app, you’ll need its URL.

  1. Click on the certificate you just added to the key vault.
  2. Similarly, also click on the current certificate version.
  3. Copy the Certificate Identifier (URL) to, e.g., Notepad. You can remove the version (GUID) from the end of the URL. This way, the latest version of the certificate will always be used. We’ll need this value in just a second!

Finalize the Function App configurations

Finally, go back to your function app in Azure Portal. Click on Configuration and add the following application settings.

Name Value Description
Tenant yourtenant.onmicrosoft.com The prefix is the same as in your SharePoint URL. This setting is needed for authentication.
ClientId Your Entra ID app/client ID You copied this earlier from the app registration Overview blade. This setting is needed for authentication.
Certificate @Microsoft.KeyVault(SecretUri=
https://yourvaultname.vault.azure.net
/certificates/yourcertname)
This is called a key vault reference. It allows our function app to retrieve the certificate from the vault using its managed identity. You must paste the certificate identifier URL we copied as the SecretUri value. This setting is needed for authentication.
WEBSITE_LOAD_USER_PROFILE 1 This setting is required to ensure the function app can fetch the certificate from the key vault (needed for authentication).

Add the script to the function app

After deploying the function app resource, click Go to resource and perform the following configurations.

  1. Open the Functions blade.
  2. Create a new function:
    • Leave Development environment to its default value (Develop in portal).
    • Select the type of trigger you want to use.
    • Give your function a descriptive name.
    • Configure the rest of the available settings (depending on the selected trigger type).
    • Click on Create.
  3. Click on Code + test in the navigation.
  4. Finally, include the following lines in your PowerShell script to implement authentication using the certificate, and click on Save.

Afterword

I write these blog posts just as much for my benefit as yours. So now, I have an article I can easily link to my colleagues whenever they need to figure out how to implement certificate authentication for using PnP PowerShell on Azure Functions with application permissions.

I hope you, my dear reader, also found this article helpful and got your script working. Happy coding, and until next time!

Laura



6 thoughts on “How to use PnP PowerShell on Azure Functions with application permissions”

  • GREAT article – thanks so much !
    I had to adjust one part with the Azure AppRole – minor bug with the script/code :

    # *** I changed to use ; instead of ,
    >> $permissionsToAdd = “Sites.FullControl.All;TermStore.ReadWrite.All”

    And then – the next line needed a SPLIT based on ;
    >> foreach ($permission in $permissionsToAdd.Split(‘;’)) {

    Otherwise – it was just ONE value – not an array. 🙂

  • Hi Laura, Great blog as always… I think the biggest challenge with using PnP.PowerShell in Azure Functions at the moment is finding a stable build that allows you to use some of the newer PnP.PowerShell modules.

    Do you have a build that you can recommend?

  • Laura, let me thank you for your post. I do appreciate that you shared your knowledge. Frankly I tried to make PowerShell Azure Function connected to SPO list, found tuns of resources out there but none of them really helped me .. but then I came across your one.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.