chore: build
ci-api / test (push) Successful in 25m49s

This commit is contained in:
Xor290
2026-08-18 20:07:52 +02:00
parent aa1aa60f00
commit dfc62c305d
25 changed files with 741 additions and 58 deletions
+197
View File
@@ -0,0 +1,197 @@
# 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
---
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 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.
resources: [schedules, backups]
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