# 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 ```yaml 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. ```yaml adminCenter: passwordExpiration: NeverExpire # NeverExpire | 90Days | 180Days idleSessionTimeoutHours: 3 restrictUserOwnedApps: true formsPhishingProtection: true customerLockbox: true restrictThirdPartyStorage: true ``` ### entraId Entra ID directory settings. ```yaml 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 `reportOnly` switch** — 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 ```yaml 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:** ```yaml sessionControls: signInFrequency: value: 12 type: hours isEnabled: true persistentBrowser: mode: never # never | always isEnabled: true ``` ### defender Defender for Office 365 policies. ```yaml 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. ```yaml exchange: enableMailboxAuditOrgWide: true blockExternalForwarding: true enableExternalSenderBanner: true externalEmailWarningRule: true ``` ### sharePoint SharePoint / OneDrive sharing settings. ```yaml sharePoint: adminUrl: "https://contoso-admin.sharepoint.com" defaultSharingLinkType: Direct sharePointExternalSharing: Disabled oneDriveExternalSharing: Disabled guestAccessExpirationDays: 30 denyCustomScripts: true ``` ### teams Microsoft Teams policies. ```yaml teams: allowAnonymousUsersToJoinMeeting: false allowAnonymousUsersToStartMeeting: false enableEmailIntegration: false allowFederatedUsers: false allowTeamsConsumer: false ``` ## Using the Draft PDF Since CIS does not publish XLS for draft benchmarks: 1. Open the PDF and work through each section 2. For **automated** controls, add them to the appropriate `tenantConfig` section with the `cisControl` field 3. For **manual** controls, skip them or add a comment 4. The `cisControl` field preserves traceability (e.g., `cisControl: "5.2.2.3"`) ## Deployment ```powershell # 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 |