# RBAC du control-plane (worker Go qui provisionne les démos) — moindre # privilège : ce ServiceAccount N'A PAS accès aux Secrets/Deployments/etc. # des autres namespaces (cert-manager, longhorn-system, kube-system...). # # Principe : # - omnex-namespace-manager (ClusterRole) : gérer les objets Namespace eux- # mêmes. Cluster-scoped par nature (RBAC ne permet pas de restreindre par # préfixe de nom "demo-*"/"premium-*"). # - omnex-demo-workload-manager (ClusterRole) : tout ce dont les charts # Helm ont besoin (Deployment, StatefulSet, Secret, ConfigMap, PVC, # NetworkPolicy, ResourceQuota, LimitRange, HPA, les CRD Traefik). JAMAIS # liée cluster-wide — seulement via un RoleBinding créé par le code Go # lui-même dans CHAQUE namespace qu'il crée (voir # control-plane/api/internal/demos/helm_provisioner.go:createNamespace/ # ensureWorkloadRoleBinding). C'est ce qui borne l'accès à un seul # namespace à la fois. # - omnex-rbac-binder (ClusterRole) : permet au ServiceAccount de créer ce # RoleBinding lui-même, dans n'importe quel namespace (obligatoire : # les namespaces de démo n'existent pas encore au moment où ce fichier # est appliqué). Verbe "bind" scopé par resourceName à # omnex-demo-workload-manager UNIQUEMENT — mécanisme RBAC standard # anti-escalade : posséder "bind" sur une ClusterRole précise autorise à # la référencer dans un RoleBinding sans posséder soi-même les droits # qu'elle contient. Le ServiceAccount ne peut donc lier AUCUNE autre # ClusterRole (ex: cluster-admin) à lui-même. apiVersion: v1 kind: Namespace metadata: name: omnex-system --- apiVersion: v1 kind: ServiceAccount metadata: name: omnex-control-plane namespace: omnex-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: omnex-demo-workload-manager rules: - apiGroups: [""] resources: - configmaps - secrets - services - persistentvolumeclaims - resourcequotas - limitranges # Le subchart officiel traefik/traefik crée son propre ServiceAccount # (nom = release Helm) — pas utilisé par nos propres charts # (backend/frontend/postgresql/redis/lbtelegram), mais nécessaire pour # que "helm install traefik" passe. - serviceaccounts verbs: [get, list, watch, create, update, patch, delete] - apiGroups: [""] resources: [pods] verbs: [get, list, watch] - apiGroups: [""] # Exec dans le pod postgres pour pg_dump/restore lors d'un passage en # premium (voir HelmProvisioner.execInPod / migratePostgresData). resources: [pods/exec] verbs: [create] - apiGroups: ["metrics.k8s.io"] # Usage CPU/mémoire live affiché dans le back-office (voir # HelmProvisioner.GetResourceState) — best-effort côté Go (montre juste # la phase du pod si absent), mais sans ce droit c'est TOUJOURS absent # (Forbidden, pas juste "metrics-server indisponible"). resources: [pods] verbs: [get, list] - apiGroups: ["apps"] resources: [deployments, statefulsets] verbs: [get, list, watch, create, update, patch, delete] - apiGroups: ["apps"] # Lecture seule : "helm --wait" liste les ReplicaSet d'un Deployment pour # vérifier l'état du rollout (jamais créés/gérés directement par nous). resources: [replicasets] verbs: [get, list, watch] - apiGroups: ["autoscaling"] resources: [horizontalpodautoscalers] verbs: [get, list, watch, create, update, patch, delete] - apiGroups: ["networking.k8s.io"] resources: [networkpolicies] verbs: [get, list, watch, create, update, patch, delete] - apiGroups: ["traefik.io"] resources: [ingressroutes, middlewares, tlsstores] verbs: [get, list, watch, create, update, patch, delete] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: omnex-namespace-manager rules: - apiGroups: [""] resources: [namespaces] verbs: [get, list, watch, create, delete] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: omnex-rbac-binder rules: - apiGroups: ["rbac.authorization.k8s.io"] resources: [rolebindings] verbs: [get, list, create] - apiGroups: ["rbac.authorization.k8s.io"] resources: [clusterroles] resourceNames: [omnex-demo-workload-manager] verbs: [bind] # Lecture seule, cluster-wide : nécessaire pour que "helm upgrade --install" # du chart traefik partagé (voir EnsureSharedInfra) puisse vérifier l'état # du ClusterRole/ClusterRoleBinding que le subchart officiel traefik/traefik # crée pour SA PROPRE identité ("gestion-traefik-traefik", pas la nôtre). # Ne permet ni de créer ni de modifier quoi que ce soit — seulement de # constater qu'ils existent déjà (installés une fois par un opérateur admin, # voir le bootstrap manuel documenté dans le plan de déploiement). - apiGroups: ["rbac.authorization.k8s.io"] resources: [clusterroles, clusterrolebindings] verbs: [get, list, watch] # Même besoin : le subchart officiel traefik/traefik crée aussi son propre # IngressClass (ressource cluster-scoped), déjà installée une fois par un # opérateur admin — lecture seule ici aussi. - apiGroups: ["networking.k8s.io"] resources: [ingressclasses] verbs: [get, list, watch] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: omnex-control-plane-namespaces subjects: - kind: ServiceAccount name: omnex-control-plane namespace: omnex-system roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: omnex-namespace-manager --- # "nodes" n'est pas un type namespaced : impossible de le scoper via un # RoleBinding par démo comme omnex-demo-workload-manager, d'où une # ClusterRole/ClusterRoleBinding dédiée. Portée strictement à "get" sur le # sous-type "nodes/proxy" — c'est tout ce dont checkPVCUsage a besoin # (voir alerts/resources.go:fetchNodeSummary, équivalent de # `kubectl get --raw /api/v1/nodes//proxy/stats/summary`) pour lire # le remplissage des PVC. Aucun accès en écriture, aucun accès aux autres # sous-ressources de Node. apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: omnex-node-stats-reader rules: - apiGroups: [""] resources: [nodes/proxy] verbs: [get] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: omnex-control-plane-node-stats subjects: - kind: ServiceAccount name: omnex-control-plane namespace: omnex-system roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: omnex-node-stats-reader --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: omnex-control-plane-rbac-binder subjects: - kind: ServiceAccount name: omnex-control-plane namespace: omnex-system roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: omnex-rbac-binder --- # Token longue durée : le control-plane tourne en docker-compose (hors du # cluster) avec un kubeconfig statique monté en fichier, pas de rotation # automatique de type projected-token. Voir ansible/playbook-deploy-site.yml. apiVersion: v1 kind: Secret metadata: name: omnex-control-plane-token namespace: omnex-system annotations: kubernetes.io/service-account.name: omnex-control-plane type: kubernetes.io/service-account-token --- # Role namespacé (pas de RoleBinding auto-créé ici : "velero" est un # namespace fixe préexistant, pas un namespace de démo créé dynamiquement # par le control-plane — pas besoin du mécanisme "bind" utilisé pour # omnex-demo-workload-manager). Portée strictement limitée aux Schedule/ # Backup/BackupRepository Velero — aucun accès aux Secrets (dont # cloud-credentials, la clé du bucket S3) ni au reste du namespace velero. apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: omnex-control-plane namespace: velero rules: - apiGroups: ["velero.io"] # Un Schedule + les Backup qu'il crée par démo (voir # HelmProvisioner.ensureDemoBackupSchedule/deleteDemoBackups) — jamais # de wildcard multi-namespace, pour pouvoir supprimer les sauvegardes # d'UNE démo sans toucher aux autres. backuprepositories : nettoyage du # dépôt Kopia du namespace détruit (deleteDemoBackups) — sans quoi # Velero continue de lancer des jobs de maintenance dessus indéfiniment. resources: [schedules, backups, backuprepositories] verbs: [get, list, watch, create, delete] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: omnex-control-plane namespace: velero subjects: - kind: ServiceAccount name: omnex-control-plane namespace: omnex-system roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: omnex-control-plane