Aller au contenu principal

Patterns

Stratégie de rotation des clés API

Deux clés actives, rotation 90 jours, dual-validation

Une clé API qui ne tourne pas est une clé compromise en sursis. Le pattern Scell.io : chaque tenant peut maintenir 2 clés `sk_live_*` simultanément actives (clé courante + clé de rotation). Workflow de rotation tous les 90 jours : (1) générer une nouvelle clé via `POST /api/v1/api-keys`, (2) déployer la nouvelle clé dans tous les environnements (CI, prod, secrets manager), (3) attendre 7 jours que la nouvelle clé soit utilisée (vérifier via `GET /api/v1/api-keys/{id}/usage`), (4) révoquer l'ancienne via `DELETE /api/v1/api-keys/{old_id}`. La fenêtre de chevauchement évite l'outage si un service oublie le rolling. Pour les secrets compromis (incident), bypass la fenêtre : révoquer immédiatement et déclencher un re-deploy. Ne JAMAIS partager une clé entre tenants ou environnements ; ne JAMAIS hardcoder dans le code source ; toujours via env var ou secret manager (cf. pattern secret-management).

À retenir

  • 2 clés actives simultanément (courante + rotation)
  • Rotation programmée tous les 90 jours
  • Fenêtre de chevauchement de 7 jours minimum
  • Vérifier l'usage via GET /api/v1/api-keys/{id}/usage avant révocation
  • Incident : révocation immédiate, pas de fenêtre

Exemple de code

// Cron job mensuel — génération clé de rotation
import { ScellClient } from '@scell/sdk';
import { vault } from './vault';

async function rotateScellKey() {
  const scell = new ScellClient(await vault.read('scell/current'));

  // 1. Generate new key
  const newKey = await scell.apiKeys.create({ label: `rotation-${Date.now()}` });

  // 2. Push to vault as 'next' (services should fall back to 'next' first)
  await vault.write('scell/next', newKey.secret);

  // 3. Trigger rolling re-deploy across services
  await ci.triggerWorkflow('rolling-deploy', { reason: 'scell-key-rotation' });

  // 4. After 7 days (separate cron), promote 'next' to 'current' and revoke old
  // scheduleAfter('7 days', async () => {
  //   await vault.copy('scell/next', 'scell/current');
  //   await scell.apiKeys.delete(oldKeyId);
  // });
}

Voir aussi

Vos préférences cookies

Nous utilisons des cookies pour améliorer votre expérience. Les cookies essentiels sont toujours actifs. Politique cookies.