Quick Start: Data Retentie Policies - Week 3

πŸ’Ό Management Samenvatting

Data retentie policies implementeren automatische bewaring van emails, documenten en Teams chats volgens compliance vereisten (7 jaar BIO/AVG) en business needs, terwijl tegelijkertijd oude data wordt opgeruimd om opslag Kosten te beperken.

Aanbeveling
IMPLEMENT
Risico zonder
Medium
Risk Score
6/10
Implementatie
8u (tech: 4u)
Van toepassing op:
βœ“ M365
βœ“ Exchange Online
βœ“ SharePoint
βœ“ Teams

Zonder retentiebeleid: kritieke business data wordt per ongeluk verwijderd door users (no recovery mogelijk), compliance schendingen (BIO, AVG, sector-specific vereisen 7-10 jaar bewaring), e-discovery incomplete bij litigation (missing emails/documents), excessive opslag Kosten (alles wordt forever bewaard), en geen systematic data lifecycle management. retentiebeleid addresseren beide extremen: te weinig retention (gegevensverlies, compliance risk) en te veel retention (privacy risk, opslag costs, GDPR Article 5 'opslag limitation'). Microsoft Purview retentiebeleid provide: automatische retention volgens geconfigureerd period, bescherming tegen deletion (users kunnen niet deleten tijdens retention), automatische deletion na retention expiration (data minimization), en granular scopes (entire org, specific sites, specific users). Voor Nederlandse org: 7 jaar is BIO/AVG minimum voor meeste business data.

PowerShell Modules Vereist
Primary API: Microsoft Graph API
Connection: Connect-MgGraph
Required Modules: ExchangeOnlineManagement, Microsoft.Graph.Compliance

Implementatie

Deze quick start implementeert binnen 1 week basis retentiebeleid voor kritieke workloads: (1) Exchange Mailboxes: Retain alle items 7 years, toepassen to alle mailboxes of specific departments (finance, legal), Delete nadat 7 years (GDPR compliance), (2) SharePoint Sites & OneDrive: Retain alle documents 7 years, toepassen to alle sites of specific sites (contracts, HR files), Preserve tijdens retentieperiode (Voorkom deletion), (3) Teams chats & channels: Retain messages 7 years (channel messages + private chats), Critical voor communications compliance, Delete nadat retentieperiode. Implementation via Microsoft Purview compliance portal met adaptive scopes voor flexible assignment. Policies zijn non-destructive (bestaande data blijft, new data wordt govered) en kunnen worden fine-tuned na deployment. Combine met litigation holds voor legal cases (indefinite retention).

Vereisten

  1. Microsoft 365 E3/E5 of compliance add-on licentie
  2. Compliance Administrator of Information bescherming Administrator rol
  3. Legal/compliance team input: Retention requirements per data type
  4. data classificatie: Welke data vereist welke retention?
  5. opslag impact beoordeling: Calculate opslag growth
  6. Budget approval (retention increases opslag Kosten ~20-40%)

Implementatie (Week 3 - Dag 17-20)

Gebruik PowerShell-script 07-data-retentie.ps1 (functie Invoke-Implementation) – Implementeren.

DAG 17: Exchange Mailbox Retention

  1. Purview compliance portal β†’ Data lifecycle management β†’ retentiebeleid
  2. Maak aan policy: 'Email - 7 Year Retention'
  3. Type: retentiebeleid
  4. Locations: Exchange email (all mailboxes)
  5. retentieperiode: 7 years
  6. Start retention: Wanneer items created
  7. Action nadat retention: Delete automatically
  8. Apply policy
  9. Wait: 24-48 hours voor volledige deployment

DAG 18: SharePoint & OneDrive Retention

  1. Maak aan policy: 'SharePoint - 7 Year Retention'
  2. Locations: SharePoint sites (all) + OneDrive accounts (all)
  3. retentieperiode: 7 years
  4. Start retention: Wanneer created
  5. During retention: Preserve (gebruikers kunnen still delete maar recoverabel)
  6. After retention: Delete permanently
  7. Exception: Specific document libraries met longer retention (contracts is 10 jaar)

DAG 19: Teams Retention

  1. Maak aan policy: 'Teams - 7 Year Retention'
  2. Locations: Teams channel messages + Teams chats
  3. Retention: 7 years
  4. Include: alle teams of specific teams (finance, legal)
  5. OPMERKING: Teams retention complex (stored in mailboxes, SharePoint)
  6. Verify: Test Teams message deletion β†’ recoverable van retention

DAG 20: validatie & Documentation

  1. Test retention: Delete Test email, Verifieer retained
  2. Recovery test: Recover deleted retained item
  3. opslag impact: monitoren opslag usage trends
  4. Documentation: Retention schedule document, Legal hold procedures
  5. Training: Teach users over retention (items retained zelfs na deletion)

monitoring

Gebruik PowerShell-script 07-data-retentie.ps1 (functie Invoke-Monitoring) – Controleren.

  1. retentiebeleid status: Verifieer policies active en deployed
  2. Retained items count: monitoren volume van retained data
  3. opslag consumption: Volg opslag Kosten impact
  4. Policy effectiveness: Items successfully retained en recovered?
  5. Compliance: Demonstrate retention voor auditors

Compliance en Auditing

gegevensretentie is VERPLICHT voor: BIO Thema 12.04 (Logging moet 7 jaar bewaard), AVG Artikel 5 (opslag limitation maar ook business need voor retention), ISO 27001:2022 A.18.1.3 (bescherming of records), NIS2 (Incident logt retention), Sector-specific: Financial (7-10 jaar), Healthcare (10+ jaar). 7 jaar is Nederlandse standard voor meeste business data.

Remediatie

Gebruik PowerShell-script 07-data-retentie.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 Quick Start: Data Retentie .DESCRIPTION Configureert retention policies voor Microsoft 365 data (Email, SharePoint, OneDrive, Teams). VOLLEDIG GEAUTOMATISEERD via Security & Compliance PowerShell. CREATES: - Retention policy voor Email (7 jaar) - Retention policy voor SharePoint/OneDrive (7 jaar) - Retention policy voor Teams (7 jaar) - Optional: Litigation Hold voor specifieke mailboxes .NOTES Filename: 07-data-retentie.ps1 Author: Nederlandse Baseline voor Veilige Cloud Created: 2025-10-16 Related JSON: content/quick-start/07-data-retentie.json Requirement: Microsoft 365 E3/E5 Priority: Week 3 #> #Requires -Version 5.1 #Requires -Modules ExchangeOnlineManagement [CmdletBinding()] param( [Parameter(HelpMessage = "Monitor retention policies")] [switch]$Monitoring, [Parameter(HelpMessage = "Create basic 7-year retention policy")] [switch]$Remediation, [Parameter(HelpMessage = "Full implementation (Email + SharePoint + Teams + Litigation Hold)")] [switch]$Implementation, [Parameter(HelpMessage = "Revert (remove policies)")] [switch]$Revert, [Parameter(HelpMessage = "Retention period in days (default: 2555 = 7 years)")] [int]$RetentionDays = 2555, [Parameter(HelpMessage = "Preview changes")] [switch]$WhatIf ) $ErrorActionPreference = 'Stop' Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "Quick Start: Data Retentie" -ForegroundColor Cyan Write-Host "WEEK 3" -ForegroundColor Cyan Write-Host "Nederlandse Baseline voor Veilige Cloud" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan function Test-Compliance { [CmdletBinding()] param() $result = Invoke-Monitoring return $result.isCompliant } function Invoke-Monitoring { <# .SYNOPSIS Monitors retention policies #> [CmdletBinding()] param() try { Write-Host "`nMonitoring:" -ForegroundColor Yellow Connect-IPPSSession -ShowBanner:$false $result = @{ isCompliant = $false timestamp = Get-Date retentionPolicies = 0 retentionRules = 0 litigationHoldMailboxes = 0 totalMailboxes = 0 policies = @() } # Check retention policies Write-Host "Checking retention policies..." -ForegroundColor Gray $policies = Get-RetentionCompliancePolicy $result.retentionPolicies = $policies.Count foreach ($policy in $policies) { Write-Host " [OK] $($policy.Name)" -ForegroundColor Green Write-Host " Enabled: $($policy.Enabled)" -ForegroundColor Gray Write-Host " Workloads: $($policy.Workload -join ', ')" -ForegroundColor Gray $policyInfo = @{ name = $policy.Name enabled = $policy.Enabled workloads = $policy.Workload } $result.policies += $policyInfo } # Check retention rules Write-Host "`nChecking retention rules..." -ForegroundColor Gray $rules = Get-RetentionComplianceRule $result.retentionRules = $rules.Count foreach ($rule in $rules) { Write-Host " β€’ $($rule.Name)" -ForegroundColor Cyan Write-Host " Duration: $($rule.RetentionDuration) days" -ForegroundColor Gray Write-Host " Action: $($rule.RetentionComplianceAction)" -ForegroundColor Gray } # Check litigation hold mailboxes Write-Host "`nChecking Litigation Hold status..." -ForegroundColor Gray Connect-ExchangeOnline -ShowBanner:$false $mailboxes = Get-EXOMailbox -ResultSize Unlimited -Properties LitigationHoldEnabled $result.totalMailboxes = $mailboxes.Count $result.litigationHoldMailboxes = ($mailboxes | Where-Object { $_.LitigationHoldEnabled -eq $true }).Count if ($result.litigationHoldMailboxes -gt 0) { Write-Host " ℹ️ Litigation Hold: $($result.litigationHoldMailboxes)/$($result.totalMailboxes) mailboxes" -ForegroundColor Cyan } else { Write-Host " ℹ️ Litigation Hold: Not configured" -ForegroundColor Yellow } # Determine compliance if ($result.retentionPolicies -gt 0 -and $result.retentionRules -gt 0) { $result.isCompliant = $true } # Summary Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "SUMMARY:" -ForegroundColor Cyan Write-Host " Retention Policies: $($result.retentionPolicies)" -ForegroundColor $(if ($result.retentionPolicies -gt 0) { 'Green' } else { 'Red' }) Write-Host " Retention Rules: $($result.retentionRules)" -ForegroundColor $(if ($result.retentionRules -gt 0) { 'Green' } else { 'Red' }) Write-Host " Litigation Hold: $($result.litigationHoldMailboxes)/$($result.totalMailboxes)" -ForegroundColor White if ($result.isCompliant) { Write-Host "`n[OK] COMPLIANT: Retention policies configured" -ForegroundColor Green } else { Write-Host "`n[FAIL] NON-COMPLIANT: No retention policies" -ForegroundColor Red } return $result } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red throw } } function Invoke-Remediation { <# .SYNOPSIS Creates basic 7-year retention policy for all workloads #> [CmdletBinding(SupportsShouldProcess)] param() try { Write-Host "`nRemediation:" -ForegroundColor Yellow Connect-IPPSSession -ShowBanner:$false $policyName = "Baseline: 7-Year Retention - All Workloads" $ruleName = "Baseline: 7-Year Retention Rule" Write-Host "Creating retention policy..." -ForegroundColor Gray Write-Host " Name: $policyName" -ForegroundColor Gray Write-Host " Duration: $RetentionDays days (~7 years)" -ForegroundColor Gray if ($PSCmdlet.ShouldProcess($policyName, "Create retention policy")) { # Check if policy exists $existingPolicy = Get-RetentionCompliancePolicy -Identity $policyName -ErrorAction SilentlyContinue if (-not $existingPolicy) { # Create retention policy $newPolicy = New-RetentionCompliancePolicy ` -Name $policyName ` -Comment "Nederlandse Baseline voor Veilige Cloud - 7 jaar retentie voor alle workloads" ` -Enabled $true ` -ExchangeLocation All ` -SharePointLocation All ` -OneDriveLocation All ` -ModernGroupLocation All ` -TeamsChannelLocation All ` -TeamsChatLocation All Write-Host " [OK] Policy created: $policyName" -ForegroundColor Green # Wait for policy to propagate Start-Sleep -Seconds 5 # Create retention rule $newRule = New-RetentionComplianceRule ` -Name $ruleName ` -Policy $policyName ` -RetentionDuration $RetentionDays ` -RetentionComplianceAction Keep ` -Comment "Keep all content for 7 years" Write-Host " [OK] Rule created: $ruleName" -ForegroundColor Green Write-Host " Duration: $RetentionDays days" -ForegroundColor Gray Write-Host " Action: Keep" -ForegroundColor Gray } else { Write-Host " ℹ️ Policy already exists: $policyName" -ForegroundColor Yellow } } Write-Host "`n[OK] Remediation completed" -ForegroundColor Green Write-Host "`nNote: Retention policy takes 24-48 hours to fully propagate" -ForegroundColor Yellow } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red throw } } function Invoke-Implementation { <# .SYNOPSIS Full implementation: Separate policies per workload + Litigation Hold #> [CmdletBinding(SupportsShouldProcess)] param() try { Write-Host "`nImplementation: COMPLETE Retention Setup..." -ForegroundColor Yellow Connect-IPPSSession -ShowBanner:$false Connect-ExchangeOnline -ShowBanner:$false # STEP 1: Email retention (7 years) Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "STEP 1: Email Retention Policy" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan if ($PSCmdlet.ShouldProcess("Email Retention", "Create")) { $emailPolicyName = "Baseline: Email Retention (7 Years)" $existingEmail = Get-RetentionCompliancePolicy -Identity $emailPolicyName -ErrorAction SilentlyContinue if (-not $existingEmail) { $emailPolicy = New-RetentionCompliancePolicy ` -Name $emailPolicyName ` -Comment "Email retention: 7 years" ` -Enabled $true ` -ExchangeLocation All Start-Sleep -Seconds 3 New-RetentionComplianceRule ` -Name "$emailPolicyName Rule" ` -Policy $emailPolicyName ` -RetentionDuration $RetentionDays ` -RetentionComplianceAction Keep Write-Host " [OK] Email retention policy created" -ForegroundColor Green } else { Write-Host " ℹ️ Email policy already exists" -ForegroundColor Yellow } } # STEP 2: SharePoint/OneDrive retention (7 years) Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "STEP 2: SharePoint/OneDrive Retention" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan if ($PSCmdlet.ShouldProcess("SharePoint Retention", "Create")) { $spPolicyName = "Baseline: SharePoint/OneDrive Retention (7 Years)" $existingSP = Get-RetentionCompliancePolicy -Identity $spPolicyName -ErrorAction SilentlyContinue if (-not $existingSP) { $spPolicy = New-RetentionCompliancePolicy ` -Name $spPolicyName ` -Comment "SharePoint and OneDrive retention: 7 years" ` -Enabled $true ` -SharePointLocation All ` -OneDriveLocation All Start-Sleep -Seconds 3 New-RetentionComplianceRule ` -Name "$spPolicyName Rule" ` -Policy $spPolicyName ` -RetentionDuration $RetentionDays ` -RetentionComplianceAction Keep Write-Host " [OK] SharePoint/OneDrive retention policy created" -ForegroundColor Green } else { Write-Host " ℹ️ SharePoint policy already exists" -ForegroundColor Yellow } } # STEP 3: Teams retention (7 years) Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "STEP 3: Teams Retention Policy" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan if ($PSCmdlet.ShouldProcess("Teams Retention", "Create")) { $teamsPolicyName = "Baseline: Teams Retention (7 Years)" $existingTeams = Get-RetentionCompliancePolicy -Identity $teamsPolicyName -ErrorAction SilentlyContinue if (-not $existingTeams) { $teamsPolicy = New-RetentionCompliancePolicy ` -Name $teamsPolicyName ` -Comment "Teams channels and chats retention: 7 years" ` -Enabled $true ` -TeamsChannelLocation All ` -TeamsChatLocation All Start-Sleep -Seconds 3 New-RetentionComplianceRule ` -Name "$teamsPolicyName Rule" ` -Policy $teamsPolicyName ` -RetentionDuration $RetentionDays ` -RetentionComplianceAction Keep Write-Host " [OK] Teams retention policy created" -ForegroundColor Green } else { Write-Host " ℹ️ Teams policy already exists" -ForegroundColor Yellow } } # STEP 4: Optional: Litigation Hold for executives/high-risk users Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "STEP 4: Litigation Hold (Optional)" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan Write-Host " ℹ️ Litigation Hold not automatically enabled" -ForegroundColor Yellow Write-Host " To enable for specific users:" -ForegroundColor Gray Write-Host " Set-Mailbox -Identity user@domain.com -LitigationHoldEnabled `$true -LitigationHoldDuration 2555" -ForegroundColor Gray Write-Host "`n========================================" -ForegroundColor Green Write-Host "[OK] IMPLEMENTATION COMPLETED!" -ForegroundColor Green Write-Host "========================================" -ForegroundColor Green Write-Host "`nCreated retention policies:" -ForegroundColor Cyan Write-Host " [OK] Email (7 years)" -ForegroundColor White Write-Host " [OK] SharePoint/OneDrive (7 years)" -ForegroundColor White Write-Host " [OK] Teams (7 years)" -ForegroundColor White Write-Host "`nNext steps:" -ForegroundColor Yellow Write-Host " 1. Wait 24-48h for policies to propagate" -ForegroundColor White Write-Host " 2. Test: Get-RetentionCompliancePolicy | fl" -ForegroundColor Gray Write-Host " 3. Monitor compliance in M365 Compliance Center" -ForegroundColor White Write-Host " 4. Consider Litigation Hold for high-risk users" -ForegroundColor White } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red throw } } function Invoke-Revert { <# .SYNOPSIS Removes retention policies #> [CmdletBinding(SupportsShouldProcess)] param() try { Write-Host "`nRevert:" -ForegroundColor Yellow Connect-IPPSSession -ShowBanner:$false $policiesToRemove = @( 'Baseline: 7-Year Retention - All Workloads', 'Baseline: Email Retention (7 Years)', 'Baseline: SharePoint/OneDrive Retention (7 Years)', 'Baseline: Teams Retention (7 Years)' ) foreach ($policyName in $policiesToRemove) { try { $policy = Get-RetentionCompliancePolicy -Identity $policyName -ErrorAction SilentlyContinue if ($policy) { Write-Host " Removing: $policyName" -ForegroundColor Gray # First remove associated rules $rules = Get-RetentionComplianceRule -Policy $policyName -ErrorAction SilentlyContinue foreach ($rule in $rules) { if ($PSCmdlet.ShouldProcess($rule.Name, "Remove rule")) { Remove-RetentionComplianceRule -Identity $rule.Name -Confirm:$false } } # Then remove policy if ($PSCmdlet.ShouldProcess($policyName, "Remove policy")) { Remove-RetentionCompliancePolicy -Identity $policyName -Confirm:$false Write-Host " [OK] Removed" -ForegroundColor Green } } } catch { Write-Host " ⚠️ Error: $_" -ForegroundColor Yellow } } Write-Host "`n[OK] Revert completed" -ForegroundColor Green } catch { Write-Host "`n[FAIL] ERROR: $_" -ForegroundColor Red throw } } # MAIN EXECUTION try { if ($Implementation) { if ($WhatIf) { Write-Host "WhatIf: Would create retention policies for all workloads" -ForegroundColor Yellow } else { Invoke-Implementation } } elseif ($Remediation) { if ($WhatIf) { Write-Host "WhatIf: Would create basic 7-year retention policy" -ForegroundColor Yellow } else { Invoke-Remediation } } elseif ($Revert) { if ($WhatIf) { Write-Host "WhatIf: Would remove retention policies" -ForegroundColor Yellow } else { Invoke-Revert } } elseif ($Monitoring) { $result = Invoke-Monitoring exit $(if ($result.isCompliant) { 0 } else { 1 }) } else { Write-Host "Available parameters:" -ForegroundColor Yellow Write-Host " -Monitoring : Check retention policies status" -ForegroundColor Gray Write-Host " -Remediation : Create 7-year retention policy (all workloads)" -ForegroundColor Gray Write-Host " -Implementation : Full setup (separate policies per workload)" -ForegroundColor Gray Write-Host " -Revert : Remove retention policies" -ForegroundColor Gray Write-Host " -RetentionDays : Custom retention period (default: 2555 = 7 years)" -ForegroundColor Gray Write-Host " -WhatIf : Preview changes" -ForegroundColor Gray } } catch { Write-Error "Script execution failed: $_" exit 2 } finally { Write-Host "`n========================================`n" -ForegroundColor Cyan }

Risico zonder implementatie

Risico zonder implementatie
Medium: HOOG: gegevensverlies door accidental deletion (no recovery), compliance schendingen (7 jaar vereist), e-discovery incomplete (litigation risk), excessive opslag Kosten (geen automatische cleanup).

Management Samenvatting

WEEK 3 (Dag 17-20): Configureer retentiebeleid voor Email (7 jaar), SharePoint/OneDrive (7 jaar), Teams (7 jaar). automatische retention + deletion. Voldoet aan BIO, AVG, NIS2. Effort: 4-8 uur. VERPLICHT voor compliance.