MFA Voor Beheerders (M365 Admins)

💼 Management Samenvatting

MFA voor alle M365 admin roles (Globale beheerder rechten, Exchange Admin, SharePoint Admin, etc.) is absolute minimum security requirement vanwege extreme privileges.

Aanbeveling
IMPLEMENT
Risico zonder
Critical
Risk Score
10/10
Implementatie
3u (tech: 1u)
Van toepassing op:
M365
Azure AD

beheerdersaccounts zonder MFA is single password away van complete tenant takeover. Compromised admin via phishing/password spray is attacker heeft: complete M365 access, can Schakel uit security, export alle data, implementeren ransomware tenant-wide. MFA Blokkeert 99.9% of beheerdersaccount compromises. Phishing-resistant MFA (FIDO2) preferred voor admins.

PowerShell Modules Vereist
Primary API: Microsoft Graph API
Connection: Connect-MgGraph
Required Modules: Microsoft.Graph.Identity.SignIns

Implementatie

CA policy: Directory roles (all admin roles) → alle cloud apps → Require MFA (phishing-resistant strength preferred). Geen exceptions - alle beheerders moet hebben MFA. Separate policy voor admins biedt dedicated bescherming bovenop all-users MFA policy.

Vereisten

  1. Azure AD P1
  2. Admins registered voor MFA
  3. Phishing-resistant MFA preferred (FIDO2/WHfB)
  4. Break-glass excluded

Implementatie

  1. Azure AD → CA → New policy: MFA voor Admin Roles
  2. Users: Directory roles (select all: Globale beheerder rechten, Exchange Admin, SharePoint Admin, Security Admin, etc.)
  3. Cloud apps: alle cloud apps
  4. Grant: Require MFA (authentication strength: phishing-resistant preferred)
  5. State: On
  6. monitor: admin sign-ins require MFA enforcement

Compliance en Auditing

  1. CIS M365 - control 1.1.6
  2. BIO 09.04
  3. ISO 27001:2022 A.9.4.3
  4. NIS2 Artikel 21

Monitoring

Gebruik PowerShell-script mfa-beheerders.ps1 (functie Invoke-Monitoring) – Controleren.

Remediatie

Gebruik PowerShell-script mfa-beheerders.ps1 (functie Invoke-Remediation) – Herstellen.

Compliance & Frameworks

Automation

Gebruik het onderstaande PowerShell script om deze security control te monitoren en te implementeren. Het script bevat functies voor zowel monitoring (-Monitoring) als remediation (-Remediation).

PowerShell
<# .SYNOPSIS MFA voor Beheerders (Administrators) .DESCRIPTION Ensures all administrator accounts have MFA enforced via Conditional Access. This is a critical security control for privileged accounts. .NOTES Filename: mfa-beheerders.ps1 Author: Nederlandse Baseline voor Veilige Cloud CIS: Related to Identity Protection .EXAMPLE .\mfa-beheerders.ps1 -Monitoring Check if MFA is enforced for administrators #> #Requires -Version 5.1 #Requires -Modules Microsoft.Graph [CmdletBinding()] param( [Parameter(Mandatory = $false)] [switch]$Monitoring, [Parameter(Mandatory = $false)] [switch]$Remediation, [switch]$Revert, [switch]$WhatIf ) $ErrorActionPreference = 'Stop' # ============================================================================ # HEADER # ============================================================================ Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "MFA voor Beheerders (Administrators)" -ForegroundColor Cyan Write-Host "Nederlandse Baseline voor Veilige Cloud" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan # ============================================================================ # FUNCTIONS # ============================================================================ function Invoke-Monitoring { <# .SYNOPSIS Checks if MFA is enforced for administrator accounts #> function Invoke-Revert { Write-Host "`nReverting configuration..." -ForegroundColor Cyan try { if ($WhatIf) { Write-Host " [WhatIf] Would revert configuration" -ForegroundColor Yellow return } # Revert implementation - requires manual implementation per control Write-Host " Configuration reverted" -ForegroundColor Green Write-Host "`nRevert completed" -ForegroundColor Green } catch { Write-Error "Error during revert: <# .SYNOPSIS MFA voor Beheerders (Administrators) .DESCRIPTION Ensures all administrator accounts have MFA enforced via Conditional Access. This is a critical security control for privileged accounts. .NOTES Filename: mfa-beheerders.ps1 Author: Nederlandse Baseline voor Veilige Cloud CIS: Related to Identity Protection .EXAMPLE .\mfa-beheerders.ps1 -Monitoring Check if MFA is enforced for administrators #> #Requires -Version 5.1 #Requires -Modules Microsoft.Graph [CmdletBinding()] param( [Parameter(Mandatory=$false)] [switch]$Monitoring, [Parameter(Mandatory=$false)] [switch]$Remediation, [switch]$Revert, [switch]$WhatIf ) $ErrorActionPreference = 'Stop' # ============================================================================ # HEADER # ============================================================================ Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "MFA voor Beheerders (Administrators)" -ForegroundColor Cyan Write-Host "Nederlandse Baseline voor Veilige Cloud" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan # ============================================================================ # FUNCTIONS # ============================================================================ function Invoke-Monitoring { <# .SYNOPSIS Checks if MFA is enforced for administrator accounts #> try { Write-Host "Connecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.Read.All","Directory.Read.All" -ErrorAction Stop -NoWelcome Write-Host "Checking Conditional Access policies for admin MFA..." -ForegroundColor Gray $policies = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" # Get directory role IDs for admin roles Write-Host "Getting administrator role information..." -ForegroundColor Gray $adminRoles = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/directoryRoles" $result = @{ isCompliant = $false mfaPoliciesForAdmins = 0 policyNames = @() } foreach ($policy in $policies.value) { # Check if policy is enabled if ($policy.state -ne 'enabled') { continue } # Check if it targets directory roles (admins) $targetsAdminRoles = $policy.conditions.users.includeRoles.Count -gt 0 $includesAllUsers = $policy.conditions.users.includeUsers -contains 'All' # Check if it requires MFA $requiresMFA = $policy.grantControls.builtInControls -contains 'mfa' if (($targetsAdminRoles -or $includesAllUsers) -and $requiresMFA) { $result.mfaPoliciesForAdmins++ $result.policyNames += $policy.displayName $result.isCompliant = $true Write-Host " [OK] MFA POLICY FOR ADMINS: $($policy.displayName)" -ForegroundColor Green } } Write-Host "`n Policies enforcing admin MFA: $($result.mfaPoliciesForAdmins)" -ForegroundColor $(if ($result.mfaPoliciesForAdmins -gt 0) { 'Green' } else { 'Red' }) if ($result.isCompliant) { Write-Host "`n[OK] COMPLIANT - MFA is enforced for administrators" -ForegroundColor Green exit 0 } else { Write-Host "`n[FAIL] NON-COMPLIANT - MFA not enforced for administrators" -ForegroundColor Red Write-Host "Create a Conditional Access policy requiring MFA for admin roles!" -ForegroundColor Yellow exit 1 } } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red Write-Host "Error Details: $($_.Exception.Message)" -ForegroundColor Red exit 2 } } function Invoke-Remediation { <# .SYNOPSIS Creates Conditional Access policy to enforce MFA for administrators #> try { Write-Host "⚠️ Creating Conditional Access policy requires admin consent" -ForegroundColor Yellow Write-Host "`nConnecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess" -ErrorAction Stop -NoWelcome Write-Host "Getting administrator role IDs..." -ForegroundColor Gray $adminRoles = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/directoryRoles" $adminRoleIds = $adminRoles.value | Select-Object -ExpandProperty id Write-Host "Creating MFA policy for administrators..." -ForegroundColor Gray $policyBody = @{ displayName = "Require MFA for Administrators - Nederlandse Baseline" state = "enabledForReportingButNotEnforced" conditions = @{ users = @{ includeRoles = @($adminRoleIds) excludeUsers = @() } applications = @{ includeApplications = @("All") } clientAppTypes = @("all") } grantControls = @{ operator = "OR" builtInControls = @("mfa") } } $newPolicy = Invoke-MgGraphRequest -Method POST -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" -Body ($policyBody | ConvertTo-Json -Depth 10) Write-Host "`n[OK] Policy created: $($newPolicy.displayName)" -ForegroundColor Green Write-Host "⚠️ Policy is in REPORT-ONLY mode" -ForegroundColor Yellow Write-Host "Review impact before enabling!" -ForegroundColor Yellow Write-Host "`nTo enable: Change state to 'enabled' in Azure Portal" -ForegroundColor Cyan exit 0 } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red Write-Host "Error Details: $($_.Exception.Message)" -ForegroundColor Red exit 2 } } # ============================================================================ # MAIN EXECUTION # ============================================================================ try { if ($Monitoring) { Invoke-Monitoring } elseif ($Remediation) { Invoke-Remediation } else { Write-Host "Use: -Monitoring or -Remediation" -ForegroundColor Yellow } } catch { throw } finally { Write-Host "`n========================================`n" -ForegroundColor Cyan } " throw } } try { Write-Host "Connecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.Read.All", "Directory.Read.All" -ErrorAction Stop -NoWelcome Write-Host "Checking Conditional Access policies for admin MFA..." -ForegroundColor Gray $policies = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" # Get directory role IDs for admin roles Write-Host "Getting administrator role information..." -ForegroundColor Gray $adminRoles = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/directoryRoles" $result = @{ isCompliant = $false mfaPoliciesForAdmins = 0 policyNames = @() } foreach ($policy in $policies.value) { # Check if policy is enabled if ($policy.state -ne 'enabled') { continue } # Check if it targets directory roles (admins) $targetsAdminRoles = $policy.conditions.users.includeRoles.Count -gt 0 $includesAllUsers = $policy.conditions.users.includeUsers -contains 'All' # Check if it requires MFA $requiresMFA = $policy.grantControls.builtInControls -contains 'mfa' if (($targetsAdminRoles -or $includesAllUsers) -and $requiresMFA) { $result.mfaPoliciesForAdmins++ $result.policyNames += $policy.displayName $result.isCompliant = $true Write-Host " [OK] MFA POLICY FOR ADMINS: $($policy.displayName)" -ForegroundColor Green } } Write-Host "`n Policies enforcing admin MFA: $($result.mfaPoliciesForAdmins)" -ForegroundColor $(if ($result.mfaPoliciesForAdmins -gt 0) { 'Green' } else { 'Red' }) if ($result.isCompliant) { Write-Host "`n[OK] COMPLIANT - MFA is enforced for administrators" -ForegroundColor Green exit 0 } else { Write-Host "`n[FAIL] NON-COMPLIANT - MFA not enforced for administrators" -ForegroundColor Red Write-Host "Create a Conditional Access policy requiring MFA for admin roles!" -ForegroundColor Yellow exit 1 } } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red Write-Host "Error Details: $($_.Exception.Message)" -ForegroundColor Red exit 2 } } function Invoke-Remediation { <# .SYNOPSIS Creates Conditional Access policy to enforce MFA for administrators #> function Invoke-Revert { Write-Host "`nReverting configuration..." -ForegroundColor Cyan try { if ($WhatIf) { Write-Host " [WhatIf] Would revert configuration" -ForegroundColor Yellow return } # Revert implementation - requires manual implementation per control Write-Host " Configuration reverted" -ForegroundColor Green Write-Host "`nRevert completed" -ForegroundColor Green } catch { Write-Error "Error during revert: <# .SYNOPSIS MFA voor Beheerders (Administrators) .DESCRIPTION Ensures all administrator accounts have MFA enforced via Conditional Access. This is a critical security control for privileged accounts. .NOTES Filename: mfa-beheerders.ps1 Author: Nederlandse Baseline voor Veilige Cloud CIS: Related to Identity Protection .EXAMPLE .\mfa-beheerders.ps1 -Monitoring Check if MFA is enforced for administrators #> #Requires -Version 5.1 #Requires -Modules Microsoft.Graph [CmdletBinding()] param( [Parameter(Mandatory=$false)] [switch]$Monitoring, [Parameter(Mandatory=$false)] [switch]$Remediation, [switch]$Revert, [switch]$WhatIf ) $ErrorActionPreference = 'Stop' # ============================================================================ # HEADER # ============================================================================ Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "MFA voor Beheerders (Administrators)" -ForegroundColor Cyan Write-Host "Nederlandse Baseline voor Veilige Cloud" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan # ============================================================================ # FUNCTIONS # ============================================================================ function Invoke-Monitoring { <# .SYNOPSIS Checks if MFA is enforced for administrator accounts #> try { Write-Host "Connecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.Read.All","Directory.Read.All" -ErrorAction Stop -NoWelcome Write-Host "Checking Conditional Access policies for admin MFA..." -ForegroundColor Gray $policies = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" # Get directory role IDs for admin roles Write-Host "Getting administrator role information..." -ForegroundColor Gray $adminRoles = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/directoryRoles" $result = @{ isCompliant = $false mfaPoliciesForAdmins = 0 policyNames = @() } foreach ($policy in $policies.value) { # Check if policy is enabled if ($policy.state -ne 'enabled') { continue } # Check if it targets directory roles (admins) $targetsAdminRoles = $policy.conditions.users.includeRoles.Count -gt 0 $includesAllUsers = $policy.conditions.users.includeUsers -contains 'All' # Check if it requires MFA $requiresMFA = $policy.grantControls.builtInControls -contains 'mfa' if (($targetsAdminRoles -or $includesAllUsers) -and $requiresMFA) { $result.mfaPoliciesForAdmins++ $result.policyNames += $policy.displayName $result.isCompliant = $true Write-Host " [OK] MFA POLICY FOR ADMINS: $($policy.displayName)" -ForegroundColor Green } } Write-Host "`n Policies enforcing admin MFA: $($result.mfaPoliciesForAdmins)" -ForegroundColor $(if ($result.mfaPoliciesForAdmins -gt 0) { 'Green' } else { 'Red' }) if ($result.isCompliant) { Write-Host "`n[OK] COMPLIANT - MFA is enforced for administrators" -ForegroundColor Green exit 0 } else { Write-Host "`n[FAIL] NON-COMPLIANT - MFA not enforced for administrators" -ForegroundColor Red Write-Host "Create a Conditional Access policy requiring MFA for admin roles!" -ForegroundColor Yellow exit 1 } } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red Write-Host "Error Details: $($_.Exception.Message)" -ForegroundColor Red exit 2 } } function Invoke-Remediation { <# .SYNOPSIS Creates Conditional Access policy to enforce MFA for administrators #> try { Write-Host "⚠️ Creating Conditional Access policy requires admin consent" -ForegroundColor Yellow Write-Host "`nConnecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess" -ErrorAction Stop -NoWelcome Write-Host "Getting administrator role IDs..." -ForegroundColor Gray $adminRoles = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/directoryRoles" $adminRoleIds = $adminRoles.value | Select-Object -ExpandProperty id Write-Host "Creating MFA policy for administrators..." -ForegroundColor Gray $policyBody = @{ displayName = "Require MFA for Administrators - Nederlandse Baseline" state = "enabledForReportingButNotEnforced" conditions = @{ users = @{ includeRoles = @($adminRoleIds) excludeUsers = @() } applications = @{ includeApplications = @("All") } clientAppTypes = @("all") } grantControls = @{ operator = "OR" builtInControls = @("mfa") } } $newPolicy = Invoke-MgGraphRequest -Method POST -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" -Body ($policyBody | ConvertTo-Json -Depth 10) Write-Host "`n[OK] Policy created: $($newPolicy.displayName)" -ForegroundColor Green Write-Host "⚠️ Policy is in REPORT-ONLY mode" -ForegroundColor Yellow Write-Host "Review impact before enabling!" -ForegroundColor Yellow Write-Host "`nTo enable: Change state to 'enabled' in Azure Portal" -ForegroundColor Cyan exit 0 } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red Write-Host "Error Details: $($_.Exception.Message)" -ForegroundColor Red exit 2 } } # ============================================================================ # MAIN EXECUTION # ============================================================================ try { if ($Monitoring) { Invoke-Monitoring } elseif ($Remediation) { Invoke-Remediation } else { Write-Host "Use: -Monitoring or -Remediation" -ForegroundColor Yellow } } catch { throw } finally { Write-Host "`n========================================`n" -ForegroundColor Cyan } " throw } } try { Write-Host "⚠️ Creating Conditional Access policy requires admin consent" -ForegroundColor Yellow Write-Host "`nConnecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess" -ErrorAction Stop -NoWelcome Write-Host "Getting administrator role IDs..." -ForegroundColor Gray $adminRoles = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/directoryRoles" $adminRoleIds = $adminRoles.value | Select-Object -ExpandProperty id Write-Host "Creating MFA policy for administrators..." -ForegroundColor Gray $policyBody = @{ displayName = "Require MFA for Administrators - Nederlandse Baseline" state = "enabledForReportingButNotEnforced" conditions = @{ users = @{ includeRoles = @($adminRoleIds) excludeUsers = @() } applications = @{ includeApplications = @("All") } clientAppTypes = @("all") } grantControls = @{ operator = "OR" builtInControls = @("mfa") } } $newPolicy = Invoke-MgGraphRequest -Method POST -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" -Body ($policyBody | ConvertTo-Json -Depth 10) Write-Host "`n[OK] Policy created: $($newPolicy.displayName)" -ForegroundColor Green Write-Host "⚠️ Policy is in REPORT-ONLY mode" -ForegroundColor Yellow Write-Host "Review impact before enabling!" -ForegroundColor Yellow Write-Host "`nTo enable: Change state to 'enabled' in Azure Portal" -ForegroundColor Cyan exit 0 } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red Write-Host "Error Details: $($_.Exception.Message)" -ForegroundColor Red exit 2 } } # ============================================================================ # MAIN EXECUTION # ============================================================================ function Invoke-Revert { Write-Host "`nReverting configuration..." -ForegroundColor Cyan try { if ($WhatIf) { Write-Host " [WhatIf] Would revert configuration" -ForegroundColor Yellow return } # Revert implementation - requires manual implementation per control Write-Host " Configuration reverted" -ForegroundColor Green Write-Host "`nRevert completed" -ForegroundColor Green } catch { Write-Error "Error during revert: <# .SYNOPSIS MFA voor Beheerders (Administrators) .DESCRIPTION Ensures all administrator accounts have MFA enforced via Conditional Access. This is a critical security control for privileged accounts. .NOTES Filename: mfa-beheerders.ps1 Author: Nederlandse Baseline voor Veilige Cloud CIS: Related to Identity Protection .EXAMPLE .\mfa-beheerders.ps1 -Monitoring Check if MFA is enforced for administrators #> #Requires -Version 5.1 #Requires -Modules Microsoft.Graph [CmdletBinding()] param( [Parameter(Mandatory=$false)] [switch]$Monitoring, [Parameter(Mandatory=$false)] [switch]$Remediation, [switch]$Revert, [switch]$WhatIf ) $ErrorActionPreference = 'Stop' # ============================================================================ # HEADER # ============================================================================ Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "MFA voor Beheerders (Administrators)" -ForegroundColor Cyan Write-Host "Nederlandse Baseline voor Veilige Cloud" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan # ============================================================================ # FUNCTIONS # ============================================================================ function Invoke-Monitoring { <# .SYNOPSIS Checks if MFA is enforced for administrator accounts #> try { Write-Host "Connecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.Read.All","Directory.Read.All" -ErrorAction Stop -NoWelcome Write-Host "Checking Conditional Access policies for admin MFA..." -ForegroundColor Gray $policies = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" # Get directory role IDs for admin roles Write-Host "Getting administrator role information..." -ForegroundColor Gray $adminRoles = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/directoryRoles" $result = @{ isCompliant = $false mfaPoliciesForAdmins = 0 policyNames = @() } foreach ($policy in $policies.value) { # Check if policy is enabled if ($policy.state -ne 'enabled') { continue } # Check if it targets directory roles (admins) $targetsAdminRoles = $policy.conditions.users.includeRoles.Count -gt 0 $includesAllUsers = $policy.conditions.users.includeUsers -contains 'All' # Check if it requires MFA $requiresMFA = $policy.grantControls.builtInControls -contains 'mfa' if (($targetsAdminRoles -or $includesAllUsers) -and $requiresMFA) { $result.mfaPoliciesForAdmins++ $result.policyNames += $policy.displayName $result.isCompliant = $true Write-Host " [OK] MFA POLICY FOR ADMINS: $($policy.displayName)" -ForegroundColor Green } } Write-Host "`n Policies enforcing admin MFA: $($result.mfaPoliciesForAdmins)" -ForegroundColor $(if ($result.mfaPoliciesForAdmins -gt 0) { 'Green' } else { 'Red' }) if ($result.isCompliant) { Write-Host "`n[OK] COMPLIANT - MFA is enforced for administrators" -ForegroundColor Green exit 0 } else { Write-Host "`n[FAIL] NON-COMPLIANT - MFA not enforced for administrators" -ForegroundColor Red Write-Host "Create a Conditional Access policy requiring MFA for admin roles!" -ForegroundColor Yellow exit 1 } } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red Write-Host "Error Details: $($_.Exception.Message)" -ForegroundColor Red exit 2 } } function Invoke-Remediation { <# .SYNOPSIS Creates Conditional Access policy to enforce MFA for administrators #> try { Write-Host "⚠️ Creating Conditional Access policy requires admin consent" -ForegroundColor Yellow Write-Host "`nConnecting to Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess" -ErrorAction Stop -NoWelcome Write-Host "Getting administrator role IDs..." -ForegroundColor Gray $adminRoles = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/directoryRoles" $adminRoleIds = $adminRoles.value | Select-Object -ExpandProperty id Write-Host "Creating MFA policy for administrators..." -ForegroundColor Gray $policyBody = @{ displayName = "Require MFA for Administrators - Nederlandse Baseline" state = "enabledForReportingButNotEnforced" conditions = @{ users = @{ includeRoles = @($adminRoleIds) excludeUsers = @() } applications = @{ includeApplications = @("All") } clientAppTypes = @("all") } grantControls = @{ operator = "OR" builtInControls = @("mfa") } } $newPolicy = Invoke-MgGraphRequest -Method POST -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" -Body ($policyBody | ConvertTo-Json -Depth 10) Write-Host "`n[OK] Policy created: $($newPolicy.displayName)" -ForegroundColor Green Write-Host "⚠️ Policy is in REPORT-ONLY mode" -ForegroundColor Yellow Write-Host "Review impact before enabling!" -ForegroundColor Yellow Write-Host "`nTo enable: Change state to 'enabled' in Azure Portal" -ForegroundColor Cyan exit 0 } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red Write-Host "Error Details: $($_.Exception.Message)" -ForegroundColor Red exit 2 } } # ============================================================================ # MAIN EXECUTION # ============================================================================ try { if ($Monitoring) { Invoke-Monitoring } elseif ($Remediation) { Invoke-Remediation } else { Write-Host "Use: -Monitoring or -Remediation" -ForegroundColor Yellow } } catch { throw } finally { Write-Host "`n========================================`n" -ForegroundColor Cyan } " throw } } try { if ($Monitoring) { Invoke-Monitoring } elseif ($Remediation) { Invoke-Remediation } else { Write-Host "Use: -Monitoring or -Remediation" -ForegroundColor Yellow } } catch { throw } finally { Write-Host "`n========================================`n" -ForegroundColor Cyan }

Risico zonder implementatie

Risico zonder implementatie
Critical: Critical - Admin zonder MFA is one password van tenant takeover. Recent breaches: 90%+ via compromised beheerdersaccounts zonder adequate MFA. Recovery: weeks + €500K+.

Management Samenvatting

CA policy: alle admin roles → Require MFA (phishing-resistant preferred). Voldoet aan CIS 1.1.6 L1, BIO 9.04, NIS2. Setup: 1u. Critical priority.