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

  1. Vue d’ensemble
  2. Sécurité — Critique
  3. Sécurité — Haute priorité
  4. Fiabilité
  5. Configuration opérationnelle
  6. Réseau et ingress
  7. Tableau récapitulatif
  8. 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é

Retour en haut