TrustM365 is a free, self-hosted dashboard for Microsoft 365 administrators and MSSPs. Connect it to one or more M365 tenants, define a gold-standard baseline of critical configuration, and know the instant something drifts — with a full property-level diff, one-click restore, and a complete audit trail.
"Is my tenant still configured the way I intended?" TrustM365 gives you a permanent, visual answer.
Most M365 drift goes undetected. A Conditional Access policy gets quietly disabled. A guest invite setting gets broadened. An admin role gets assigned to the wrong account. TrustM365 is the safety net that catches those changes before they become incidents.
- Pull your live M365 configuration via the Microsoft Graph API
- Baseline it — choose exactly which resources and properties to monitor
- Detect drift automatically on every sync — property-level, not just "something changed"
- Restore with one click — push baseline values back to Graph per property, per resource, or all at once
- Report — generate branded PDF and Word reports for client delivery or internal audit
- Alert — push drift notifications to Teams, Slack, PagerDuty, or any webhook endpoint
- Audit every change — full restore log with before/after values and timestamps
- Selective monitoring — include only the resources that matter; everything else sits in "Not in Baseline" and is ignored
- Two monitoring modes per resource:
- Properties mode — monitor specific named fields. Only changes to those fields raise a drift alert
- Snapshot mode — hash the entire resource. Any field change triggers drift
- Property-level diff — see exactly which field changed, from what value to what, side by side
- Three drift states: Drifted, Clean, Missing (resource no longer exists in tenant)
- Baseline Active / No Baseline indicator — clearly visible status badge on every area view
- Per-area last-synced timestamp — each area shows its own last pull time independently
- Auto-restore — toggle per area to automatically revert drift on the next sync
- Bulk restore — restore all drifted resources in an area with one button
- Resource groups — organise monitored resources into named, colour-coded groups within an area
- Baseline version history — every save archives the previous version; restore any archived version at any time
- Select All / Deselect All — bulk include or exclude all resources when setting a baseline
- Resource search — filter by name or ID within any area
- Per-tenant App Registration — each tenant uses its own Entra ID App Registration, stored encrypted with AES-256-GCM
- Live permission checks — permissions re-verified on every sync; area access badges update automatically
- Permission Sync — on-demand re-check of all App Registration permissions from Graph; unlocks newly consented areas immediately. Accessible from ⚙ → App Registration section
- Credential rotation — update an App Registration secret without losing any data. Validates the new secret before saving. Accessible from ⚙ → App Registration section at any time
- Auth failure banner — specific, plain-English error messages for expired secrets, missing permissions, and network failures — clears automatically on the next successful sync
- Tenant Overview panel — users, groups, devices, app registrations at a glance
- Tenant Insights — Graph-based security metrics including MFA registration rate, authentication method breakdown, guest ratio, and device compliance
- Per-tenant notes and tags — annotate tenants for easy identification in an MSSP context
- Portfolio Overview — all tenants in Scorecard and Matrix views with cross-tenant drift visibility
- Bulk sync — refresh all tenants in parallel with one button
- Cross-tenant drift export — CSV and JSON reports across all tenants and areas
- Webhook notifications — push JSON drift alerts to any HTTP endpoint on first detection or every sync. Compatible with Teams, Slack, and PagerDuty out of the box
- Baseline Templates (Security Checks) — Maester and CISA SCuBA-referenced security checks as a read-only assessment layer across selected tenants
- MSSP Settings — organisation name, tagline, logo, brand colour, report accent colour
- White-labelling — all generated reports carry your company name and branding; commentary label reads "YourCompany Commentary"
- Tenant reports — full HTML report with Executive Summary, Drift History, Remediation Log, Baseline Coverage, Current Configuration State, and Technical Appendix
- Always light mode — all reports use a professional light colour scheme suitable for printing, PDF, and formal client delivery
- Download as PDF — browser print-to-PDF via the in-app viewer
- Download as Word (.docx) — fully structured Word document with tables, formatted headings, MSSP branding, and a per-page footer
- MSSP commentary — add plain-English context to any section before generating; commentary label carries your company name
- Report filtering — filter by tenant, date range, or report type
- Baseline Export — report on your current baseline configuration, useful for audit proof, project documentation, or just peace of mind.
- Single property restore — patch exactly one property back to its baseline value
- Full resource restore — restore all monitored properties for a resource in one operation
- Bulk restore — loop through all drifted resources in an area sequentially
- Auto-restore — trigger on sync automatically when enabled
- Rich restore log — every action logged with resource name, restore type (Property / Full / Bulk / Auto), properties restored, and error detail on failure
| Area | Monitors | Restores |
|---|---|---|
| Directory Role Assignments | ✅ | ✅ |
| User Accounts | ✅ | ✅ |
| Groups | ✅ | ✅ |
| App Registrations | ✅ | ✅ |
| Authentication Policies | ✅ | ✅ |
| Conditional Access Policies | ✅ | ✅ |
| Area | Monitors | Restores |
|---|---|---|
| Device Compliance Policies | ✅ | ✅ |
| Device Configuration Profiles | ✅ | ✅ |
| Windows Update Rings | ✅ | ✅ |
| Mobile Threat Defense Connectors | ✅ | ✅ |
| App Protection Policies (MAM) | ✅ | — Monitor only |
| Area | Monitors | Restores |
|---|---|---|
| Endpoint Security — Antivirus | ✅ | ✅ |
| Endpoint Security — Firewall | ✅ | ✅ |
| Endpoint Security — Disk Encryption (BitLocker) | ✅ | ✅ |
| Endpoint Security — Attack Surface Reduction | ✅ | ✅ |
Licence-gated areas show as Licence required rather than erroring. TrustM365 detects available features automatically on first sync.
Custom Collectors — monitor any additional Microsoft Graph endpoint using the Custom Collectors wizard.
The Baseline Templates section provides a read-only security assessment layer based on Maester and CISA SCuBA guidance. It runs independently of tenant baselines and does not modify any configuration.
| Group | Checks |
|---|---|
| Multi-Factor Authentication | MFA required for all users · MFA for privileged roles · Legacy auth blocked |
| Authentication Methods | SMS disabled · Voice call disabled · Phishing-resistant method enabled |
| Guest & External Access | Guest invitations restricted to admins · MFA required for guests |
| Admin Account Protection | Admins required to use compliant devices · Global Admin count within range |
| Conditional Access Hygiene | No policies in report-only mode · No permanently disabled policies |
trustm365/
├── frontend/ React 18 + Vite + Tailwind CSS
│ └── src/
│ ├── pages/ Dashboard, AreaView, BaselineEditor, Portfolio,
│ │ Reports, Templates, MsspSettings, CustomCollectors…
│ └── components/ Sidebar, TenantOverview, TenantInsights,
│ GenerateReportModal
├── backend/
│ ├── collectors/ Graph API pullers — 15 built-in areas + custom collectors
│ ├── engine/
│ │ ├── drift.js Property-level deep diff + hash-based snapshot engine
│ │ ├── sync.js Pull, re-check permissions, compute drift, fire webhooks
│ │ ├── restore.js PATCH/PUT baseline values back to Graph API
│ │ └── webhooks.js HTTP delivery engine — first/every fire modes
│ ├── reports/
│ │ ├── assembler.js Collects drift history, remediation log, config state
│ │ ├── renderer.js HTML report renderer (light mode, MSSP branding)
│ │ └── docx-renderer.js Word document renderer (light mode, MSSP branding)
│ ├── routes/ REST API (Express 4)
│ ├── services/ MSAL auth · Graph API client · permission checker
│ └── database/ SQLite (WAL mode, AES-256-GCM encrypted secrets)
├── docs/
│ ├── guides/ 18 step-by-step feature guides
│ ├── prerequisites.md App Registration setup
│ ├── deployment.md Local, Azure App Service, Docker Compose
│ ├── security.md Encryption model, network hardening
│ └── usage.md Full usage reference
└── scripts/ Key generation and database backup utilities
Tech stack — all free, all open-source:
| Layer | Technology |
|---|---|
| Runtime | Node.js 20 LTS |
| Frontend | React 18, Vite, Tailwind CSS |
| Backend | Express 4, MSAL Node, sql.js, Zod, Pino, docx |
| Auth | OAuth 2.0 client credentials (app-only, no user sign-in required) |
| Database | SQLite with WAL mode — zero extra infrastructure |
| Security | AES-256-GCM secret encryption, Helmet.js, CORS lockdown |
| Testing | Jest — 53 unit tests covering drift engine, assembler, restore logic |
1. Create an Entra ID App Registration (~10 minutes)
See docs/prerequisites.md for the full step-by-step guide. At minimum, grant these Application permissions and consent them:
Policy.Read.All
RoleManagement.Read.Directory
User.Read.All
Group.Read.All
Application.Read.All
Note your Directory (Tenant) ID, Application (Client) ID, and Client Secret Value.
2. Deploy TrustM365 locally
# Windows
git clone https://github.com/AntoPorter/trustm365.git
cd trustm365
npm run install:all
npm run generate:key # generates a 64-char hex encryption key
notepad .env # paste: ENCRYPTION_KEY=<the key above>
npm run dev # opens on http://localhost:5173# macOS / Linux
git clone https://github.com/AntoPorter/trustm365.git
cd trustm365
npm run install:all
npm run generate:key
echo "ENCRYPTION_KEY=$(node scripts/generateKey.js)" >> .env
npm run dev3. Register your first tenant
Click Add Tenant in the sidebar. Paste your Tenant ID, Client ID, and Client Secret. TrustM365 validates your credentials and checks which permissions are granted — showing which areas are unlocked before you save.
4. Pull live data and set a baseline
Click Sync All on the tenant dashboard. Once data loads, click Manage on any area card, then Set Baseline. Select resources to monitor, choose Properties or Snapshot mode, and save. Drift detection starts on the next sync.
For Docker and Azure App Service deployment options, see docs/deployment.md.
Pull live config → Set Baseline → Sync → Drift detected?
│
Yes ──→ View diff → Restore / Auto-restore
│
No ──→ Clean ✓ → Generate Report
Monitoring modes:
- Properties — select which specific fields to watch. Only those fields are compared on each sync.
- Snapshot — the entire resource is hashed at baseline save time. Any change to any field triggers drift.
Drift states:
| State | Meaning |
|---|---|
| Drifted | One or more monitored properties differ from the baseline value |
| Clean | All monitored properties exactly match the baseline |
| Missing | The resource was in the baseline but no longer exists in the tenant |
| Badge | Where shown | Meaning |
|---|---|---|
| 🟢 Baseline Active | Area header | A baseline is set and drift detection is running |
| 🟡 No Baseline | Area header | Live data has been pulled but no baseline has been set |
| ✅ All clean | Configuration tab | All monitored resources match the baseline exactly |
| 🔴 Drifted (N) | Configuration tab, sidebar, portfolio | N resources have properties that differ from baseline |
| 🟠 Missing (N) | Configuration tab | N baseline resources no longer exist in the tenant |
| Permission | Purpose |
|---|---|
Policy.Read.All |
Authentication policies, Conditional Access |
RoleManagement.Read.Directory |
Directory role assignments |
User.Read.All |
User accounts |
Group.Read.All |
Security and M365 groups |
Application.Read.All |
App registrations and credential expiry |
DeviceManagementConfiguration.Read.All |
Intune compliance, config, update rings, EP security |
DeviceManagementServiceConfig.Read.All |
Mobile Threat Defense connector states |
DeviceManagementApps.Read.All |
App Protection Policies (MAM) |
AuditLog.Read.All |
Tenant Insights — MFA registration rates and auth method breakdown |
| Permission | Enables restore for |
|---|---|
Policy.ReadWrite.ConditionalAccess |
Conditional Access policies |
Policy.ReadWrite.AuthenticationMethod |
Authentication method policies |
RoleManagement.ReadWrite.Directory |
Directory role assignments |
User.ReadWrite.All |
User account properties |
Group.ReadWrite.All |
Group settings |
Application.ReadWrite.All |
App registration settings |
DeviceManagementConfiguration.ReadWrite.All |
All Intune policies (compliance, config, EP security) |
DeviceManagementServiceConfig.ReadWrite.All |
Mobile Threat Defense connector restore |
All permissions are Application (not delegated). TrustM365 acts as itself — no user sign-in required. Read-only deployments can omit all
ReadWritepermissions; restore buttons are hidden automatically.
| Document | Description |
|---|---|
| Prerequisites | Entra ID App Registration — complete this before deployment |
| Deployment | Local, Azure App Service, and Docker Compose |
| Usage Guide | Registering tenants, baselines, drift detection, restore, MSSP |
| Security | Credential handling, encryption model, network hardening |
| Contributing | How to add resource area collectors and contribute |
| Changelog | Release history |
Step-by-step guides for every component of TrustM365, in docs/guides/:
| Guide | Description |
|---|---|
| 01 — Registering a tenant | Connect TrustM365 to a Microsoft 365 tenant |
| 02 — Configuring a baseline | Define the intended state and start monitoring |
| 03 — Understanding drift detection | How drift is detected, surfaced, and categorised |
| 04 — Restoring to baseline | Per-property, full resource, bulk, auto-restore, and dry-run |
| 05 — The Dashboard | Tenant dashboard, sync, settings, credential rotation, auto-restore |
| 06 — Area View | Resource-level diff view, restore log, baseline history |
| 07 — Tenant Insights | MFA, auth methods, devices, guest ratio panels |
| 08 — Search and filtering | Local page filters — Portfolio, Area View, Baseline Editor, Reports |
| 09 — Portfolio Overview | Cross-tenant Scorecard and Matrix views |
| 10 — Generating reports | Tenant reports — HTML viewer, PDF, and Word (.docx) export |
| 11 — Report scheduling | Automated weekly and monthly report generation |
| 12 — Webhook notifications | Drift alerts to Teams, Slack, PagerDuty, or any HTTP endpoint |
| 13 — White-labelling | Company branding, logo, colours for client-facing output |
| 14 — Baseline Templates | Security posture checks (Maester / CISA SCuBA) |
| 15 — Custom Collectors | Monitor any Graph endpoint without code |
| 16 — Intune endpoint security | Compliance, Update Rings, MTD, App Protection, Antivirus, Firewall, BitLocker, ASR |
| 17 — Credential rotation | Updating an App Registration secret without data loss |
| 18 — Troubleshooting | Common problems and how to fix them |
- Exchange Online — transport rules, connectors, anti-spam policies
- Microsoft Teams — meeting policies, external access, app permissions
- SharePoint / OneDrive — sharing settings, access control
- Audit Log Export - Export audit trail to Log Analytics
- Azure AD SSO login for the dashboard
- Role-based access — read-only vs restore permissions per user
- Multi-user audit trail
- Bugs: Open an issue
- Questions & feature requests: Start a discussion
- Security vulnerabilities: Email the maintainer directly — do not open a public issue
TrustM365 — Open-source Microsoft 365 baseline drift monitoring
by Anto Porter · MIT License
