DjangoのSECRET_KEY_FALLBACKSを使ってSECRET_KEYをローテーションする

Djangoの小ネタです。

SECRET_KEY に入れた値などを変更したい場合、素直に SECRET_KEY の値を差し替えてしまうとユーザのログイン情報やセッションの値がクリアされてしまい、利用するユーザに影響が出てしまいます。

この対応として Django 4.1 から settings.SECRET_KEY_FALLBACKS が導入されました。

https://docs.djangoproject.com/ja/4.1/ref/settings/#std-setting-SECRET_KEY_FALLBACKS

settings.SECRET_KEY_FALLBACKS にはリストが入ります。名前の通りSECRET_KEY を使ったチェックのフォールバックとして機能するため、ユーザへの影響を小さく留めることができます。

なお、本記事の動作確認は Django 6.0.2 で行っています。

使い方

  1. 新しいSECRET_KEYを設定し、古いSECRET_KEYの値をSECRET_KEY_FALLBACKS に導入する
  2. SESSION_COOKIE_AGE(デフォルト: 2週間), PASSWORD_RESET_TIMEOUT(デフォルト: 3日)のうち、長いほうの期間が経過するまで SECRET_KEY_FALLBACKS を維持する
  3. 期間が過ぎたことを確認してから、SECRET_KEY_FALLBACKS を空にする(または削除する)

django.core.signing で有効期限なしの署名を使っている場合、SECRET_KEY_FALLBACKS から削除した時点で BadSignature が発生します。該当箇所がないか事前に確認してください。

注意点

ドキュメントにも記載ありますが、SECRET_KEY_FALLBACKS はリストのため複数の古いキーを保持できます。

検証時はリストの先頭から順にキーを試すため、値が多いほどオーバーヘッドが増加します。古いキーは期間が過ぎ次第、速やかに削除してください。