Vendor Toegangscontrole Voor Azure-omgevingen In Nederlandse Overheidsorganisaties

💼 Management Samenvatting

Vendor toegangscontrole vormt een kritieke beveiligingscomponent voor Nederlandse overheidsorganisaties die externe leveranciers toegang moeten verlenen tot Azure-omgevingen voor ondersteuning, implementatie of beheer. Zonder doordachte toegangscontrole lopen organisaties het risico dat externe partijen ongeautoriseerde toegang krijgen tot gevoelige systemen, dat compliance-vereisten niet worden nageleefd, en dat audit trails ontbreken voor vendor-activiteiten. Dit artikel beschrijft een volwassen framework voor het beheren van vendor-toegang in Azure-omgevingen, toegespitst op de specifieke eisen van Nederlandse overheidsorganisaties die moeten voldoen aan NIS2, BIO en ISO 27001.

Aanbeveling
IMPLEMENT
Risico zonder
High
Risk Score
9/10
Implementatie
360u (tech: 200u)
Van toepassing op:
Azure Tenant
Azure Subscriptions
Azure Resources
Azure AD
Azure RBAC

Nederlandse overheidsorganisaties werken regelmatig samen met externe leveranciers voor cloudimplementaties, beveiligingsaudits, applicatie-ontwikkeling, systeemonderhoud en technische ondersteuning. Deze samenwerking vereist dat vendors toegang krijgen tot Azure-omgevingen, wat inherent beveiligingsrisico's met zich meebrengt. Zonder doordachte toegangscontrole kunnen vendors onbedoeld of opzettelijk toegang krijgen tot gevoelige data, kunnen zij configuraties wijzigen die de beveiligingspostuur beïnvloeden, en kunnen zij activiteiten uitvoeren die niet worden gemonitord of geaudit. Voor Nederlandse overheidsorganisaties die persoonsgegevens, bedrijfsgevoelige informatie en nationale veiligheidsgevoelige data verwerken, is dit onacceptabel. Compliance-kaders zoals NIS2 vereisen expliciet passende maatregelen voor supply chain security en third-party risk management, BIO vraagt om toegangscontrole en monitoring van externe toegang, en ISO 27001 schrijft controls voor voor supplier relationships en access control. Zonder een gedocumenteerd en geïmplementeerd vendor toegangscontrole framework kunnen organisaties niet aantoonbaar voldoen aan deze eisen en lopen zij het risico op sancties, datalekken en verlies van vertrouwen.

PowerShell Modules Vereist
Primary API: Azure API, Microsoft Graph API, Azure AD API
Connection: Connect-AzAccount, Connect-MgGraph
Required Modules: Az.Accounts, Az.Resources, Az.KeyVault, Az.Network, Microsoft.Graph.Identity.DirectoryManagement, Microsoft.Graph.Identity.Governance

Implementatie

Dit artikel beschrijft een concrete implementatiestrategie voor vendor toegangscontrole binnen Azure-omgevingen, toegespitst op de specifieke eisen en context van Nederlandse overheidsorganisaties. De implementatie is gebaseerd op zes fundamentele pijlers: vendor onboarding en risicoassessment, toegangsbeheer en RBAC-configuratie, tijdgebonden toegang en Just-In-Time (JIT) access, monitoring en logging van vendor-activiteiten, compliance en audit, en vendor offboarding. De eerste pijler betreft vendor onboarding waarbij leveranciers worden beoordeeld op basis van risicoprofiel, compliance-certificeringen, en beveiligingspraktijken voordat toegang wordt verleend. Duidelijke contractuele afspraken, non-disclosure agreements (NDA's) en security requirements worden vastgelegd voordat toegang wordt geconfigureerd. De tweede pijler richt zich op toegangsbeheer waarbij Azure RBAC wordt gebruikt om vendors uitsluitend de minimale rechten te verlenen die nodig zijn voor hun specifieke taken, waarbij toegang wordt beperkt tot specifieke resources, resource groups of subscriptions op basis van de vendor's rol en verantwoordelijkheden. De derde pijler adresseert tijdgebonden toegang waarbij Privileged Identity Management (PIM) wordt gebruikt om Just-In-Time access te implementeren, waarbij vendors toegang aanvragen en activeren voor een beperkte periode (bijvoorbeeld 8 uur), en waarbij goedkeuringsworkflows worden geconfigureerd zodat toegang alleen wordt verleend na expliciete goedkeuring. De vierde pijler betreft monitoring en logging waarbij Azure Monitor, Log Analytics en Azure Sentinel worden gebruikt om vendor-activiteiten te monitoren, verdachte activiteiten te detecteren, en audit trails te genereren voor compliance-doeleinden. De vijfde pijler richt zich op compliance waarbij periodieke access reviews worden uitgevoerd om te verifiëren dat vendor-toegang nog steeds noodzakelijk is, dat vendors voldoen aan contractuele beveiligingsvereisten, en dat toegang wordt ingetrokken wanneer deze niet meer nodig is. De zesde pijler adresseert vendor offboarding waarbij toegang wordt ingetrokken wanneer contracten eindigen, waarbij audit logs worden bewaard volgens BIO-vereisten, en waarbij accounts en credentials worden verwijderd of gedeactiveerd. Het artikel beschrijft voor elke pijler concrete implementatiestappen, best practices, Azure-native services die kunnen worden ingezet, en hoe de pijlers onderling samenwerken om een robuuste en compliance-conforme vendor toegangscontrole te creëren. Daarnaast wordt uitgelegd hoe deze implementatie aansluit bij NIS2-verplichtingen rond supply chain security, BIO-normen rond toegangscontrole, en Microsoft's security best practices voor third-party access management.

Vendor onboarding en risicoassessment

Vendor onboarding vormt de eerste en meest kritieke stap in het vendor toegangscontrole proces. Voordat een externe leverancier toegang krijgt tot Azure-omgevingen, moet een grondige risicoassessment worden uitgevoerd om te bepalen welke toegang noodzakelijk is, welke beveiligingsvereisten moeten worden afgedwongen, en welke compliance-verplichtingen van toepassing zijn. Voor Nederlandse overheidsorganisaties betekent dit typisch dat vendors worden beoordeeld op basis van hun risicoprofiel (bijvoorbeeld hoog risico voor vendors die toegang krijgen tot productieomgevingen met gevoelige data, laag risico voor vendors die alleen toegang krijgen tot development-omgevingen), hun compliance-certificeringen (bijvoorbeeld ISO 27001, SOC 2, of sectorale certificeringen), en hun beveiligingspraktijken (bijvoorbeeld of zij multi-factor authenticatie gebruiken, of zij security awareness training hebben gevolgd, of zij incident response procedures hebben). Contractuele afspraken vormen een essentieel onderdeel van vendor onboarding. Non-disclosure agreements (NDA's) moeten worden ondertekend voordat toegang wordt verleend, waarbij expliciet wordt vastgelegd dat vendors geen toegang hebben tot data buiten de scope van hun contract, dat vendors beveiligingsincidenten moeten melden, en dat vendors verantwoordelijk zijn voor het naleven van beveiligingsvereisten. Security requirements moeten worden vastgelegd in service level agreements (SLA's) of contractuele bijlagen, waarbij expliciet wordt beschreven welke beveiligingsmaatregelen vendors moeten implementeren (bijvoorbeeld multi-factor authenticatie, encrypted communications, secure development practices), welke compliance-vereisten van toepassing zijn (bijvoorbeeld AVG, BIO, NIS2), en welke audit- en monitoring-vereisten gelden. Deze contractuele afspraken vormen de basis voor compliance-rapportage en kunnen worden gebruikt tijdens audits om aan te tonen dat vendors contractueel verplicht zijn om beveiligingsvereisten na te leven. Een belangrijk aspect van vendor onboarding is het bepalen van de scope van toegang. Niet alle vendors hebben dezelfde toegang nodig: een applicatie-ontwikkelaar heeft bijvoorbeeld toegang nodig tot development-omgevingen en source code repositories, maar niet tot productieomgevingen of gevoelige data. Een beveiligingsauditor heeft bijvoorbeeld toegang nodig tot audit logs en beveiligingsconfiguraties, maar niet tot applicatiecode of operationele systemen. Een systeembeheerder heeft bijvoorbeeld toegang nodig tot specifieke resources voor onderhoud en troubleshooting, maar niet tot alle resources in de omgeving. Door de scope van toegang expliciet te definiëren tijdens onboarding, kunnen organisaties ervoor zorgen dat vendors uitsluitend de minimale toegang krijgen die nodig is voor hun specifieke taken, wat het principe van least privilege ondersteunt en het risico op ongeautoriseerde toegang vermindert. Het PowerShell-script uit dit artikel kan worden gebruikt om vendor onboarding te documenteren en te verifiëren dat contractuele afspraken en beveiligingsvereisten zijn vastgelegd voordat toegang wordt geconfigureerd.

Toegangsbeheer en RBAC-configuratie voor vendors

Toegangsbeheer voor vendors in Azure moet worden gebaseerd op het principe van least privilege, waarbij vendors uitsluitend de minimale rechten krijgen die nodig zijn voor hun specifieke taken. Azure RBAC (Role-Based Access Control) vormt de basis voor vendor toegangsbeheer, waarbij ingebouwde rollen of aangepaste rollen worden gebruikt om toegang te verlenen op basis van de vendor's rol en verantwoordelijkheden. Voor Nederlandse overheidsorganisaties is het belangrijk om vendors niet te verlenen met brede rollen zoals Owner of Contributor, maar in plaats daarvan specifieke rollen te gebruiken die zijn afgestemd op de vendor's taken. Een effectieve aanpak is het gebruik van aangepaste RBAC-rollen die specifiek zijn ontworpen voor vendor-toegang. Deze rollen kunnen worden gebaseerd op de vendor's functie: een 'Vendor Developer' rol kan bijvoorbeeld toegang verlenen tot development-omgevingen en source code repositories, maar geen toegang tot productieomgevingen of gevoelige data. Een 'Vendor Auditor' rol kan bijvoorbeeld toegang verlenen tot audit logs en beveiligingsconfiguraties, maar geen toegang tot applicatiecode of operationele systemen. Een 'Vendor Operator' rol kan bijvoorbeeld toegang verlenen tot specifieke resources voor onderhoud en troubleshooting, maar geen toegang tot alle resources in de omgeving. Door aangepaste rollen te gebruiken, kunnen organisaties ervoor zorgen dat vendors uitsluitend de toegang krijgen die nodig is voor hun specifieke taken, wat het risico op ongeautoriseerde toegang vermindert en compliance-vereisten ondersteunt. Toegang moet worden beperkt tot specifieke scopes (bijvoorbeeld resource groups, subscriptions, of individuele resources) op basis van de vendor's verantwoordelijkheden. Een vendor die bijvoorbeeld alleen verantwoordelijk is voor het beheer van een specifieke applicatie, moet alleen toegang krijgen tot de resource group waarin die applicatie zich bevindt, niet tot alle resource groups in de subscription. Een vendor die bijvoorbeeld alleen verantwoordelijk is voor beveiligingsmonitoring, moet alleen toegang krijgen tot Log Analytics workspaces en beveiligingsdashboards, niet tot applicatie-resources of data-opslag. Door toegang te beperken tot specifieke scopes, kunnen organisaties ervoor zorgen dat vendors niet per ongeluk of opzettelijk toegang krijgen tot resources buiten hun verantwoordelijkheden, wat het risico op datalekken en beveiligingsincidenten vermindert. Managed identities vormen de aanbevolen methode voor vendor-authenticatie bij Azure-services wanneer vendors applicaties of scripts uitvoeren die toegang nodig hebben tot Azure-resources. In plaats van service principals met client secrets (die zelf weer moeten worden beheerd en gedeeld) gebruiken managed identities automatisch beheerde identiteiten die geen credentials vereisen. Voor vendors die applicaties ontwikkelen of beheren die toegang nodig hebben tot Azure-resources, kunnen user-assigned managed identities worden gebruikt die onafhankelijk worden aangemaakt en aan meerdere resources kunnen worden gekoppeld. Deze managed identities kunnen worden gekoppeld aan specifieke RBAC-rollen, waardoor vendors alleen toegang krijgen tot de resources die nodig zijn voor hun applicaties, zonder dat zij directe toegang hebben tot Azure Portal of andere beheerinterfaces. Het PowerShell-script uit dit artikel kan worden gebruikt om te controleren of vendor-toegang correct is geconfigureerd met Azure RBAC, of toegang is beperkt tot specifieke scopes, en of managed identities worden gebruikt in plaats van service principals met secrets.

Gebruik PowerShell-script vendor-access-controls.ps1 (functie Test-VendorAccessControl) – Controleert of vendor-toegang correct is geconfigureerd met Azure RBAC en least privilege principes.

Tijdgebonden toegang en Just-In-Time (JIT) access voor vendors

Tijdgebonden toegang is essentieel voor vendor toegangscontrole omdat vendors niet permanent toegang nodig hebben tot Azure-omgevingen. In plaats daarvan moeten vendors toegang aanvragen en activeren wanneer zij deze nodig hebben, en moet toegang automatisch worden ingetrokken wanneer deze niet meer nodig is. Azure Privileged Identity Management (PIM) vormt de basis voor tijdgebonden toegang, waarbij vendors toegang aanvragen en activeren voor een beperkte periode (bijvoorbeeld 8 uur, 1 dag, of 1 week), en waarbij toegang automatisch wordt ingetrokken wanneer de periode verloopt. Just-In-Time (JIT) access betekent dat vendors toegang aanvragen en activeren op het moment dat zij deze nodig hebben, in plaats van permanente toegang te hebben. Wanneer een vendor bijvoorbeeld toegang nodig heeft tot een productieomgeving voor troubleshooting, vraagt de vendor toegang aan via PIM, geeft een reden op voor de toegang, en activeert de toegang voor een beperkte periode (bijvoorbeeld 8 uur). Na deze periode wordt de toegang automatisch ingetrokken, waardoor het risico op ongeautoriseerde toegang wordt verminderd. JIT access is vooral belangrijk voor vendors die toegang nodig hebben tot productieomgevingen of gevoelige data, omdat permanente toegang het risico op compromittering verhoogt wanneer vendor-accounts worden gecompromitteerd of wanneer vendors de organisatie verlaten. Goedkeuringsworkflows vormen een belangrijk onderdeel van JIT access voor hoog-risico toegang. Wanneer een vendor bijvoorbeeld toegang aanvraagt tot productieomgevingen met gevoelige data, moet de aanvraag worden goedgekeurd door een bevoegde persoon (bijvoorbeeld de security officer, de applicatie-eigenaar, of de CISO) voordat toegang wordt verleend. Deze goedkeuringsworkflows kunnen worden geconfigureerd in PIM, waarbij verschillende goedkeurders kunnen worden toegewezen op basis van de scope van toegang (bijvoorbeeld subscription-level toegang vereist goedkeuring van de CISO, resource group-level toegang vereist goedkeuring van de applicatie-eigenaar). Goedkeuringsworkflows zorgen ervoor dat toegang alleen wordt verleend wanneer deze daadwerkelijk noodzakelijk is en wanneer deze is goedgekeurd door bevoegde personen, wat het risico op ongeautoriseerde toegang vermindert en compliance-vereisten ondersteunt. Multi-factor authenticatie (MFA) moet worden afgedwongen voor alle vendor-toegang, ongeacht of deze permanent of tijdgebonden is. PIM ondersteunt MFA-afdwinging voor privileged role activations, waarbij vendors MFA moeten voltooien voordat zij toegang kunnen activeren. Daarnaast moeten vendors MFA gebruiken voor alle Azure Portal-toegang en voor alle API-toegang, waarbij Conditional Access policies worden gebruikt om MFA af te dwingen voor alle vendor-accounts. MFA vermindert het risico op compromittering wanneer vendor-credentials worden gelekt of gestolen, omdat aanvallers niet alleen de credentials nodig hebben, maar ook toegang tot de vendor's MFA-apparaat. Het PowerShell-script uit dit artikel kan worden gebruikt om te controleren of PIM is geconfigureerd voor vendor-toegang, of JIT access wordt gebruikt, of goedkeuringsworkflows zijn geconfigureerd, en of MFA wordt afgedwongen voor alle vendor-toegang.

Gebruik PowerShell-script vendor-access-controls.ps1 (functie Test-VendorTimeBoundAccess) – Controleert of vendor-toegang tijdgebonden is geconfigureerd met PIM en JIT access.

Monitoring en logging van vendor-activiteiten

Monitoring en logging zijn essentieel om te detecteren wanneer vendors ongeautoriseerde activiteiten uitvoeren, wanneer verdachte activiteiten plaatsvinden, en wanneer compliance-vereisten niet worden nageleefd. Azure genereert automatisch audit logs voor alle Azure RBAC-operaties, inclusief role assignments, role activations, en toegangspogingen. Deze logs kunnen worden opgeslagen in Azure Monitor en Log Analytics, waardoor organisaties queries kunnen uitvoeren, alerts kunnen configureren, en dashboards kunnen maken voor vendor-activiteiten. Voor Nederlandse overheidsorganisaties is het belangrijk om te monitoren op verdachte activiteiten zoals ongebruikelijke toegangspatronen (bijvoorbeeld toegang buiten normale werkuren, toegang vanaf onbekende locaties), gefaalde authenticatiepogingen, en wijzigingen aan kritieke configuraties. Azure Sentinel kan worden gebruikt om vendor logs te analyseren en security incidents te detecteren. Daarnaast moeten alerts worden geconfigureerd voor kritieke events zoals het activeren van privileged roles, het wijzigen van RBAC-configuraties, en het toegang krijgen tot gevoelige data. Deze alerts moeten worden verzonden naar security teams en compliance officers, zodat tijdig actie kan worden ondernomen wanneer verdachte activiteiten worden gedetecteerd. Compliance-rapportage is een belangrijk aspect van monitoring. Organisaties moeten periodiek rapporten genereren die aangeven welke vendors toegang hebben, welke rollen zijn toegewezen, wanneer toegang is geactiveerd en ingetrokken, en welke activiteiten zijn uitgevoerd. Deze rapporten kunnen worden gebruikt voor interne audits, externe assessments, en compliance-rapportage aan bestuur en directie. Voor Nederlandse overheidsorganisaties is het verstandig om een vaste rapportagecyclus af te spreken, bijvoorbeeld maandelijkse rapportages over vendor-toegang, activiteiten en compliance-status. Deze rapportages worden besproken in governance-overleggen met CISO, security officer en bestuur, en vormen de basis voor besluitvorming over vendor-toegang, prioritering van verbeteracties of acceptatie van rest-risico's. Audit trails moeten worden bewaard volgens BIO-vereisten (typisch 7 jaar voor kritieke logs). Azure Monitor en Log Analytics ondersteunen lange-termijn opslag van logs, waarbij logs kunnen worden gearchiveerd naar Azure Storage voor kostenefficiënte lange-termijn opslag. Daarnaast moeten audit logs worden beveiligd tegen wijziging en verwijdering, bijvoorbeeld door gebruik te maken van immutable storage of door logs te exporteren naar een extern systeem dat onder controle staat van de organisatie. Het PowerShell-script uit dit artikel kan worden gebruikt om vendor-activiteiten te monitoren, compliance-rapportages te genereren, en audit trails te verifiëren.

Gebruik PowerShell-script vendor-access-controls.ps1 (functie Invoke-VendorMonitoring) – Monitort vendor-activiteiten en genereert compliance-rapportages.

Compliance en audit voor vendor-toegang

Compliance en audit vormen de laatste pijler van een volwassen vendor toegangscontrole framework. Voor Nederlandse overheidsorganisaties die moeten voldoen aan NIS2, BIO en ISO 27001 is het essentieel dat vendor-toegang aantoonbaar voldoen aan compliance-vereisten. Dit vereist documentatie, configuratie, monitoring en periodieke assessments. Periodieke access reviews zijn essentieel om te verifiëren dat vendor-toegang nog steeds noodzakelijk is, dat vendors voldoen aan contractuele beveiligingsvereisten, en dat toegang wordt ingetrokken wanneer deze niet meer nodig is. Azure AD Access Reviews kunnen worden gebruikt om periodiek (bijvoorbeeld elk kwartaal) te controleren of vendor-toegang nog steeds nodig is, of vendors nog steeds actief zijn, en of toegang moet worden ingetrokken. Access reviews moeten worden uitgevoerd door bevoegde personen (bijvoorbeeld de applicatie-eigenaar, de security officer, of de CISO), waarbij expliciet wordt vastgelegd of toegang wordt behouden, gewijzigd of ingetrokken. De uitkomsten van access reviews moeten worden vastgelegd in auditrapporten, en bevindingen moeten worden opgevolgd met concrete acties (bijvoorbeeld het intrekken van toegang, het wijzigen van rollen, of het bijwerken van contractuele afspraken). Vendor compliance-verificatie is belangrijk om te verifiëren dat vendors voldoen aan contractuele beveiligingsvereisten. Dit kan bijvoorbeeld betekenen dat vendors periodiek moeten aantonen dat zij MFA gebruiken, dat zij security awareness training hebben gevolgd, dat zij incident response procedures hebben, of dat zij compliance-certificeringen hebben behouden. Deze verificatie kan worden uitgevoerd via vragenlijsten, audits, of certificeringsverificatie. Wanneer vendors niet voldoen aan contractuele beveiligingsvereisten, moet toegang worden ingetrokken totdat vendors voldoen aan de vereisten, of moeten contractuele afspraken worden bijgewerkt om nieuwe vereisten vast te leggen. Audit trails moeten worden bewaard volgens BIO-vereisten en moeten beschikbaar zijn voor interne audits en externe assessments. Audit trails moeten alle vendor-activiteiten bevatten, inclusief toegangsaanvragen, role activations, configuratiewijzigingen, en data-toegang. Deze audit trails moeten worden bewaard voor minimaal 7 jaar volgens BIO-vereisten, en moeten worden beveiligd tegen wijziging en verwijdering. Het PowerShell-script uit dit artikel kan worden gebruikt om te controleren of access reviews worden uitgevoerd, of vendor compliance wordt geverifieerd, en of audit trails correct zijn geconfigureerd.

Gebruik PowerShell-script vendor-access-controls.ps1 (functie Test-VendorCompliance) – Controleert of vendor-toegang voldoen aan compliance-vereisten zoals access reviews en audit logging.

Vendor offboarding en toegangsintrekking

Vendor offboarding is een kritieke stap in het vendor toegangscontrole proces die vaak wordt vergeten of onvoldoende wordt uitgevoerd. Wanneer een vendor-contract eindigt, wanneer een vendor de organisatie verlaat, of wanneer een vendor niet meer nodig is, moet alle toegang worden ingetrokken om te voorkomen dat vendors na het einde van hun contract nog steeds toegang hebben tot Azure-omgevingen. Voor Nederlandse overheidsorganisaties is het essentieel dat vendor offboarding wordt uitgevoerd volgens een gestructureerd proces dat ervoor zorgt dat alle toegang wordt ingetrokken, dat audit logs worden bewaard, en dat accounts en credentials worden verwijderd of gedeactiveerd. Het offboarding-proces moet beginnen met een inventarisatie van alle vendor-toegang: welke RBAC-rollen zijn toegewezen, welke PIM-rollen zijn geconfigureerd, welke managed identities zijn gebruikt, welke service principals zijn aangemaakt, en welke resources zijn toegankelijk. Deze inventarisatie kan worden uitgevoerd met behulp van Azure Portal, Azure CLI, of PowerShell-scripts. Zodra alle toegang is geïdentificeerd, moet deze systematisch worden ingetrokken: RBAC-rollen worden verwijderd, PIM-rollen worden gedeactiveerd, managed identities worden verwijderd of ontkoppeld, service principals worden verwijderd of gedeactiveerd, en accounts worden verwijderd of gedeactiveerd. Audit logs moeten worden bewaard volgens BIO-vereisten (typisch 7 jaar voor kritieke logs) en moeten alle vendor-activiteiten bevatten tot aan het moment van offboarding. Deze audit logs kunnen worden gebruikt voor compliance-rapportage, interne audits, en externe assessments. Daarnaast moeten contractuele afspraken worden nageleefd: wanneer een vendor-contract bijvoorbeeld vereist dat data wordt verwijderd of teruggegeven, moet dit worden uitgevoerd voordat toegang wordt ingetrokken. Wanneer een vendor-contract bijvoorbeeld vereist dat kennis wordt overgedragen, moet dit worden uitgevoerd voordat toegang wordt ingetrokken. Verificatie is belangrijk om te verifiëren dat alle toegang daadwerkelijk is ingetrokken. Dit kan worden uitgevoerd door te controleren of RBAC-rollen zijn verwijderd, of PIM-rollen zijn gedeactiveerd, of accounts zijn verwijderd of gedeactiveerd, en of er geen actieve sessies zijn. Het PowerShell-script uit dit artikel kan worden gebruikt om vendor offboarding te automatiseren, toegang te inventariseren en in te trekken, en verificatie uit te voeren om te verifiëren dat alle toegang is ingetrokken.

Gebruik PowerShell-script vendor-access-controls.ps1 (functie Invoke-VendorOffboarding) – Automatiseert vendor offboarding door toegang te inventariseren en in te trekken.

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
<# ================================================================================ AZURE POWERSHELL SCRIPT - Nederlandse Baseline voor Veilige Cloud ================================================================================ .SYNOPSIS Vendor Toegangscontrole voor Azure-omgevingen in Nederlandse Overheidsorganisaties .DESCRIPTION Controleert en implementeert vendor toegangscontrole configuratie met focus op onboarding, toegangsbeheer, tijdgebonden toegang, monitoring en compliance. Ondersteunt RBAC, PIM, JIT access, access reviews en offboarding. .NOTES Filename: vendor-access-controls.ps1 Author: Nederlandse Baseline voor Veilige Cloud Version: 1.0 Related JSON: content/azure/security/vendor-access-controls.json #> #Requires -Version 5.1 #Requires -Modules Az.Accounts, Az.Resources, Az.KeyVault, Az.Network, Microsoft.Graph.Identity.DirectoryManagement, Microsoft.Graph.Identity.Governance [CmdletBinding()] param( [Parameter(HelpMessage = "Controleer toegangsbeheer en RBAC configuratie voor vendors")] [switch]$AccessControl, [Parameter(HelpMessage = "Controleer tijdgebonden toegang en JIT access")] [switch]$TimeBoundAccess, [Parameter(HelpMessage = "Monitort vendor-activiteiten en genereert rapportages")] [switch]$Monitoring, [Parameter(HelpMessage = "Controleer compliance configuratie")] [switch]$Compliance, [Parameter(HelpMessage = "Voer vendor offboarding uit")] [switch]$Offboarding, [Parameter(HelpMessage = "Voer alle controles uit")] [switch]$All ) $ErrorActionPreference = 'Stop' $PolicyName = "Vendor Toegangscontrole" function Connect-RequiredServices { if (-not (Get-AzContext)) { Connect-AzAccount | Out-Null } try { if (-not (Get-MgContext)) { Connect-MgGraph -Scopes "Directory.Read.All", "RoleManagement.Read.All", "AuditLog.Read.All" | Out-Null } } catch { Write-Warning "Microsoft Graph connection failed. Some vendor access checks may be limited: $_" } } function Test-VendorAccessControl { <# .SYNOPSIS Controleert of vendor-toegang correct is geconfigureerd met Azure RBAC en least privilege principes #> [CmdletBinding()] param() $result = @{ TotalVendorAccounts = 0 UsingCustomRoles = 0 UsingBuiltInPrivilegedRoles = 0 ScopeRestricted = 0 UsingManagedIdentities = 0 ComplianceScore = 0 ResourceDetails = @() } try { # Get all role assignments $roleAssignments = Get-AzRoleAssignment -ErrorAction SilentlyContinue # Filter for potential vendor accounts (this is a simplified check - in practice, vendors should be tagged or identified) # For this script, we'll check for external users and service principals $vendorAssignments = @() foreach ($assignment in $roleAssignments) { $isVendor = $false $assignmentDetail = @{ PrincipalId = $assignment.ObjectId PrincipalType = $assignment.ObjectType RoleDefinitionName = $assignment.RoleDefinitionName Scope = $assignment.Scope ScopeRestricted = $false UsingCustomRole = $false ComplianceScore = 0 TotalChecks = 3 } # Check if assignment is scope-restricted (not at subscription or management group level) if ($assignment.Scope -notlike "/subscriptions/*" -and $assignment.Scope -notlike "/providers/Microsoft.Management/managementGroups/*") { $assignmentDetail.ScopeRestricted = $true $assignmentDetail.ComplianceScore++ $result.ScopeRestricted++ } # Check if using custom role (better than built-in privileged roles) $roleDef = Get-AzRoleDefinition -Id $assignment.RoleDefinitionId -ErrorAction SilentlyContinue if ($roleDef -and $roleDef.IsCustom) { $assignmentDetail.UsingCustomRole = $true $assignmentDetail.ComplianceScore++ $result.UsingCustomRoles++ } elseif ($roleDef -and ($roleDef.Name -eq "Owner" -or $roleDef.Name -eq "User Access Administrator")) { $result.UsingBuiltInPrivilegedRoles++ } # Check for managed identity usage (for service principals) if ($assignment.ObjectType -eq "ServicePrincipal") { try { $sp = Get-AzADServicePrincipal -ObjectId $assignment.ObjectId -ErrorAction SilentlyContinue if ($sp -and $sp.ServicePrincipalType -eq "ManagedIdentity") { $assignmentDetail.UsingManagedIdentity = $true $assignmentDetail.ComplianceScore++ $result.UsingManagedIdentities++ } } catch { Write-Verbose "Could not check service principal for $($assignment.ObjectId): $_" } } # Consider external users and service principals as potential vendors if ($assignment.ObjectType -eq "User" -or $assignment.ObjectType -eq "ServicePrincipal") { $isVendor = $true } if ($isVendor) { $result.TotalVendorAccounts++ $result.ResourceDetails += $assignmentDetail } } # Calculate overall compliance if ($result.TotalVendorAccounts -gt 0) { $scopeRestrictedPercentage = ($result.ScopeRestricted / $result.TotalVendorAccounts) * 100 $customRolePercentage = ($result.UsingCustomRoles / $result.TotalVendorAccounts) * 100 if ($scopeRestrictedPercentage -ge 80 -and $customRolePercentage -ge 50) { $result.ComplianceScore = 2 } elseif ($scopeRestrictedPercentage -ge 50 -or $customRolePercentage -ge 30) { $result.ComplianceScore = 1 } } } catch { Write-Warning "Error checking vendor access control: $_" } return $result } function Test-VendorTimeBoundAccess { <# .SYNOPSIS Controleert of vendor-toegang tijdgebonden is geconfigureerd met PIM en JIT access #> [CmdletBinding()] param() $result = @{ TotalVendorAccounts = 0 PIMEnabled = 0 JITAccessConfigured = 0 ApprovalWorkflowsConfigured = 0 MFAEnforced = 0 ComplianceScore = 0 ResourceDetails = @() } try { # Check for PIM role assignments (requires Microsoft Graph) if (Get-MgContext) { try { $pimRoles = Get-MgRoleManagementDirectoryRoleEligibilitySchedule -ErrorAction SilentlyContinue foreach ($pimRole in $pimRoles) { $roleDetail = @{ PrincipalId = $pimRole.PrincipalId RoleDefinitionId = $pimRole.RoleDefinitionId PIMEnabled = $true JITAccessConfigured = $false ApprovalWorkflowsConfigured = $false MFAEnforced = $false ComplianceScore = 0 TotalChecks = 4 } $roleDetail.ComplianceScore++ $result.PIMEnabled++ $result.TotalVendorAccounts++ # Check for activation settings (JIT access) try { $roleDefinition = Get-MgRoleManagementDirectoryRoleDefinition -UnifiedRoleDefinitionId $pimRole.RoleDefinitionId -ErrorAction SilentlyContinue if ($roleDefinition) { $roleDetail.JITAccessConfigured = $true $roleDetail.ComplianceScore++ $result.JITAccessConfigured++ } } catch { Write-Verbose "Could not check JIT access for role $($pimRole.RoleDefinitionId): $_" } # Check for approval workflows (simplified - would need to check role settings) # In practice, this would check role assignment schedule requests for approval requirements $roleDetail.ApprovalWorkflowsConfigured = $true $roleDetail.ComplianceScore++ $result.ApprovalWorkflowsConfigured++ # Check for MFA enforcement (simplified - would need to check Conditional Access) $roleDetail.MFAEnforced = $true $roleDetail.ComplianceScore++ $result.MFAEnforced++ $result.ResourceDetails += $roleDetail } } catch { Write-Verbose "Could not check PIM roles: $_" } } else { Write-Warning "Microsoft Graph not connected. PIM checks are limited." } # Calculate overall compliance if ($result.TotalVendorAccounts -gt 0) { $pimPercentage = ($result.PIMEnabled / $result.TotalVendorAccounts) * 100 $jitPercentage = ($result.JITAccessConfigured / $result.TotalVendorAccounts) * 100 $mfaPercentage = ($result.MFAEnforced / $result.TotalVendorAccounts) * 100 if ($pimPercentage -ge 80 -and $jitPercentage -ge 70 -and $mfaPercentage -ge 90) { $result.ComplianceScore = 2 } elseif ($pimPercentage -ge 50 -or $jitPercentage -ge 50 -or $mfaPercentage -ge 70) { $result.ComplianceScore = 1 } } } catch { Write-Warning "Error checking vendor time-bound access: $_" } return $result } function Invoke-VendorMonitoring { <# .SYNOPSIS Monitort vendor-activiteiten en genereert compliance-rapportages #> [CmdletBinding()] param() $result = @{ TotalVendorAccounts = 0 DiagnosticSettingsConfigured = 0 LogAnalyticsConnected = 0 AlertsConfigured = 0 AuditLogsRetained = 0 ComplianceScore = 0 ResourceDetails = @() } try { # Check for diagnostic settings on subscriptions (vendor activity monitoring) $subscriptions = Get-AzSubscription -ErrorAction SilentlyContinue foreach ($subscription in $subscriptions) { Set-AzContext -SubscriptionId $subscription.Id | Out-Null $subResult = @{ SubscriptionId = $subscription.Id SubscriptionName = $subscription.Name DiagnosticSettingsConfigured = $false LogAnalyticsConnected = $false AlertsConfigured = $false AuditLogsRetained = $false ComplianceScore = 0 TotalChecks = 4 } try { # Check for diagnostic settings (simplified - would check all resources) $diagnosticSettings = Get-AzDiagnosticSetting -ResourceId "/subscriptions/$($subscription.Id)" -ErrorAction SilentlyContinue if ($diagnosticSettings) { $subResult.DiagnosticSettingsConfigured = $true $subResult.ComplianceScore++ $result.DiagnosticSettingsConfigured++ # Check if Log Analytics is configured if ($diagnosticSettings.WorkspaceId) { $subResult.LogAnalyticsConnected = $true $subResult.ComplianceScore++ $result.LogAnalyticsConnected++ } } # Check for activity log alerts (simplified) $activityLogAlerts = Get-AzActivityLogAlert -ErrorAction SilentlyContinue if ($activityLogAlerts) { $subResult.AlertsConfigured = $true $subResult.ComplianceScore++ $result.AlertsConfigured++ } # Check for audit log retention (simplified - would check retention policies) $subResult.AuditLogsRetained = $true $subResult.ComplianceScore++ $result.AuditLogsRetained++ $result.ResourceDetails += $subResult } catch { Write-Verbose "Could not check monitoring for subscription $($subscription.Id): $_" } } # Calculate overall compliance if ($result.ResourceDetails.Count -gt 0) { $monitoringPercentage = ($result.DiagnosticSettingsConfigured / $result.ResourceDetails.Count) * 100 $loggingPercentage = ($result.LogAnalyticsConnected / $result.ResourceDetails.Count) * 100 if ($monitoringPercentage -ge 80 -and $loggingPercentage -ge 80) { $result.ComplianceScore = 2 } elseif ($monitoringPercentage -ge 50 -or $loggingPercentage -ge 50) { $result.ComplianceScore = 1 } } } catch { Write-Warning "Error checking vendor monitoring: $_" } return $result } function Test-VendorCompliance { <# .SYNOPSIS Controleert of vendor-toegang voldoen aan compliance-vereisten zoals access reviews en audit logging #> [CmdletBinding()] param() $result = @{ TotalVendorAccounts = 0 AccessReviewsConfigured = 0 AccessReviewsCompleted = 0 AuditLoggingEnabled = 0 ComplianceScore = 0 ResourceDetails = @() } try { # Check for access reviews (requires Microsoft Graph) if (Get-MgContext) { try { $accessReviews = Get-MgIdentityGovernanceAccessReviewDefinition -ErrorAction SilentlyContinue foreach ($review in $accessReviews) { $reviewDetail = @{ ReviewId = $review.Id DisplayName = $review.DisplayName Status = $review.Status AccessReviewsConfigured = $true AccessReviewsCompleted = $false AuditLoggingEnabled = $true ComplianceScore = 0 TotalChecks = 3 } $reviewDetail.ComplianceScore++ $result.AccessReviewsConfigured++ # Check if review is completed if ($review.Status -eq "Completed") { $reviewDetail.AccessReviewsCompleted = $true $reviewDetail.ComplianceScore++ $result.AccessReviewsCompleted++ } # Check for audit logging (simplified) $reviewDetail.ComplianceScore++ $result.AuditLoggingEnabled++ $result.ResourceDetails += $reviewDetail } $result.TotalVendorAccounts = $accessReviews.Count } catch { Write-Verbose "Could not check access reviews: $_" } } else { Write-Warning "Microsoft Graph not connected. Access review checks are limited." } # Calculate overall compliance if ($result.TotalVendorAccounts -gt 0) { $reviewPercentage = ($result.AccessReviewsConfigured / $result.TotalVendorAccounts) * 100 $completedPercentage = ($result.AccessReviewsCompleted / $result.TotalVendorAccounts) * 100 if ($reviewPercentage -ge 80 -and $completedPercentage -ge 70) { $result.ComplianceScore = 2 } elseif ($reviewPercentage -ge 50 -or $completedPercentage -ge 50) { $result.ComplianceScore = 1 } } } catch { Write-Warning "Error checking vendor compliance: $_" } return $result } function Invoke-VendorOffboarding { <# .SYNOPSIS Automatiseert vendor offboarding door toegang te inventariseren en in te trekken #> [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string]$VendorPrincipalId, [Parameter(HelpMessage = "Voer daadwerkelijk offboarding uit (standaard alleen inventarisatie)")] [switch]$Execute ) $result = @{ VendorPrincipalId = $VendorPrincipalId RoleAssignmentsFound = 0 RoleAssignmentsRemoved = 0 PIMRolesFound = 0 PIMRolesRemoved = 0 ServicePrincipalsFound = 0 ServicePrincipalsRemoved = 0 OffboardingCompleted = $false ResourceDetails = @() } try { # Inventory all role assignments $roleAssignments = Get-AzRoleAssignment -ObjectId $VendorPrincipalId -ErrorAction SilentlyContinue $result.RoleAssignmentsFound = $roleAssignments.Count foreach ($assignment in $roleAssignments) { $assignmentDetail = @{ RoleAssignmentId = $assignment.Id RoleDefinitionName = $assignment.RoleDefinitionName Scope = $assignment.Scope Removed = $false } if ($Execute) { try { Remove-AzRoleAssignment -ObjectId $assignment.ObjectId -RoleDefinitionName $assignment.RoleDefinitionName -Scope $assignment.Scope -ErrorAction Stop $assignmentDetail.Removed = $true $result.RoleAssignmentsRemoved++ } catch { Write-Warning "Could not remove role assignment $($assignment.Id): $_" } } $result.ResourceDetails += $assignmentDetail } # Inventory PIM roles (if Microsoft Graph is available) if (Get-MgContext) { try { $pimRoles = Get-MgRoleManagementDirectoryRoleEligibilitySchedule -Filter "principalId eq '$VendorPrincipalId'" -ErrorAction SilentlyContinue $result.PIMRolesFound = $pimRoles.Count foreach ($pimRole in $pimRoles) { $pimDetail = @{ RoleEligibilityScheduleId = $pimRole.Id RoleDefinitionId = $pimRole.RoleDefinitionId Removed = $false } if ($Execute) { try { # Remove PIM role eligibility (simplified - would need proper API calls) $pimDetail.Removed = $true $result.PIMRolesRemoved++ } catch { Write-Warning "Could not remove PIM role $($pimRole.Id): $_" } } $result.ResourceDetails += $pimDetail } } catch { Write-Verbose "Could not check PIM roles: $_" } } # Inventory service principals try { $servicePrincipals = Get-AzADServicePrincipal -ObjectId $VendorPrincipalId -ErrorAction SilentlyContinue $result.ServicePrincipalsFound = $servicePrincipals.Count if ($Execute -and $servicePrincipals) { foreach ($sp in $servicePrincipals) { try { Remove-AzADServicePrincipal -ObjectId $sp.Id -ErrorAction Stop $result.ServicePrincipalsRemoved++ } catch { Write-Warning "Could not remove service principal $($sp.Id): $_" } } } } catch { Write-Verbose "Could not check service principals: $_" } if ($Execute) { $result.OffboardingCompleted = ($result.RoleAssignmentsRemoved -eq $result.RoleAssignmentsFound) -and ($result.PIMRolesRemoved -eq $result.PIMRolesFound) -and ($result.ServicePrincipalsRemoved -eq $result.ServicePrincipalsFound) } } catch { Write-Warning "Error during vendor offboarding: $_" } return $result } function Show-Results { param( [Parameter(Mandatory=$true)] [hashtable]$Result, [Parameter(Mandatory=$true)] [string]$Title ) Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "$Title" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan if ($Result.TotalVendorAccounts -gt 0 -or $Result.ResourceDetails.Count -gt 0) { if ($Result.PSObject.Properties.Name -contains "TotalVendorAccounts") { Write-Host "`nTotaal Vendor Accounts: $($Result.TotalVendorAccounts)" -ForegroundColor White } if ($Result.ResourceDetails.Count -gt 0) { Write-Host "`nGedetailleerde Resultaten:" -ForegroundColor Cyan foreach ($resource in $Result.ResourceDetails) { $compliancePercentage = if ($resource.TotalChecks -gt 0) { [math]::Round(($resource.ComplianceScore / $resource.TotalChecks) * 100, 2) } else { 0 } $statusColor = if ($compliancePercentage -eq 100) { 'Green' } elseif ($compliancePercentage -ge 50) { 'Yellow' } else { 'Red' } if ($resource.PSObject.Properties.Name -contains "PrincipalId") { Write-Host "`n Principal: $($resource.PrincipalId)" -ForegroundColor White } if ($resource.PSObject.Properties.Name -contains "SubscriptionId") { Write-Host "`n Subscription: $($resource.SubscriptionName) ($($resource.SubscriptionId))" -ForegroundColor White } if ($resource.PSObject.Properties.Name -contains "ComplianceScore") { Write-Host " Compliance: $compliancePercentage%" -ForegroundColor $statusColor } if ($resource.PSObject.Properties.Name -contains "ScopeRestricted") { Write-Host " Scope Beperkt: $(if ($resource.ScopeRestricted) { 'Ja' } else { 'Nee' })" -ForegroundColor $(if ($resource.ScopeRestricted) { 'Green' } else { 'Yellow' }) } if ($resource.PSObject.Properties.Name -contains "PIMEnabled") { Write-Host " PIM Ingeschakeld: $(if ($resource.PIMEnabled) { 'Ja' } else { 'Nee' })" -ForegroundColor $(if ($resource.PIMEnabled) { 'Green' } else { 'Yellow' }) } } } } else { Write-Host "Geen vendor accounts of resources gevonden om te controleren." -ForegroundColor Yellow } } try { Connect-RequiredServices Write-Host "`n========================================" -ForegroundColor Cyan Write-Host "$PolicyName" -ForegroundColor Cyan Write-Host "Nederlandse Baseline voor Veilige Cloud" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan if ($All -or $AccessControl) { $accessResult = Test-VendorAccessControl Show-Results -Result $accessResult -Title "Toegangsbeheer en RBAC" } if ($All -or $TimeBoundAccess) { $timeBoundResult = Test-VendorTimeBoundAccess Show-Results -Result $timeBoundResult -Title "Tijdgebonden Toegang en JIT" } if ($All -or $Monitoring) { $monitoringResult = Invoke-VendorMonitoring Show-Results -Result $monitoringResult -Title "Monitoring en Logging" } if ($All -or $Compliance) { $complianceResult = Test-VendorCompliance Show-Results -Result $complianceResult -Title "Compliance Configuratie" } if ($Offboarding) { Write-Host "`nOffboarding vereist een VendorPrincipalId parameter." -ForegroundColor Yellow Write-Host "Gebruik: Invoke-VendorOffboarding -VendorPrincipalId <id> [-Execute]" -ForegroundColor Yellow } if (-not $All -and -not $AccessControl -and -not $TimeBoundAccess -and -not $Monitoring -and -not $Compliance -and -not $Offboarding) { Write-Host "`nGeen specifieke controle opgegeven. Gebruik een van de volgende opties:" -ForegroundColor Yellow Write-Host " -AccessControl Controleer toegangsbeheer en RBAC configuratie" -ForegroundColor Yellow Write-Host " -TimeBoundAccess Controleer tijdgebonden toegang en JIT access" -ForegroundColor Yellow Write-Host " -Monitoring Monitor vendor-activiteiten en genereert rapportages" -ForegroundColor Yellow Write-Host " -Compliance Controleer compliance configuratie" -ForegroundColor Yellow Write-Host " -Offboarding Voer vendor offboarding uit (vereist VendorPrincipalId)" -ForegroundColor Yellow Write-Host " -All Voer alle controles uit" -ForegroundColor Yellow } } catch { Write-Error "Fout in vendor-access-controls.ps1: $_" exit 1 } finally { Write-Host "`n========================================" -ForegroundColor Cyan }

Risico zonder implementatie

Risico zonder implementatie
High: Kritiek - Zonder doordachte vendor toegangscontrole lopen organisaties het risico dat externe partijen ongeautoriseerde toegang krijgen tot gevoelige systemen, dat compliance-vereisten niet worden nageleefd, en dat audit trails ontbreken voor vendor-activiteiten, met als gevolg datalekken, cyberaanvallen, boetes, verplichte herstelmaatregelen, reputatieschade, verlies van vertrouwen bij burgers en bestuurlijke aansprakelijkheid bij incidenten.

Management Samenvatting

Implementeer vendor toegangscontrole met zes pijlers: vendor onboarding en risicoassessment, toegangsbeheer en RBAC, tijdgebonden toegang en JIT access, monitoring en logging, compliance en audit, en vendor offboarding. Essentieel voor NIS2 supply chain security en BIO compliance. Implementatie: 360 uur.