Scenario
You run some PnP PowerShell code unattended e.g. daemon/service app, background job – under application permissions – with no user interaction.
Your app needs to connect to SharePoint and/or Microsoft Graph API. Your organization require authentication with a certificate (no secrets). You want certificate stored securely in Azure Key Vault.
Solution (Step-by-step process)
- Obtain a certificate (create a self-signed or request trusted)
- In Azure where you have Microsoft 365 SharePoint tenant
- Create a new Registered App in Azure; save App (client) id, Directory (Tenant) Id
- Configure App: add MS Graph and SharePoint API application (not delegated) permissions
- Upload the certificate to the app under “Certificates & secrets”
- In Azure where you have paid subscription (could be same or different)
- Create an Azure Key Vault
- Upload certificate to the Key Vault manually (with GUI)
- While you develop/debug your custom daemon application at your local machine
- Provide permissions to the Key Vault via Access Control and Access Policies to your personal account
- Connect to Azure (the one where your Key Vault is) running Connect-AzAccount
– so your app can get a Certificate to authenticate to SharePoint Online
- For your application deployed to Azure (e.g. Azure Function App )
- Turn On managed identity (Your Function App -> Identity -> Status:On) and Save; notice an Object (Principal) Id just created
- Provide for your managed identity principal Id permissions to the Key Vault via Key Vault Access Policies, so when your daemon app is running in the cloud – it could go to the key Vault and retrieve Certificate
Here is the sample PowerShell code to get certificate from Azure Key Vault and Connect to SharePoint with PnP (Connect-PnPOnline):
# ensure you use PowerShell 7
$PSVersionTable
# connect to your Azure subscription
Connect-AzAccount -Subscription "<subscription id>" -Tenant "<tenant id>"
Get-AzSubscription | fl
Get-AzContext
# Specify Key Vault Name and Certificate Name
$VaultName = "<azure key vault name>"
$certName = "certificate name as it stored in key vault"
# Get certificate stored in KeyVault (Yes, get it as SECRET)
$secret = Get-AzKeyVaultSecret -VaultName $vaultName -Name $certName
$secretValueText = ($secret.SecretValue | ConvertFrom-SecureString -AsPlainText )
# connect to PnP
$tenant = "contoso.onmicrosoft.com" # or tenant Id
$siteUrl = "https://contoso.sharepoint.com"
$clientID = "<App (client) Id>" # Azure Registered App with the same certificate and API permissions configured
Connect-PnPOnline -Url $siteUrl -ClientId $clientID -Tenant $tenant -CertificateBase64Encoded $secretValueText
Get-PnPSite
The same PowerShell code in GitHub: Connect-PnPOnline-with-certificate.ps1
References:
- https://docs.microsoft.com/en-us/powershell/module/az.keyvault/get-azkeyvaultcertificate?view=azps-5.3.0
- https://stackoverflow.com/questions/43837362/keyvault-generated-certificate-with-exportable-private-key
- Do I need certificate or secret to Connect to SharePoint Online from code
- Register and configure Azure App to Get access to an SPO site from code