--- title: Rotation des clés icon: rotate --- Twenty possède deux familles de clés indépendantes : * **Clés de signature JWT** — paires de clés asymétriques ES256 (avec balise `kid`) stockées dans `core."signingKey"`, utilisées pour signer et vérifier les jetons d’accès / de rafraîchissement. * **Clé de chiffrement au repos** — `ENCRYPTION_KEY`, utilisée pour chiffrer les jetons OAuth, les variables d’application, les clés privées de clés de signature, les valeurs de configuration sensibles et les secrets TOTP à l’intérieur d’une enveloppe `enc:v2:`. `APP_SECRET` est un secret hérité conservé pour la rétrocompatibilité : lorsque `ENCRYPTION_KEY` n’est pas défini, il agit comme mécanisme de secours pour le chiffrement au repos / le cookie de session, et il continue de vérifier les jetons d’accès HS256 préexistants. Il sera déprécié. ## Clés de signature JWT Chaque clé contient une `publicKey` (conservée indéfiniment afin de pouvoir vérifier les jetons émis précédemment), une `privateKey` chiffrée (utilisée uniquement tant que la clé est actuelle), un indicateur `isCurrent` (exactement une ligne à la fois) et un champ `revokedAt` facultatif. ### Faire pivoter la clé actuelle Définissez `SIGNING_KEY_ROTATION_DAYS` pour l’activer : une tâche cron quotidienne émet alors une nouvelle clé actuelle dès que l’ancienne dépasse ce seuil. Les clés précédentes ne sont *pas* révoquées, donc les jetons signés avec celles-ci restent vérifiables. Laissez la variable non définie pour désactiver la rotation automatique. La rotation automatique est disponible à partir de la v2.6+. ### Révoquer une clé (fuite / urgence uniquement) **Settings → Admin Panel → Signing keys → Revoke** sur une ligne non actuelle. Efface le matériel privé chiffré, définit `revokedAt` et rejette chaque jeton existant signé avec ce `kid`. ## Faire pivoter `ENCRYPTION_KEY` La commande `secret-encryption:rotate` décrite ci-dessous est fournie à partir de la v2.6+. Chaque valeur chiffrée est encapsulée sous la forme `enc:v2:\:\`, où `\` est un préfixe hexadécimal sur 8 caractères dérivé de la clé brute. La rotation est en ligne et reprenable. 1. **Générez une nouvelle clé** : `openssl rand -base64 32`. 2. **Configurez les deux clés côte à côte** dans `.env`, puis redémarrez : ```ini ENCRYPTION_KEY=NEW_VALUE FALLBACK_ENCRYPTION_KEY=OLD_VALUE ``` Les nouvelles écritures utilisent la nouvelle clé, les lignes existantes se déchiffrent toujours via la clé de secours. 3. **Rechiffrez les lignes existantes** : ```bash docker exec -it {server_container} yarn command:prod secret-encryption:rotate ``` La commande parcourt six sites (`connected-account-tokens`, `application-variable`, `application-registration-variable`, `signing-key-private-keys`, `sensitive-config-storage`, `totp-secrets`). Un filtre SQL ignore les lignes déjà sur le nouveau `\`, de sorte que la commande est idempotente : interrompez-la et relancez-la si nécessaire. Quitte avec un code de sortie non nul si une ligne échoue — relancez pour réessayer. | Option | Description | | ---------------------------------------- | ----------------------------------------------------------------- | | `-s, --site \` | Limiter à un seul site. | | `-b, --batch-size \` | Lignes par lot (valeur par défaut `200`, maximum `5000`). | | `-d, --dry-run` | Déchiffrer + rechiffrer en mémoire, ignorer la commande `UPDATE`. | 4. **Supprimez la clé de secours** une fois que `--dry-run` n’affiche plus aucune ligne restante : supprimez `FALLBACK_ENCRYPTION_KEY` et redémarrez. ## Prise en charge héritée de `APP_SECRET` Les instances plus anciennes qui n’ont jamais défini `ENCRYPTION_KEY` utilisent `APP_SECRET` comme clé de chiffrement au repos (et comme secret de cookie de session, dérivé de celle-ci). Ce chemin est conservé pour la rétrocompatibilité mais est **déprécié** — définissez une `ENCRYPTION_KEY` dédiée et suivez la procédure de rotation ci-dessus pour migrer. `APP_SECRET` reste lui-même utilisé pour vérifier les anciens jetons d’accès HS256.