A complete, real-world guide to building a self-service SharePoint provisioning platform that saves 500+ engineer hours per year. This is Part 1 of a 4-part series.
The Problem Every Enterprise Faces
If you manage Microsoft 365 at any sizable organization, this will sound painfully familiar. Requesting a new SharePoint site typically looks like:
- User submits a ticket describing what they need
- IT reviews and validates the request
- Security groups created via IT ticketing (2–5 days)
- Admin manually creates the site
- Manual permission configuration
- Manual notification to the user
- Documentation managed separately
The cost: 4–6 hours of engineer time per request, plus days of user waiting.
What We’re Building
A fully automated, governance-first platform that delivers:
- ✅ Self-service intake via a Power Apps form
- ✅ Multi-stage approvals (manager + admin)
- ✅ Automated provisioning with enterprise-grade permissions
- ✅ Automatic email notifications
- ✅ Complete audit trail
Result: ~10 minutes end-to-end (with instant approvals) and 500–1,200 engineer hours saved per year.
Technology Stack
| Component | Role |
|---|---|
| Power Apps | User intake form |
| Power Automate | Approval orchestration (3 flows) |
| Azure Automation | Provisioning runbook |
| PnP.PowerShell | SharePoint operations |
| Microsoft Graph | Security group validation |
| Entra ID | Certificate-based authentication |
Architecture Overview
[INSERT ARCHITECTURE DIAGRAM IMAGE HERE]
The system is organized into six logical layers: Users → Power Apps → Power Automate → Data → Azure Automation → Outputs.
Prerequisites
1. Entra ID App Registration
Create an app registration (e.g., SharePoint-Provisioner) with these Application permissions:
- Microsoft Graph:
Sites.FullControl.All - Microsoft Graph:
Group.ReadWrite.All - Microsoft Graph:
Directory.Read.All - SharePoint:
Sites.FullControl.All
Then grant admin consent for all permissions.
2. Certificate Authentication
$cert = New-SelfSignedCertificate `
-Subject "CN=SharePoint-Provisioner" `
-CertStoreLocation "Cert:\CurrentUser\My" `
-KeyExportPolicy Exportable `
-KeySpec Signature `
-KeyLength 2048 `
-KeyAlgorithm RSA `
-HashAlgorithm SHA256 `
-NotAfter (Get-Date).AddYears(2)
# For Entra upload
$cert | Export-Certificate -FilePath "C:\Temp\provisioner.cer"
# For Azure Automation
$pwd = ConvertTo-SecureString "StrongPass" -Force -AsPlainText
$cert | Export-PfxCertificate -FilePath "C:\Temp\provisioner.pfx" -Password $pwd
Write-Host "Thumbprint: $($cert.Thumbprint)"Upload the .cer to your Entra app, and import the .pfx to Azure Automation.
3. Security Groups
Governance groups (create once):
SG-SharePoint-Admins— persistent site adminsSG-SharePoint-Approvers— governance approvers
Per-site groups (naming convention):
SG-{prefix}-Sites-{alias}-OwnersSG-{prefix}-Sites-{alias}-MembersSG-{prefix}-Sites-{alias}-Visitors
4. Azure Automation Account
- Runtime Environment: PowerShell 7.2
- Module: PnP.PowerShell 2.12.0 (custom package)
- Certificate imported
- Private endpoint (for production)
Custom module packaging tip:
Save-Module -Name PnP.PowerShell -RequiredVersion 2.12.0 -Path "C:\Temp\PnP"
Compress-Archive -Path "C:\Temp\PnP\PnP.PowerShell\2.12.0\*" `
-DestinationPath "C:\Temp\PnP.PowerShell.zip"The SharePoint List (Central Data Store)
Create a list named SiteProvisioningRequests with these columns:
| Column | Type | Notes |
|---|---|---|
| Title | Text | Site display name |
| SiteAlias | Text | URL slug |
| Description | Multi-line | Purpose |
| BusinessJustification | Multi-line | Why needed |
| PrimaryOwner | Person | Requester |
| SensitivityLabel | Choice | Public/Internal/etc. |
| OwnersGroupName | Text | SG name |
| OwnersGroupId | Text | Auto-populated |
| MembersGroupName / Id | Text | SG name + ID |
| VisitorsGroupName / Id | Text | SG name + ID |
| Status | Choice | Workflow status |
| ManagerApprover | Person | Auto-set |
| M365AdminApprover | Person | Auto-set |
| SiteUrl | Hyperlink | Final URL |
| ProvisionedOn | DateTime | Completion |
| ErrorDetails | Multi-line | If failed |
Status choices: Pending Manager Approval → Pending M365 Admin Approval → Provisioning → Provisioned (or Rejected/Failed)
💡 Tip: Enable item-level permissions so users see only their own requests.
Coming up in Part 2: Building the three Power Automate flows that orchestrate approvals and trigger provisioning — including the sneaky SharePoint newline bug that cost me hours.