Implementatie Van End-to-end Versleuteling In Microsoft 365
📅 2025-11-27
•
⏱️ 32 minuten lezen
•
🔴 Must-Have
💼 Management Samenvatting
Versleuteling pas echt waardevol wanneer ontwerpkeuzes, sleutelbeheer en dagelijks beheer op elkaar aansluiten. Binnen de Nederlandse Baseline voor Veilige Cloud betekent dit dat encryptie niet alleen wordt aangezet, maar dat elke stap van ontwerp tot operatie aantoonbaar onder architectuur valt.
Aanbeveling
IMPLEMENT
Risico zonder
High
Risk Score
9/10
Implementatie
72u (tech: 40u)
Van toepassing op:
✓ Microsoft 365 E5 ✓ Microsoft 365 E3 ✓ Exchange Online ✓ SharePoint Online ✓ OneDrive for Business ✓ Microsoft Teams ✓ Microsoft Purview ✓ Azure Key Vault
Veel overheden hebben losse encryptieprojecten uitgevoerd waardoor TLS, Customer Key, Double Key Encryption en Purview labels naast elkaar bestaan zonder gedeelde routekaart. Bij audits blijkt vervolgens dat sleutelrotaties niet zijn vastgelegd, dat change management prestaties niet controleert en dat bestuurders geen integraal beeld kunnen tonen richting toezichthouders zoals de Autoriteit Persoonsgegevens of de Algemene Rekenkamer. Deze hiaten vergroten het risico op datalekken omdat dienstonderdelen aannemen dat een andere afdeling encryptie heeft geregeld en omdat ketenpartners geen duidelijk beleid ontvangen. Alleen een volledige implementatieaanpak zorgt ervoor dat bestuurders daadwerkelijk grip houden op alle lagen van de encryptiestack en dat er geen organisatorische blinde vlekken overblijven.
PowerShell Modules Vereist
Primary API: Microsoft Graph, Exchange Online PowerShell, Purview Information Protection, Azure Automation Connection:Connect-MgGraph, Connect-ExchangeOnline, Connect-IPPSSession Required Modules: Microsoft.Graph, ExchangeOnlineManagement
Implementatie
Dit artikel beschrijft hoe organisaties binnen de Nederlandse Baseline voor Veilige Cloud een integraal encryptieprogramma ontwerpen en uitvoeren. We werken de governancebesluiten uit, vertalen architectuurprincipes naar concrete technische blauwdrukken, leggen uit hoe sleutelbeheer en change control worden geborgd en laten zien hoe automatisering via het script `encryption-implementation.ps1` zorgt voor doorlopende monitoring en bewijsvoering. De focus ligt op uitvoerbare maatregelen die passen binnen Nederlandse wet- en regelgeving en die direct aansluiten op bestaande Microsoft 365 voorzieningen.
Programma-aanpak en bestuurlijke borging
De implementatie van versleuteling begint bij een bestuurlijk besluit dat encryptie niet langer als technisch thema maar als kerntaak van informatiebeveiliging wordt beschouwd. Bestuurders vertalen het strategische kader van de Nederlandse Baseline voor Veilige Cloud naar een programma-opdracht met duidelijke doelstellingen, budget en mandaat. Tijdens de startfase wordt bepaald welke datacategorieën minimaal versleuteld moeten worden, hoe BBN-classificaties en BIO-maatregelen worden vertaald naar concrete workloads en hoe prioritering plaatsvindt tussen messaging, samenwerkingsplatformen en dataopslag. Door het encryptieprogramma als portfolio-initiatie onder te brengen bij de CIO-office ontstaat een directe koppeling met projectgovernance, waardoor beslissingen over sleutelmaterialen of licenties standaard via het change advisory board lopen. Deze organisatorische verankering voorkomt dat encryptieinitiatieven in de lijn verzanden of dat besluitvorming afhankelijk wordt van incidentele projectteams.
In de tweede stap wordt governance concreet gemaakt via beleid, standaarden en rollen. De Chief Information Security Officer stelt een encryptiehandboek op waarin verantwoordelijkheden voor sleutelbeheer, incidentrespons, documentatie en externe rapportage zijn vastgelegd. Elke organisatie-eenheid wijst een systeemeigenaar aan die toeziet op naleving van de cryptografische standaarden binnen de eigen workload. Het handboek bevat ook escalatieregels voor uitzonderingen, bijvoorbeeld wanneer een ketenpartner tijdelijk geen Double Key Encryption kan ondersteunen. Door duidelijke beslislijnen en goedgekeurde uitzonderingsformulieren te gebruiken, blijft zichtbaar dat versleuteling de norm is en dat afwijkingen slechts tijdelijk worden toegestaan na een risicoafweging. Hierdoor beschikt de organisatie bij audits over een consistent verhaal en kan men aantonen dat board en directies actief sturen op de encryptiedoelstellingen.
Een derde programmapijler betreft communicatie en opleidingsplannen. Sleutelbeheer kan alleen slagen wanneer architecten, beheerders en juristen dezelfde begrippen gebruiken en begrijpen waarom bepaalde keuzes zijn gemaakt. Het programma organiseert daarom kennissessies waarin verschillen tussen Customer Key en Double Key Encryption worden uitgelegd, waarin lifecycle-processen voor Azure Key Vault worden doorgenomen en waarin duidelijk wordt gemaakt hoe encryptie zich verhoudt tot wetgeving zoals de AVG en de Woo. Naast formele trainingen worden communities of practice opgezet zodat lessons learned snel worden gedeeld tussen Rijk, uitvoeringsorganisaties en gemeenten. Deze kennisdeling versnelt beslissingen omdat teams niet telkens zelf hoeven uit te zoeken welke instellingen noodzakelijk zijn en welke tooling al beschikbaar is binnen Microsoft 365.
Tot slot borgt het programma dat encryptie niet eindigt bij de technische implementatie maar onderdeel wordt van de bredere risicosturing. KPI’s zoals tijd tot sleutelrotatie, aantal afwijkingen in TLS-configuraties en percentage documenten met labels worden opgenomen in de kwartaalrapportages richting CIO-beraad en college van B en W of ministeriële stuurgroepen. Door deze indicatoren te koppelen aan de enterprise risk management cyclus ontstaat een directe link tussen beveiligingsmaatregelen en bestuurlijke aansprakelijkheid. Bestuurders kunnen aantonen dat zij actief toezicht houden op de effectiviteit van versleuteling en dat zij tijdig bijsturen wanneer KPI’s of auditbevindingen daarom vragen. Daarmee wordt encryptie niet langer gezien als technologische randvoorwaarde maar als bestuurlijke randvoorwaarde voor betrouwbare digitale dienstverlening.
Architectuur voor transport-, service- en klantsleutels
Een doordachte architectuur onderscheidt drie lagen: transportversleuteling, serviceversleuteling en klantbeheer van sleutels. Voor transport wordt vastgesteld dat alle mailstromen, Teams-sessies en SharePoint-synchronisaties minimaal TLS 1.2 gebruiken, waarbij legacy protocollen alleen nog worden toegestaan voor strikt noodzakelijke interfaces met hulp van conditional access beperkingen. Serviceversleuteling verwijst naar de standaardbescherming die Microsoft levert, zoals BitLocker in de datacenters en Azure Service Encryption. Hoewel deze laag automatisch actief is, documenteert de architectuur hoe de organisatie controleert dat workloads binnen de EU-datagrens blijven en hoe failover naar andere regio’s wordt beoordeeld. De derde laag is klant-sleutelbeheer via Customer Key of Double Key Encryption voor BBN3-gegevens. Hier bepaalt de architectuur welke datasets het strengste regime vereisen, welke Azure Key Vaults worden gebruikt, hoe Hardware Security Modules worden ingericht en hoe sleutels logisch gescheiden blijven tussen productie, test en noodscenario’s.
In de architectuurfase wordt eveneens vastgelegd hoe encryptie zich verhoudt tot identiteits- en toegangsbeheer. Sensitivity labels vormen de verbindende factor tussen data-classificatie en technische maatregelen. Ze activeren client-side encryptie in Office-apps, sturen de instellingen van Teams-vergaderingen aan en bepalen of documenten buiten de organisatie kunnen worden gedeeld. Architecten modelleren daarom labelsets in Microsoft Purview die rechtstreeks aansluiten op het BIO-classificatiemodel en het gegevenslandschap van de organisatie. Elk label bevat configuraties voor encryptiealgoritmen, toegestane gebruikersgroepen, offline toegangstijd en bescherming tegen forwarding. Door deze details in architectuurdocumenten vast te leggen, ontstaat een herhaalbare manier om nieuwe labels of beleidsregels te introduceren zonder dat de beveiligingspositie verzwakt.
Het architectuurontwerp beschrijft ook ondersteunende diensten zoals logging, sleutelmonitoring en integratie met Security Operations. Alle sleutelhanteeracties in Azure Key Vault worden naar Microsoft Sentinel of een ander SIEM gestuurd zodat verdachte gebeurtenissen direct zichtbaar zijn. Logboeken over labelwijzigingen, TLS-configuraties en IRM-instellingen worden gecentraliseerd zodat correlatie mogelijk is tussen verschillende lagen van de encryptiestack. Daarnaast worden architectuurafspraken gemaakt over fallback-scenario’s. Wanneer Customer Key tijdelijk niet beschikbaar is, omschrijft het ontwerp hoe workloads overschakelen naar serviceversleuteling zonder data bloot te stellen en welke escalaties dan actief worden. Hierdoor blijft bedrijfscontinuïteit gegarandeerd terwijl compliance-eisen intact blijven.
Tot slot beschrijft de architectuur hoe externe partijen worden meegenomen. Ketensamenwerking is cruciaal voor Nederlandse overheden en vraagt om interoperabele encryptieafspraken. Het ontwerp bepaalt daarom hoe Multi-Geo-configuraties worden gebruikt om gegevens van Europese agentschappen gescheiden te houden, hoe guest-toegang wordt beperkt tot apparaten met Microsoft Defender for Endpoint status ‘gezond’ en hoe sleuteluitwisseling contractueel is geregeld. Door deze afspraken vooraf vast te leggen, blijven aanbestedingen en service level agreements consistent met de technische realiteit en kunnen leveranciers aantonen dat zij voldoen aan dezelfde eisen als de primaire tenant. Dit voorkomt discussies achteraf en zorgt dat encryptie-implementaties ook in de keten een betrouwbaar fundament vormen.
Operationele uitvoering en sleutelbeheer
Wanneer de architectuur staat, verschuift de aandacht naar operationele procedures die versleuteling daadwerkelijk uitrollen. Het change team plant implementaties per workload en koppelt elke stap aan duidelijke verificatiecriteria. Voor Exchange Online betekent dit dat partnerconnectors worden herzien, dat Mutually Authenticated TLS voor overheidskoppelingen wordt ingevoerd en dat Office Message Encryption configuraties consistent zijn met het Purview-labelbeleid. SharePoint en OneDrive krijgen gesegmenteerde Customer Key associaties, waarbij hoog-risicosites worden gekoppeld aan hun eigen sleutel. Teams-chats met vertrouwelijke data gebruiken labels die end-to-end versleuteling afdwingen op apparaten die via Intune compliant zijn verklaard. Elke wijziging wordt gedocumenteerd in het configuratieregister inclusief aanwijzingen wie heeft gevalideerd dat de maatregel werkt en hoe rollback wordt uitgevoerd bij incidenten.
Sleutelbeheerprocessen vormen de ruggengraat van deze fase. De organisatie hanteert een strak schema voor sleutelrotatie waarbij productie- en noodsleutels gescheiden worden beheerd door verschillende teams. Sleutelgeneratie vindt plaats in een dedicated secure admin workstation dat voldoet aan de eisen uit de Baseline Informatiebeveiliging Overheid. De procedures beschrijven exact wanneer sleutels worden aangemaakt, hoe ze worden opgeslagen in Azure Key Vault met role-based access control, hoe auditlogs worden gecontroleerd en hoe de Functionaris Gegevensbescherming wordt geïnformeerd over belangrijke wijzigingen. Daarnaast staat vast hoe men omgaat met calamiteiten zoals een vermoeden van sleutelcompromittering: het incidentresponsplan beschrijft welke stappen binnen welke tijd moeten worden genomen om sleutels in te trekken, workloads om te schakelen en toezichthouders te informeren.
Operationele teams richten ook ondersteunende controles in. Configuration drift wordt beperkt door Infrastructure as Code templates te gebruiken voor labelpublicaties, Purview policies en connectorconfiguraties. Elk template bevat parameters voor tenant-specifieke gegevens maar borgt de baselinewaardes zodat afwijkingen snel zichtbaar zijn. Daarnaast wordt een vier-ogen-mechanisme toegepast voor alle wijzigingen aan encryptie-instellingen, ongeacht of deze via PowerShell, Graph of beheerportalen plaatsvinden. Dit sluit aan op de eisen vanuit de Comptabiliteitswet en de BIO dat kritieke beveiligingsinstellingen nooit door één persoon mogen worden gewijzigd. Wanneer partners of leveranciers werkzaamheden uitvoeren, schrijft het proces voor dat hun accounts tijdelijke privileged access management toewijzingen krijgen en dat activiteiten live worden gemonitord via session recording.
Een essentieel onderdeel van de uitvoering is documentatie. Voor elke workload bestaan sjablonen waarin doel, scope, toegepaste sleutels, afhankelijkheden en testresultaten worden ingevuld. Deze documenten vormen samen het encryptie-implementatie dossier dat bij audits direct kan worden overhandigd. Door op dossierniveau te werken ontstaat er overzicht: bestuurders zien welke onderdelen volledig compliant zijn, welke nog in transitie zitten en waar externe afhankelijkheden spelen. Bovendien kunnen lessons learned eenvoudig worden teruggekoppeld naar de architectuur- en programmasturing, waardoor verbeteringen snel hun weg vinden naar nieuwe releases.
Automatisering, monitoring en bewijsvoering
Gebruik PowerShell-script encryption-implementation.ps1 (functie Invoke-ImplementationReport) – Controleert TLS-vereisten, Data Encryption Policies, Double Key Encryption labels en IRM/OME-instellingen en exporteert een auditrapport..
Het programma rondt af met een volwassen monitoringketen die voortdurend bewijs levert dat encryptie functioneert zoals ontworpen. Het PowerShell-script `encryption-implementation.ps1` vormt de spil: het maakt verbinding met Microsoft Graph en Exchange Online, controleert of TLS-vereisten gelden op alle connectors, leest de status van Data Encryption Policies en verifieert of het Double Key Encryption label daadwerkelijk is gepubliceerd. De uitvoer wordt opgeslagen als JSON-rapport, gekoppeld aan Azure Monitor en opgenomen in een Power BI dashboard dat bestuurders en auditors realtime inzicht geeft. Omdat het script een lokale debugmodus ondersteunt kan elke wijziging eerst op een beheerswerkstation worden getest zonder productiesessies te openen, in lijn met de eis dat alle scripts lokaal worden gevalideerd.
Monitoring gaat verder dan techniek en omvat procesindicatoren. Change management controleert of elke sleutelrotatie binnen de afgesproken termijn wordt voltooid en of de benodigde goedkeuringen aanwezig zijn. Het security operations center bekijkt Sentinel-queries die TLS-configuraties, Purview labelwijzigingen en Key Vault-activiteit combineren tot één tijdlijn. Afwijkingen worden gekoppeld aan Jira- of Azure DevOps-workitems zodat opvolging traceerbaar blijft. Door het script periodiek aan te roepen ontstaat bovendien een trendanalyse: men ziet hoeveel tijd er zit tussen detectie en remediatie, welke workloads het vaakst aandacht nodig hebben en welke leveranciers afhankelijk zijn van uitzonderingen. Deze inzichten voeden de strategische rapportages naar CIO-beraad, controllers en toezichthouders.
Bewijsvoering richting externe partijen vereist een zorgvuldig archief. Alle rapporten, key rotation logs, change tickets en scriptoutputs worden bewaard in een digitaal kluisdossier met retentie conform de Archiefwet. Auditors kunnen daardoor zonder aanvullende interviews precies zien welke instellingen op een bepaald moment actief waren en welke mitigerende acties zijn uitgevoerd wanneer een afwijking werd ontdekt. Deze transparantie is essentieel voor NIS2-rapportages en voor het vertrouwen van burgers en ketenpartners. Door monitoringgegevens te koppelen aan risico- en prestatie-indicatoren is het bovendien mogelijk om bestuurlijke dashboards te genereren die laten zien hoe encryptie bijdraagt aan beleidsdoelen zoals digitale autonomie en privacybescherming.
Ten slotte voorziet de automatisering in feedback naar innovatie. Wanneer Sentinel of het script structureel terugkerende issues signaleert, bijvoorbeeld connectors die bij grote organisaties moeilijk naar MTLS zijn om te zetten, dan wordt deze thematiek toegevoegd aan de roadmap zodat architecten, leveranciers en security officers gezamenlijk een structurele oplossing zoeken. Hierdoor blijft het encryptieprogramma geen statische set controles maar een levend geheel dat meegroeit met wetgeving, cloudroadmaps en maatschappelijke verwachtingen. De combinatie van automatisering, menselijk toezicht en duidelijke rapportages maakt dat versleuteling aantoonbaar deel uitmaakt van de governancecyclus van de Nederlandse Baseline voor Veilige Cloud.
Compliance & Frameworks
BIO: 10.01, 10.02, 12.05, 14.03 - Cryptografische maatregelen zijn gepland, ingericht, bewaakt en voorzien van sleutelbeheerprocessen met aantoonbare audittrail.
ISO 27001:2022: A.8.24, A.8.25, A.5.17 - Versleutelingsarchitectuur en sleutelbeheer sluiten aan op het ISMS en worden continu verbeterd via monitoring en management review.
NIS2: Artikel - Essentiële en belangrijke entiteiten implementeren passende technische maatregelen, waaronder sleutelbeheer, en rapporteren aantoonbaar over effectiviteit.
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
Bevestigt de implementatie van end-to-end versleuteling in Microsoft 365.
.DESCRIPTION
Controleert of TLS-vereisten, Data Encryption Policies, Double Key Encryption labels
en IRM/OME-instellingen overeenkomen met de Nederlandse Baseline voor Veilige Cloud.
Het script kan resultaten exporteren, een implementatieplan genereren en gerichte
remediatieacties uitvoeren. Ondersteunt lokale debugruns zodat wijzigingen eerst
veilig getest kunnen worden.
.NOTES
Filename : encryption-implementation.ps1
Author : Nederlandse Baseline voor Veilige Cloud
Created : 2025-11-27
Version : 1.0
Workload : m365
Category : information-protection
.EXAMPLE
.\encryption-implementation.ps1 -Monitoring -ExportPath .\rapport.json
Voert alle controles uit en schrijft het JSON-resultaat naar rapport.json.
.EXAMPLE
.\encryption-implementation.ps1 -Remediation -WhatIf
Toont welke wijzigingen zouden worden toegepast om encryptie te herstellen.
.EXAMPLE
.\encryption-implementation.ps1 -PlanReport
Genereert een samenvatting van acties voor bestuurders en auditors.
#>
#Requires -Version 5.1#Requires -Modules Microsoft.Graph
#Requires -Modules ExchangeOnlineManagement
[CmdletBinding()]
param(
[switch]$Monitoring,
[switch]$Remediation,
[switch]$PlanReport,
[switch]$LocalDebug,
[switch]$WhatIf,
[string]$DataEncryptionPolicy = "NBVC - Customer Key Productie",
[string]$DkeLabelName = "NBVC - BBN3 Dubbele Sleutel",
[string]$ExportPath = ".\nbvc-encryption-implementation-report.json"
)
$ErrorActionPreference = 'Stop'
$script:LocalDebug = $LocalDebug$script:LastTlsFindings = @{
Inbound = @()
Outbound = @()
}
function Write-Banner {
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "NBVC - Encryption Implementation Check" -ForegroundColor Cyan
Write-Host "Nederlandse Baseline voor Veilige Cloud" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
}
function Ensure-GraphConnection {
if ($script:LocalDebug) { return }
$context = Get-MgContext -ErrorAction SilentlyContinue
if (-not $context) {
Write-Host "Verbinden met Microsoft Graph..." -ForegroundColor Gray
Connect-MgGraph -Scopes "InformationProtectionPolicy.Read.All","Policy.Read.All" -ErrorAction Stop | Out-Null
Write-Host " [OK] Verbonden met Microsoft Graph" -ForegroundColor Green
}
}
function Ensure-ExchangeConnection {
if ($script:LocalDebug) { return }
$session = Get-PSSession | Where-Object { $_.ConfigurationName -eq "Microsoft.Exchange" -and $_.State -eq "Opened" -and $_.ComputerName -like "*.outlook.com" }
if (-not $session) {
Write-Host "Verbinden met Exchange Online..." -ForegroundColor Gray
Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop | Out-Null
Write-Host " [OK] Verbonden met Exchange Online" -ForegroundColor Green
}
}
function Ensure-ComplianceConnection {
if ($script:LocalDebug) { return }
$session = Get-PSSession | Where-Object {
$_.ConfigurationName -eq "Microsoft.Exchange" -and
$_.State -eq "Opened" -and
$_.Name -like "*IPPSSession*"
}
if (-not $session) {
Write-Host "Verbinden met Microsoft Purview PowerShell..." -ForegroundColor Gray
Connect-IPPSSession -ShowBanner:$false -ErrorAction Stop | Out-Null
Write-Host " [OK] Verbonden met Purview PowerShell" -ForegroundColor Green
}
}
function Ensure-ServiceConnections {
Ensure-GraphConnection
Ensure-ExchangeConnection
Ensure-ComplianceConnection
}
functionTest-TlsConnectors {
if ($script:LocalDebug) {
$script:LastTlsFindings = @{
Inbound = @()
Outbound = @("Outbound-NBVC-Relay")
}
return [PSCustomObject]@{
Status = "Partial"
Message = "Lokale debugmodus: outbound connector vereist aanpassing."
Compliant = $false
InboundMissing = @()
OutboundMissing = @("Outbound-NBVC-Relay")
}
}
$nonCompliantInbound = @()
$nonCompliantOutbound = @()
try {
$inbound = Get-InboundConnector -ErrorAction Stop
$nonCompliantInbound = $inbound | Where-Object { $_.ConnectorType -eq "Partner" -and $_.RequireTls -ne $true }
}
catch {
Write-Host "[WARN] Kon inbound connectors niet ophalen: $($_.Exception.Message)" -ForegroundColor Yellow
}
try {
$outbound = Get-OutboundConnector -ErrorAction Stop
$nonCompliantOutbound = $outbound | Where-Object {
$_.ConnectorType -eq "Partner" -and
($_.TlsSettings -ne "DomainValidation" -and $_.TlsSettings -ne "CertificateValidation")
}
}
catch {
Write-Host "[WARN] Kon outbound connectors niet ophalen: $($_.Exception.Message)" -ForegroundColor Yellow
}
$script:LastTlsFindings = @{
Inbound = $nonCompliantInbound
Outbound = $nonCompliantOutbound
}
$status = if ($nonCompliantInbound.Count -eq 0 -and $nonCompliantOutbound.Count -eq 0) { "Compliant" } elseif ($nonCompliantInbound.Count -eq 0 -or $nonCompliantOutbound.Count -eq 0) { "Partial" } else { "NonCompliant" }
return [PSCustomObject]@{
Status = $status
Message = if ($status -eq "Compliant") { "Alle partnerconnectors forceren TLS 1.2 of hoger." } else { "Minstens één connector heeft RequireTLS of streng TLS-profiel uitgeschakeld." }
Compliant = $status -eq "Compliant"
InboundMissing = $nonCompliantInbound.Identity
OutboundMissing = $nonCompliantOutbound.Identity
}
}
functionTest-IrmConfiguration {
if ($script:LocalDebug) {
return [PSCustomObject]@{
Status = "Compliant"
Message = "IRM-instellingen gesimuleerd."
Internal = $true
External = $true
AzureRMS = $true
Compliant = $true
}
}
try {
$irm = Get-IRMConfiguration -ErrorAction Stop
$compliant = $irm.InternalLicensingEnabled -and $irm.ExternalLicensingEnabled -and $irm.AzureRMSLicensingEnabled
return [PSCustomObject]@{
Status = if ($compliant) { "Compliant" } else { "NonCompliant" }
Message = "IRM-configuratie opgehaald."
Internal = $irm.InternalLicensingEnabled
External = $irm.ExternalLicensingEnabled
AzureRMS = $irm.AzureRMSLicensingEnabled
Compliant = $compliant
}
}
catch {
return [PSCustomObject]@{
Status = "Unknown"
Message = "Fout bij ophalen IRM-configuratie: $($_.Exception.Message)"
Compliant = $false
}
}
}
functionTest-OmeConfiguration {
if ($script:LocalDebug) {
return [PSCustomObject]@{
Status = "Partial"
Message = "OME actief maar bijlagenbescherming ontbreekt (debug)."
ProtectAttachment = $false
Compliant = $false
}
}
try {
$ome = Get-OMEConfiguration -ErrorAction Stop
if (-not $ome) {
return [PSCustomObject]@{
Status = "NonCompliant"
Message = "Geen OME-configuratie gevonden."
Compliant = $false
}
}
$nonProtecting = $ome | Where-Object { $_.ProtectAttachment -ne $true }
$compliant = $nonProtecting.Count -eq 0return [PSCustomObject]@{
Status = if ($compliant) { "Compliant" } else { "Partial" }
Message = if ($compliant) { "OME beschermt berichten en bijlagen." } else { "Minstens één OME-configuratie mist bijlagenbescherming." }
ProtectAttachment = $compliant
Compliant = $compliant
}
}
catch {
return [PSCustomObject]@{
Status = "Unknown"
Message = "Fout bij ophalen OME-configuratie: $($_.Exception.Message)"
Compliant = $false
}
}
}
functionTest-DataEncryptionPolicy {
if ($script:LocalDebug) {
return [PSCustomObject]@{
Status = "Partial"
Message = "Debugdata: beleid bestaat maar is niet toegewezen."
Exists = $true
Assigned = $false
KeyVault = "KV-NBVC-Prod"
Compliant = $false
}
}
try {
$policy = Get-DataEncryptionPolicy -Identity $DataEncryptionPolicy -ErrorAction Stop
$org = Get-OrganizationConfig -ErrorAction Stop
$assigned = $falseif ($org.DataEncryptionPolicy) {
$assigned = $org.DataEncryptionPolicy -contains $policy.Name
}
return [PSCustomObject]@{
Status = if ($assigned) { "Compliant" } else { "Partial" }
Message = if ($assigned) { "Data Encryption Policy toegewezen aan tenant." } else { "Beleid gevonden maar nog niet gekoppeld aan workload." }
Exists = $true
Assigned = $assigned
KeyVault = $policy.KeyVault
Compliant = $assigned
}
}
catch {
return [PSCustomObject]@{
Status = "NonCompliant"
Message = "Beleid '$DataEncryptionPolicy' niet gevonden: $($_.Exception.Message)"
Exists = $false
Assigned = $false
Compliant = $false
}
}
}
functionTest-DkeLabel {
if ($script:LocalDebug) {
return [PSCustomObject]@{
Status = "Compliant"
Message = "Debuglabel met Double Key Encryption actief."
Exists = $true
Encryption = $true
DoubleKey = $true
Published = $true
Compliant = $true
}
}
try {
$label = Get-Label -Identity $DkeLabelName -ErrorAction Stop
$doubleKey = $falseif ($label.DoubleKeyEncryptionStatus -and $label.DoubleKeyEncryptionStatus -ne "NotEnabled") {
$doubleKey = $true
}
return [PSCustomObject]@{
Status = if ($label.EncryptionEnabled -and $doubleKey) { "Compliant" } else { "Partial" }
Message = if ($doubleKey) { "Label ondersteunt Double Key Encryption." } else { "Label mist Double Key Encryption." }
Exists = $true
Encryption = [bool]$label.EncryptionEnabled
DoubleKey = $doubleKey
Published = -not [string]::IsNullOrEmpty(($label.Policy) -join "")
Compliant = $label.EncryptionEnabled -and $doubleKey
}
}
catch {
return [PSCustomObject]@{
Status = "NonCompliant"
Message = "Label '$DkeLabelName' niet gevonden: $($_.Exception.Message)"
Exists = $false
Encryption = $false
DoubleKey = $false
Published = $false
Compliant = $false
}
}
}
functionGet-ImplementationStatus {
if (-not $script:LocalDebug) {
Ensure-ServiceConnections
}
$tls = Test-TlsConnectors$irm = Test-IrmConfiguration$ome = Test-OmeConfiguration$dep = Test-DataEncryptionPolicy$dke = Test-DkeLabel$overall = $tls.Compliant -and $irm.Compliant -and $ome.Compliant -and $dep.Compliant -and $dke.Compliant
$recommendations = @()
if (-not $tls.Compliant) {
if ($tls.InboundMissing -and $tls.InboundMissing.Count -gt 0) {
$recommendations += "Schakel RequireTLS in op: $($tls.InboundMissing -join ', ')."
}
if ($tls.OutboundMissing -and $tls.OutboundMissing.Count -gt 0) {
$recommendations += "Wijzig TlsSettings naar DomainValidation voor: $($tls.OutboundMissing -join ', ')."
}
}
if (-not $irm.Compliant) {
$recommendations += "Activeer InternalLicensingEnabled, ExternalLicensingEnabled en AzureRMSLicensingEnabled via Set-IRMConfiguration."
}
if (-not $ome.Compliant) {
$recommendations += "Controleer OME-configuraties en zet ProtectAttachment op True."
}
if (-not $dep.Compliant) {
if (-not $dep.Exists) {
$recommendations += "Maak Data Encryption Policy '$DataEncryptionPolicy' aan volgens Customer Key handleiding."
}
else {
$recommendations += "Koppel Data Encryption Policy '$DataEncryptionPolicy' aan de tenant via Set-OrganizationConfig."
}
}
if (-not $dke.Compliant) {
if (-not $dke.Exists) {
$recommendations += "Publiceer het Double Key Encryption label '$DkeLabelName' in Microsoft Purview."
}
else {
$recommendations += "Zorg dat het label '$DkeLabelName' Double Key Encryption activeert en is gepubliceerd naar relevante groepen."
}
}
return [PSCustomObject]@{
Script = "encryption-implementation.ps1"
Timestamp = Get-Date
IsCompliant = $overall
Details = @{
TLS = $tls
IRM = $irm
OME = $ome
DataEncryptionPolicy = $dep
DoubleKeyLabel = $dke
}
Recommendations = $recommendations
}
}
function Export-ImplementationStatus {
param(
[Parameter(Mandatory)]
[pscustomobject]$Status,
[string]$Path
)
try {
$resolved = Resolve-Path -Path $Path -ErrorAction SilentlyContinue
if (-not $resolved) {
$directory = Split-Path -Path $Path -Parent
if (-not [string]::IsNullOrWhiteSpace($directory) -and -not (Test-Path -Path $directory)) {
New-Item -ItemType Directory -Path $directory -Force | Out-Null
}
$resolved = $Path
}
else {
$resolved = $resolved.Path
}
$Status | ConvertTo-Json -Depth 6 | Out-File -FilePath $resolved -Encoding UTF8
Write-Host "[OK] Rapport opgeslagen naar $resolved" -ForegroundColor Green
}
catch {
Write-Host "[WARN] Kon rapport niet opslaan: $($_.Exception.Message)" -ForegroundColor Yellow
}
}
function Invoke-ImplementationReport {
$status = Get-ImplementationStatus
Export-ImplementationStatus -Status $status -Path $ExportPathWrite-Host "TLS : $($status.Details.TLS.Status)" -ForegroundColor White
Write-Host "IRM : $($status.Details.IRM.Status)" -ForegroundColor White
Write-Host "OME : $($status.Details.OME.Status)" -ForegroundColor White
Write-Host "DEP : $($status.Details.DataEncryptionPolicy.Status)" -ForegroundColor White
Write-Host "DKE : $($status.Details.DoubleKeyLabel.Status)" -ForegroundColor White
if ($status.IsCompliant) {
Write-Host "`n[OK] Encryptie-implementatie voldoet aan de baseline." -ForegroundColor Green
}
else {
Write-Host "`n[WARN] Afwijkingen gevonden. Zie aanbevelingen hieronder." -ForegroundColor Yellow
foreach ($rec in $status.Recommendations) {
Write-Host " - $rec" -ForegroundColor Yellow
}
}
return$status
}
function Invoke-Remediation {
if ($script:LocalDebug) {
Write-Host "[DEBUG] Remediatieoverzicht (er worden geen verbindingen gemaakt)." -ForegroundColor Yellow
Write-Host " - TLS: zou RequireTLS en DomainValidation afdwingen." -ForegroundColor Gray
Write-Host " - IRM: zou Set-IRMConfiguration uitvoeren." -ForegroundColor Gray
Write-Host " - OME: zou ProtectAttachment inschakelen." -ForegroundColor Gray
Write-Host " - DEP: zou Set-OrganizationConfig updaten." -ForegroundColor Gray
Write-Host " - DKE: zou controleren of label is gepubliceerd." -ForegroundColor Gray
return
}
Ensure-ServiceConnections
$status = Get-ImplementationStatusif ($script:LastTlsFindings.Inbound.Count -gt 0) {
foreach ($connector in $script:LastTlsFindings.Inbound) {
$msg = "RequireTLS inschakelen voor inbound connector '$($connector.Identity)'"
if ($WhatIf) {
Write-Host "[WhatIf] $msg" -ForegroundColor Yellow
}
else {
Set-InboundConnector -Identity $connector.Identity -RequireTls $true -ErrorAction Stop
Write-Host "[OK] $msg voltooid." -ForegroundColor Green
}
}
}
if ($script:LastTlsFindings.Outbound.Count -gt 0) {
foreach ($connector in $script:LastTlsFindings.Outbound) {
$msg = "DomainValidation TLS afdwingen voor outbound connector '$($connector.Identity)'"
if ($WhatIf) {
Write-Host "[WhatIf] $msg" -ForegroundColor Yellow
}
else {
Set-OutboundConnector -Identity $connector.Identity -TlsSettings DomainValidation -ErrorAction Stop
Write-Host "[OK] $msg voltooid." -ForegroundColor Green
}
}
}
if (-not $status.Details.IRM.Compliant) {
if ($WhatIf) {
Write-Host "[WhatIf] Zou IRM-licenties inschakelen via Set-IRMConfiguration." -ForegroundColor Yellow
}
else {
Set-IRMConfiguration -InternalLicensingEnabled $true -ExternalLicensingEnabled $true -AzureRMSLicensingEnabled $true -ErrorAction Stop
Write-Host "[OK] IRM-licenties ingeschakeld." -ForegroundColor Green
}
}
if (-not $status.Details.OME.Compliant) {
$configs = Get-OMEConfiguration -ErrorAction Stop
foreach ($config in $configs) {
if ($config.ProtectAttachment -ne $true) {
$msg = "ProtectAttachment activeren op '$($config.Identity)'"
if ($WhatIf) {
Write-Host "[WhatIf] $msg" -ForegroundColor Yellow
}
else {
Set-OMEConfiguration -Identity $config.Identity -ProtectAttachment $true -ErrorAction Stop
Write-Host "[OK] $msg" -ForegroundColor Green
}
}
}
}
if (-not $status.Details.DataEncryptionPolicy.Compliant -and $status.Details.DataEncryptionPolicy.Exists) {
if ($WhatIf) {
Write-Host "[WhatIf] Zou Data Encryption Policy '$DataEncryptionPolicy' koppelen aan de tenant." -ForegroundColor Yellow
}
else {
$org = Get-OrganizationConfig -ErrorAction Stop
$current = @()
if ($org.DataEncryptionPolicy) {
$current = @($org.DataEncryptionPolicy)
}
if ($current -notcontains $DataEncryptionPolicy) {
$updated = $current + $DataEncryptionPolicySet-OrganizationConfig -DataEncryptionPolicy $updated -ErrorAction Stop
Write-Host "[OK] Data Encryption Policy gekoppeld aan tenant." -ForegroundColor Green
}
}
}
if (-not $status.Details.DoubleKeyLabel.Exists) {
Write-Host "[INFO] Double Key Encryption label ontbreekt. Maak het label aan in Purview en voer het script opnieuw uit." -ForegroundColor Yellow
}
elseif (-not $status.Details.DoubleKeyLabel.Compliant) {
Write-Host "[INFO] Pas het label '$DkeLabelName' aan zodat Double Key Encryption actief is en publiceer het naar de juiste groepen." -ForegroundColor Yellow
}
}
function Invoke-PlanReport {
$status = Get-ImplementationStatusWrite-Host "=== Implementatieplan ===" -ForegroundColor Cyan
Write-Host "Rapportdatum : $($status.Timestamp)" -ForegroundColor Gray
Write-Host "Compliant : $($status.IsCompliant)" -ForegroundColor Gray
Write-Host ""
Write-Host "Belangrijkste bevindingen:" -ForegroundColor White
Write-Host " TLS-status : $($status.Details.TLS.Status)"
Write-Host " IRM-status : $($status.Details.IRM.Status)"
Write-Host " OME-status : $($status.Details.OME.Status)"
Write-Host " DEP-status : $($status.Details.DataEncryptionPolicy.Status)"
Write-Host " DKE-label : $($status.Details.DoubleKeyLabel.Status)"
Write-Host ""
if ($status.Recommendations.Count -gt 0) {
Write-Host "Aanbevolen acties:" -ForegroundColor Yellow
foreach ($rec in $status.Recommendations) {
Write-Host " - $rec" -ForegroundColor Yellow
}
}
else {
Write-Host "Geen aanvullende acties vereist; alle controles voldoen." -ForegroundColor Green
}
return$status
}
try {
Write-Banner
if ($Monitoring) {
$result = Invoke-ImplementationReport
if ($result.IsCompliant) { exit 0 } else { exit 1 }
}
elseif ($Remediation) {
Invoke-Remediation
}
elseif ($PlanReport) {
$result = Invoke-PlanReport
if ($result.IsCompliant) {
exit 0
}
else {
exit 1
}
}
else {
Write-Host "Gebruik één van de modi: -Monitoring, -Remediation of -PlanReport." -ForegroundColor Yellow
Write-Host "Optioneel: -LocalDebug, -WhatIf, -DataEncryptionPolicy, -DkeLabelName, -ExportPath." -ForegroundColor Gray
}
}
catch {
Write-Host "[FAIL] $($_.Exception.Message)" -ForegroundColor Red
exit 2
}
finally {
if (-not $script:LocalDebug) {
try {
Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue | Out-Null
}
catch { }
}
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
}
# Exitcodes:
# 0 = Compliant / succes (PlanReport/Monitoring)
# 1 = Niet volledig compliant
# 2 = Fout tijdens uitvoering
Risico zonder implementatie
Risico zonder implementatie
High: Zonder integraal encryptieprogramma ontbreken aantoonbare waarborgen waardoor toezichthouders aanvullende maatregelen kunnen opleggen en digitale dienstverlening stil kan komen te liggen.
Management Samenvatting
Zorg dat architectuur, sleutelbeheer en monitoring één programma vormen, gebruik Customer Key en Double Key Encryption voor hoogrisicodata en automatiseer bewijsvoering met het script `encryption-implementation.ps1`.