Runbook: Get-MfaGapReport.ps1
Script: scripts/powershell/Get-MfaGapReport.ps1
Owner: Max Simon (build), Juan Munoz (graduation execution)
Schedule: Weekly, every Monday, 06:00 UTC
Azure Automation Account: pdr-sharepoint-automation (West US 2, rg-it-automation)
Graduation Path: See CLAUDE.md "Azure Automation Graduation Path" (8 stages)
Zendesk: #17348
Compliance: SOC 2 CC6.5 — Logical access controls, MFA enforcement evidence
Purpose
Weekly automated MFA gap detection across the org. Identifies users without MFA registered. Generates SOC 2 CC6.5 compliance evidence. Feeds Zendesk tickets for remediation. Critical gate before MFA enforcement date (March 23, 2026).
Pipeline
Azure Automation (Monday 06:00 UTC)
|
v
Get-MfaGapReport.ps1 -Scope All -ConfirmProduction
|
v
Graph API: GET /v1.0/users (User.Read.All)
+ GET /v1.0/reports/authenticationMethods/userRegistrationDetails (Reports.Read.All)
|
v
Cross-reference: users with no MFA method registered
|
v
Evidence output:
./evidence/mfa-gaps/YYYY-MM-DD-mfa-gap-report.json
./evidence/mfa-gaps/YYYY-MM-DD-mfa-gap-report.md
|
v
Zendesk: one ticket per gap user (New-ZendeskTicket.ps1)
|
v
Slack alert via Send-SecOpsAlert:
- HIGH (red) if any users missing MFA
- INFO (green) if zero gaps
Prerequisites
- Graph API scopes confirmed:
User.Read.All,Reports.Read.All,AuditLog.Read.All(already approved in app registration) - MFA bypass group documented in Entra (break-glass accounts)
- Zendesk API credentials in Azure Automation Credentials vault
- Graph API credentials in Azure Automation Credentials vault
- No SharePoint dependency — evidence writes to repo only
Healthy Run
| Indicator | Expected |
|---|---|
| Slack alert | INFO (green) if zero gaps, HIGH (red) if gaps found |
| Evidence JSON | Written to ./evidence/mfa-gaps/YYYY-MM-DD-mfa-gap-report.json |
| Evidence MD | Written to ./evidence/mfa-gaps/YYYY-MM-DD-mfa-gap-report.md |
| Zendesk tickets | Created for each gap user (assigned to Juan) |
| Log file | Written to ./logs/Get-MfaGapReport/YYYY-MM-DD.log |
| Exit code | 0 |
Failure Modes
| Failure | Cause | Resolution |
|---|---|---|
| Graph API 401 | Token expired or client secret rotated | Rotate client secret in Bitwarden, update Azure Automation Credentials vault, verify in .env for local dev |
| Graph API 403 | Missing scope on app registration | Check app registration in Entra portal, confirm User.Read.All and Reports.Read.All have admin consent |
| Zendesk ticket creation failure | Non-blocking. Evidence still writes, alert fires medium severity | Check Zendesk API token expiration, verify credentials in vault. Gap users are still captured in evidence files |
| Zero users returned | Likely Graph API pagination issue | Check ./logs/Get-MfaGapReport/ for pagination debug output. Verify Get-AllGraphPages is following @odata.nextLink |
| Heartbeat alert (no run in 8 days) | Schedule missed or runbook disabled | Check Azure Automation schedule status, verify runbook is published and enabled |
Ongoing Operations
| Cadence | Task |
|---|---|
| Weekly | Verify Slack alert fired Monday morning. Check ./evidence/mfa-gaps/ for current week's timestamp |
| Monthly | Review gap count trend — should decrease as MFA rollout matures. Compare month-over-month in evidence files |
| Quarterly | Rotate Graph API client secret per credential rotation schedule (CLAUDE.md) |
| Post-March 23 | MFA enforcement goes live. Gap count should drop to near zero. Tune alert threshold — consider switching HIGH alert to only fire if gap count exceeds a baseline (e.g., > 2 accounts, to allow for new hires in onboarding) |
Sunset Criteria
Two consecutive months of zero MFA gaps with no manual intervention. When met:
- Move
scripts/powershell/Get-MfaGapReport.ps1tocompleted/ - Move this runbook to
runbooks/completed/ - Disable Azure Automation schedule
- Close Zendesk #17348
- Update PROJECTS.md
Rollback
If the Azure Automation runbook produces incorrect output or fails:
- Disable the schedule in Azure portal
- Run locally as a stopgap:
```powershell
.\scripts\powershell\Get-MfaGapReport.ps1 -Scope All -ConfirmProduction -Verbose
```
- Check evidence output — confirm JSON and MD files are correct
- Investigate — review Azure Automation job logs and
./logs/Get-MfaGapReport/ - Fix and re-test — re-publish runbook, manual test run, then re-enable schedule
Source: secops-pipeline/runbooks/Get-MfaGapReport.md | Last synced: 2026-03-23T08:24:29Z | Do not edit in Zendesk -- changes will be overwritten on next sync.
Comments
0 comments
Please sign in to leave a comment.