-
Notifications
You must be signed in to change notification settings - Fork 250
Microsoft 365 AI Readiness Export ‐ Execution and Operations Guide
This guide documents how m365-ai-ready-export.ps1 executes, what each phase does, how permissions are handled, and how to run and operationalize it reliably.
m365-ai-ready-export.ps1 is a read-only assessment script that:
- Connects to Microsoft Graph and optional Microsoft 365 service endpoints.
- Collects tenant posture signals for AI/Copilot readiness.
- Computes readiness flags, scores, and recommendations.
- Writes one consolidated JSON report file.
Read-only guarantee:
- The script uses
Get-*,Connect-*, andDisconnect-*patterns. - It does not apply tenant configuration changes.
- It writes only to a local JSON output file.
The script accepts these parameters:
-
-TenantId(optional): Tenant GUID or tenant domain context for auth/connector calls. -
-OutputPath(optional): Output JSON path. Default is timestamped file in current folder. -
-GraphClientId(optional): App client ID used for device-code auth. Default is Microsoft first-party client ID. -
-GraphScopes(optional): Explicit delegated Graph scopes (for custom app registrations). -
-IncludeSampling(switch): Enables sampling mode for heavy collectors. -
-IncludeDetailedData(switch): Reserved toggle stored in metadata. -
-SampleSize(int, default 200): Max sampled items when sampling is enabled.
- PowerShell 7+ recommended.
- Microsoft.Graph (for context detection and compatibility).
- PnP.PowerShell (SharePoint/OneDrive tenant and site metadata).
- ExchangeOnlineManagement (Exchange and Purview compliance session data).
- MicrosoftTeams (Teams policy metadata).
The script still runs partially if optional modules are missing.
Use an account that can read tenant-level configuration and usage reports. The exact permission model depends on whether you use:
- Default Microsoft client ID with
.defaultscope. - Custom app registration with explicit delegated scopes.
The script validates required Graph delegated scopes against what was actually granted to the token/session.
Current required baseline scopes:
DeviceManagementManagedDevices.Read.AllDirectory.Read.AllExternalConnection.Read.AllGroup.Read.AllInformationProtectionPolicy.Read.AllOrganization.Read.AllPolicy.Read.AllReports.Read.All
How missing permissions are handled:
- Missing scopes are recorded in
Metadata.MissingGraphPermissions. - Collection continues.
- Affected sections return
Statusor fields asnot collectedwith reason text.
Consent behavior:
- The script checks consent state and reports if admin action is needed.
- It does not grant consent itself (read-only design).
Execution uses a phased startup:
- Connection checks.
- Graph auth/token logic.
- Optional service connections.
- Scope validation.
- Data collection.
- Summary/scoring.
- JSON output.
- Disconnect/cleanup.
- Uses device-code OAuth flow.
- Opens browser to verification URL.
- Polls token endpoint until success/expiry.
- Caches token and expiration in script scope.
- Reuses valid cached token when allowed.
If using default Microsoft client ID:
- The script uses
https://graph.microsoft.com/.default. - Returned permissions depend on what is already consented in your tenant.
- If required scopes are not pre-consented, they appear as missing.
If using custom app registration:
- Provide explicit delegated scopes via
-GraphScopes. - Admin consent can be granted for that custom app.
- This path is best for deterministic scope coverage.
The script attempts best-effort connection to:
- Microsoft Teams
- SharePoint/PnP Online
- Exchange Online
- Microsoft Purview compliance session (IPPS)
Each successful connection prints a green success confirmation.
Key helper behavior:
-
Invoke-Collector: Runs each collector in try/catch, records timings and errors, never hard-fails full run. -
Get-GraphRest: Single Graph GET with warning suppression for known expected failures. -
Get-GraphRestAll: Handles Graph pagination (@odata.nextLink) and request-level cache. -
Get-GraphReportRows: Normalizes report endpoints that return CSV, JSON, or temporary download URL. - Value parsers (
Get-IntValue,Get-DoubleValue): Defensive type conversion for stable JSON output.
The script writes each section into one ordered report object.
-
Metadata: Tenant identity, run metadata, granted scopes, consent/missing permissions, user counts. -
Licensing: SKU inventory, Copilot SKU detection, prerequisite service-plan readiness. -
Identity: MFA capability/registration, passwordless signal, stale users, role membership, security defaults. -
ConditionalAccess: Policy inventory and coverage flags ifPolicy.Read.Allavailable. -
DataGovernance: Sensitivity labels, DLP policies, retention policies. -
SharePointOneDrive: Tenant sharing posture, sampled site summaries, oversharing signal best-effort. -
Exchange: Mailbox posture via EXO cmdlets or Graph fallback. -
Teams: Team inventory and meeting policy signals. -
SearchIndex: External connections and readiness indicators. -
Apps: M365 app usage report availability and endpoint placeholders. -
AdoptionSignals: Office 365 active-user counts and Copilot usage snapshot.
These depend mostly on earlier sections and compute additional posture signals:
IdentityAccessAdvancedDataProtectionAdvancedSharePointExposureAdvancedTeamsAdvancedSearchSemanticAdvancedEndpointAppAdvancedAdoptionAdvancedAppGovernanceAdvanced
After all collection:
-
ReadinessFlagsis computed from collected sections. -
ReadinessEvidencecomputes domain scores and overall score. -
Recommendationsgenerates top risks and quick wins.
Scoring domains:
- IdentityAccess
- DataGovernance
- ContentExposure
- Adoption
- EndpointReadiness
Confidence adjustment:
- Completeness is section-level, not field-level.
- Score is adjusted by completeness percentage.
Top-level keys include:
MetadataLicensingIdentityConditionalAccessDataGovernanceSharePointOneDriveExchangeTeamsSearchIndexAppsAdoptionSignalsIdentityAccessAdvancedDataProtectionAdvancedSharePointExposureAdvancedTeamsAdvancedSearchSemanticAdvancedEndpointAppAdvancedAdoptionAdvancedAppGovernanceAdvancedReadinessFlagsReadinessEvidenceRecommendationsCollectorTimingsErrors
Interpretation notes:
-
not collectedmeans data path was unavailable or permission was missing. -
Errorscaptures collector failures without aborting whole run. -
CollectorTimingshelps identify slow sections.
pwsh -File .\m365-ai-ready-export.ps1pwsh -File .\m365-ai-ready-export.ps1 -TenantId "<tenant-guid>" -OutputPath ".\AIReadiness.json"pwsh -File .\m365-ai-ready-export.ps1 -IncludeSampling -SampleSize 100pwsh -File .\m365-ai-ready-export.ps1 `
-TenantId "<tenant-guid>" `
-GraphClientId "<app-client-id>" `
-GraphScopes \
"https://graph.microsoft.com/DeviceManagementManagedDevices.Read.All",\
"https://graph.microsoft.com/Directory.Read.All",\
"https://graph.microsoft.com/ExternalConnection.Read.All",\
"https://graph.microsoft.com/Group.Read.All",\
"https://graph.microsoft.com/InformationProtectionPolicy.Read.All",\
"https://graph.microsoft.com/Organization.Read.All",\
"https://graph.microsoft.com/Policy.Read.All",\
"https://graph.microsoft.com/Reports.Read.All"Use this checklist for repeatable operation.
Before run:
- Confirm PowerShell 7+.
- Confirm required modules available where needed.
- Confirm account has read access.
- Choose auth path (default client vs custom app).
- If custom app, verify delegated scope consent in Entra ID.
During run:
- Complete device-code login in browser.
- Watch success messages for each service connection.
- Review warnings for missing scopes or unavailable connectors.
After run:
- Open output JSON.
- Check
Metadata.MissingGraphPermissionsfirst. - Check
ErrorsandCollectorTimings. - Review
ReadinessEvidenceandRecommendationsfor action plan.
Cause:
- Token lacks one or more required delegated scopes.
Actions:
- Use custom app + explicit
-GraphScopes. - Grant admin consent for that app.
- Rerun script and verify
Metadata.GrantedScopesandMetadata.MissingGraphPermissions.
Cause:
- Graph context may not expose scopes in all module/session combinations.
Behavior:
- Script now also falls back to token-derived scope claims where possible.
Cause:
- Missing permission, module, or service connection.
Actions:
- Check section
Reasonvalue. - Check module availability.
- Check connector login outcome in console output.
Cause:
- Reports API may return no data for license/feature/tenant maturity reasons.
Actions:
- Verify
Reports.Read.Allis consented. - Recheck tenant report readiness and service enablement.
For productionized execution:
- Run from a controlled admin workstation or secure automation host.
- Keep output files in a dated evidence folder per tenant/run.
- Track drift by comparing
ReadinessEvidenceacross runs. - Build a simple parser with three alerts:
MissingGraphPermissionsis non-empty;Errorscount is greater than 0; overall score drops significantly between runs.
If you extend this script:
- Keep collectors read-only.
- Add new sections as ordered hashtables for deterministic JSON.
- Wrap each collector with existing
Invoke-Collectorpattern. - Gate permission-dependent calls with
Test-GraphPermissionsAvailable. - Return
not collectedwith clear reason instead of throwing.
This script is built to be:
- Safe (read-only)
- Resilient (partial results over hard failure)
- Observable (timings, errors, status signals)
- Actionable (scores and recommendations)
If your goal is consistent full-fidelity output, the most important implementation decision is using a custom app registration with explicit delegated Graph permissions and admin consent.