K3S/Calico – A (long) way to DevSecOps – Épisode 8
Rappel de la saga : A long way to DevSecOps : Épisode 1, Épisode 2, Épisode 3, Épisode 4, Épisode 5, Épisode 6, Épisode 7, Épisode 8.
Dans DevSecOps, il y a aussi « Sec ». C’est la partie que j’ai le moins abordée pour l’instant d’un point de vue technique. Même si pour moi l’organisationnel reste encore sous estimé dans la constitution d’une équipe DevOps.
Cela reste un article qui survole rapidement les fonctionnalités Network Policies de Calico, la documentation de ce logiciel est suffisante sur le site officiel.
Déploiement d’un WordPress
J’ai abordé récemment la migration de mon site Web avec au passage l’installation de Calico. Les instructions dans cet article sont encore valables.
Une fois déployé, on peut tester et accéder à l’interface Web.
Bon c’est classique et tout fonctionne parfaitement par défaut.
Utilisation de Calico
Par défaut un déploiement de Kubernetes tout est « ouvert », nous allons pratiquer la politique du « default deny ». Et à l’intérieur du namespace « dev-wordpress » tout sera bloqué par défaut.
Voilà le code à appliquer au niveau du Kubernetes :
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: dev-wordpress
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Voilà le résultat si on se connecte sur l’URL :
Le flux vers l’application est désormais fermé. Il suffit d’ouvrir le flux du pod traefik vers le conteneur wordpress. Voilà une des façons de le faire :
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: ingress-allow-traefik
namespace: dev-wordpress
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
namespace: kube-system
podSelector:
matchLabels:
app: traefik-ingress-controller
egress:
- to:
- podSelector:
matchLabels:
tier: frontend
Explication rapide : les flux sont ouverts entre le pod qui se nomme « traefik-ingress-controller » et le pod qui possède le label « tier=frontend ». Ici on voit toute la puissance des règles qui peuvent être conçues de manière générique. Par exemple un administrateur pourrait ouvrir des flux par défaut vers des pods qui seront identifiés avec des labels spécifiques. Bien entendu l’équipe sécurité devra valider la bonne utilisation des labels, mais cela peut faciliter grandement la création et la gestion de règles en factorisant certaines règles entre différentes équipes.
Voilà ce qui se passe une fois la règle appliquée :
On est près du but. Le pod wordpress doit pouvoir se connecter à sa base de données MySQL. On va ouvrir les ports de manière plus traditionnelle cette fois-ci (comme on pourrait le faire au niveau d’un firewall).
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-db
namespace: dev-wordpress
spec:
podSelector: {}
ingress:
- from:
- ipBlock:
cidr: 0.0.0.0/0
ports:
- protocol: TCP
port: 3306
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
Explication rapide : ouverture pour tous les pods du namespace du port 3306. On pourrait aussi limiter cette ouverture au pod MySQL en mettant un « podSelector », permettant à la règle d’être plus fine (ou de définir une IP fixe au pod MySQL). Mais l’objectif de cet exemple est de démontrer toute la puissance des Network Policies en mixant toutes les techniques possibles.
Résultat dans le navigateur :
L’application est de retour : BRAVO !!!
Conclusion
L’application de règles réseau au niveau d’un cluster Kubernetes est grandement facilitée par l’implémentation des Network Policies. C’est donc possible pour une équipe DevOps, d’intégrer ses propres règles au moment du déploiement de l’application et donc d’avoir une approche intégrée qui sera versionnée au niveau du Git. Avec une approche vérifiant de manière rigoureuse les droits du système de fichier, des conteneurs, et maintenant des flux entre ceux-ci, on commence à avoir un cluster Kubernetes qui d’un point de vue sécurité tient la route. De plus tout ceci est facilitée par le fait que tout est vérifiable dans le code aisément. Nous avons donc ici les bases du DevSecOps, mais on peut encore faire mieux. La suite dans le prochain épisode…