How I Built a PowerShell Toolkit That Audits Your Entire Microsoft 365 Tenant in Minutes
the problem with most M365 audits
Most M365 security audits fall into one of two categories. Either a consultant runs a manual checklist through the portal and produces a Word document, or an expensive third-party tool produces a 200-page PDF that nobody reads. Neither is useful for an SMB IT admin who needs to know what is broken and how to fix it.
what the toolkit does
Two PowerShell scripts that connect to your tenant using certificate-based app authentication, run a series of checks, and produce a clean HTML report you can open in any browser, share with your team, or export to PDF in one click.
how it actually runs
Once the app registration is set up, running the audit is three parameters and done. No interactive login, no browser window, no MFA prompt:
.\Invoke-AroraMSPTenantAudit.ps1 `
-TenantId "your-tenant-id" `
-ClientId "your-app-client-id" `
-CertificateThumbprint "your-cert-thumbprint" The script connects to Microsoft Graph and Exchange Online using the certificate stored in your local certificate store, runs all checks, and writes a self-contained HTML report to the output directory. No data leaves your machine except the Graph and Exchange API calls to your own tenant.
what a check looks like under the hood
Each check follows the same pattern: query the API, evaluate the result, emit a PASS, WARNING, or FAIL with a remediation recommendation. Here is the legacy authentication check:
$legacyBlock = $caPolicies | Where-Object {
$_.State -eq 'enabled' -and
$_.Conditions.ClientAppTypes -contains 'exchangeActiveSync' -and
$_.Conditions.ClientAppTypes -contains 'other' -and
$_.GrantControls.BuiltInControls -contains 'block'
}
if ($legacyBlock) {
Add-Finding 'Identity & Access' 'Legacy authentication blocked via CA' 'PASS' `
"$($legacyBlock.Count) enabled policy/policies block legacy authentication."
} else {
Add-Finding 'Identity & Access' 'Legacy authentication blocked via CA' 'FAIL' `
'No enabled Conditional Access policy blocks legacy authentication.' `
'Create a CA policy targeting Exchange ActiveSync and Other clients with grant control = Block.'
} This checks your Conditional Access policies for one that targets both exchangeActiveSync and other client app types with a block grant control. If none exists, the report flags it as a FAIL with the exact remediation step. The same pattern applies to all 20 checks across the four categories.
the DMARC check as another example
Email security checks query DNS directly for each verified domain in your tenant. The DMARC check resolves the _dmarc.yourdomain.com TXT record and grades the policy level:
$rec = Resolve-DnsName -Name "_dmarc.$d" -Type TXT -ErrorAction Stop
$policy = if ($dmarcTxt -match 'p=(\w+)') { $matches[1].ToLower() } else { 'unknown' }
switch ($policy) {
'reject' { Add-Finding 'Email Security' "DMARC: $d" 'PASS' 'p=reject (enforced)' }
'quarantine' { Add-Finding 'Email Security' "DMARC: $d" 'WARNING' 'p=quarantine'
'Move to p=reject after monitoring rua aggregate reports for 30+ days.' }
'none' { Add-Finding 'Email Security' "DMARC: $d" 'WARNING' 'p=none (monitor-only)'
'Move to p=quarantine, then p=reject.' }
default { Add-Finding 'Email Security' "DMARC: $d" 'FAIL' 'No DMARC TXT record found.'
"Publish: v=DMARC1; p=quarantine; rua=mailto:dmarc@$d" }
} p=reject is a PASS. p=quarantine or p=none is a WARNING with the next step. No record at all is a FAIL with the exact DNS record to publish. Every check in the toolkit works the same way: a clear status and a specific action, not a vague recommendation.
what the tenant audit checks
Identity and Access:
- Legacy authentication blocked via Conditional Access
- Tenant-wide MFA policy exists
- Break-glass accounts excluded from CA policies
- Global Administrator count
Email Security:
- DMARC policy level (none, quarantine, or reject)
- SPF hard fail vs soft fail
- DKIM signing enabled
- External auto-forwarding blocked
App Registrations:
- Certificates expiring within 30 days
- Client secrets expiring within 30 days
- Apps holding high-privilege Graph permissions
- App registrations with no owners assigned
Endpoint and Licensing:
- Intune compliance policies deployed
- App protection policies deployed
- Unassigned licences by SKU
- Shared mailboxes with paid licences
the mailbox report
Pulls every mailbox in your tenant showing used storage, quota, available space, used percentage, archive status, and licence per mailbox. Sorted by storage descending. Highlights anything over 80% quota automatically. Export to PDF or CSV in one click.
The report also surfaces shared mailboxes with paid licences assigned, which is one of the most common sources of unnecessary licence spend in SMB tenants. A shared mailbox does not need a paid licence unless it has an archive or specific compliance requirements. The toolkit flags every instance so you can review and reassign.
what the output looks like
Both reports are self-contained HTML files with no external dependencies. Open them in any browser, print to PDF, or share the file directly. The audit report groups findings by category with colour-coded status indicators: green for PASS, amber for WARNING, red for FAIL. Each FAIL and WARNING includes the specific remediation step inline so whoever reads the report knows exactly what to do next without needing to cross-reference external documentation.
The report also includes an executive summary at the top showing total checks, pass rate, and a count of items requiring attention. Designed to be handed to a business owner or a compliance team without requiring a translation layer.
how authentication works
Both scripts use certificate-based app-only authentication. No interactive login prompts. No browser windows. Set up an app registration once, run the scripts with three parameters, and the reports generate automatically. Full setup documentation is included covering every step of the app registration, certificate creation, and permission assignment.
get the toolkit
Available at aroramsp.com/whatido. Includes both scripts, full setup guide, prerequisites documentation, and sample reports so you know exactly what the output looks like before you run anything. USD 99 one-time payment.
Download a sample audit report to see exactly what you get.