Azure Private Endpoints: Inschakelen En Configureren Voor Netwerkisolatie

💼 Management Samenvatting

Azure Private Endpoints vormen een fundamentele beveiligingsmaatregel die Platform-as-a-Service (PaaS) diensten binnen een Azure Virtual Network brengt met privé IP-adressen, waardoor publieke internetblootstelling volledig wordt geëlimineerd. Het inschakelen van Private Endpoints is essentieel voor het implementeren van Zero Trust-architectuur, netwerksegmentatie en compliance met moderne beveiligingsstandaarden zoals NIS2, ISO 27001 en BIO. Deze netwerkisolatie is niet langer optioneel maar een verplichte beveiligingsmaatregel voor alle productieomgevingen die gevoelige gegevens verwerken of kritieke bedrijfsfunctionaliteit leveren.

Aanbeveling
SCHAKEL PRIVATE ENDPOINTS IN VOOR ALLE KRITIEKE PAAS-DIENSTEN
Risico zonder
High
Risk Score
9/10
Implementatie
80u (tech: 60u)
Van toepassing op:
Azure Storage Accounts
Azure SQL Database
Azure Key Vault
Azure Cosmos DB
Azure App Service
Azure Container Registry
Azure Cognitive Services
Azure Event Hubs
Azure Service Bus
Andere Azure PaaS Services

Publieke eindpunten voor Azure PaaS-diensten creëren een aanzienlijk en onacceptabel aanvalsoppervlak dat door kwaadwillenden kan worden geëxploiteerd voor verschillende doeleinden. Wanneer PaaS-diensten zoals Azure Storage Accounts, SQL-databases, Key Vault, Cosmos DB en App Services rechtstreeks via het internet toegankelijk zijn, worden ze blootgesteld aan continue scanpogingen, brute-force aanvallen, distributed denial-of-service (DDoS) aanvallen, en geavanceerde persistent threat (APT) campagnes. Zelfs met firewallregels en authenticatie blijven publiek toegankelijke eindpunten kwetsbaar omdat ze technisch beschikbaar zijn op internet, wat betekent dat gelekte credentials direct wereldwijde toegang kunnen geven zonder geografische of netwerkgebaseerde beperkingen. Deze blootstelling vergemakkelijkt gegevensexfiltratie, maakt diensten kwetsbaar voor externe dreigingen, en creëert compliance-hiaten omdat frameworks zoals NIS2 Artikel 21 expliciet netwerkisolatie vereisen voor kritieke informatiesystemen. Bovendien wordt al het verkeer gerouteerd via het publieke internet, wat zowel hogere latency oplevert als beveiligingsrisico's introduceert door potentiële verkeersinterceptie. Private Endpoints lossen deze risico's fundamenteel op door PaaS-diensten uitsluitend toegankelijk te maken vanuit resources binnen het virtuele netwerk of verbonden netwerken via ExpressRoute of VPN. Alle verkeer blijft binnen het Azure-backbonenetwerk en wordt nooit gerouteerd via het publieke internet, waardoor het aanvalsoppervlak wordt geminimaliseerd, netwerksegmentatie wordt gerealiseerd, en compliance wordt gewaarborgd met moderne beveiligingsstandaarden.

PowerShell Modules Vereist
Primary API: Azure API
Connection: Connect-AzAccount
Required Modules: Az.Network, Az.Resources, Az.Accounts

Implementatie

Dit artikel beschrijft de volledige implementatieprocedure voor het inschakelen en configureren van Azure Private Endpoints voor alle relevante PaaS-diensten binnen de Nederlandse Baseline voor Veilige Cloud. De focus ligt op zes hoofdcomponenten. Ten eerste strategie en planning: het identificeren van alle PaaS-diensten die Private Endpoints vereisen, het prioriteren van implementatie op basis van gegevensgevoeligheid en bedrijfskritiek, het definiëren van netwerkarchitectuur en subnet-toewijzingen, en het opstellen van een implementatieplan met tijdlijnen en verantwoordelijkheden. Ten tweede Private Endpoint-implementatie: het aanmaken van Private Endpoint-resources voor elke PaaS-service, het koppelen aan geschikte subnetten binnen Virtual Networks, het configureren van subresource-selectie voor services met meerdere endpoints, en het valideren van IP-adrestoewijzingen en connectiviteit. Ten derde DNS-configuratie: het aanmaken en configureren van Private DNS Zones voor automatische naamresolutie, het koppelen van zones aan Virtual Networks, het verifiëren van DNS-resolutie en het testen van connectiviteit vanuit verschillende netwerksegmenten. Ten vierde publieke toegang uitschakelen: het configureren van service-specifieke firewall-instellingen, het uitschakelen van publieke netwerktoegang na verificatie van Private Endpoint-connectiviteit, het implementeren van geautomatiseerde controles om te voorkomen dat publieke toegang opnieuw wordt ingeschakeld, en het documenteren van uitzonderingen waar publieke toegang tijdelijk nodig is. Ten vijfde monitoring en validatie: het inschakelen van logging en monitoring voor Private Endpoint-activiteiten, het configureren van alertregels voor configuratiedrift, het uitvoeren van regelmatige compliance-scans, en het genereren van rapportages voor audit-doeleinden. Ten zesde operationele best practices: het opzetten van change management-processen voor Private Endpoint-wijzigingen, het implementeren van geautomatiseerde validatie via Azure Policy, het documenteren van configuraties en wijzigingen, en het definiëren van incidentresponsprocedures. Het bijbehorende PowerShell-script valideert of Private Endpoints zijn ingeschakeld voor alle relevante PaaS-diensten, identificeert diensten die nog publieke toegang toestaan, controleert DNS-configuraties, en genereert compliance-rapportages.

Strategie en planning

Het succesvol inschakelen van Private Endpoints voor Azure PaaS-diensten vereist een doordachte strategie en grondige planning voordat de daadwerkelijke implementatie begint. Deze planningfase is cruciaal omdat een slecht geplande implementatie kan leiden tot service-onderbrekingen, connectiviteitsproblemen, en onnodige operationele complexiteit. De eerste stap in het planningsproces is het uitvoeren van een uitgebreide inventarisatie van alle PaaS-diensten die momenteel actief zijn binnen de Azure-omgeving. Deze inventarisatie moet alle Azure Storage-accounts omvatten die bedrijfsgevoelige data bevatten, SQL-databases die kritieke applicatiegegevens hosten, Key Vault-instanties die geclassificeerde sleutels en geheimen beheren, Cosmos DB-accounts die real-time transactiegegevens verwerken, App Services die interne bedrijfsapplicaties hosten, Container Registry-instances die container-images bevatten, Cognitive Services die AI-functionaliteit leveren, Event Hubs en Service Bus die messaging-services bieden, en talrijke andere relevante PaaS-diensten. Voor elke geïdentificeerde dienst moet worden geëvalueerd of Private Endpoints technisch worden ondersteund, aangezien niet alle Azure-services Private Endpoint-functionaliteit bieden, en voor services die wel worden ondersteund moet worden bepaald welke subresources moeten worden geconfigureerd. Bijvoorbeeld, voor Azure Storage-accounts moeten aparte Private Endpoints worden geconfigureerd voor blob storage, file storage, queue storage en table storage, elk met hun eigen subresource-specificatie.

Na de inventarisatie moet een prioriteringsstrategie worden ontwikkeld die bepaalt welke diensten als eerste Private Endpoints moeten krijgen. Deze prioritering moet gebaseerd zijn op meerdere kritieke factoren, waaronder de gevoeligheid en classificatie van de gegevens die worden verwerkt, de bedrijfskritiek van de dienst en de impact op operationele continuïteit, de compliance-vereisten die van toepassing zijn op de organisatie en de betreffende gegevens, en de complexiteit van de implementatie en het risico op service-onderbrekingen. Diensten die hoogwaardige of uiterst gevoelige gegevens verwerken, zoals persoonsgegevens onder de AVG, medische informatie, financiële transacties, of intellectueel eigendom, moeten de hoogste prioriteit krijgen en moeten onmiddellijk worden beveiligd met Private Endpoints. Diensten die kritiek zijn voor bedrijfsprocessen en waarvan een onderbreking significante operationele impact zou hebben, moeten ook hoge prioriteit krijgen, maar de implementatie moet zorgvuldig worden gepland tijdens onderhoudsvensters om verstoringen te minimaliseren. Minder kritieke diensten kunnen worden aangepakt in latere fasen van het implementatietraject, hoewel ook deze binnen redelijke termijnen moeten worden beveiligd om consistentie in de beveiligingspostuur te waarborgen.

Netwerkarchitectuur en subnet-toewijzingen vormen een ander kritiek aspect van de planning. Organisaties moeten bepalen welke subnetten binnen hun Virtual Networks geschikt zijn voor Private Endpoints, rekening houdend met beschikbare IP-adresruimte, netwerksegmentatieprincipes, en beveiligingszones. Een veelgebruikte best practice is het creëren van een dedicated subnet dat uitsluitend is gereserveerd voor Private Endpoints, wat netwerkbeheer vereenvoudigt, isolatie bevordert, en het beheer van IP-adresruimte optimaliseert. Dit subnet moet voldoende groot zijn om toekomstige groei te accommoderen, maar niet zo groot dat het waardevolle IP-adresruimte verspilt. Een /24 subnet (256 adressen) is meestal voldoende voor de meeste organisaties, hoewel grotere organisaties met veel PaaS-diensten mogelijk een /23 subnet nodig hebben. Het subnet moet worden geconfigureerd met Network Security Groups die specifieke regels bevatten voor Private Endpoint-verkeer, en het moet worden geplaatst in een logische beveiligingszone die overeenkomt met de gevoeligheid van de diensten die via Private Endpoints worden benaderd. Daarnaast moeten organisaties overwegen of meerdere Private Endpoints nodig zijn voor dezelfde dienst om hoge beschikbaarheid te garanderen of om toegang te bieden vanuit verschillende Virtual Networks of on-premises locaties via ExpressRoute of VPN.

Het opstellen van een gedetailleerd implementatieplan met duidelijke tijdlijnen, mijlpalen, verantwoordelijkheden en rollback-procedures is essentieel voor een succesvolle implementatie. Dit plan moet per dienst of per dienstcategorie specifieke implementatiestappen definiëren, inclusief de volgorde van acties, afhankelijkheden tussen verschillende configuratiestappen, en verificatiecriteria om te bevestigen dat elke stap succesvol is voltooid. Het plan moet ook onderhoudsvensters identificeren wanneer implementaties kunnen worden uitgevoerd met minimale impact op productieomgevingen, en het moet communicatieplannen bevatten om stakeholders te informeren over geplande wijzigingen en mogelijke impact. Rollback-procedures moeten worden gedocumenteerd voor het geval implementaties problemen veroorzaken of onverwachte service-onderbrekingen introduceren. Deze procedures moeten duidelijk maken hoe publieke toegang opnieuw kan worden ingeschakeld indien nodig, hoe Private Endpoints kunnen worden verwijderd zonder dataverlies, en hoe DNS-configuraties kunnen worden teruggedraaid. Testscenario's moeten worden gedefinieerd om te verifiëren dat alle applicaties en diensten correct blijven functioneren na de implementatie van Private Endpoints, en deze tests moeten worden uitgevoerd in niet-productieomgevingen voordat productie-implementaties worden gestart.

Private Endpoint-implementatie

De daadwerkelijke implementatie van Private Endpoints begint met het aanmaken van Private Endpoint-resources voor elke geïdentificeerde PaaS-service volgens het opgestelde implementatieplan. Deze implementatie kan worden uitgevoerd via verschillende methoden, waaronder de Azure Portal voor ad-hoc implementaties, Azure PowerShell of Azure CLI voor geautomatiseerde en herhaalbare implementaties, of infrastructure-as-code tools zoals Azure Resource Manager-templates, Bicep of Terraform voor volledig geautomatiseerde en versioned implementaties. De keuze voor het implementatiemiddel hangt af van de organisatorische voorkeur, bestaande DevOps-processen, de behoefte aan herhaalbaarheid en versionering van infrastructuurconfiguraties, en de complexiteit van de omgeving. Voor organisaties die infrastructure-as-code omarmen, is het sterk aanbevolen om Private Endpoint-implementaties te automatiseren via templates of scripts, wat consistentie waarborgt, menselijke fouten reduceert, en het mogelijk maakt om configuraties te versioneren en te reviewen voordat ze worden geïmplementeerd.

Bij het aanmaken van een Private Endpoint moet zorgvuldig worden geselecteerd welke subresource moet worden gekoppeld, aangezien veel Azure-services meerdere subresources ondersteunen die elk een apart Private Endpoint vereisen. Voor Azure Storage-accounts moeten bijvoorbeeld aparte Private Endpoints worden geconfigureerd voor blob storage (subresource: blob), file storage (subresource: file), queue storage (subresource: queue), en table storage (subresource: table). Voor Azure SQL Database moet de subresource worden ingesteld op 'sqlServer', terwijl voor SQL Managed Instance 'managedInstance' moet worden gebruikt. Azure Key Vault gebruikt 'vault' als subresource, Cosmos DB gebruikt verschillende subresources afhankelijk van het API-type (bijvoorbeeld 'Sql' voor SQL API, 'MongoDB' voor MongoDB API), en App Services gebruiken 'sites' als subresource. Het is cruciaal om de juiste subresource te selecteren omdat een verkeerde selectie resulteert in een Private Endpoint die niet correct functioneert of die niet de beoogde service-connectiviteit biedt. Microsoft-documentatie moet worden geraadpleegd voor de exacte subresource-namen per service-type, aangezien deze kunnen variëren tussen verschillende service-versies en regio's.

Na het selecteren van de juiste subresource moet het Private Endpoint worden gekoppeld aan een geschikt subnet binnen het virtuele netwerk. Dit subnet moet voldoende beschikbare IP-adressen bevatten in zijn adresbereik, aangezien elk Private Endpoint een uniek privé IP-adres uit het subnetbereik consumeert. Het subnet moet ook correct zijn geconfigureerd met Network Security Groups die specifieke regels bevatten voor Private Endpoint-verkeer, hoewel het belangrijk is op te merken dat Network Security Groups standaard geen effect hebben op Private Endpoint-verkeer zelf, maar wel kunnen worden gebruikt om verkeer te controleren dat naar resources gaat die via Private Endpoints worden benaderd. Na het aanmaken van het Private Endpoint en de koppeling aan het subnet, wijst Azure automatisch een privé IP-adres toe uit het subnetbereik. Dit IP-adres wordt gebruikt als het enige toegangspunt voor de PaaS-service vanuit het virtuele netwerk, en alle verkeer naar deze service wordt gerouteerd via dit privé IP-adres binnen het Azure-backbonenetwerk zonder het publieke internet te passeren. De IP-adrestoewijzing moet worden geverifieerd na implementatie om te bevestigen dat het Private Endpoint correct is geconfigureerd en dat het IP-adres daadwerkelijk is toegewezen en bereikbaar is vanuit het virtuele netwerk.

Voor services die meerdere Private Endpoints ondersteunen of die hoge beschikbaarheid vereisen, kunnen meerdere Private Endpoints worden geconfigureerd in verschillende subnetten of zelfs verschillende Virtual Networks. Deze aanpak biedt redundantie en maakt het mogelijk om toegang te bieden vanuit verschillende netwerksegmenten of on-premises locaties via ExpressRoute of VPN. Bijvoorbeeld, een organisatie kan Private Endpoints configureren voor een Azure SQL Database in zowel een productie-subnet als een beheer-subnet, waardoor verschillende workloads toegang hebben via verschillende netwerkpaden terwijl beide volledig geïsoleerd blijven van het publieke internet. Deze multi-endpoint configuratie vereist echter zorgvuldige planning om te voorkomen dat IP-adresruimte wordt verspild en om ervoor te zorgen dat alle benodigde subnetten voldoende beschikbare adressen bevatten. Na voltooiing van de Private Endpoint-implementatie moet connectiviteit uitgebreid worden getest vanuit virtuele machines die zich binnen het virtuele netwerk bevinden om te verifiëren dat de service daadwerkelijk bereikbaar is via het privé IP-adres en dat alle benodigde functionaliteit correct werkt.

Gebruik PowerShell-script private-endpoints-enabled.ps1 (functie Invoke-Implementation) – Voert een validatiecontrole uit op Private Endpoint-configuraties om te bepalen of Private Endpoints zijn ingeschakeld voor alle relevante PaaS-diensten en identificeert diensten die nog publieke toegang toestaan..

DNS-configuratie en naamresolutie

Correcte DNS-configuratie vormt de hoeksteen van een succesvolle Private Endpoint-implementatie, omdat zonder juiste DNS-resolutie applicaties en diensten nog steeds proberen verbinding te maken via publieke eindpunten, waardoor het beoogde beveiligingsdoel volledig teniet wordt gedaan. Azure Private DNS Zones moeten worden geconfigureerd voor elk type PaaS-dienst dat binnen de organisatie wordt gebruikt, waarbij elke service zijn eigen specifieke Private DNS Zone-vereisten heeft. Voor Azure Storage-accounts moeten bijvoorbeeld Private DNS Zones worden aangemaakt voor 'privatelink.blob.core.windows.net' voor blob storage, 'privatelink.file.core.windows.net' voor Azure Files, 'privatelink.queue.core.windows.net' voor queue storage, en 'privatelink.table.core.windows.net' voor table storage. Azure SQL Database vereist 'privatelink.database.windows.net', Azure Key Vault vereist 'privatelink.vaultcore.azure.net', Cosmos DB vereist verschillende zones afhankelijk van het API-type zoals 'privatelink.documents.azure.com' voor SQL API en 'privatelink.mongo.cosmos.azure.com' voor MongoDB API, en App Services vereisen 'privatelink.azurewebsites.net'. Deze Private DNS Zones moeten worden gekoppeld aan het virtuele netwerk, zodat alle resources binnen dat netwerk automatisch de juiste privé IP-adressen ontvangen wanneer ze proberen verbinding te maken met de service.

De automatische naamresolutie die wordt geboden door Private DNS Zones zorgt ervoor dat applicaties naadloos blijven functioneren zonder codeaanpassingen, terwijl alle communicatie wordt gerouteerd via het privé netwerk. Wanneer een applicatie binnen het virtuele netwerk probeert verbinding te maken met een PaaS-service via de standaard FQDN (Fully Qualified Domain Name), wordt de DNS-query automatisch omgezet naar het privé IP-adres van het Private Endpoint in plaats van het publieke IP-adres. Deze transparante resolutie betekent dat bestaande applicaties en connection strings kunnen blijven functioneren zonder wijzigingen, wat de implementatie aanzienlijk vereenvoudigt en het risico op service-onderbrekingen minimaliseert. Het is echter belangrijk om te verifiëren dat DNS-resolutie correct werkt na de implementatie van Private DNS Zones, omdat onjuiste of incompleet geconfigureerde DNS-instellingen kunnen leiden tot connectiviteitsproblemen die moeilijk te diagnosticeren zijn. DNS-resolutie kan worden getest door nslookup of dig-commando's uit te voeren vanuit virtuele machines binnen het virtuele netwerk, waarbij moet worden geverifieerd dat de service FQDN wordt omgezet naar het privé IP-adres van het Private Endpoint en niet naar een publiek IP-adres.

Voor complexe omgevingen met meerdere Virtual Networks of hybride connectiviteit via ExpressRoute of VPN moet zorgvuldig worden overwogen hoe DNS-resolutie wordt geconfigureerd voor on-premises resources of resources in andere Virtual Networks. In sommige scenario's kunnen on-premises DNS-servers moeten worden geconfigureerd om door te verwijzen naar Azure Private DNS Zones, of kunnen aangepaste DNS-configuraties nodig zijn om ervoor te zorgen dat alle benodigde resources correct kunnen resolven naar Private Endpoint IP-adressen. Deze configuraties vereisen vaak samenwerking tussen netwerk- en cloud-teams en moeten zorgvuldig worden getest om te verifiëren dat alle connectiviteitsscenario's correct functioneren. Daarnaast moeten organisaties overwegen om DNS-logging in te schakelen om te monitoren welke DNS-queries worden uitgevoerd en om te detecteren wanneer applicaties nog steeds proberen verbinding te maken via publieke eindpunten, wat kan wijzen op configuratiefouten of legacy-applicaties die handmatige updates vereisen.

Publieke toegang uitschakelen

Na het succesvol implementeren van Private Endpoints en het verifiëren dat DNS-resolutie correct functioneert, vormt het uitschakelen van publieke netwerktoegang de kritieke laatste stap in het beveiligingsproces. Deze stap is absoluut essentieel omdat zolang publieke toegang nog actief is, blijven PaaS-diensten kwetsbaar voor aanvallen via het publieke internet, zelfs wanneer Private Endpoints correct zijn geconfigureerd. Het uitschakelen van publieke toegang moet worden uitgevoerd via service-specifieke firewall-instellingen in de Azure Portal of via Azure PowerShell, Azure CLI, of infrastructure-as-code tools. Voor de meeste Azure-services kan publieke toegang worden uitgeschakeld door de optie voor toegang vanaf alle netwerken uit te schakelen en uitsluitend toegang vanaf geselecteerde virtuele netwerken en IP-adressen te activeren, waarbij alleen het virtuele netwerk dat de Private Endpoints bevat wordt geselecteerd. Voor sommige services zoals Azure Storage Accounts kan publieke toegang volledig worden geblokkeerd door de 'AllowBlobPublicAccess' eigenschap in te stellen op 'false' en door netwerkregels te configureren die alleen toegang toestaan vanuit het virtuele netwerk.

Het is cruciaal om eerst uitgebreid te testen dat alle applicaties en diensten daadwerkelijk verbinding kunnen maken via de Private Endpoints voordat publieke toegang wordt geblokkeerd, om te voorkomen dat kritieke bedrijfsprocessen worden verstoord of dat gebruikers geen toegang meer hebben tot essentiële systemen. Deze testfase moet verschillende gebruiksscenario's omvatten, waaronder normale werking van workloads, beheeractiviteiten, backup- en monitoring-activiteiten, en disaster recovery-scenario's. Uitgebreide testscripts kunnen worden uitgevoerd om verschillende scenario's te valideren, zoals lees- en schrijfbewerkingen naar storage-accounts, databasequeries naar SQL-instances, het ophalen van geheimen uit Key Vault, en complexe transacties naar Cosmos DB. Daarnaast moeten authenticatie- en autorisatiemechanismen worden getest om te verifiëren dat deze correct functioneren via Private Endpoints, en moeten prestatiekarakteristieken worden gemeten om te bevestigen dat Private Endpoints geen onacceptabele vertraging introduceren. Alleen na succesvolle verificatie van alle testscenario's moet publieke toegang worden uitgeschakeld, en deze wijziging moet worden uitgevoerd tijdens geplande onderhoudsvensters om eventuele problemen op te kunnen lossen zonder impact op productieomgevingen.

Na het uitschakelen van publieke toegang moeten geautomatiseerde controles worden geïmplementeerd om te voorkomen dat publieke toegang opnieuw wordt ingeschakeld, hetzij per ongeluk door onbevoegde gebruikers, hetzij opzettelijk door kwaadwillenden. Azure Policy kan worden gebruikt om policies te definiëren die vereisen dat publieke toegang is uitgeschakeld voor specifieke service-types, en deze policies kunnen worden toegepast op abonnements- of management group-niveau om ervoor te zorgen dat alle resources binnen de scope voldoen aan de gestelde eisen. Azure Policy biedt ook de mogelijkheid om automatische remediatie uit te voeren wanneer niet-compliant configuraties worden gedetecteerd, bijvoorbeeld door automatisch publieke toegang uit te schakelen wanneer deze per ongeluk wordt ingeschakeld. Daarnaast moeten regelmatige compliance-scans worden uitgevoerd om te detecteren wanneer diensten nog steeds publieke toegang toestaan, en moeten alertregels worden geconfigureerd die waarschuwingen genereren wanneer wijzigingen worden gedetecteerd in netwerktoegangsinstellingen. Deze geautomatiseerde aanpak vermindert de werklast voor IT-teams en zorgt voor consistente beveiliging, zelfs wanneer er frequente wijzigingen zijn aan de cloudomgeving.

In sommige gevallen kunnen er legitieme uitzonderingen zijn waar publieke toegang tijdelijk nodig is, bijvoorbeeld voor externe partners, mobiele gebruikers, of specifieke integratiescenario's. Deze uitzonderingen moeten zorgvuldig worden gedocumenteerd met duidelijke rechtvaardigingen, tijdslimieten, en alternatieve beveiligingsmaatregelen zoals IP-whitelisting, multi-factor authenticatie, of tijdelijke toegang via Azure Bastion of VPN. De documentatie moet ook bevatten wie verantwoordelijk is voor het beheer van deze uitzonderingen, wanneer ze moeten worden geëvalueerd voor verwijdering, en welke aanvullende monitoring en logging moet worden geïmplementeerd om de risico's te mitigeren. Regelmatige reviews van deze uitzonderingen moeten worden uitgevoerd om te verifiëren dat ze nog steeds nodig zijn en dat alternatieve oplossingen niet kunnen worden geïmplementeerd om publieke toegang volledig te elimineren.

Monitoring en validatie

Effectieve en continue monitoring van Private Endpoints vormt de hoeksteen van een robuuste beveiligingsstrategie en is absoluut essentieel om te garanderen dat de beveiligingsconfiguratie intact blijft gedurende de volledige levenscyclus van de cloud-infrastructuur. Zonder adequate monitoring kunnen configuratiedrift, onbevoegde toegangspogingen, en onbedoelde wijzigingen onopgemerkt blijven, waardoor de beveiligingspositie van organisaties wordt gecompromitteerd zonder dat dit wordt gedetecteerd. Monitoring moet zich richten op meerdere kritieke aspecten van de Private Endpoint-implementatie, waaronder de continue beschikbaarheid en gezondheid van de Private Endpoints zelf, de nauwkeurigheid en consistentie van DNS-resolutie binnen het virtuele netwerk, en de periodieke verificatie dat publieke netwerktoegang inderdaad volledig is uitgeschakeld voor alle relevante PaaS-diensten. Deze multidimensionale monitoringbenadering zorgt ervoor dat organisaties proactief kunnen reageren op potentiële beveiligingsproblemen voordat deze zich ontwikkelen tot volledige incidenten.

Azure Monitor en Azure Network Watcher bieden uitgebreide en krachtige mogelijkheden voor het volgen van netwerkverkeer, het analyseren van connectiviteitspatronen, en het detecteren van afwijkingen in het normale verkeersgedrag. Deze tools stellen beveiligingsteams in staat om real-time inzicht te verkrijgen in alle netwerkactiviteit en om automatisch waarschuwingen te genereren wanneer verdachte patronen worden geïdentificeerd. Network Security Groups kunnen worden geconfigureerd met uitgebreide loggingmogelijkheden om alle inkomende en uitgaande verbindingen gedetailleerd te registreren, wat waardevolle auditinformatie oplevert voor compliance-doeleinden en helpt bij het identificeren en onderzoeken van potentiële beveiligingsincidenten. Deze logs bevatten cruciale informatie zoals bron- en doel-IP-adressen, poorten, protocollen en tijdsstempels, waardoor forensische analyses mogelijk worden na een beveiligingsincident. Log Analytics-werkruimten kunnen worden gebruikt om geavanceerde queries uit te voeren op netwerklogs, om trendanalyses uit te voeren, en om geautomatiseerde waarschuwingen te configureren die worden geactiveerd wanneer onverwacht verkeer wordt gedetecteerd of wanneer diensten nog steeds via publieke eindpunten worden benaderd ondanks de implementatie van Private Endpoints.

Regelmatige en systematische verificatie van de Private Endpoint-configuratie moet worden uitgevoerd volgens een vastgesteld schema om te controleren dat alle kritieke PaaS-diensten daadwerkelijk zijn gekoppeld aan Private Endpoints en dat er geen nieuwe diensten zijn toegevoegd aan de omgeving zonder de juiste beveiligingsconfiguratie. Deze verificatieprocessen kunnen worden geautomatiseerd door middel van Azure Policy, PowerShell-scripts zoals het bijbehorende script bij dit artikel, of andere infrastructure-as-code tools, waardoor de consistentie en volledigheid van de configuratie worden gegarandeerd. Geautomatiseerde scans kunnen worden geïmplementeerd die periodiek alle PaaS-diensten in het Azure-abonnement controleren en proactief waarschuwingen genereren wanneer diensten worden gedetecteerd die nog steeds publieke toegang toestaan of die niet voldoen aan de gestelde beveiligingsstandaarden. Deze scans moeten deel uitmaken van een continu compliance-monitoringproces dat ervoor zorgt dat beveiligingsstandaarden worden gehandhaafd en dat nieuwe resources automatisch worden geconfigureerd volgens de vastgestelde best practices en organisatorische beleidsregels.

Gebruik PowerShell-script private-endpoints-enabled.ps1 (functie Invoke-Monitoring) – Voert een read-only validatie uit van Private Endpoint-configuraties en toont een samenvatting van de huidige status..

Operationele best practices

Effectief beheer van Private Endpoint-configuraties vereist duidelijke processen, gedefinieerde verantwoordelijkheden en continue monitoring. Organisaties moeten vastleggen wie verantwoordelijk is voor het dagelijks beheer van Private Endpoint-configuraties, wie Private Endpoints mag toevoegen of wijzigen, en hoe wijzigingen worden gecontroleerd en goedgekeurd. Role-Based Access Control (RBAC) in Azure moet worden gebruikt om toegang te beperken tot alleen die personen en rollen die daadwerkelijk Private Endpoint-beheer nodig hebben. Het is aanbevolen om verschillende rollen te definiëren: Private Endpoint-beheerders die volledige controle hebben over Private Endpoint-configuraties, configuratiebeheerders die Private Endpoints kunnen toevoegen en wijzigen maar geen fundamentele configuraties kunnen aanpassen, en lezers die alleen monitoring en rapportage kunnen uitvoeren. Just-in-Time-toegang via Azure Privileged Identity Management kan worden gebruikt om beheeracties te beperken in tijd en scope, waardoor het risico van misbruik wordt verminderd.

Change management is cruciaal voor het voorkomen van configuratiefouten en het borgen van compliance. Alle wijzigingen aan Private Endpoint-configuraties moeten worden gedocumenteerd met informatie over wie de wijziging heeft aangevraagd, waarom de wijziging nodig is, welke risico's zijn geëvalueerd, en wie de wijziging heeft goedgekeurd. Voor productieomgevingen moeten wijzigingen eerst worden getest in een niet-productieomgeving om te verifiëren dat de wijzigingen werken zoals bedoeld en geen onbedoelde gevolgen hebben. Wijzigingen moeten worden gepland tijdens onderhoudsvensters wanneer mogelijk, en er moeten rollback-plannen zijn voor het geval een wijziging problemen veroorzaakt. Organisaties moeten een changelog bijhouden waarin alle wijzigingen worden vastgelegd, inclusief datum, tijd, persoon, reden en impact, voor auditdoeleinden en troubleshooting.

Het automatiseren van Private Endpoint-configuratiechecks via Azure Policy en scripts kan helpen bij het waarborgen van consistentie en het voorkomen van configuratiefouten. Organisaties kunnen policies definiëren die vereisen dat specifieke PaaS-diensten Private Endpoints hebben geconfigureerd, dat publieke toegang is uitgeschakeld, of dat bepaalde configuraties worden gebruikt. Deze policies kunnen worden toegepast op abonnements- of management group-niveau om ervoor te zorgen dat alle resources binnen de scope voldoen aan de gestelde eisen. Azure Policy biedt ook de mogelijkheid om automatische remediatie uit te voeren wanneer niet-compliant configuraties worden gedetecteerd. Het bijbehorende PowerShell-script kan worden gebruikt om regelmatige validatiechecks uit te voeren die controleren of Private Endpoint-configuraties voldoen aan beveiligingsbest practices en compliance-vereisten. Deze geautomatiseerde aanpak vermindert de werklast voor IT-teams en zorgt voor consistente beveiliging, zelfs wanneer er frequente wijzigingen zijn aan de cloudomgeving.

Periodieke reviews en audits zijn essentieel om te waarborgen dat Private Endpoint-configuraties up-to-date blijven en aansluiten bij veranderende bedrijfsbehoeften en beveiligingsvereisten. Organisaties moeten minimaal kwartaalgewijs een review uitvoeren van alle Private Endpoint-configuraties om te verifiëren dat alle kritieke PaaS-diensten Private Endpoints hebben, dat publieke toegang is uitgeschakeld, en dat DNS-configuraties correct zijn. Tijdens deze reviews moeten ongebruikte Private Endpoints worden geïdentificeerd en verwijderd, configuraties moeten worden geoptimaliseerd voor betere beveiliging en prestaties, en nieuwe bedrijfsvereisten moeten worden geëvalueerd voor nieuwe Private Endpoint-implementaties. Deze reviews moeten worden gedocumenteerd en gerapporteerd aan security- en risicocomités, en bevindingen moeten worden vertaald naar concrete verbeteracties met eigenaren en deadlines.

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 Azure Private Endpoints: Inschakelen en Configureren voor Netwerkisolatie .DESCRIPTION Dit script ondersteunt Nederlandse overheidsorganisaties bij het valideren en implementeren van Private Endpoints voor alle relevante Azure PaaS-diensten. Het script controleert of Private Endpoints zijn ingeschakeld voor Storage Accounts, SQL-databases, Key Vault, Cosmos DB, App Services, Container Registry, en andere relevante services, identificeert diensten die nog publieke toegang toestaan, en genereert compliance-rapportages. Het script is ontworpen om veilig lokaal of vanuit een beheerde automation-runner te draaien met READ-ONLY rechten voor monitoring, en met beperkte schrijfrechten voor remediatie. Het voert configuratiewijzigingen alleen uit na expliciete bevestiging of in WhatIf-modus. .NOTES Filename: private-endpoints-enabled.ps1 Author: Nederlandse Baseline voor Veilige Cloud Created: 2025-01-15 Version: 1.0 Related JSON: content/azure/network-security/private-endpoints-enabled.json Category: network-security Workload: azure .LINK https://github.com/m365-tenant-best-practise .EXAMPLE .\private-endpoints-enabled.ps1 -Monitoring Voert een read-only validatie uit van alle Private Endpoint-configuraties en toont een samenvatting van de huidige status. .EXAMPLE .\private-endpoints-enabled.ps1 -Remediation -WhatIf Genereert een rapport met concrete aanbevelingen zonder wijzigingen aan te brengen. .EXAMPLE .\private-endpoints-enabled.ps1 -ExportPath .\private-endpoints-report.json Exporteert de validatie- en aanbevelingsgegevens naar een JSON-bestand. #> #Requires -Version 5.1 #Requires -Modules Az.Accounts, Az.Network, Az.Resources, Az.Storage, Az.Sql, Az.KeyVault, Az.CosmosDB, Az.Websites, Az.ContainerRegistry [CmdletBinding()] param( [Parameter(HelpMessage = "Voer een read-only validatie uit van alle Private Endpoint-configuraties")] [switch]$Monitoring, [Parameter(HelpMessage = "Genereer aanbevelingen en implementatie-instructies voor Private Endpoints")] [switch]$Remediation, [Parameter(HelpMessage = "Draai implementatiewijzigingen terug (indien mogelijk)")] [switch]$Revert, [Parameter(HelpMessage = "Toon welke acties zouden worden uitgevoerd zonder deze echt uit te voeren")] [switch]$WhatIf, [Parameter(HelpMessage = "Optioneel pad om resultaten als JSON te exporteren")] [string]$ExportPath ) $ErrorActionPreference = 'Stop' # ============================================================================ # HEADER # ============================================================================ Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "Azure Private Endpoints – Validatie" -ForegroundColor Cyan Write-Host "Nederlandse Baseline voor Veilige Cloud" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan # ============================================================================ # HULPFUNCTIES # ============================================================================ function Connect-NbvvcAzContext { <# .SYNOPSIS Zorgt voor een geldige Az-context voor leesacties .DESCRIPTION Probeert eerst een bestaande context te gebruiken. Als er geen context is, wordt Connect-AzAccount aangeroepen. Dit is geschikt voor lokale debug- scenario's met een interactieve sessie of een managed identity. #> [CmdletBinding()] param() try { $context = Get-AzContext -ErrorAction SilentlyContinue if (-not $context) { Write-Host "Geen actieve Azure-context gevonden. Probeer te verbinden..." -ForegroundColor Yellow Connect-AzAccount -ErrorAction Stop | Out-Null $context = Get-AzContext -ErrorAction Stop } Write-Host "Actieve Azure-context: $($context.Subscription.Name) [$($context.Subscription.Id)]" -ForegroundColor Gray return $context } catch { Write-Host "[FAIL] Kon geen geldige Azure-context verkrijgen: $_" -ForegroundColor Red throw } } function Get-NbvvcPrivateEndpointStatus { <# .SYNOPSIS Verzamelt de configuratiestatus van Private Endpoints voor alle relevante PaaS-diensten .DESCRIPTION Haalt de configuratiestatus op van Private Endpoints voor Storage Accounts, SQL-databases, Key Vault, Cosmos DB, App Services, en andere relevante services. De validatie is read-only en bedoeld als input voor verder architectuur- en compliancewerk. .OUTPUTS Hashtable met Private Endpoint-configuratiestatus per service-type #> [CmdletBinding()] param() $status = @{ timestamp = Get-Date subscriptionId = (Get-AzContext).Subscription.Id privateEndpoints = @{ totalCount = 0 compliantCount = 0 nonCompliantCount = 0 serviceDetails = @() findings = @() } servicesWithoutPE = @{ storageAccounts = @() sqlServers = @() keyVaults = @() cosmosDbAccounts = @() appServices = @() containerRegistries = @() } publicAccessEnabled = @{ storageAccounts = @() sqlServers = @() keyVaults = @() cosmosDbAccounts = @() appServices = @() } overallScore = 0 } Write-Host "`nValidatie van Private Endpoint-configuraties (read-only)..." -ForegroundColor Yellow # Private Endpoints - Inventariseer alle Private Endpoints try { $privateEndpoints = Get-AzPrivateEndpoint -ErrorAction SilentlyContinue $status.privateEndpoints.totalCount = $privateEndpoints.Count Write-Host " Private Endpoints: $($privateEndpoints.Count) gevonden" -ForegroundColor Gray foreach ($pe in $privateEndpoints) { $peDetail = @{ name = $pe.Name resourceGroup = $pe.ResourceGroupName location = $pe.Location id = $pe.Id privateIPAddress = $pe.NetworkInterfaces[0].IpConfigurations[0].PrivateIPAddress subnetId = $pe.NetworkInterfaces[0].IpConfigurations[0].Subnet.Id connectionState = $pe.PrivateLinkServiceConnections[0].PrivateLinkServiceConnectionState.Status isCompliant = $false } if ($peDetail.connectionState -eq 'Approved') { $peDetail.isCompliant = $true $status.privateEndpoints.compliantCount++ } else { $status.privateEndpoints.nonCompliantCount++ } $status.privateEndpoints.serviceDetails += $peDetail } } catch { Write-Host " [WARN] Kon Private Endpoints niet volledig valideren: $_" -ForegroundColor Yellow $status.privateEndpoints.findings += "Kon Private Endpoint-status niet volledig valideren; controleer rechten en Az.Network-module." } # Storage Accounts - Controleer Private Endpoints try { Write-Host " Storage Accounts controleren..." -ForegroundColor Gray $storageAccounts = Get-AzStorageAccount -ErrorAction SilentlyContinue foreach ($sa in $storageAccounts) { $peConnections = Get-AzPrivateEndpointConnection -PrivateLinkResourceId $sa.Id -ErrorAction SilentlyContinue $approvedPE = $peConnections | Where-Object { $_.PrivateLinkServiceConnectionState.Status -eq 'Approved' } if (-not $approvedPE) { $status.servicesWithoutPE.storageAccounts += @{ name = $sa.StorageAccountName resourceGroup = $sa.ResourceGroupName id = $sa.Id } } # Controleer publieke toegang if ($sa.AllowBlobPublicAccess -eq $true) { $status.publicAccessEnabled.storageAccounts += @{ name = $sa.StorageAccountName resourceGroup = $sa.ResourceGroupName } } } } catch { Write-Host " [WARN] Kon Storage Accounts niet volledig controleren: $_" -ForegroundColor Yellow } # SQL Servers - Controleer Private Endpoints try { Write-Host " SQL Servers controleren..." -ForegroundColor Gray $sqlServers = Get-AzSqlServer -ErrorAction SilentlyContinue foreach ($sql in $sqlServers) { $peConnections = Get-AzPrivateEndpointConnection -PrivateLinkResourceId $sql.ResourceId -ErrorAction SilentlyContinue $approvedPE = $peConnections | Where-Object { $_.PrivateLinkServiceConnectionState.Status -eq 'Approved' } if (-not $approvedPE) { $status.servicesWithoutPE.sqlServers += @{ name = $sql.ServerName resourceGroup = $sql.ResourceGroupName id = $sql.ResourceId } } # Controleer publieke toegang if ($sql.PublicNetworkAccess -eq 'Enabled') { $status.publicAccessEnabled.sqlServers += @{ name = $sql.ServerName resourceGroup = $sql.ResourceGroupName } } } } catch { Write-Host " [WARN] Kon SQL Servers niet volledig controleren: $_" -ForegroundColor Yellow } # Key Vaults - Controleer Private Endpoints try { Write-Host " Key Vaults controleren..." -ForegroundColor Gray $keyVaults = Get-AzKeyVault -ErrorAction SilentlyContinue foreach ($kv in $keyVaults) { $peConnections = Get-AzPrivateEndpointConnection -PrivateLinkResourceId $kv.ResourceId -ErrorAction SilentlyContinue $approvedPE = $peConnections | Where-Object { $_.PrivateLinkServiceConnectionState.Status -eq 'Approved' } if (-not $approvedPE) { $status.servicesWithoutPE.keyVaults += @{ name = $kv.VaultName resourceGroup = $kv.ResourceGroupName id = $kv.ResourceId } } # Controleer publieke toegang (via network rules) $networkRules = Get-AzKeyVaultNetworkRuleSet -VaultName $kv.VaultName -ResourceGroupName $kv.ResourceGroupName -ErrorAction SilentlyContinue if ($networkRules -and $networkRules.DefaultAction -eq 'Allow') { $status.publicAccessEnabled.keyVaults += @{ name = $kv.VaultName resourceGroup = $kv.ResourceGroupName } } } } catch { Write-Host " [WARN] Kon Key Vaults niet volledig controleren: $_" -ForegroundColor Yellow } # Cosmos DB Accounts - Controleer Private Endpoints try { Write-Host " Cosmos DB Accounts controleren..." -ForegroundColor Gray $cosmosAccounts = Get-AzCosmosDBAccount -ErrorAction SilentlyContinue foreach ($cosmos in $cosmosAccounts) { $peConnections = Get-AzPrivateEndpointConnection -PrivateLinkResourceId $cosmos.Id -ErrorAction SilentlyContinue $approvedPE = $peConnections | Where-Object { $_.PrivateLinkServiceConnectionState.Status -eq 'Approved' } if (-not $approvedPE) { $status.servicesWithoutPE.cosmosDbAccounts += @{ name = $cosmos.Name resourceGroup = $cosmos.ResourceGroupName id = $cosmos.Id } } # Controleer publieke toegang if ($cosmos.PublicNetworkAccess -eq 'Enabled') { $status.publicAccessEnabled.cosmosDbAccounts += @{ name = $cosmos.Name resourceGroup = $cosmos.ResourceGroupName } } } } catch { Write-Host " [WARN] Kon Cosmos DB Accounts niet volledig controleren: $_" -ForegroundColor Yellow } # App Services - Controleer Private Endpoints try { Write-Host " App Services controleren..." -ForegroundColor Gray $appServices = Get-AzWebApp -ErrorAction SilentlyContinue foreach ($app in $appServices) { $peConnections = Get-AzPrivateEndpointConnection -PrivateLinkResourceId $app.Id -ErrorAction SilentlyContinue $approvedPE = $peConnections | Where-Object { $_.PrivateLinkServiceConnectionState.Status -eq 'Approved' } if (-not $approvedPE) { $status.servicesWithoutPE.appServices += @{ name = $app.Name resourceGroup = $app.ResourceGroupName id = $app.Id } } } } catch { Write-Host " [WARN] Kon App Services niet volledig controleren: $_" -ForegroundColor Yellow } # Container Registries - Controleer Private Endpoints try { Write-Host " Container Registries controleren..." -ForegroundColor Gray $registries = Get-AzContainerRegistry -ErrorAction SilentlyContinue foreach ($reg in $registries) { $peConnections = Get-AzPrivateEndpointConnection -PrivateLinkResourceId $reg.Id -ErrorAction SilentlyContinue $approvedPE = $peConnections | Where-Object { $_.PrivateLinkServiceConnectionState.Status -eq 'Approved' } if (-not $approvedPE) { $status.servicesWithoutPE.containerRegistries += @{ name = $reg.Name resourceGroup = $reg.ResourceGroupName id = $reg.Id } } } } catch { Write-Host " [WARN] Kon Container Registries niet volledig controleren: $_" -ForegroundColor Yellow } # Bereken overall score $totalServices = ( $status.servicesWithoutPE.storageAccounts.Count + $status.servicesWithoutPE.sqlServers.Count + $status.servicesWithoutPE.keyVaults.Count + $status.servicesWithoutPE.cosmosDbAccounts.Count + $status.servicesWithoutPE.appServices.Count + $status.servicesWithoutPE.containerRegistries.Count ) if ($totalServices -gt 0) { $compliantServices = $status.privateEndpoints.compliantCount $totalWithPE = $totalServices + $compliantServices if ($totalWithPE -gt 0) { $status.overallScore = [math]::Round(($compliantServices / $totalWithPE) * 100, 1) } } else { $status.overallScore = 100 } return $status } function Invoke-Monitoring { <# .SYNOPSIS Voert een read-only Private Endpoint-configuratievalidatie uit .DESCRIPTION Gebruikt configuratiecontroles om inzicht te geven in de huidige Private Endpoint- configuraties per service-type. Dit helpt bij het prioriteren van implementatietrajecten en het identificeren van diensten die Private Endpoints missen. .OUTPUTS Hashtable met samenvattende metrics en status per service-type #> [CmdletBinding()] param() $null = Connect-NbvvcAzContext $status = Get-NbvvcPrivateEndpointStatus Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "SAMENVATTING PRIVATE ENDPOINT STATUS" -ForegroundColor Cyan Write-Host " Overall Score : $($status.overallScore)%" -ForegroundColor White Write-Host "`n Private Endpoints:" -ForegroundColor Yellow Write-Host " Totaal aantal PE's : $($status.privateEndpoints.totalCount)" -ForegroundColor Gray Write-Host " Compliant PE's : $($status.privateEndpoints.compliantCount)" -ForegroundColor Green Write-Host " Non-compliant PE's : $($status.privateEndpoints.nonCompliantCount)" -ForegroundColor $(if ($status.privateEndpoints.nonCompliantCount -gt 0) { "Red" } else { "Gray" }) Write-Host "`n Diensten zonder Private Endpoints:" -ForegroundColor Yellow Write-Host " Storage Accounts : $($status.servicesWithoutPE.storageAccounts.Count)" -ForegroundColor $(if ($status.servicesWithoutPE.storageAccounts.Count -gt 0) { "Red" } else { "Green" }) Write-Host " SQL Servers : $($status.servicesWithoutPE.sqlServers.Count)" -ForegroundColor $(if ($status.servicesWithoutPE.sqlServers.Count -gt 0) { "Red" } else { "Green" }) Write-Host " Key Vaults : $($status.servicesWithoutPE.keyVaults.Count)" -ForegroundColor $(if ($status.servicesWithoutPE.keyVaults.Count -gt 0) { "Red" } else { "Green" }) Write-Host " Cosmos DB Accounts : $($status.servicesWithoutPE.cosmosDbAccounts.Count)" -ForegroundColor $(if ($status.servicesWithoutPE.cosmosDbAccounts.Count -gt 0) { "Red" } else { "Green" }) Write-Host " App Services : $($status.servicesWithoutPE.appServices.Count)" -ForegroundColor $(if ($status.servicesWithoutPE.appServices.Count -gt 0) { "Red" } else { "Green" }) Write-Host " Container Registries : $($status.servicesWithoutPE.containerRegistries.Count)" -ForegroundColor $(if ($status.servicesWithoutPE.containerRegistries.Count -gt 0) { "Red" } else { "Green" }) Write-Host "`n Diensten met publieke toegang:" -ForegroundColor Yellow Write-Host " Storage Accounts : $($status.publicAccessEnabled.storageAccounts.Count)" -ForegroundColor $(if ($status.publicAccessEnabled.storageAccounts.Count -gt 0) { "Red" } else { "Green" }) Write-Host " SQL Servers : $($status.publicAccessEnabled.sqlServers.Count)" -ForegroundColor $(if ($status.publicAccessEnabled.sqlServers.Count -gt 0) { "Red" } else { "Green" }) Write-Host " Key Vaults : $($status.publicAccessEnabled.keyVaults.Count)" -ForegroundColor $(if ($status.publicAccessEnabled.keyVaults.Count -gt 0) { "Red" } else { "Green" }) Write-Host " Cosmos DB Accounts : $($status.publicAccessEnabled.cosmosDbAccounts.Count)" -ForegroundColor $(if ($status.publicAccessEnabled.cosmosDbAccounts.Count -gt 0) { "Red" } else { "Green" }) if ($status.servicesWithoutPE.storageAccounts.Count -gt 0 -or $status.servicesWithoutPE.sqlServers.Count -gt 0 -or $status.servicesWithoutPE.keyVaults.Count -gt 0) { Write-Host "`nAandachtspunten:" -ForegroundColor Yellow if ($status.servicesWithoutPE.storageAccounts.Count -gt 0) { Write-Host " - $($status.servicesWithoutPE.storageAccounts.Count) Storage Account(s) zonder Private Endpoints" -ForegroundColor Yellow } if ($status.servicesWithoutPE.sqlServers.Count -gt 0) { Write-Host " - $($status.servicesWithoutPE.sqlServers.Count) SQL Server(s) zonder Private Endpoints" -ForegroundColor Yellow } if ($status.servicesWithoutPE.keyVaults.Count -gt 0) { Write-Host " - $($status.servicesWithoutPE.keyVaults.Count) Key Vault(s) zonder Private Endpoints" -ForegroundColor Yellow } } else { Write-Host "`nGeen specifieke aandachtspunten gedetecteerd op basis van deze scan." -ForegroundColor Green } return @{ status = $status } } function Invoke-Remediation { <# .SYNOPSIS Genereert Private Endpoint-implementatieaanbevelingen en instructies .DESCRIPTION Op basis van de configuratievalidatie worden concrete aanbevelingen gegenereerd voor vervolgstappen zoals het implementeren van Private Endpoints voor diensten die deze nog missen, of het uitschakelen van publieke toegang. Het script voert configuratiewijzigingen alleen uit na expliciete bevestiging of in WhatIf-modus. #> [CmdletBinding(SupportsShouldProcess)] param( [string]$ReportPath ) if ($WhatIf) { Write-Host "`nWhatIf: er wordt een aanbevelingsrapport gegenereerd op basis van configuratievalidatie, maar er vinden geen wijzigingen plaats." -ForegroundColor Yellow } $result = Invoke-Monitoring $status = $result.status $recommendations = @() if ($status.servicesWithoutPE.storageAccounts.Count -gt 0) { $recommendations += "Implementeer Private Endpoints voor $($status.servicesWithoutPE.storageAccounts.Count) Storage Account(s); zie Azure Portal of gebruik New-AzPrivateEndpoint." } if ($status.servicesWithoutPE.sqlServers.Count -gt 0) { $recommendations += "Implementeer Private Endpoints voor $($status.servicesWithoutPE.sqlServers.Count) SQL Server(s); zie Azure Portal of gebruik New-AzPrivateEndpoint met subresource 'sqlServer'." } if ($status.servicesWithoutPE.keyVaults.Count -gt 0) { $recommendations += "Implementeer Private Endpoints voor $($status.servicesWithoutPE.keyVaults.Count) Key Vault(s); zie Azure Portal of gebruik New-AzPrivateEndpoint met subresource 'vault'." } if ($status.servicesWithoutPE.cosmosDbAccounts.Count -gt 0) { $recommendations += "Implementeer Private Endpoints voor $($status.servicesWithoutPE.cosmosDbAccounts.Count) Cosmos DB Account(s); zie Azure Portal of gebruik New-AzPrivateEndpoint met de juiste subresource per API-type." } if ($status.servicesWithoutPE.appServices.Count -gt 0) { $recommendations += "Implementeer Private Endpoints voor $($status.servicesWithoutPE.appServices.Count) App Service(s); vereist Premium v2/v3 of Isolated tier." } if ($status.publicAccessEnabled.storageAccounts.Count -gt 0) { $recommendations += "Schakel publieke toegang uit voor $($status.publicAccessEnabled.storageAccounts.Count) Storage Account(s) na verificatie van Private Endpoint-connectiviteit." } if ($status.publicAccessEnabled.sqlServers.Count -gt 0) { $recommendations += "Schakel publieke netwerktoegang uit voor $($status.publicAccessEnabled.sqlServers.Count) SQL Server(s) na verificatie van Private Endpoint-connectiviteit." } if ($recommendations.Count -eq 0) { $recommendations += "Geen specifieke aanbevelingen op basis van deze scan; alle relevante diensten hebben Private Endpoints geconfigureerd." } Write-Host "`nAanbevolen vervolgstappen:" -ForegroundColor Cyan foreach ($rec in $recommendations) { Write-Host " - $rec" -ForegroundColor White } Write-Host "`nBELANGRIJK:" -ForegroundColor Yellow Write-Host " - Private Endpoints vereisen een Virtual Network met geschikt subnet" -ForegroundColor Gray Write-Host " - Configureer Private DNS Zones voor automatische naamresolutie" -ForegroundColor Gray Write-Host " - Test connectiviteit uitgebreid voordat publieke toegang wordt uitgeschakeld" -ForegroundColor Gray Write-Host " - Kosten: circa €6 per Private Endpoint per maand" -ForegroundColor Gray $report = @{ generatedAt = Get-Date subscriptionId = $status.subscriptionId overallScore = $status.overallScore privateEndpointStatus = @{ status = $status recommendations = $recommendations } } $targetPath = $null if ($PSBoundParameters.ContainsKey("ReportPath") -and $ReportPath) { $targetPath = $ReportPath } elseif ($ExportPath) { $targetPath = $ExportPath } if ($targetPath) { if ($PSCmdlet.ShouldProcess($targetPath, "Schrijf Private Endpoint-rapport naar JSON-bestand")) { $report | ConvertTo-Json -Depth 6 | Out-File -FilePath $targetPath -Encoding UTF8 Write-Host "`n[OK] Rapport geschreven naar: $targetPath" -ForegroundColor Green } } } function Invoke-Revert { <# .SYNOPSIS Draai implementatiewijzigingen terug .DESCRIPTION Dit script voert configuratiewijzigingen alleen uit na expliciete bevestiging. Revert-functionaliteit is beperkt omdat Private Endpoint-configuraties complex zijn en handmatige interventie vereisen. De functie is aanwezig voor consistentie met andere scripts binnen de Nederlandse Baseline voor Veilige Cloud. #> [CmdletBinding(SupportsShouldProcess)] param() Write-Host "`nPrivate Endpoint-configuraties vereisen handmatige interventie voor revert-operaties." -ForegroundColor Yellow Write-Host "Raadpleeg de documentatie en Azure-portal voor specifieke revert-stappen per component." -ForegroundColor Gray Write-Host "`nAlgemene stappen:" -ForegroundColor Yellow Write-Host " 1. Verwijder Private Endpoint-resources via Azure Portal of Remove-AzPrivateEndpoint" -ForegroundColor Gray Write-Host " 2. Herstel publieke netwerktoegang indien nodig" -ForegroundColor Gray Write-Host " 3. Update DNS-configuraties indien nodig" -ForegroundColor Gray } function Invoke-Implementation { <# .SYNOPSIS Implementeert Private Endpoints voor relevante PaaS-diensten .DESCRIPTION Deze functie is een alias voor Invoke-Remediation voor consistentie met andere scripts binnen de Nederlandse Baseline voor Veilige Cloud. #> [CmdletBinding()] param() Invoke-Remediation } # ============================================================================ # MAIN EXECUTION # ============================================================================ try { if ($Revert) { Invoke-Revert } elseif ($Remediation) { Invoke-Remediation -ReportPath $ExportPath } elseif ($Monitoring) { $null = Invoke-Monitoring } else { Write-Host "Beschikbare parameters:" -ForegroundColor Yellow Write-Host " -Monitoring : Voer een read-only Private Endpoint-configuratievalidatie uit" -ForegroundColor Gray Write-Host " -Remediation : Genereer Private Endpoint-implementatieaanbevelingen (geen wijzigingen)" -ForegroundColor Gray Write-Host " -Revert : Beperkte revert-functionaliteit (handmatige interventie vereist)" -ForegroundColor Gray Write-Host " -WhatIf : Toon welke acties logisch zouden zijn zonder uitvoer" -ForegroundColor Gray Write-Host " -ExportPath : Optioneel pad voor JSON-rapport" -ForegroundColor Gray Write-Host "`nVoorbeeld: .\private-endpoints-enabled.ps1 -Monitoring" -ForegroundColor Cyan } } catch { Write-Error "Scriptuitvoering mislukt: $_" exit 2 } finally { Write-Host "`n========================================`n" -ForegroundColor Cyan } # Exitcodes: # 0 = Succesvolle uitvoering # 2 = Fout tijdens uitvoering

Risico zonder implementatie

Risico zonder implementatie
High: Wanneer PaaS-diensten via publieke eindpunten worden blootgesteld aan het internet, ontstaat een significant en onacceptabel aanvalsoppervlak dat door kwaadwillenden kan worden geëxploiteerd. Diensten zoals SQL-databases, opslagaccounts, Key Vault, Cosmos DB en App Services zijn via publieke eindpunten toegankelijk voor iedereen op internet, wat het risico op ongeautoriseerde toegang, gegevensexfiltratie, datalekken, distributed denial-of-service (DDoS) aanvallen, en geavanceerde persistent threat (APT) campagnes drastisch verhoogt. Zelfs met firewallregels en authenticatie blijven publiek toegankelijke eindpunten kwetsbaar omdat ze technisch beschikbaar zijn op internet. Compliance met NIS2-vereisten, Zero Trust-principes, ISO 27001 en BIO wordt onmogelijk zonder netwerkisolatie via Private Endpoints. Voor productieomgevingen waar PaaS-diensten kritieke gegevens verwerken, is het risico buitengewoon hoog en kan het leiden tot operationele verstoringen, financiële schade, reputatieschade, en boetes van toezichthouders.

Management Samenvatting

Private Endpoints inschakelen: Implementeer Private Endpoints voor alle productie PaaS-diensten inclusief SQL-databases, opslagaccounts, Key Vault, Cosmos DB, App Services en andere relevante services om uitsluitend toegang via het virtuele netwerk te garanderen. De kosten bedragen ongeveer €6 per maand per Private Endpoint. De implementatie vereist vier kritieke stappen: maak Private Endpoint-resources aan en koppel deze aan subnetten, configureer Private DNS Zones voor automatische naamresolutie, test connectiviteit uitgebreid, en schakel publieke netwerktoegang uit. Deze maatregel is verplicht voor compliance met NIS2, Zero Trust-architectuur, ISO 27001 en BIO. De implementatietijd bedraagt ongeveer 60 tot 80 uur afhankelijk van het aantal diensten en de complexiteit van de omgeving. Private Endpoints zijn essentieel voor het isoleren van productie PaaS-diensten en vormen de basis voor een veilige cloud-architectuur. Het bijbehorende PowerShell-script valideert automatisch of Private Endpoints zijn ingeschakeld voor alle relevante PaaS-diensten, identificeert diensten die nog publieke toegang toestaan, controleert DNS-configuraties, en genereert compliance-rapportages.