Zero Trust-ontwerp Voor Veilige Remote Access

💼 Management Samenvatting

Zero Trust-remote access betekent dat elk verzoek tot toegang expliciet wordt gevalideerd, ongeacht waar de gebruiker zich bevindt, welk apparaat wordt gebruikt of welke netwerkroute wordt gekozen. Voor Nederlandse overheden is het de enige duurzame manier om hybride werken, ketensamenwerking en ad-hoc crisisoperaties veilig mogelijk te maken zonder terug te vallen op verouderde VPN-constructies.

Aanbeveling
PLAN_EN_IMPLEMENTEER
Risico zonder
High
Risk Score
8/10
Implementatie
300u (tech: 180u)
Van toepassing op:
Microsoft 365 E5
Entra ID
Entra Global Secure Access
Microsoft Intune
Microsoft Defender voor Cloud Apps

De combinatie van BIO, AVG, NIS2 en sectorale normen zoals BIR 2017 vereist dat organisaties aantoonbaar kunnen uitleggen hoe zij identiteiten, apparaten, applicaties en data beschermen zodra medewerkers buiten het Rijks-netwerk werken. Traditionele VPN-toegang voldoet niet langer omdat er te weinig zicht bestaat op posture, device health en gedrag. Zero Trust-remote access verbindt beleid, identiteit en netwerksegmentatie, zodat elke sessie kan worden beoordeeld op risico en realtime kan worden gestopt wanneer afwijkingen zichtbaar worden.

PowerShell Modules Vereist
Primary API: Microsoft Graph PowerShell, Entra Global Secure Access API, Intune Graph API
Connection: Interactieve Graph-authenticatie voor assessments, service principal voor monitoring in CI/CD en JSON-rapportage naar Secure Score dashboards
Required Modules: Microsoft.Graph.Authentication

Implementatie

Dit artikel beschrijft hoe u bestuurlijke kaders formuleert, hoe een Zero Trust-architectuur voor remote access in Microsoft 365 wordt opgebouwd, en hoe u met het script zero-trust-remote-access.ps1 voortdurend bewijs verzamelt. Het stuk is geschreven voor CISO’s, architecten en operationele teams die zowel beleidsmatige duiding als technische diepgang nodig hebben om bestuurders en auditors mee te nemen.

Bestuurlijke regie, beleid en juridische borging

Zero Trust-remote access begint bij een expliciet mandaat van bestuurders. Zij moeten begrijpen dat traditionele perimeterbeveiliging ongeschikt is voor samenwerkingen met provincies, gemeenten, waterschappen en leveranciers die allemaal op hun eigen infrastructuur draaien. Het beleid moet beschrijven welke rollen remote access mogen gebruiken, hoe gevoelige processen (bijvoorbeeld crisiscommunicatie of informatie-uitwisseling rond strafrechtelijk onderzoek) worden afgeschermd en welke escalatieprocedures gelden bij afwijkend gedrag. Dit beleidskader moet worden afgestemd met CIO-Rijk, Rijksinspecties en de departementale auditdiensten, zodat iedereen dezelfde definities hanteert voor termen als “vertrouwd apparaat” of “inbraakdetectie”.

Juridische borging vereist dat DPIA’s, verwerkersovereenkomsten en convenanten met ondernemingsraden beschrijven hoe remote access data verzamelt, verwerkt en verwijdert. Overheden moeten kunnen aantonen dat logging van sessies, Conditional Access-besluiten en netwerksegmentatie voldoet aan AVG-artikelen 5, 24 en 32. Een veelgemaakte fout is het ontbreken van duidelijke bewaartermijnen voor sessielogs, waardoor audits stranden of WOO-verzoeken niet goed kunnen worden beantwoord. Door Zero Trust-remote access te koppelen aan het informatiebeheerbeleid en de archiefwet kan een organisatie aantonen dat logs integraal onderdeel zijn van het digitale archief.

Stakeholdermanagement omvat naast interne teams ook externe leveranciers van SaaS-applicaties, ketenpartners en shared service centers. Zij moeten contractueel verplicht worden om moderne federatieprotocollen te ondersteunen, device contexten te respecteren en inline inspectie door Microsoft Defender voor Cloud Apps niet te blokkeren. De beleidssectie moet helder maken dat nee zeggen tegen deze voorwaarden betekent dat toegang alleen via streng gecontroleerde virtual desktop-omgevingen mogelijk blijft. Door scenario’s uit te werken – bijvoorbeeld een accountantsdienst die buiten kantooruren dossiers inziet – kunnen bestuurders de balans tussen gebruiksgemak en risico expliciet afwegen.

Een Zero Trust-programma vereist bovendien structurele financiering. Het beleid moet beschrijven hoe licentiekosten (Entra ID P2, Microsoft Defender for Cloud Apps, Global Secure Access), connectiviteit (Private Access connectors) en personele inzet worden gedekt. Door de business case te koppelen aan concrete baten – minder beheer van legacy VPN’s, snellere onboarding van leveranciers en betere inzichtelijkheid richting toezichthouders – ontstaat draagvlak bij financieel directeuren. Het artikel adviseert om een stuurgroep in te richten waarin CISO, CIO, privacy officer, architect en lijnmanagement kwartaalrapportages beoordelen en besluiten welke verbeteringen prioriteit krijgen.

Technische architectuur, Conditional Access en netwerksegmentatie

Gebruik PowerShell-script zero-trust-remote-access.ps1 (functie Invoke-ZtraAssessment) – Voert een Zero Trust-remote access-gezondheidsscan uit op Conditional Access-beleid, Entra Global Secure Access connectors en Application Proxy-statussen. Rapporteert directe bevindingen en KPI’s..

De technische architectuur bestaat uit drie lagen: identiteitsbewuste toegang via Conditional Access, risicogebaseerde netwerksegmentatie via Entra Global Secure Access (Private en Internet Access) en sessiebescherming via Defender voor Cloud Apps. Elke laag moet signalen delen zodat blokkades realtime kunnen plaatsvinden. Conditional Access zorgt voor de eerste poortwachter: per applicatie wordt geëist dat gebruikers meervoudige authenticatie gebruiken, dat apparaten compliant zijn of een Defender for Endpoint signaal “gezond” afgeven, en dat sessies worden beoordeeld op sign-in risk en locatiecontext. Regelsets moeten specifiek zijn voor remote access scenario’s: denk aan beleid voor beheeraccounts, externe consultants en onregelmatige werktijden. Het script inventariseert of deze beleidsregels bestaan, ingeschakeld zijn en de vereiste controles afdwingen.

De tweede laag betreft netwerksegmentatie via Entra Global Secure Access, waarmee organisaties private applicaties kunnen publiceren zonder traditionele VPN’s. Branches, remote networks en connectoren moeten redundant zijn over minimaal twee datacenters of cloudregio’s om beschikbaarheid tijdens crisissituaties te garanderen. Het artikel legt uit hoe u routingbeleid opbouwt, hoe device tags en gebruikersgroepen bepalen welke applicaties beschikbaar zijn, en hoe inspectiebeleid inline openbaar verkeer scant op datalekken of malware. Het script controleert de status van connectors, het aantal remote networks en of er fallback-routes zijn geconfigureerd.

De derde laag richt zich op applicatiepublicatie via Entra Application Proxy en Defender voor Cloud Apps. Legacy webapplicaties kunnen op een Zero Trust-manier worden ontsloten door publicatierichtlijnen te combineren met session policies die bijvoorbeeld downloadblokkades afdwingen wanneer een gebruiker zich op een onbekend device bevindt. Het artikel beschrijft hoe u labeling, DLP en session controls koppelt zodat gevoelige documenten nooit buiten de gecontroleerde container komen. Scriptresultaten laten zien of connectors actief zijn, of health checks tijdig worden uitgevoerd en of er voldoende capaciteit beschikbaar is voor piekverkeer.

Tot slot wordt ingegaan op integratie met SIEM en automatisering. Logs uit Global Secure Access, Conditional Access en Defender voor Cloud Apps moeten worden verzonden naar Microsoft Sentinel of een ander platform, waar hunting queries afwijkingen detecteren. Automatiseringsplaybooks kunnen direct accounts blokkeren, labels aanpassen of SOC-analisten alarmeren. Het artikel levert voorbeeld-KPI’s, zoals de gemiddelde tijd tussen connectorfout en herstel, het percentage remote sessies dat inline inspectie doorloopt en het aantal geblokkeerde downloads. Door deze KPI’s naast de scriptuitvoer te leggen ontstaat een 360-gradenbeeld van de Zero Trust-architectuur.

Operationele uitvoering, monitoring en aantoonbaarheid

Gebruik PowerShell-script zero-trust-remote-access.ps1 (functie Invoke-ZtraMonitoring) – Combineert actuele metingen met het referentieconfiguratiebestand en schrijft auditklare JSON-rapporten inclusief trendgegevens en verbeteracties..

Operationele teams moeten dagelijks zicht hebben op connectorstatussen, policywijzigingen en afwijkende sessies. Het artikel adviseert om een runbook in te richten waarin verantwoordelijkheden tussen CISO-office, SOC, netwerkbeheer, identiteitsbeheer en applicatie-eigenaren zijn verdeeld. Elke wijziging in Conditional Access of Global Secure Access moet via change management verlopen en automatisch worden vastgelegd in het referentieconfiguratiebestand dat door het script wordt beheerd. Servicedesks kunnen met DebugMode lokale tests uitvoeren, zodat validatie nooit langer dan vijftien seconden duurt en nieuwe releases veilig kunnen worden uitgerold.

Rapportage is cruciaal richting bestuurders en toezichthouders. Het script levert JSON-rapporten die direct kunnen worden ingelezen in Power BI of GRC-tools. Deze rapportages bevatten onder meer het aantal actieve connectors, de leeftijd van beleid, het percentage gebruikers dat voldoet aan de aangestelde eisen en de lijst met bevindingen. Door maandelijkse trendanalyses op te stellen kan de organisatie aantonen dat verbeteracties daadwerkelijk effect hebben, bijvoorbeeld een daling van het aantal hoge risicoaanmeldingen na invoering van phishing-resistente MFA.

Een Zero Trust-programma kan alleen succesvol zijn als lessons learned uit incidenten, penetratietests en pentestbevindingen worden vertaald naar nieuwe beleidsregels. Het artikel beschrijft hoe u een feedbacklus inricht waarin SOC-rapportages, red team-oefeningen en gebruikerservaringen samenkomen. Tevens wordt uitgelegd hoe u met Microsoft Sentinel notebooks en KQL-hunting queries afwijkende remote sessies detecteert, waarna automatisering via Logic Apps direct maatregelen kan nemen. De combinatie van tooling en proces zorgt ervoor dat remote access niet alleen veilig maar ook aantoonbaar beheerst is.

Tot slot wordt benadrukt dat transparante communicatie richting medewerkers en ketenpartners noodzakelijk is. Publiceer duidelijke handleidingen over hoe remote access werkt, welke gegevens worden gelogd en hoe privacy wordt beschermd. Documenteer procedures voor bezwaar, incidentmelding en forensische onderzoeken. Door deze documentatie te koppelen aan het auditdossier en de output van het script kunnen organisaties snel reageren op vragen van de Algemene Rekenkamer, NCSC of Autoriteit Persoonsgegevens.

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 Zero Trust-remote access toetsen, baselines publiceren en monitoringrapportages genereren. .DESCRIPTION Controleert Conditional Access-beleid, Entra Global Secure Access connectors, Application Proxy status en named locations. Het script kan een referentieconfiguratie schrijven, monitoring uitvoeren en ondersteunt DebugMode voor lokale tests binnen vijftien seconden. .NOTES Filename: zero-trust-remote-access.ps1 Author: Nederlandse Baseline voor Veilige Cloud Created: 2025-11-27 Version: 1.0 Gerelateerd JSON: content/m365/remote-work/zero-trust-remote-access.json Workload: m365 Category: remote-work .EXAMPLE .\zero-trust-remote-access.ps1 -Assessment -ReportPath .\rapporten\ztra-assessment.json Voert een gezondheidsscan uit en schrijft de output naar JSON. .EXAMPLE .\zero-trust-remote-access.ps1 -PublishBaseline Genereert of actualiseert het referentieconfiguratiebestand voor Zero Trust-remote access. .EXAMPLE .\zero-trust-remote-access.ps1 -Monitoring -ReportPath .\rapporten\ztra-monitoring.json Combineert actuele metingen met de baseline voor audit- en KPI-doeleinden. #> #Requires -Version 5.1 [CmdletBinding()] param( [switch]$Assessment, [switch]$PublishBaseline, [switch]$Monitoring, [string]$ReportPath, [switch]$DebugMode, [switch]$WhatIf ) $ErrorActionPreference = 'Stop' $VerbosePreference = 'Continue' Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "Zero Trust Remote Access Toolkit" -ForegroundColor Cyan Write-Host "Nederlandse Baseline voor Veilige Cloud" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan function Get-ZtraConfigPath { [CmdletBinding()] param() $scriptDir = Split-Path -Parent $PSCommandPath return (Join-Path -Path $scriptDir -ChildPath "zero-trust-remote-access.config.json") } function Test-RequiredModules { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string[]]$ModuleNames ) foreach ($moduleName in $ModuleNames) { if (-not (Get-Module -ListAvailable -Name $moduleName -ErrorAction SilentlyContinue)) { throw "Vereiste module '$moduleName' is niet gevonden. Installeer de module en voer het script opnieuw uit." } } } function Ensure-GraphConnection { [CmdletBinding()] param() Test-RequiredModules -ModuleNames @('Microsoft.Graph.Authentication') Import-Module Microsoft.Graph.Authentication -ErrorAction Stop | Out-Null $requiredScopes = @( 'Policy.Read.All', 'Application.Read.All', 'Directory.Read.All', 'NetworkAccess.Read.All' ) $context = Get-MgContext -ErrorAction SilentlyContinue $needsConnect = $true if ($context) { $scopeDifference = Compare-Object -ReferenceObject $requiredScopes -DifferenceObject $context.Scopes if ($scopeDifference.Count -eq 0 -and $context.ExpirationTime -gt (Get-Date)) { $needsConnect = $false } } if ($needsConnect) { Write-Host "Verbinding maken met Microsoft Graph..." -ForegroundColor Gray Connect-MgGraph -Scopes $requiredScopes -NoWelcome | Out-Null } try { Select-MgProfile -Name beta } catch { throw "Het Microsoft Graph-profiel 'beta' kan niet worden geselecteerd. Update de Microsoft.Graph modules." } } function Invoke-GraphPagedRequest { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Uri ) $results = @() $nextLink = $Uri while ($nextLink) { $response = Invoke-MgGraphRequest -Method GET -Uri $nextLink -OutputType PSObject if ($response.value) { $results += $response.value } else { $results += $response } $nextLink = $response.'@odata.nextLink' } return $results } function Get-ZtraConditionalAccessSnapshot { [CmdletBinding()] param( [switch]$DebugMode ) if ($DebugMode) { return @( [PSCustomObject]@{ PolicyId = 'remote-admins' Name = 'CA - Remote admins Zero Trust' State = 'enabled' RequiresMfa = $true RequiresCompliant = $true SessionControls = @('signInFrequency', 'appEnforcedRestrictions') SignInRiskLevels = @('high', 'medium') }, [PSCustomObject]@{ PolicyId = 'remote-suppliers' Name = 'CA - Leveranciers Private Access' State = 'enabled' RequiresMfa = $true RequiresCompliant = $false SessionControls = @('continuousAccessEvaluation') SignInRiskLevels = @('high') } ) } Ensure-GraphConnection $uri = "https://graph.microsoft.com/beta/identity/conditionalAccess/policies?`$select=id,displayName,state,conditions,grantControls,sessionControls" $policies = Invoke-GraphPagedRequest -Uri $uri $snapshots = @() foreach ($policy in $policies) { $grantControls = $policy.grantControls $sessionControls = @() if ($policy.sessionControls) { if ($policy.sessionControls.signInFrequency) { $sessionControls += 'signInFrequency' } if ($policy.sessionControls.applicationEnforcedRestrictions) { $sessionControls += 'appEnforcedRestrictions' } if ($policy.sessionControls.cloudAppSecurity) { $sessionControls += 'defenderSessionControl' } if ($policy.sessionControls.continuousAccessEvaluation) { $sessionControls += 'continuousAccessEvaluation' } } $requiresMfa = $false $requiresCompliant = $false if ($grantControls -and $grantControls.builtInControls) { $requiresMfa = $grantControls.builtInControls -contains 'mfa' $requiresCompliant = $grantControls.builtInControls -contains 'compliantDevice' } $signInRiskLevels = @() if ($policy.conditions -and $policy.conditions.signInRiskLevels) { $signInRiskLevels = $policy.conditions.signInRiskLevels } $snapshots += [PSCustomObject]@{ PolicyId = $policy.id Name = $policy.displayName State = $policy.state RequiresMfa = $requiresMfa RequiresCompliant = $requiresCompliant SessionControls = $sessionControls SignInRiskLevels = $signInRiskLevels } } return $snapshots } function Get-ZtraNetworkAccessSnapshot { [CmdletBinding()] param( [switch]$DebugMode ) if ($DebugMode) { return @( [PSCustomObject]@{ ConnectorId = 'branch-ams-01' Name = 'Rijkskantoor Amsterdam' Status = 'running' Region = 'West-Europe' RemoteNetwork = 'PrivateAccess' LastHeartbeat = (Get-Date).AddMinutes(-3) }, [PSCustomObject]@{ ConnectorId = 'branch-utrecht-02' Name = 'SSC-Utrecht' Status = 'running' Region = 'North-Europe' RemoteNetwork = 'PrivateAccess' LastHeartbeat = (Get-Date).AddMinutes(-6) } ) } Ensure-GraphConnection $snapshots = @() try { $uri = "https://graph.microsoft.com/beta/networkAccess/connectivity/branches?`$expand=connectivityConfiguration" $branches = Invoke-GraphPagedRequest -Uri $uri foreach ($branch in $branches) { $connectorStatus = if ($branch.connectivityConfiguration -and $branch.connectivityConfiguration.status) { $branch.connectivityConfiguration.status } else { 'unknown' } $lastHeartbeat = $null if ($branch.connectivityConfiguration -and $branch.connectivityConfiguration.lastUpdatedDateTime) { $lastHeartbeat = [datetime]$branch.connectivityConfiguration.lastUpdatedDateTime } $snapshots += [PSCustomObject]@{ ConnectorId = $branch.id Name = $branch.displayName Status = $connectorStatus Region = $branch.region RemoteNetwork = $branch.connectivityConfiguration.type LastHeartbeat = $lastHeartbeat } } } catch { Write-Warning "Kon Global Secure Access-gegevens niet ophalen: $_" } return $snapshots } function Get-ZtraApplicationProxySnapshot { [CmdletBinding()] param( [switch]$DebugMode ) if ($DebugMode) { return @( [PSCustomObject]@{ ConnectorId = 'apxy-01' Name = 'App Proxy Amsterdam' Status = 'active' Machine = 'APPX01' Version = '1.6.3805.0' } ) } Ensure-GraphConnection $uri = "https://graph.microsoft.com/beta/onPremisesPublishingProfiles/applicationProxy/connectors?`$select=id,displayName,externalIp,connectorMachineName,version,connectorGroupId,systemStatus" $connectors = Invoke-GraphPagedRequest -Uri $uri $snapshots = @() foreach ($connector in $connectors) { $status = if ($connector.systemStatus -and $connector.systemStatus.status) { $connector.systemStatus.status } else { 'unknown' } $snapshots += [PSCustomObject]@{ ConnectorId = $connector.id Name = $connector.displayName Status = $status Machine = $connector.connectorMachineName Version = $connector.version } } return $snapshots } function Get-ZtraNamedLocationSnapshot { [CmdletBinding()] param( [switch]$DebugMode ) if ($DebugMode) { return @( [PSCustomObject]@{ LocationId = 'trusted-gov' Name = 'Trusted Rijksnetwerk' Type = 'ip' IsTrusted = $true } ) } Ensure-GraphConnection $uri = "https://graph.microsoft.com/beta/identity/conditionalAccess/namedLocations?`$select=id,displayName,isTrusted,@odata.type" $locations = Invoke-GraphPagedRequest -Uri $uri $snapshots = @() foreach ($location in $locations) { $type = $location.'@odata.type' if ($type -match 'ipNamedLocation') { $typeName = 'ip' } elseif ($type -match 'countryNamedLocation') { $typeName = 'country' } else { $typeName = 'unknown' } $snapshots += [PSCustomObject]@{ LocationId = $location.id Name = $location.displayName Type = $typeName IsTrusted = [bool]$location.isTrusted } } return $snapshots } function Invoke-ZtraAssessment { [CmdletBinding()] param( [switch]$DebugMode ) $caPolicies = Get-ZtraConditionalAccessSnapshot -DebugMode:$DebugMode $gsaConnectors = Get-ZtraNetworkAccessSnapshot -DebugMode:$DebugMode $appProxy = Get-ZtraApplicationProxySnapshot -DebugMode:$DebugMode $namedLocations = Get-ZtraNamedLocationSnapshot -DebugMode:$DebugMode $issues = [System.Collections.Generic.List[string]]::new() if (-not $caPolicies -or $caPolicies.Count -eq 0) { $issues.Add("Er zijn geen Conditional Access-beleidsregels gevonden.") } else { $remotePolicies = $caPolicies | Where-Object { $_.State -eq 'enabled' } if ($remotePolicies.Count -lt 2) { $issues.Add("Configureer minimaal twee actieve Conditional Access-beleidsregels specifiek voor remote access scenario\u2019s.") } if (-not ($remotePolicies | Where-Object { $_.RequiresMfa })) { $issues.Add("Geen enkel actief beleid vereist MFA voor remote toegang.") } if (-not ($remotePolicies | Where-Object { $_.RequiresCompliant })) { $issues.Add("Geen enkel actief beleid vereist een compliant apparaat of device signaal.") } foreach ($policy in $remotePolicies) { if ($policy.SessionControls.Count -eq 0) { $issues.Add("Policy '$($policy.Name)' gebruikt geen sessiecontroles zoals Defender voor Cloud Apps of sign-in frequenties.") } if ($policy.SignInRiskLevels.Count -eq 0) { $issues.Add("Policy '$($policy.Name)' monitort sign-in risk niet. Activeer minimaal medium risk.") } } } if (-not $gsaConnectors -or $gsaConnectors.Count -lt 2) { $issues.Add("Er zijn minder dan twee Global Secure Access connectors actief. Configureer redundantie over meerdere locaties.") } else { foreach ($connector in $gsaConnectors) { if ($connector.Status -ne 'running') { $issues.Add("Connector '$($connector.Name)' heeft status '$($connector.Status)'.") } if ($connector.LastHeartbeat -and ((Get-Date) - $connector.LastHeartbeat).TotalMinutes -gt 15) { $issues.Add("Connector '$($connector.Name)' heeft langer dan 15 minuten geen heartbeat verstuurd.") } } } if (-not $appProxy -or $appProxy.Count -eq 0) { $issues.Add("Geen Application Proxy-connectors gevonden. Legacy-applicaties kunnen daardoor niet Zero Trust worden ontsloten.") } else { foreach ($connector in $appProxy) { if ($connector.Status -ne 'active') { $issues.Add("Application Proxy-connector '$($connector.Name)' heeft status '$($connector.Status)'.") } } } if (-not $namedLocations -or -not ($namedLocations | Where-Object { $_.IsTrusted })) { $issues.Add("Er zijn geen vertrouwde named locations gedefinieerd voor Rijks- of partnernetwerken.") } $assessment = [PSCustomObject]@{ Script = 'zero-trust-remote-access.ps1' Timestamp = Get-Date ConditionalAccess = $caPolicies GlobalSecureAccess = $gsaConnectors ApplicationProxy = $appProxy NamedLocations = $namedLocations Issues = $issues IsHealthy = ($issues.Count -eq 0) } return $assessment } function Initialize-ZtraConfig { [CmdletBinding()] param( [Parameter(Mandatory = $true)] $Assessment ) $config = [ordered]@{ version = "1.0" lastUpdated = (Get-Date).ToString("yyyy-MM-dd") owner = "Zero Trust Remote Access Stuurgroep" governance = @( "Voorzie alle remote toegang van MFA, compliant device-eisen en sessiecontroles.", "Houd Global Secure Access connectors redundant in minimaal twee regio's.", "Combineer Application Proxy met Defender for Cloud Apps session policies." ) conditionalAccess = @() connectors = @() applicationProxy = @() namedLocations = @() } foreach ($policy in $Assessment.ConditionalAccess) { $config.conditionalAccess += [ordered]@{ id = $policy.PolicyId name = $policy.Name requiresMfa = $policy.RequiresMfa requiresCompliant = $policy.RequiresCompliant sessionControls = $policy.SessionControls } } foreach ($connector in $Assessment.GlobalSecureAccess) { $config.connectors += [ordered]@{ id = $connector.ConnectorId name = $connector.Name region = $connector.Region type = $connector.RemoteNetwork } } foreach ($proxy in $Assessment.ApplicationProxy) { $config.applicationProxy += [ordered]@{ id = $proxy.ConnectorId name = $proxy.Name version = $proxy.Version } } foreach ($location in $Assessment.NamedLocations) { $config.namedLocations += [ordered]@{ id = $location.LocationId name = $location.Name type = $location.Type isTrusted = $location.IsTrusted } } return $config } function Invoke-ZtraBaselinePublish { [CmdletBinding()] param( [switch]$DebugMode ) $assessment = Invoke-ZtraAssessment -DebugMode:$DebugMode $config = Initialize-ZtraConfig -Assessment $assessment $configPath = Get-ZtraConfigPath if ($WhatIf) { Write-Host "[WhatIf] Configuratie zou worden opgeslagen op $configPath" -ForegroundColor Yellow } else { $config | ConvertTo-Json -Depth 6 | Out-File -FilePath $configPath -Encoding UTF8 -Force Write-Host "[OK] Zero Trust-configuratie opgeslagen: $configPath" -ForegroundColor Green } return $config } function Invoke-ZtraMonitoring { [CmdletBinding()] param( [switch]$DebugMode ) $assessment = Invoke-ZtraAssessment -DebugMode:$DebugMode $configPath = Get-ZtraConfigPath $config = $null if (Test-Path -Path $configPath) { $config = Get-Content -Path $configPath -Raw | ConvertFrom-Json } else { Write-Host "[WARN] Geen configuratiebestand gevonden op $configPath." -ForegroundColor Yellow } $monitoring = [PSCustomObject]@{ Script = 'zero-trust-remote-access.ps1' Timestamp = Get-Date ConfigPath = $configPath ConfigDetected = [bool]$config ConfigVersion = if ($config) { $config.version } else { "not-found" } LastConfigUpdate = if ($config) { $config.lastUpdated } else { $null } Assessment = $assessment } return $monitoring } function Write-ZtraReport { [CmdletBinding()] param( [Parameter(Mandatory = $true)] $Payload, [Parameter(Mandatory = $true)] [string]$Path ) if (-not $Path) { return } $directory = Split-Path -Parent $Path if ($directory -and -not (Test-Path -Path $directory)) { New-Item -ItemType Directory -Path $directory -Force | Out-Null } $Payload | ConvertTo-Json -Depth 6 | Out-File -FilePath $Path -Encoding UTF8 -Force Write-Host "[OK] Rapport geschreven naar $Path" -ForegroundColor Green } $executed = $false if ($PublishBaseline) { $config = Invoke-ZtraBaselinePublish -DebugMode:$DebugMode if ($ReportPath) { Write-ZtraReport -Payload $config -Path $ReportPath } $executed = $true $config } if ($Assessment) { $result = Invoke-ZtraAssessment -DebugMode:$DebugMode if ($ReportPath) { Write-ZtraReport -Payload $result -Path $ReportPath } $executed = $true $result } if ($Monitoring) { $monitoringResult = Invoke-ZtraMonitoring -DebugMode:$DebugMode if ($ReportPath) { Write-ZtraReport -Payload $monitoringResult -Path $ReportPath } $executed = $true $monitoringResult } if (-not $executed) { Write-Host "Geen modus opgegeven. Gebruik ten minste een van de volgende opties:" -ForegroundColor Yellow Write-Host " -Assessment Voer een Zero Trust-gezondheidsscan uit." -ForegroundColor Yellow Write-Host " -PublishBaseline Genereer of vernieuw het configuratiebestand." -ForegroundColor Yellow Write-Host " -Monitoring Combineer assessmentgegevens met het configuratiebestand." -ForegroundColor Yellow Write-Host "Optioneel: -DebugMode voor lokale tests, -ReportPath voor JSON-rapportage." -ForegroundColor Yellow } Write-Host "`n========================================`n" -ForegroundColor Cyan

Risico zonder implementatie

Risico zonder implementatie
High: Zonder Zero Trust-remote access blijven remote sessies afhankelijk van verouderde VPN’s, ontbreekt zicht op wie toegang heeft en kan de organisatie geen compliance aantonen.

Management Samenvatting

Vervang traditionele VPN-toegang door een Zero Trust-architectuur met Conditional Access, Global Secure Access en Defender voor Cloud Apps, en gebruik het script zero-trust-remote-access.ps1 om bewijslast te verzamelen.