What PnP is (and isn't)
PnP PowerShell is a community-built module (Patterns & Practices) that operates
inside SharePoint sites: lists, libraries, items, pages, permissions, and
provisioning. It complements the Microsoft SPO Management Shell (Get-SPO*),
which is tenant/site-collection admin. Rule of thumb: tenant knobs → SPO cmdlets;
everything inside a site → PnP. It is community-maintained and not a
Microsoft-supported product — powerful, fast-moving, and yours to pin and test.
Provisioning at scale
PnP's signature capability is site templates: capture a site's structure
(lists, content types, columns, pages, nav, settings) as a template with
Get-PnPSiteTemplate, then stamp it onto new sites with Invoke-PnPSiteTemplate.
That turns "every project needs an identical site" into a repeatable, versionable
deployment instead of manual clicking — the provisioning backbone of a governed
estate.
App-only auth (how unattended automation runs)
Unattended PnP runs as an app-only identity with a certificate, via an
Entra app registration (Register-PnPEntraIDApp scaffolds one). No user, no
interactive sign-in — the cert authenticates the app. The critical decision is what
that app is granted.
The Sites.FullControl.All trade (the sensitive bit)
PnP's deepest reach — enumerating every item's unique permissions across all
sites, provisioning structure, bulk remediation — historically wants
Sites.FullControl.All: a powerful, write-capable, ALL-sites grant. That
single permission is effectively a tenant-wide SharePoint master key. The
discipline:
- Grant it only to automation that genuinely needs deep write across sites.
- For reporting/read workloads, prefer
Sites.Read.All(or the newerSites.Selectedto scope an app to named sites only) — never hand a read-only robot a FullControl key. - serv365's own history is the cautionary tale: it tested
Sites.FullControl.All, proved it gives the deep read, then revoked it as too broad for a read-only product — the deepest visibility carries the heaviest permission, so scope it.
The failure modes
- Over-permissioned apps. A FullControl app credential leaking is a tenant-wide write compromise; treat the cert as a crown-jewel secret.
- Throttling (429). Bulk PnP hammering SharePoint gets throttled; honour the
Retry-Afterheader, batch, and back off — ignoring it makes jobs slower, not faster. - Version drift. PnP releases frequently and can introduce breaking changes; pin the module version in automation and read release notes before upgrading.
- Community, not supported — no Microsoft support ticket covers PnP behaviour; the code is the documentation.
Sites.Selectedmisconfigured — the app must ALSO be granted per-site access; the permission alone grants nothing until sites are assigned.
What to watch (proofs)
- App permission inventory: the service principal's SharePoint/Graph app roles —
which apps hold
Sites.FullControl.AllvsSites.Read.AllvsSites.Selected(audit the FullControl holders). - Cert hygiene: the app registration's certificate expiry and rotation — an automation identity's most sensitive secret.
- Throttling signals: 429 responses /
Retry-Afterin job logs — proof back-off is actually implemented. - Pinned version: the PnP module version in the automation host vs latest — pinned and deliberately upgraded, not floating.