SharePoint Governance: Policies, Compliance, and Best Practices
Introduction
SharePoint governance defines policies, processes, and controls for managing SharePoint environments effectively. This guide covers site lifecycle management, retention policies, compliance features, access governance, and frameworks for building scalable, secure SharePoint ecosystems.
SharePoint Governance Framework
Core Components
- Site Provisioning - Controlled site creation process
- Access Management - Permission governance
- Information Architecture - Consistent structure
- Lifecycle Management - Site creation to retirement
- Compliance - Retention, DLP, sensitivity labels
- Monitoring - Usage analytics and auditing
Governance Roles
- SharePoint Administrator - Tenant configuration, policies
- Site Owner - Site management, permissions
- Compliance Officer - Retention, legal holds
- Content Manager - Information architecture
- End Users - Content creators within policies
Site Provisioning and Templates
Controlled Site Creation
Problem: Uncontrolled site proliferation ("site sprawl")
Solution: Governance-controlled provisioning
Site Creation Approval Flow
{
"trigger": {
"type": "For a selected item",
"list": "Site Requests"
},
"actions": [
{
"type": "Start and wait for an approval",
"approvalType": "Approve/Reject",
"assignedTo": "sharepoint-admins@contoso.com",
"title": "Site Request: @{triggerOutputs()?['entity/Title']}",
"details": "Business Justification: @{triggerOutputs()?['entity/Justification']}\nOwner: @{triggerOutputs()?['entity/Owner/DisplayName']}\nTemplate: @{triggerOutputs()?['entity/Template']}"
},
{
"type": "Condition",
"if": "Approval outcome equals 'Approve'",
"then": [
{
"type": "HTTP",
"method": "POST",
"uri": "https://contoso.sharepoint.com/sites/hr/_api/SPSiteManager/create",
"headers": {
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"request": {
"Title": "@{triggerOutputs()?['entity/Title']}",
"Url": "https://contoso.sharepoint.com/sites/@{triggerOutputs()?['entity/Alias']}",
"Owner": "@{triggerOutputs()?['entity/Owner/Email']}",
"WebTemplate": "@{triggerOutputs()?['entity/Template']}"
}
}
},
{
"type": "Apply site template",
"site": "@{outputs('HTTP')?['body/d/SiteUrl']}",
"template": "@{triggerOutputs()?['entity/Template']}.pnp"
},
{
"type": "Send email",
"to": "@{triggerOutputs()?['entity/Owner/Email']}",
"subject": "Site Created: @{triggerOutputs()?['entity/Title']}",
"body": "Your SharePoint site has been created.\n\nURL: @{outputs('HTTP')?['body/d/SiteUrl']}\n\nPlease review the governance guidelines: https://intranet.contoso.com/governance"
},
{
"type": "Update item",
"fields": {
"Status": "Approved",
"SiteURL": "@{outputs('HTTP')?['body/d/SiteUrl']}",
"CreatedDate": "@{utcNow()}"
}
}
],
"else": [
{
"type": "Update item",
"fields": {
"Status": "Rejected",
"Comments": "@{outputs('Start_and_wait_for_an_approval')?['body/responses'][0]/comments]}"
}
},
{
"type": "Send email",
"to": "@{triggerOutputs()?['entity/Owner/Email']}",
"subject": "Site Request Rejected",
"body": "Your site request was not approved.\n\nReason: @{outputs('Start_and_wait_for_an_approval')?['body/responses'][0]/comments]}"
}
]
}
]
}
PnP Site Templates
Create standardized templates:
# Extract template from existing site
Connect-PnPOnline -Url "https://contoso.sharepoint.com/sites/template" -Interactive
Get-PnPSiteTemplate -Out "ProjectSiteTemplate.xml" `
-Handlers Lists,ContentTypes,Fields,Navigation,Pages,SiteSecurity
# Apply template to new site
Connect-PnPOnline -Url "https://contoso.sharepoint.com/sites/newproject" -Interactive
Invoke-PnPSiteTemplate -Path "ProjectSiteTemplate.xml"
Template Components:
- List and library structures
- Content types and site columns
- Navigation configuration
- Default pages and web parts
- Permission groups
- Site settings
Site Design and Site Scripts
{
"verb": "createSPList",
"listName": "Project Tasks",
"templateType": 171,
"subactions": [
{
"verb": "setDescription",
"description": "Track project tasks and milestones"
},
{
"verb": "addSPField",
"fieldType": "Choice",
"displayName": "Priority",
"choices": ["High", "Medium", "Low"],
"isRequired": true
},
{
"verb": "addSPField",
"fieldType": "User",
"displayName": "Assigned To",
"isRequired": true
}
]
}
Apply site design:
# Register site script
$script = Get-Content "site-script.json" -Raw
Add-PnPSiteScript -Title "Project Site Configuration" -Content $script
# Create site design
Add-PnPSiteDesign -Title "Standard Project Site" `
-SiteScriptIds $scriptId `
-WebTemplate "64" `
-Description "Standardized project collaboration site"
# Apply to existing site
Invoke-PnPSiteDesign -Identity "Standard Project Site" -WebUrl "https://contoso.sharepoint.com/sites/project1"
Site Lifecycle Management
Lifecycle Stages
- Requested - Site request submitted
- Active - Site in use
- Archived - Read-only, retained for compliance
- Deleted - Soft-deleted (93-day retention)
- Permanently Deleted - Removed from recycle bin
Inactive Site Policy
Identify and manage inactive sites:
# Get sites with last activity > 90 days ago
$cutoffDate = (Get-Date).AddDays(-90)
$inactiveSites = Get-PnPTenantSite | Where-Object {
$_.LastContentModifiedDate -lt $cutoffDate -and
$_.Template -ne "RedirectSite#0"
}
$report = @()
foreach ($site in $inactiveSites) {
$siteOwners = Get-PnPSiteCollectionAdmin -Connection (Connect-PnPOnline -Url $site.Url -ReturnConnection)
$report += [PSCustomObject]@{
Title = $site.Title
URL = $site.Url
LastActivity = $site.LastContentModifiedDate
DaysSinceActivity = ((Get-Date) - $site.LastContentModifiedDate).Days
StorageUsed = $site.StorageUsageCurrent
Owners = ($siteOwners.Email -join "; ")
}
}
$report | Export-Csv "InactiveSites.csv" -NoTypeInformation
Automated Site Archival
{
"trigger": {
"type": "Recurrence",
"frequency": "Month",
"interval": 1
},
"actions": [
{
"type": "HTTP",
"method": "GET",
"uri": "https://graph.microsoft.com/v1.0/sites?$filter=lastModifiedDateTime lt @{addDays(utcNow(), -180)}"
},
{
"type": "Apply to each",
"items": "@{outputs('HTTP')?['body/value']}",
"actions": [
{
"type": "Send email",
"to": "@{item()?['owner/email']}",
"subject": "Site Archival Notice: @{item()?['displayName']}",
"body": "Your site @{item()?['displayName']} has been inactive for 6 months.\n\nIf you still need this site, click here to keep it active.\nOtherwise, it will be archived on @{addDays(utcNow(), 30)}."
},
{
"type": "Create item",
"list": "Site Lifecycle Tracking",
"fields": {
"SiteTitle": "@{item()?['displayName']}",
"SiteURL": "@{item()?['webUrl']}",
"Status": "Pending Archival",
"NotificationSent": "@{utcNow()}",
"ArchivalDate": "@{addDays(utcNow(), 30)}"
}
}
]
}
]
}
Site Storage Limits
# Set storage quota for site
Set-PnPSite -Identity "https://contoso.sharepoint.com/sites/project1" `
-StorageMaximumLevel 5000 `
-StorageWarningLevel 4500
# Get sites exceeding storage quota
$sites = Get-PnPTenantSite
$overQuota = $sites | Where-Object {
$_.StorageUsageCurrent -gt ($_.StorageMaximumLevel * 0.9)
}
foreach ($site in $overQuota) {
Write-Host "$($site.Title): $($site.StorageUsageCurrent) MB of $($site.StorageMaximumLevel) MB"
}
Retention Policies
Retention Labels
Create retention policy:
# Connect to Security & Compliance Center
Connect-IPPSSession
# Create retention label (retain 7 years)
New-ComplianceTag -Name "Financial Records - 7 Years" `
-Comment "Financial documents retained for 7 years" `
-RetentionAction Keep `
-RetentionDuration 2555 `
-RetentionType ModificationAgeInDays
# Create retention label (delete after 1 year)
New-ComplianceTag -Name "Temporary Documents - 1 Year" `
-RetentionAction DeleteAndRecordRetention `
-RetentionDuration 365 `
-RetentionType CreationAgeInDays
# Publish retention labels
New-RetentionCompliancePolicy -Name "Document Retention Policy" `
-SharePointLocation "https://contoso.sharepoint.com/sites/finance"
New-RetentionComplianceRule -Policy "Document Retention Policy" `
-ContentMatchQuery "ContentType:'Financial Document'" `
-ComplianceTag "Financial Records - 7 Years"
Auto-Apply Retention Labels
# Auto-apply based on content type
New-AutoSensitivityLabelPolicy -Name "Auto-Apply Financial Retention" `
-SharePointLocation "All" `
-ApplySensitivityLabel "Financial Records - 7 Years" `
-Conditions @{
ContentType = "Financial Document"
}
# Auto-apply based on keywords
New-AutoSensitivityLabelPolicy -Name "Auto-Apply Contract Retention" `
-SharePointLocation "https://contoso.sharepoint.com/sites/legal" `
-ApplySensitivityLabel "Contracts - 10 Years" `
-Conditions @{
ContentContains = @("contract", "agreement", "NDA")
}
Document Deletion Policy
# Create policy to delete documents after 3 years
New-RetentionCompliancePolicy -Name "3 Year Deletion Policy" `
-SharePointLocation "https://contoso.sharepoint.com/sites/archive"
New-RetentionComplianceRule -Policy "3 Year Deletion Policy" `
-ContentMatchQuery "FileExtension:docx OR FileExtension:pdf" `
-RetentionComplianceAction Delete `
-RetentionDuration 1095 `
-RetentionDurationType CreationAgeInDays
Data Loss Prevention (DLP)
Create DLP Policy
# DLP policy to prevent sharing documents with credit card numbers
New-DlpCompliancePolicy -Name "Prevent Credit Card Sharing" `
-SharePointLocation "All" `
-Mode Enable
New-DlpComplianceRule -Policy "Prevent Credit Card Sharing" `
-ContentContainsSensitiveInformation @{
Name = "Credit Card Number"
MinCount = 1
} `
-BlockAccess $true `
-NotifyUser Owner `
-NotifyUserType NotSet
DLP for External Sharing
# Block external sharing of files containing SSNs
New-DlpComplianceRule -Policy "Protect PII" `
-ContentContainsSensitiveInformation @{
Name = "U.S. Social Security Number (SSN)"
MinCount = 1
} `
-BlockAccess $true `
-BlockAccessScope All `
-NotifyUser Owner,SiteAdmin
DLP Policy Testing
# Set policy to test mode (audit only)
Set-DlpCompliancePolicy -Identity "Prevent Credit Card Sharing" -Mode TestWithNotifications
# After testing, enable enforcement
Set-DlpCompliancePolicy -Identity "Prevent Credit Card Sharing" -Mode Enable
Sensitivity Labels
Create Sensitivity Labels
# Connect to Security & Compliance
Connect-IPPSSession
# Create sensitivity labels
New-Label -DisplayName "Public" `
-Name "Public" `
-Comment "Information suitable for public disclosure"
New-Label -DisplayName "Internal" `
-Name "Internal" `
-Comment "Internal business information" `
-EncryptionEnabled $true `
-EncryptionRightsDefinitions "contoso.com:VIEW,EDIT"
New-Label -DisplayName "Confidential" `
-Name "Confidential" `
-Comment "Sensitive business information" `
-EncryptionEnabled $true `
-EncryptionRightsDefinitions "ConfidentialGroup@contoso.com:VIEW,EDIT"
New-Label -DisplayName "Highly Confidential" `
-Name "HighlyConfidential" `
-Comment "Highly sensitive information" `
-EncryptionEnabled $true `
-EncryptionRightsDefinitions "ExecutiveTeam@contoso.com:VIEW,EDIT" `
-SiteAndGroupProtectionEnabled $true `
-SiteAndGroupProtectionPrivacy Private
Publish Sensitivity Labels
# Create label policy
New-LabelPolicy -Name "Company Sensitivity Policy" `
-Labels "Public","Internal","Confidential","HighlyConfidential" `
-SharePointLocation "All"
Apply Labels Programmatically
# Apply sensitivity label to document
Set-PnPFileSensitivityLabel -Url "/sites/finance/Shared Documents/Q4Report.docx" `
-SensitivityLabel "Confidential"
# Apply to all documents in library
$files = Get-PnPListItem -List "Documents" -Fields "FileLeafRef"
foreach ($file in $files) {
Set-PnPFileSensitivityLabel -Url $file["FileRef"] -SensitivityLabel "Internal"
}
Access Governance
Permission Review Process
# Generate permission report
$sites = Get-PnPTenantSite
$permissionReport = @()
foreach ($site in $sites) {
Connect-PnPOnline -Url $site.Url -Interactive
$groups = Get-PnPGroup
foreach ($group in $groups) {
$users = Get-PnPGroupMember -Identity $group.LoginName
foreach ($user in $users) {
$permissionReport += [PSCustomObject]@{
Site = $site.Title
SiteURL = $site.Url
Group = $group.Title
User = $user.Email
UserTitle = $user.Title
}
}
}
}
$permissionReport | Export-Csv "PermissionAudit.csv" -NoTypeInformation
Quarterly Access Review
{
"trigger": {
"type": "Recurrence",
"frequency": "Month",
"interval": 3
},
"actions": [
{
"type": "HTTP",
"method": "POST",
"uri": "https://contoso.com/api/generatePermissionReport"
},
{
"type": "Apply to each",
"items": "@{outputs('HTTP')?['body/siteOwners']}",
"actions": [
{
"type": "Send email",
"to": "@{item()?['email']}",
"subject": "Quarterly Permission Review Required",
"body": "Please review the attached permission report for your site and confirm or remove access.\n\nDeadline: @{addDays(utcNow(), 14)}"
}
]
}
]
}
Remove External Users
# List all external users
$externalUsers = Get-PnPExternalUser
# Remove external user access
Remove-PnPExternalUser -UniqueIds $externalUsers[0].UniqueId
Monitoring and Auditing
SharePoint Audit Log
# Enable auditing
Set-PnPAuditing -EnableAll
# Search audit log
Search-UnifiedAuditLog -StartDate (Get-Date).AddDays(-30) `
-EndDate (Get-Date) `
-RecordType SharePointFileOperation `
-Operations FileDeleted,FileDownloaded
Usage Analytics
# Get site usage analytics
$usage = Get-PnPSiteAnalyticsData -Identity "https://contoso.sharepoint.com/sites/project1"
Write-Host "Page Views: $($usage.PageViews)"
Write-Host "Unique Visitors: $($usage.UniqueVisitors)"
Write-Host "Files Viewed: $($usage.FilesViewed)"
Best Practices
Site Naming Conventions
[Department]-[ProjectName]-[Year]
Examples:
- HR-Onboarding-2025
- Finance-BudgetPlanning-2025
- IT-Infrastructure-2025
Metadata Standards
Define required metadata for all documents:
- Document Type (Contract, Invoice, Report)
- Department (Finance, HR, IT)
- Status (Draft, Review, Final)
- Retention Category (Temporary, Standard, Long-term)
Training and Communication
- New User Onboarding - Governance overview
- Site Owner Training - Responsibilities and policies
- Quarterly Updates - Policy changes and reminders
- Help Documentation - Self-service governance guide
Key Takeaways
- Governance prevents site sprawl and ensures compliance
- Site templates standardize structure and configuration
- Lifecycle management includes archival and deletion policies
- Retention labels automate compliance requirements
- DLP policies prevent data leakage
- Regular access reviews maintain security
- Monitoring and auditing provide visibility
Next Steps
- Document governance policies and procedures
- Implement site provisioning approval workflow
- Deploy PnP site templates for consistency
- Configure retention policies for compliance
- Train site owners on governance responsibilities
Additional Resources
Govern wisely. Scale securely.