CKS - Minimize Microservice Vulnerabilities
🎯 Objectifs
Tu vas sécuriser les communications entre microservices :
- ✅ Implémenter des Network Policies complexes
- ✅ Configurer le mTLS (mutual TLS) avec Istio
- ✅ Sécuriser la gestion des Secrets
- ✅ Scanner les dépendances pour les CVEs
- ✅ Valider la pod-to-pod encryption
- ✅ Implémenter les Security Contexts avancés
🔗 Network Policies Avancés
Le problème
Par défaut, tous les pods peuvent se parler. Si ton API compromet, elle peut parler à la base de données. Mauvais.
Solution : "Default Deny" + ALLOW explicites
# 1. Default deny TOUT le trafic (ingress ET egress)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# 2. Allow API pods à accepter du trafic depuis le load balancer
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-ingress
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx # Limite à ingress-nginx namespace
ports:
- protocol: TCP
port: 8080
---
# 3. Allow API to DATABASE
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-to-db
namespace: production
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 5432
---
# 4. Allow API to make external requests (for logging, etc)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-egress
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Egress
egress:
# Allowthis pod to reach database
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
# Allow DNS (necessary for lookups)
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
# Allow external HTTP/HTTPS for logging service
- to:
- namespaceSelector:
matchLabels:
name: logging
ports:
- protocol: TCP
port: 9200 # ElasticsearchÀ faire :
- Crée 3 namespaces : api, database, logging
- Déploie 3 apps simples dans chaque (nginx est OK)
- Applique les Network Policies ci-dessus
- Teste :
- API → Database : ✅ doit marcher
- API → Logging : ✅ doit marcher
- Database → API : ❌ devrait échouer
- Database → Logging : ❌ devrait échouer
🔐 mTLS - Mutual TLS avec Istio
Pourquoi ?
Network Policies bloquent au niveau réseau, mais peuvent être contournées. mTLS chiffre et authentifie chaque communication pod-to-pod.
Concept
API pod Database pod
↓ (TLS) ↓
Client cert ←→ Server cert
↓ (vérifié) ↓
Authentifié AuthentifiéChaque pod a un certificat unique. Les communications sont chiffrées ET authentifiées.
Installation d'Istio
# Télécharge Istio
curl -L https://istio.io/downloadIstio | sh -
cd istio-*
# Installe Istio
./bin/istioctl install --set profile=demo -y
# Injecte automatiquement les sidecars Envoy
kubectl label namespace production istio-injection=enabledActiver mTLS
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: production
spec:
mtls:
mode: STRICT # Enforcement : tout doit être mTLS
# PERMISSIVE = mTLS optionnel (backward compat)
# STRICT = mTLS requis (ce qu'on veut)Vérifier que mTLS marche
# Entre dans un pod
kubectl exec -it <api-pod> -- /bin/bash
# Lance tcpdump pour voir si le trafic est chiffré
tcpdump -i eth0 -A | grep -i database
# Si tu vois du texte en clair : mTLS ne marche pas
# Si tu vois du gibberish (chiffré) : mTLS marche!
# Ou utilise istioctl pour vérifier
kubectl get peerauthentication -AÀ faire :
- Installe Istio
- Active mTLS STRICT dans le namespace
- Redéploie tes pods (injection automatique)
- Vérifie que les communications marche toujours
- Teste que les pods de l'extérieur ne peuvent plus se connecter
🔑 Secrets Management
Le problème
# ❌ MAUVAIS : Secret en plain text dans le YAML
apiVersion: v1
kind: Secret
metadata:
name: db-password
type: Opaque
data:
password: cGFzc3dvcmQxMjM= # base64, PAS du chiffrement!Base64 n'est PAS du chiffrement. N'importe qui peut faire echo "cGFzc3dvcmQxMjM=" | base64 -d.
Bonnes pratiques
1. Chiffrer les Secrets dans etcd
# Déjà vu : encryption at-rest2. Utiliser un gestionnaire de secrets externe
# Option 1 : HashiCorp Vault
apiVersion: v1
kind: SecretProviderClass
metadata:
name: vault-database
spec:
provider: vault
parameters:
vaultAddress: "https://vault.company.com"
vaultSkipTLSVerify: "false"
roleName: "kubernetes-role"
secretPath: "secret/data/database/password"
# Dans le Pod
spec:
volumes:
- name: vault-token
projected:
sources:
- serviceAccountToken:
path: token
expirationSeconds: 3600
- name: vault-secrets
csi:
driver: "secrets-store.csi.k8s.io"
readOnly: true
volumeAttributes:
secretProviderClass: "vault-database"
containers:
- name: app
volumeMounts:
- name: vault-secrets
mountPath: /mnt/secrets
# Option 2 : AWS Secrets Manager
# Option 3 : Azure Key Vault3. Rotation automatique des Secrets
# Les Secrets ne devraient JAMAIS être stockés durée longue
# Rotation chaque 30-90 jours4. Audit des accès aux Secrets
# Audit logs doivent tracker chaque access à un Secret
# Via l'EncryptionConfiguration policyÀ faire :
- Audite tous tes Secrets : vérifiez qu'aucun n'est en plaintext dans Git
- Implémenter le chiffrement at-rest
- Rotate une clé de chiffrement (advanced)
🔎 Vulnerability Scanning des Dépendances
Pourquoi ?
Une image peut inclure une librairie avec une CVE CRITICAL. Lors du build, tu dois scanner.
Outils populaires
npm audit (Node.js)
npm audit
npm audit fixpip-audit (Python)
pip install pip-audit
pip-auditTrivy (toutes les images)
trivy image myapp:latest
trivy config . --severity CRITICALIntégrer au CI/CD
# GitHub Actions
name: Security Scan
on: push
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Trivy scan
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload to GitHub Security
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'À faire :
- Ajoute
trivyounpm audità ton CI - Configure le build pour échouer si CRITICAL CVE
- Teste avec une image connue vulnérable
📝 Checklist Microservice Security
- Network Policies : default-deny + ALLOW explicites
- mTLS : activé STRICT sur tous les pods
- Secrets : chiffrés at-rest, rotés régulièrement
- Dépendances : scannées à chaque build
- Pod Security : runAsNonRoot, read-only filesystem
- Audit : tous les accès aux Secrets loggés
- Monitoring : alertes sur connexions non-autorisées