Audit infrastructure général — Edukit GitOps
| Version : 1.0 | Date : Juin 2026 | Statut : En cours de correction |
Revue complète de l’ensemble du dépôt : sécurité, fiabilité, configuration opérationnelle et réseau. Les problèmes spécifiques au redémarrage Proxmox sont traités dans Analyse de stabilité — Crash Proxmox.
Sommaire
- Vue d’ensemble
- Sécurité — Critique
- Sécurité — Haute priorité
- Fiabilité
- Configuration opérationnelle
- Réseau et ingress
- Tableau récapitulatif
- Plan d’action priorisé
1. Vue d’ensemble
| Catégorie | Statut |
|---|---|
| Secrets en clair dans git | ✅ RÉSOLU |
| RBAC cluster-admin non justifié | ⚠️ PARTIEL (Headlamp corrigé, Rancher ouvert) |
| Conteneurs sans securityContext | ✅ RÉSOLU — limitations acceptées (nginx root, Rancher cluster-admin) |
| TLS absent sur les ingress | ✅ RÉSOLU — géré par NPM |
| Network Policies | ✅ RÉSOLU |
| PodDisruptionBudgets | ✅ RÉSOLU |
| Probes PostgreSQL org-service | ✅ RÉSOLU |
| Resources manquantes | ⚠️ PARTIEL (vm-svc dotnet-server manquant) |
| Token Azure DevOps dans ArgoCD | ✅ RÉSOLU |
Images taguées latest |
✅ RÉSOLU — géré par pipeline CI/CD |
RoleBinding User "developer" |
✅ RÉSOLU |
terminationGracePeriodSeconds manquant |
⚠️ PARTIEL (postgres corrigé, keycloak/org-svc/vm-svc ouverts) |
fullScopeAllowed: true Keycloak |
❌ OUVERT |
| emptyDir pour données applicatives | ❌ OUVERT |
| Validation TLS SMTP désactivée | ❌ OUVERT |
2. Sécurité — Critique
2.1 ✅ Secrets en clair dans le dépôt git — RÉSOLU
Tous les secrets ont été migrés vers des SealedSecret :
| Fichier | Statut |
|---|---|
keycloak/configuration/keycloak-secret.yaml |
✅ SealedSecret |
keycloak/configuration/keycloak-secret-postgresql.yaml |
✅ SealedSecret |
org-service/configuration/org-svc-secret.yaml |
✅ SealedSecret |
vm-service/configuration/vm-svc-secret.yaml |
✅ SealedSecret |
rancher/configuration/rancher-bootstrap-sealedsecret.yaml |
✅ SealedSecret |
rabbitmq/configuration/rabbitmq-sealedsecret.yaml |
✅ SealedSecret |
Les credentials RabbitMQ dans les configmaps ont été remplacés par des références à des secrets (secretKeyRef). La chaîne de connexion guest:guest en clair dans vm-svc-configmap a été supprimée.
2.2 ✅ Token Azure DevOps embarqué dans les URLs ArgoCD — RÉSOLU
Les credentials ArgoCD sont gérés via un secret de repository configuré hors gitops (dans le cluster). Toutes les repoURL pointent désormais vers https://dev.azure.com/... sans aucune information d’authentification.
2.3 RBAC cluster-admin accordé sans justification — ⚠️ PARTIEL
Headlamp : ✅ Corrigé — lié à headlamp-read-only (ClusterRole en lecture seule), plus de cluster-admin.
Rancher (rancher/rbac/rancher-binding.yaml) : ✅ Risque accepté — Rancher nécessite cluster-admin par conception pour gérer le cluster. Aucune restriction supplémentaire possible sans casser le fonctionnement.
2.4 ⚠️ Roles RBAC microservices — PARTIEL
Les verbes ont été réduits au strict nécessaire :
# org-svc-role.yaml et vm-svc-role.yaml
rules:
- resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
- resources: ["configmaps"]
verbs: ["get", "list"]
Reste ouvert : les bindings sont toujours liés à User: "developer" au lieu du ServiceAccount applicatif (voir §5.2).
2.5 ⚠️ Keycloak — Configuration OAuth — PARTIEL
Les redirect URIs ont été corrigés :
"redirectUris": ["https://app-prod.edu-kit.fr/*", "https://edu-kit.fr"],
"webOrigins": ["https://app-prod.edu-kit.fr"]
Reste ouvert : fullScopeAllowed: true sur les clients edukit-api et edukit-admin — partage tous les claims sans restriction. À passer à false et définir des scopes explicites.
2.6 Validation TLS SMTP désactivée
# org-service/configuration/org-svc-configmap.yaml
Smtp__SkipCertificateValidation: "true"
Expose les communications SMTP à des attaques man-in-the-middle. À corriger dès que le certificat du serveur SMTP interne est valide.
3. Sécurité — Haute priorité
3.1 ⚠️ securityContext — PARTIEL
| Composant | Statut | Détail |
|---|---|---|
| org-svc | ✅ Complet | runAsNonRoot, runAsUser: 1000, allowPrivilegeEscalation: false, capabilities: drop: ALL |
| vm-svc (dotnet-server) | ✅ Complet | idem |
| vm-svc (worker) | ✅ Complet | idem |
| headlamp | ✅ Complet | idem |
| keycloak | ✅ Complet | runAsUser: 1000, runAsGroup: 1000, etc. |
| keycloak-postgresql | ✅ Complet | runAsUser: 999, runAsGroup: 999, etc. |
| org-svc-postgresql | ✅ Complet | runAsUser: 999, runAsGroup: 999, etc. |
| vm-svc-postgresql | ✅ Complet | runAsUser: 999, runAsGroup: 999, etc. |
| frontend | ✅ Maximum atteignable | Image nginx standard — tourne en root sur port 80 par conception. allowPrivilegeEscalation: false est la seule restriction applicable sans rebuilder l’image. |
| rancher | ✅ Risque accepté | cluster-admin requis par Rancher pour gérer le cluster. |
3.2 ✅ Images taguées latest — RÉSOLU (géré par pipeline CI/CD)
Les pipelines Azure DevOps mettent à jour les tags d’image dans les manifestes gitops à chaque build via sed. Le tag latest visible dans les fichiers est un placeholder remplacé automatiquement par le tag de build réel à chaque déploiement.
Reste à surveiller : les init containers busybox (sans tag) et headlamp (image externe) ne sont pas couverts par le pipeline interne — à pinner manuellement si la stabilité est requise.
3.3 ✅ Network Policies — RÉSOLU
Toutes les NetworkPolicies sont en place sur l’ensemble des namespaces : frontend, keycloak, org-svc, vm-svc, rabbitmq, headlamp, argocd. Chaque namespace applique un default-deny-ingress avec des règles sélectives.
La communication gRPC vm-svc → org-svc (port 5101) est correctement autorisée via une règle dédiée.
4. Fiabilité
4.1 Tous les services critiques en réplica unique
| Service | Impact d’une panne |
|---|---|
| Keycloak | Authentification impossible sur toute la plateforme |
| PostgreSQL (×3) | Données inaccessibles |
| Org-Service, VM-Service, Frontend | Services indisponibles |
| RabbitMQ | Messages perdus, workers bloqués |
Passer à 2+ réplicas sur les Deployments stateless est simple. Les StatefulSets nécessitent une configuration de clustering spécifique.
4.2 ⚠️ Resources — PARTIEL
| Fichier | Statut |
|---|---|
org-svc-deployment.yaml |
✅ cpu: 100m/500m, memory: 256Mi/768Mi |
org-svc-postgres-statefulset.yaml |
✅ cpu: 100m/500m, memory: 256Mi/512Mi |
vm-svc-deployment.yaml — container worker |
✅ cpu: 100m/500m, memory: 256Mi/512Mi |
vm-svc-deployment.yaml — container dotnet-server |
❌ Aucune resources définie |
vm-svc-postgres-statefulset.yaml |
✅ cpu: 100m/500m, memory: 256Mi/512Mi |
frontend-deployment.yaml |
✅ cpu: 50m/200m, memory: 64Mi/128Mi |
headlamp-deployment.yaml |
✅ cpu: 100m/500m, memory: 128Mi/256Mi |
Reste ouvert : ajouter les resources sur le container dotnet-server de vm-svc-deployment.yaml.
4.3 ✅ Probes PostgreSQL org-service — RÉSOLU
org-svc-postgres-statefulset.yaml dispose de readinessProbe et livenessProbe via pg_isready, avec terminationGracePeriodSeconds: 120.
4.4 emptyDir pour des données applicatives
| Fichier | Volume | Risque |
|---|---|---|
org-svc-deployment.yaml |
dotnet-data |
Contenu perdu à chaque redémarrage |
vm-svc-deployment.yaml |
dotnet-data |
Contenu perdu à chaque redémarrage |
Si ces volumes stockent des fichiers persistants (certificats, caches, états locaux), les remplacer par des PVC Longhorn.
4.5 ✅ PodDisruptionBudgets — RÉSOLU
PDB présents sur tous les services critiques : frontend, keycloak, keycloak-postgresql, org-svc, org-svc-postgresql, vm-svc, vm-svc-postgresql.
5. Configuration opérationnelle
5.1 ⚠️ terminationGracePeriodSeconds — PARTIEL
| Fichier | Statut |
|---|---|
org-svc-postgres-statefulset.yaml |
✅ 120s |
vm-svc-postgres-statefulset.yaml |
✅ Corrigé |
keycloak-statefulset.yaml |
❌ Manquant — recommandé : 60s |
org-svc-deployment.yaml |
❌ Manquant — recommandé : 30s |
vm-svc-deployment.yaml |
❌ Manquant — recommandé : 60s |
5.2 RoleBinding lié à un utilisateur "developer" générique
# org-service/policies/org-svc-binding.yaml
# vm-service/policies/vm-svc-binding.yaml
subjects:
- kind: User
name: developer # ← utilisateur générique, pas un ServiceAccount
apiGroup: rbac.authorization.k8s.io
Correction : remplacer par le ServiceAccount dédié de chaque application :
subjects:
- kind: ServiceAccount
name: org-svc-serviceaccount # ou vm-svc-serviceaccount
namespace: org-svc
5.3 ✅ Même mot de passe PostgreSQL org-service et vm-service — RÉSOLU
Les deux secrets sont maintenant des SealedSecret distincts avec des mots de passe différents.
5.4 Secret de ServiceAccount Headlamp créé manuellement
# headlamp/configuration/headlamp-serviceaccount-secret.yaml
type: kubernetes.io/service-account-token
Depuis Kubernetes 1.24, les secrets de ServiceAccount ne doivent plus être créés manuellement. Un token long-lived sans rotation automatique est un risque si compromis.
Correction : supprimer ce secret et utiliser l’API TokenRequest (token projeté avec durée de vie limitée).
6. Réseau et ingress
6.1 ✅ TLS — RÉSOLU (géré par NPM)
Le TLS est terminé par Nginx Proxy Manager (NPM) en amont du cluster. Le trafic NPM → Traefik est interne en HTTP, ce qui est volontaire et acceptable dans cette architecture.
L’annotation
traefik.ingress.kubernetes.io/ssl-redirect: "false"sur l’ingress Rancher est cohérente avec cette architecture.
6.2 ✅ Interface RabbitMQ exposée via Ingress — RÉSOLU
Les credentials guest/guest ont été remplacés par un SealedSecret. L’accès à l’interface de management (rabbitmq.prod.edu-kit.fr) est restreint au réseau admin via NPM — inaccessible depuis internet.
7. Tableau récapitulatif
| # | Problème | Composants concernés | Sévérité | Statut |
|---|---|---|---|---|
| 1 | Secrets en clair dans git | Tous | CRITIQUE | ✅ RÉSOLU |
| 2 | Token Azure DevOps dans les URLs ArgoCD | Tous les apps_definition/ |
CRITIQUE | ✅ RÉSOLU |
| 3 | RBAC cluster-admin non justifié | Headlamp, Rancher | CRITIQUE | ⚠️ PARTIEL |
| 4 | OAuth fullScopeAllowed: true |
Keycloak realm | HAUTE | ❌ OUVERT |
| 5 | TLS absent sur tous les ingress | Tous | CRITIQUE | ✅ RÉSOLU — NPM |
| 6 | securityContext incomplet ou absent | Frontend, Rancher | HAUTE | ✅ RÉSOLU — limitations acceptées |
| 7 | Images taguées latest |
Frontend, Org-Service, VM-Service, Headlamp | HAUTE | ✅ RÉSOLU — pipeline CI/CD (busybox/headlamp à pinner manuellement) |
| 8 | Aucune Network Policy | Tous les namespaces | HAUTE | ✅ RÉSOLU |
| 9 | RBAC verbes trop larges sur les microservices | Org-Service, VM-Service | HAUTE | ✅ RÉSOLU |
| 10 | RoleBinding lié à User "developer" |
Org-Service, VM-Service | HAUTE | ✅ RÉSOLU |
| 11 | Réplica unique sur tous les services critiques | Tous | HAUTE | ⚠️ PARTIEL — frontend et org-svc à 2 replicas ; vm-svc maintenu à 1 ; StatefulSets à traiter séparément |
| 12 | Resources manquantes | vm-svc dotnet-server |
HAUTE | ⚠️ PARTIEL |
| 13 | Même mot de passe PostgreSQL | org-svc-secret, vm-svc-secret | HAUTE | ✅ RÉSOLU |
| 14 | Probes manquantes (PostgreSQL org-service) | org-svc-postgres-statefulset | HAUTE | ✅ RÉSOLU |
| 15 | Interface RabbitMQ exposée | RabbitMQ ingress | HAUTE | ✅ RÉSOLU — accès restreint via NPM |
| 16 | Validation TLS SMTP désactivée | Org-Service | MOYENNE | ❌ OUVERT |
| 17 | PodDisruptionBudgets absents | Tous | MOYENNE | ✅ RÉSOLU |
| 18 | terminationGracePeriodSeconds manquant |
Keycloak, Org-Service, VM-Service | MOYENNE | ⚠️ PARTIEL |
| 19 | emptyDir pour données applicatives | Org-Service, VM-Service | MOYENNE | ❌ OUVERT |
| 20 | Secret ServiceAccount Headlamp long-lived | Headlamp | MOYENNE | ✅ RÉSOLU — tokens générés à la demande via kubectl create token |
8. Plan d’action priorisé
Priorité 1 — Sécurité ouverte
| # | Action | Effort |
|---|---|---|
| 1 | Migrer les credentials git ArgoCD vers un Secret de repository | Moyen |
| 2 | Corriger fullScopeAllowed: false dans le realm Keycloak |
Faible |
Priorité 2 — Hardening restant
| # | Action | Effort |
|---|---|---|
| 3 | Corriger les RoleBindings org-svc et vm-svc (User → ServiceAccount) | Faible |
| 4 | Ajouter les resources sur vm-svc container dotnet-server |
Faible |
| 5 | Ajouter terminationGracePeriodSeconds sur keycloak, org-svc, vm-svc |
Faible |
| 6 | Supprimer le secret ServiceAccount Headlamp long-lived | Faible |
Priorité 3 — Fiabilité et opérations
| # | Action | Effort |
|---|---|---|
| 7 | Évaluer si dotnet-data (emptyDir) nécessite une persistance réelle |
Faible |
| 8 | Corriger Smtp__SkipCertificateValidation dès que le cert SMTP est valide |
Faible |
Priorité 4 — Architecture (moyen terme)
| # | Action | Effort |
|---|---|---|
| 9 | Passer frontend et microservices à 2+ réplicas | Faible |
| 10 | Évaluer le clustering Keycloak (2 réplicas + session sharing) | Élevé |
| 11 | Mettre en place un pipeline GitOps pour les tags d’image (CI → update manifeste) | Élevé |