2025-08-05
Automate Microsoft 365 Tenant Cleanup with PowerShell

Microsoft 365 governance PowerShell, automate tenant audits, inactive users M365, guest access report SharePoint, license optimization Office 365, AzureAD PowerShell scripts, Exchange Online audit, SharePoint PnP report, Azure Automation runbooks, M365 compliance automation
Episode Overview
Manual portal checks feel productive—but miss stale accounts, risky sharing, and license drain. This episode shows how to replace spot checks with scheduled PowerShell: the right modules, the core reports to run weekly, how to surface issues in Teams/email, and the guardrails (logging, RBAC, approvals) that keep automation safe.
Who This Is For
-
Microsoft 365 admins, SecOps, MSPs, and platform owners
-
IT managers chasing audits, offboarding, and license costs
-
Anyone tired of “it looked fine in the portal” surprises
Key Takeaways
-
Read-only first: Start with audit reports before enforcing changes.
-
Right modules, right scope: MSOnline/Entra, AzureAD, ExchangeOnline, SharePoint PnP—each solves a slice.
-
Tenant hygiene on a schedule: Weekly reports > quarterly fire drills.
-
No secrets in scripts: Use managed identities/secure stores; log everything.
-
Make it tenant-aware: Config files & exceptions—not hardcoded IDs.
Highlights
-
Why manual reviews miss blind spots (guest links, unused licenses, stale sites)
-
The “Friday audit” that becomes a 10-minute read of auto-generated reports
-
Real-world pitfalls: service accounts misclassified as inactive; token/consent issues; proxy/VPN sync quirks
-
Safe rollout recipe: dev tenant → read-only → pilot → phased remediation
Quickstart Checklist (Copy/Paste)
-
Pick your modules
-
Entra/AzureAD for users/groups/app registrations
-
MSOnline (if still used) or Microsoft Graph PowerShell for licenses
-
ExchangeOnlineManagement for mailboxes/forwarding
-
PnP.PowerShell for SharePoint/guest links/sites
-
-
Define weekly audits (read-only):
-
Inactive users (≥90 days) and orphaned/blocked sign-ins
-
Guest users & external sharing by site (with last activity)
-
License assignments vs. last sign-in; duplicate/unused SKUs
-
Mailbox forwards, inbox rules, shared mailboxes w/ owners
-
Teams/Groups with no owners or no activity
-
-
Ship results automatically:
-
Output CSV + HTML summary → email/Teams channel
-
Store artifacts in a governance SharePoint library
-
-
Schedule safely:
-
Azure Automation runbooks with managed identity (preferred)
-
Or Windows Task Scheduler + secure credential store
-
-
Add guardrails:
-
Verbose logging + correlation IDs
-
Try/Catch with error reporting to a shared mailbox
-
“Pending actions” queue (no auto-delete/disable at first)
-
-
Phase remediation:
-
Week 1–2: reports only
-
Week 3–4: soft actions (expire guest links, remove unused licenses with approval)
-
Ongoing: auto-remediate low-risk items; require approval for high-risk changes
-
Core Reports to Automate (Examples)
-
Inactive Users Report: Users w/ no sign-in ≥90 days; exclude service/break-glass accounts by tag/OU/UPN pattern.
-
License Waste Report: Assigned licenses where last sign-in ≥60–90 days; map SKU → department/manager for action.
-
Guest Access & Sharing: Tenant-wide guest list + site-level external links; flag links w/o expiration or broad sharing.
-
Mailbox Risk Sweep: Inbox rules/forwards to external domains; shared mailboxes with no owner.
-
Ownership & Sprawl: M365 Groups/Teams with zero owners; SharePoint sites with no edits in ≥120 days.
Scheduling & Tooling
-
Azure Automation: Runbooks, schedules, managed identities, output to Storage/Log Analytics.
-
Power Automate (optional): Trigger approvals from “pending actions” list (e.g., disable account, remove license).
-
Dashboards: Surface KPIs (inactive users, license recovery, guest link count) in Power BI or a Teams tab.
Safety & Compliance Guardrails
-
Least-privilege roles for runbooks; no global admin on scheduled jobs.
-
Secrets in Key Vault / Automation assets; never in code.
-
Version control (Git) + code review; changelog per script.
-
Dry-run mode for every destructive script; approval workflow for deletes/disable.
-
Retain logs/reports for audit (≥12–24 months, per policy).
Troubleshooting Fast
-
Empty results? Check scopes/permissions and module versions; test same query with Graph Explorer.
-
Random failures? Inspect throttling, proxy/VPN, MFA/token expiry; add backoff & retry.
-
False positives on “inactive”? Whitelist service/break-glass accounts; consider app-only auth patterns.
FAQs
Will automation break my tenant?
Not if you start read-only, add approvals, and restrict permissions.
Do I need Graph PowerShell now?
It’s the modern path. Use it alongside ExchangeOnline/PnP as needed.
How fast can we see ROI?
First weekly run typically surfaces unused licenses and stale guests immediately.
What about multi-geo or MSPs?
Parameterize tenant config; centralize logging; tag outputs by tenant ID.
Host: Mirko Peters