Aller au contenu principal

Durcissement sécurité

Identités et mTLS​

  • Chaque workload reçoit une identité SPIFFE spiffe://enterprise-ai.internal/ns/<ns>/sa/<sa> (annotation spiffe.io/spiffe-id sur les ServiceAccounts, ClusterSPIFFEID dans deploy/spire/registration-entries.yaml).
  • Cilium mutual auth (authentication.mode: required) entre le control plane et LiteLLM, et entre APISIX et le control plane ; chiffrement WireGuard nœud à nœud.
  • Câblage de l'authentification mutuelle Cilium avec SPIRE (charts durcis spire 0.30.4 et spire-crds 0.6.1, Cilium 1.16.5) :
    • authentication.mutual.spire.serverAddress: spire-server.spire-server.svc:443 (Service spire-server du namespace spire-server, port 443 vers le port conteneur 8081), trustDomain: enterprise-ai.internal, install.enabled: false (deploy/terraform/modules/platform-bootstrap/values/cilium.yaml).
    • Socket Workload API de l'agent SPIRE : /run/spire/agent-sockets/spire-agent.sock sur l'hôte (répertoire publié aux pods par le pilote SPIFFE CSI), utilisé par l'opérateur Cilium.
    • Socket d'administration (API Delegated Identity) : /run/spire/agent/sockets/csi.spiffe.io/admin/admin.sock sur l'hôte (/tmp/spire-agent/private/admin.sock dans le conteneur, sockets.admin.mountOnHost: true). Ce répertoire n'est pas publié par le pilote CSI : seul l'agent Cilium le monte.
    • authorized_delegates = ["spiffe://enterprise-ai.internal/cilium-agent"] dans la configuration de l'agent SPIRE (deploy/spire/values.yaml).
    • Entrées (deploy/spire/registration-entries.yaml) : ClusterSPIFFEID cilium-agent (kube-system, SA cilium) vers spiffe://enterprise-ai.internal/cilium-agent et cilium-operator (kube-system, SA cilium-operator, admin: true) vers spiffe://enterprise-ai.internal/cilium-operator ; l'opérateur crée ensuite les entrées /identity/<id> par l'API du serveur. controllerManager.ignoreNamespaces ne contient plus kube-system afin que ces deux objets soient réconciliés.
    • Réseau : agents SPIRE et Cilium en hostNetwork (entités host et remote-node) ; aucun refus par défaut sur le namespace spire-server, le port 8081 reste joignable.
  • cert-manager émet des certificats ECDSA de 30 jours (rotation de la clé à chaque renouvellement).
  • EAI_AUTH_SPIFFE=1 uniquement derrière le mesh ; APISIX supprime tout en-tête X-SPIFFE-ID et X-Dev-* venant de l'extérieur. EAI_AUTH_DEV doit valoir 0 hors développement.

Réseau​

  • Default deny par namespace (CiliumNetworkPolicy du chart) et listes d'autorisation explicites.
  • Egress Internet limité aux FQDN des fournisseurs autorisés, une politique par fournisseur, activable par étiquette. Pas d'egress pour le namespace sandbox.
  • Ne jamais ajouter de egressDeny vers world sur les pods LiteLLM : les règles deny priment sur les autorisations FQDN.

Secrets​

  • Aucun secret dans Git ni dans les values : OpenBao (KV v2) + External Secrets ou injecteur agent.
  • Chiffrement d'enveloppe par tenant via transit eai-tenant-*, signature des points de contrôle d'audit par eai-audit (ed25519, non exportable).
  • Politiques HCL à moindre privilège par service (deploy/openbao/policies). Rotation : bao write -f transit/keys/<cle>/rotate.

Chaîne d'approvisionnement​

  • CI : Trivy fs + image, SBOM SPDX et CycloneDX (Syft), signature cosign et attestation SBOM.
  • Kyverno vérifie les signatures par clé cosign (la même clé publique que la CI pour nos images harbor.*/eai/* et pour le miroir ; la CI refuse de signer sans COSIGN_PRIVATE_KEY), impose non-root, rootfs en lecture seule, limites de ressources, interdit latest, impose gVisor/Kata dans le sandbox et les labels tenant/owner.

Pods​

  • runAsNonRoot, UID 10001, readOnlyRootFilesystem, capabilities.drop: [ALL], seccomp RuntimeDefault, Pod Security restricted.

Audit​

  • Événements d'audit chaînés par hash, export WORM vers le bucket object lock, transfert vers Wazuh (règles deploy/wazuh/rules).
  • Télémétrie : le collecteur OTel supprime prompts, complétions, en-têtes d'authentification et masque e-mails, IBAN, numéros de carte et clés eai_/sk-.