- Restructure launchers: Start-IntuneToolkit.ps1 moves to repo root; Start-HeadlessIntune.ps1 moves to Scripts/; TUI helper moves to Scripts/Private/ - Add AGENTS.md with project architecture, entry points, and security notes - Add CIS M365 baseline assets (CISM365-v7, M365-CIS-Rapid) and reporting scripts - Add Python reporting utilities (Export-SettingsReport, Export-AssignmentReport, Export-ObjectInventoryReport) and CA wizard helpers - Update Deploy-IntuneBaseline.ps1 with Merge conflict resolution, ReportPath, and optimized group loading - Update Initialize-IntuneAuth.ps1 with -RotateSecret and configurable secret expiry - Update Extensions for Settings Catalog definition auto-export - Update README with v4.1.0, new entry points and script catalog - Bump VERSION to 4.1.0 - Harden .gitignore against .DS_Store, __pycache__, .venv-pdf/, local exports, Settings.json and IntuneManagement.log
6.9 KiB
CIS M365 v7.0.0 YAML Baseline Format
This document describes the YAML schema for CISM365-v7.example.yaml, which extends the existing OpenIntuneBaseline.example.yaml format to cover tenant-level M365 configuration.
Why This Format?
The existing Intune baseline YAML works great for device policies. For CIS M365 compliance, you need the same declarative approach but for:
- Entra ID settings (password policies, device quotas, consent)
- Conditional Access policies
- Defender for Office 365 policies
- Exchange Online transport rules
- SharePoint / OneDrive sharing
- Microsoft Teams policies
This YAML keeps the same root structure as the Intune baseline so you can optionally include Intune policies in the same manifest, or keep them separate.
Root Structure
baseline:
name: string
conflictResolution: Skip | Update | Error
whatIf: false
tenantMutation:
search: string # optional
replace: string # optional
prefix: string # optional (alternative to search/replace)
groups: [] # Cloud-only security groups (same as Intune baseline)
policies: [] # Intune policies (optional, same schema as Intune baseline)
tenantConfig: # NEW: M365 tenant-level configuration
adminCenter: {}
entraId: {}
conditionalAccess: {}
defender: {}
exchange: {}
sharePoint: {}
teams: {}
tenantConfig Sections
adminCenter
M365 Admin Center settings.
adminCenter:
passwordExpiration: NeverExpire # NeverExpire | 90Days | 180Days
idleSessionTimeoutHours: 3
restrictUserOwnedApps: true
formsPhishingProtection: true
customerLockbox: true
restrictThirdPartyStorage: true
entraId
Entra ID directory settings.
entraId:
blockUserConsent: true
blockTenantCreation: true
restrictAdminCenterAccess: true
disableLinkedIn: true
maxDevicesPerUser: 5
gaLocalAdminDisabled: true
bannedPasswords:
- "Contoso"
- "Password"
conditionalAccess
The most powerful section. Supports automatic CA policy creation with:
- Global
reportOnlyswitch — all policies default to report-only - Automatic break-glass exclusion — specify one group, it's excluded from every policy
- Custom naming via
tenantMutation - Role name resolution — use friendly names like "Global Administrator", script maps to template IDs
conditionalAccess:
reportOnly: true # Global switch
breakGlassGroup: "CIS-BreakGlass" # Auto-excluded from all policies
policies:
- name: "Block-Legacy-Auth"
cisControl: "5.2.2.3"
description: "Block legacy authentication"
state: enabledForReportingButNotEnforced
conditions:
applications:
includeApplications: ["All"]
users:
includeUsers: ["All"]
excludeGroups: ["CIS-Pilot-Users"]
clientAppTypes: ["exchangeActiveSync", "other"]
grantControls:
builtInControls: ["block"]
operator: "OR"
CA Policy Conditions Supported:
| Condition | YAML Key | Example |
|---|---|---|
| Apps | applications.includeApplications |
["All"] or ["Office365"] |
| User actions | applications.includeUserActions |
["urn:user:registersecurityinfo"] |
| Users | users.includeUsers |
["All"] or specific UPNs |
| Groups | users.includeGroups / excludeGroups |
["CIS-Pilot-Users"] — resolved by displayName |
| Roles | users.includeRoles / excludeRoles |
["Global Administrator"] — friendly names mapped to template IDs |
| Client apps | clientAppTypes |
["exchangeActiveSync", "other"] |
| Sign-in risk | signInRiskLevels |
["medium", "high"] |
| Locations | locations.includeLocations |
["AllTrusted"] or ["All"] |
| Auth flows | authenticationFlows.deviceCodeFlow |
{ isEnabled: true } |
Grant Controls Supported:
| Control | YAML Key |
|---|---|
| Block | grantControls.builtInControls: ["block"] |
| Require MFA | grantControls.builtInControls: ["mfa"] |
| Compliant device | grantControls.builtInControls: ["compliantDevice", "domainJoinedDevice"] |
| Phishing-resistant MFA | grantControls.builtInControls: ["authenticationStrength"] + grantControls.authenticationStrength.id |
Session Controls Supported:
sessionControls:
signInFrequency:
value: 12
type: hours
isEnabled: true
persistentBrowser:
mode: never # never | always
isEnabled: true
defender
Defender for Office 365 policies.
defender:
safeLinks:
- name: "SafeLinks-Default"
cisControl: "2.1.1"
enabled: true
trackClicks: true
allowClickThrough: false
scanUrls: true
enableForInternalSenders: true
safeAttachments:
- name: "SafeAttachments-Default"
cisControl: "2.1.4"
enabled: true
action: Block
quarantineMessages: true
antiMalware:
- name: "AntiMalware-Default"
cisControl: "2.1.2"
enabled: true
enableInternalNotifications: true
fileTypes: ["ace", "exe", "jar", "vbs"]
exchange
Exchange Online settings.
exchange:
enableMailboxAuditOrgWide: true
blockExternalForwarding: true
enableExternalSenderBanner: true
externalEmailWarningRule: true
sharePoint
SharePoint / OneDrive sharing settings.
sharePoint:
adminUrl: "https://contoso-admin.sharepoint.com"
defaultSharingLinkType: Direct
sharePointExternalSharing: Disabled
oneDriveExternalSharing: Disabled
guestAccessExpirationDays: 30
denyCustomScripts: true
teams
Microsoft Teams policies.
teams:
allowAnonymousUsersToJoinMeeting: false
allowAnonymousUsersToStartMeeting: false
enableEmailIntegration: false
allowFederatedUsers: false
allowTeamsConsumer: false
Using the Draft PDF
Since CIS does not publish XLS for draft benchmarks:
- Open the PDF and work through each section
- For automated controls, add them to the appropriate
tenantConfigsection with thecisControlfield - For manual controls, skip them or add a comment
- The
cisControlfield preserves traceability (e.g.,cisControl: "5.2.2.3")
Deployment
# Assess (read-only)
./Scripts/Deploy-CISM365Baseline.ps1 -BaselinePath ./Baselines/mytenant-cisv7.yaml
# Deploy (applies changes)
./Scripts/Deploy-CISM365Baseline.ps1 -BaselinePath ./Baselines/mytenant-cisv7.yaml -Mode Deploy -Apply -Verbose
# Deploy only specific workloads
./Scripts/Deploy-CISM365Baseline.ps1 -BaselinePath ./Baselines/mytenant-cisv7.yaml -Mode Deploy -Apply -Workloads ConditionalAccess,EntraID
Safety Defaults
| Feature | Default | Why |
|---|---|---|
Mode |
Assess |
Must explicitly opt in to changes |
conditionalAccess.reportOnly |
true |
All CA policies created in report-only mode |
breakGlassGroup |
Auto-excluded | Prevents lockout |
Apply switch |
Required for Deploy | Double-confirmation pattern |
-WhatIf |
Supported | Native PowerShell WhatIf |