Waarom uw VPN een risico is: Zero-Trust Network Access in moderne SaaS
Zero-Trust Network Access in moderne SaaS: Breek uw VPN's af
We moeten het hebben over uw perimeterbeveiliging. Als u in 2026 nog steeds vertrouwt op een traditioneel Virtual Private Network (VPN) om interne diensten te beveiligen, bouwt u aan een risico. Het klassieke "castle and moat"-model is dood. Zodra een aanvaller de gracht oversteekt, heeft deze onbeperkte laterale bewegingsvrijheid door uw gehele interne netwerk. Dit is onacceptabel voor moderne Software as a Service (SaaS)-omgevingen.
De enige levensvatbare weg voorwaarts is Zero-Trust Network Access (ZTNA). In een zero-trust-model wordt het netwerk zelf als vijandig beschouwd. Elk afzonderlijk verzoek, of het nu afkomstig is van een externe medewerker in een coffeeshop of een microservice binnen uw eigen Kubernetes cluster, moet expliciet worden geauthenticeerd, geautoriseerd en continu worden gevalideerd.
Dit artikel behandelt het probleem van traditionele perimeters, de vereiste architectonische verschuiving naar ZTNA en een concrete implementatiestrategie met behulp van moderne identity-aware proxies.
Het probleem: Perimeterbeveiliging is een fantasie
Traditionele netwerkbeveiliging vertrouwt op IP-adressen en netwerkgrenzen. U plaatst een firewall aan de rand van uw infrastructuur en een VPN gateway voor toegang op afstand. Zodra een gebruiker zich heeft geauthenticeerd bij de VPN, krijgt deze een intern IP-adres en brede toegang tot het zakelijke LAN.
Deze architectuur heeft drie fatale gebreken:
- Impliciet vertrouwen: Het systeem vertrouwt impliciet elke entiteit die actief is vanaf een intern IP-adres. Als de laptop van een ontwikkelaar wordt gecompromitteerd, heeft de aanvaller een directe tunnel naar uw productieomgeving.
- Gebrek aan granulariteit: VPN's werken op OSI-laag 3 of 4 (OSI Layer 3 or 4). Ze verlenen toegang tot volledige netwerksegmenten (subnets), niet tot individuele applicaties. U kunt niet eenvoudig instellen: "Alice heeft toegang tot het interne metrics-dashboard, maar niet tot de billing-API," zonder een doolhof van complexe netwerk-ACL's te beheren.
- Slechte gebruikerservaring: Het routeren van al het verkeer via een centrale VPN gateway veroorzaakt enorme latentie en bandbreedte-knelpunten.
U beveiligt het verkeerde. U beveiligt het netwerk, terwijl u de applicatie zou moeten beveiligen.
Waarom het moeilijk is: De complexiteit van Identity-Aware Access
Als Zero-Trust Network Access zo superieur is, waarom doet niet iedereen het dan? Omdat de overstap van netwerkgerichte beveiliging naar identiteitsgerichte beveiliging conceptueel en operationeel complex is.
Het vereist dat u IP-adressen als vertrouwenseenheid loslaat en vervangt door cryptografische identiteit en context.
Dit is wat de overgang lastig maakt:
- Identity Federation: U moet het identiteitsbeheer centraliseren. Elke applicatie moet integreren met uw Identity Provider (IdP) - meestal Google Workspace, Okta of Azure AD. Het aanpassen van oudere interne tools die alleen Basic Auth of helemaal geen authenticatie ondersteunen, is een enorme hoofdpijn.
- Beleidsbeheer: In een VPN-wereld is toegang binair: u bevindt zich op het netwerk of niet. In een ZTNA-wereld zijn toegangsregels zeer gedetailleerd en contextueel. U moet regels definiëren op basis van de rol van de gebruiker, de status van het apparaat (is het een door het bedrijf beheerd apparaat? is schijfversleuteling ingeschakeld?), het tijdstip van de dag en de gevoeligheid van de applicatie.
- Prestaties en latentie: Elk verzoek moet worden onderschept, geauthenticeerd en geautoriseerd. Als uw identity-aware proxy traag is, voelt uw hele applicatiesuite traag aan.
Ondanks deze uitdagingen is de verschuiving verplicht. Een gecompromitteerde perimeter is een kwestie van "wanneer", niet van "of".
Architectuur: De Zero-Trust Network Access blauwdruk
Een robuuste Zero-Trust Network Access-architectuur in een SaaS-omgeving vervangt de VPN gateway door een Identity-Aware Proxy (IAP). De proxy bevindt zich direct voor uw interne applicaties en bemiddelt elk HTTP-verzoek.
De kerncomponenten van deze architectuur zijn:
- Identity Provider (IdP): De bron van waarheid voor gebruikersidentiteiten en groepslidmaatschappen (bijv. Okta).
- Device Trust Provider: Een systeem dat de status en beveiliging van endpoints evalueert (bijv. CrowdStrike, Kolide).
- Policy Engine: Een gecentraliseerde service die toegangsregels opslaat en evalueert.
- Identity-Aware Proxy (IAP): Het handhavingspunt. Het onderschept verzoeken, raadpleegt de Policy Engine en stuurt het verzoek door naar de upstream-applicatie of weigert het.
De Request Flow
Wanneer een ontwikkelaar toegang probeert te krijgen tot een interne dienst (bijv. metrics.internal.yourcompany.com), vindt de volgende flow plaats:
- De DNS van de gebruiker vertaalt de hostnaam naar het openbare IP van de Identity-Aware Proxy.
- De browser van de gebruiker start een TLS-verbinding met de proxy.
- De proxy controleert op een geldige cryptografische sessiecookie. Als deze niet bestaat, wordt de gebruiker omgeleid naar de IdP via OpenID Connect (OIDC).
- De gebruiker authenticeert zich bij de IdP (wat phishing-resistente MFA vereist, zoals een YubiKey).
- De IdP stuurt de gebruiker terug naar de proxy met een identity token.
- De proxy geeft de identiteit van de gebruiker, de apparaatcontext en de opgevraagde URL door aan de Policy Engine.
- De Policy Engine evalueert het verzoek aan de hand van gedefinieerde regels (bijv. "Alleen engineers op apparaten van het bedrijf hebben toegang tot metrics").
- Indien geautoriseerd, stuurt de proxy het verzoek door naar de upstream-applicatie. Cruciaal is dat de proxy een assertion (vaak een ondertekende JWT) in de request headers injecteert.
- De upstream-applicatie valideert de JWT om er zeker van te zijn dat het verzoek afkomstig is van de vertrouwde proxy, en niet van een ongeoorloofd proces binnen het cluster.
Deze architectuur zorgt voor continue verificatie op OSI-laag 7 (Layer 7).
Implementatie: ZTNA bouwen met Pomerium en Kubernetes
Laten we eens kijken naar een concrete implementatie. We gebruiken Pomerium als onze identity-aware proxy en implementeren dit op een Kubernetes cluster (v1.29+). Pomerium is een uitstekende keuze omdat het open-source is, ontzettend snel werkt en standaard integreert met bekende IdPs.
We gaan ervan uit dat u een draaiend Kubernetes cluster heeft en een service die u veilig wilt ontsluiten, zoals een Grafana dashboard.
Stap 1: Pomerium implementeren
Eerst moeten we Pomerium configureren om verbinding te maken met onze IdP. We gebruiken een standaard Helm chart. Hier is een voorbeeld van een values.yaml-configuratie voor Pomerium, gekoppeld aan Google Workspace.
# pomerium-values.yaml
authenticate:
idp:
provider: google
clientID: "YOUR_GOOGLE_CLIENT_ID"
clientSecret: "YOUR_GOOGLE_CLIENT_SECRET"
serviceAccount: "base64_encoded_service_account_json"
ingress:
enabled: true
className: "nginx"
hosts:
- authenticate.internal.yourcompany.com
tls:
- secretName: pomerium-tls
hosts:
- authenticate.internal.yourcompany.com
config:
# The shared secret for communication between Pomerium components
sharedSecret: "generate_a_random_base64_string_here"
cookieSecret: "generate_another_random_base64_string_here"
Installeer de Helm-chart:
helm repo add pomerium https://helm.pomerium.io
helm install pomerium pomerium/pomerium -f pomerium-values.yaml --namespace pomerium --create-namespace
Stap 2: Toegangsbeleid definiëren
Nu moeten we onze Grafana-instantie beveiligen. Dit doen we door een Ingress resource te definiëren met specifieke annotaties die Pomerium begrijpt. In plaats van een standaard Kubernetes Ingress, gebruiken we Pomerium's Custom Resource Definition (CRD), PomeriumRoute.
Dit is waar de kracht van ZTNA tot uiting komt. We definiëren beleid als code (policy as code) naast de implementatie van onze applicatie.
# grafana-route.yaml
apiVersion: ingress.pomerium.io/v1
kind: PomeriumRoute
metadata:
name: grafana-secure-route
namespace: monitoring
spec:
from: https://metrics.internal.yourcompany.com
to: http://grafana.monitoring.svc.cluster.local:80
policy:
- allow:
and:
- domain:
is: yourcompany.com
- claim/groups:
has: "engineering-team@yourcompany.com"
Deze configuratie stelt: Verleen ALLEEN toegang tot https://metrics.internal.yourcompany.com ALS de gebruiker zich authenticeert met een @yourcompany.com e-mailadres EN lid is van de groep engineering-team.
Pas de route toe:
kubectl apply -f grafana-route.yaml
Stap 3: Upstream-validatie (De cruciale stap)
Als u stopt bij Stap 2, heeft u een kwetsbaarheid. Wat gebeurt er als een aanvaller een pod binnen uw Kubernetes cluster compromitteert? Deze kan Pomerium dan volledig omzeilen en rechtstreeks verzoeken sturen naar http://grafana.monitoring.svc.cluster.local:80.
Om echte Zero-Trust Network Access to bereiken, moet de upstream-applicatie (Grafana) verifiëren dat elk verzoek via Pomerium is verlopen.
Pomerium injecteert een X-Pomerium-Jwt-Assertion-header in elk verzoek dat het doorstuurt. Deze JWT is ondertekend met de privésleutel van Pomerium.
Uw applicatie moet deze JWT valideren. Als u aangepaste Go-microservices bouwt (bijvoorbeeld met Go 1.22), implementeert u middleware om deze controle uit te voeren.
package main
import (
"context"
"crypto/rsa"
"fmt"
"net/http"
"strings"
"github.com/golang-jwt/jwt/v5"
"github.com/lestrrat-go/jwx/v2/jwk"
)
// JWKS URL for Pomerium
const pomeriumJWKSURL = "https://authenticate.internal.yourcompany.com/.well-known/pomerium/jwks.json"
func requirePomeriumAssertion(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assertion := r.Header.Get("X-Pomerium-Jwt-Assertion")
if assertion == "" {
http.Error(w, "Missing Pomerium Assertion", http.StatusUnauthorized)
return
}
// Fetch and cache the public keys from Pomerium
ctx := context.Background()
set, err := jwk.Fetch(ctx, pomeriumJWKSURL)
if err != nil {
http.Error(w, "Failed to fetch keys", http.StatusInternalServerError)
return
}
// Parse and validate the JWT
token, err := jwt.Parse(assertion, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodES256); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
kid, ok := token.Header["kid"].(string)
if !ok {
return nil, fmt.Errorf("missing kid header")
}
key, ok := set.LookupKeyID(kid)
if !ok {
return nil, fmt.Errorf("key %v not found", kid)
}
var rawKey interface{}
if err := key.Raw(&rawKey); err != nil {
return nil, err
}
return rawKey, nil
})
if err != nil || !token.Valid {
http.Error(w, "Invalid Assertion", http.StatusForbidden)
return
}
// Proceed to the application
next.ServeHTTP(w, r)
})
}
Door JWT-validatie af te dwingen op de applicatielaag, maakt u netwerkgrenzen irrelevant. Zelfs als een aanvaller zich op hetzelfde subnet bevindt, kan deze de autorisatiecontroles niet omzeilen.
Valkuilen: Waar ZTNA-implementaties falen
Het implementeren van een identity-aware proxy is vrij eenvoudig. Een organisatie daadwerkelijk overzetten naar een zero-trust-model is daarentegen lastig. Dit zijn de meest voorkomende faalfactoren.
1. Het negeren van legacy-applicaties
Moderne SaaS-apps spreken HTTP en begrijpen standaard OAuth of OIDC. Oudere interne tools doen dat vaak niet. Ze vertrouwen mogelijk op hardcoded IP-adressen of basic authentication.
Probeer deze applicaties niet meteen te herschrijven. Gebruik in plaats daarvan uw proxy om headers te injecteren of basic auth-vertalingen uit te voeren. Als een applicatie een niet-HTTP-protocol gebruikt (zoals SSH of RDP), heeft u een proxy nodig die tunneling ondersteunt (zowel Pomerium als Teleport lossen dit goed op).
2. Het "Break Glass"-antipatron
Teams implementeren vaak strikte ZTNA-regels, maar laten een backdoor-VPN draaien "voor het geval dat" de identity provider uitvalt. Dit doet het doel teniet. Aanvallers zullen deze VPN vinden.
In plaats van een parallel, onveilig netwerk, moet u uw ZTNA-architectuur ontwerpen voor hoge beschikbaarheid (high availability). Gebruik redundante IdPs of zorg ervoor dat uw proxy beleidsbeslissingen en cryptografische sleutels kan cachen om korte IdP-storingen te overbruggen.
3. Alert-moeheid
Een zero-trust-architectuur genereert een enorme hoeveelheid logbestanden. Elk verzoek is immers een autorisatiegebeurtenis. Als u al deze logs zonder agressieve filtering en correlatie in een SIEM dumpt, zal uw securityteam overweldigd raken door alert-moeheid.
Richt u op het loggen van geweigerde verzoeken die afkomstig zijn van bekende bedrijfsapparaten, of onmogelijke reis-scenario's (impossible travel) binnen uw identiteitslogs.
Resultaat: Een veerkrachtige moderne SaaS
Overstappen op Zero-Trust Network Access is een aanzienlijke technische investering. Het vereist het omscholen van teams, het bijwerken van de infrastructuur en het aannemen van een nieuwe operationele mindset.
Maar het resultaat is een fundamenteel veerkrachtigere organisatie.
Wanneer u de VPN elimineert, elimineert u het concept van interne versus externe netwerken. U verleent toegang op basis van identiteit en context, niet op basis van IP-adressen. U krijgt microscopisch inzicht in wie wat op welk moment opvraagt.
Het belangrijkste is dat u de impact (blast radius) van een gecompromitteerd endpoint drastisch verkleint. In een op perimeter gebaseerde wereld is een gestolen laptop van een ontwikkelaar een catastrofale inbreuk. In een zero-trust-wereld is het een beheersbaar incident.
Breek uw grachten af. Beveilig uw applicaties. Begin vandaag nog met het bouwen van een zero-trust-architectuur.
Seven Labs Dienst
VAPT Penetratietesten & Cybersecurity
