機密設定の暗号化
CROWI_ENCRYPTION_KEY による機密設定の暗号化
Crowi は OAuth シークレットや AWS のクレデンシャル、SMTP パスワード、
Slack トークンといった 機密性の高い設定値を、保存時に暗号化 できます。
暗号化を有効にするには、マスターキー CROWI_ENCRYPTION_KEY を設定します。
重要:
CROWI_ENCRYPTION_KEYは任意ですが、本番運用では設定を 強く推奨 します。未設定でもアプリは動作しますが、機密値が MongoDB に 平文のまま保存されます (後述の legacy モード)。
暗号化の対象
暗号化されるのは MongoDB の Config コレクションのうち、機密扱いとして
登録されたキーだけです。
1. プラグインの機密フィールド (主な対象)
ストレージ・メール・検索などサードパーティ連携のクレデンシャルは、その
プラグインの設定名前空間 (crowi:plugin:<プラグイン名>:<フィールド>)
に保存されます。プラグインが @sensitive マーカーを付けたフィールドは
起動時に自動で機密リストへ登録され、暗号化経路をたどります。例:
| 名前空間:キー | 内容 |
|---|---|
crowi:plugin:@crowi/plugin-aws:secretAccessKey | AWS クレデンシャル (S3 ストレージ / SES メール) |
crowi:plugin:@crowi/plugin-mail-smtp:password | SMTP パスワード |
crowi:plugin:@crowi/plugin-mail-resend:apiKey | Resend API キー |
2. コア設定に残る機密キー
| 名前空間:キー | 内容 |
|---|---|
notification:slack:clientSecret / token | 旧 Slack 連携のシークレット / トークン |
外部サインイン (Google など) やストレージ・メールの認証情報は、コア設定では
なく それぞれのプラグインの名前空間 (crowi:plugin:<プラグイン名>:<フィールド>)
に保存され、同じ仕組みで暗号化されます。v1 から移行する場合の注意は
v1 からの移行 を参照してください。
Note: ユーザーのパスワードは別途 bcrypt でハッシュ化されており、 ここでの暗号化対象には含まれません。個人アクセストークンも、等価検索が 必要なため別の仕組みです。
マスターキーの生成
CROWI_ENCRYPTION_KEY は base64 エンコードされた 32 バイト の値で
なければなりません (デコード後ちょうど 32 バイト = AES-256 の鍵長)。
次のいずれかで生成します。
openssl rand -base64 32生成した値を .env に設定します。
CROWI_ENCRYPTION_KEY="生成された base64 文字列"設定後に API を再起動すると、機密値の暗号化が有効になります。
暗号化の仕組み
暗号化は AES-256-GCM で、暗号化された値には enc:v1: というプレフィックスが
付きます。データベースを覗いたときに、その値が暗号化済みかどうかはこの
プレフィックスで判別できます。
機密キーは保存するときに自動で暗号化され、読み込むときに自動で復号されます。 運用者が明示的に何かを実行する必要はありません。
legacy モード (キー未設定時)
CROWI_ENCRYPTION_KEY が設定されていない、またはデコード後 32 バイトに
ならない場合、Crowi は legacy モード で動作します。
- 機密値は 平文のまま MongoDB に保存されます。
- 起動時に警告ログが出力されます。
- 暗号化は「ベストエフォート」として扱われるため、鍵が無くてもアプリが クラッシュすることはありません。
また、暗号化を有効にした後でも、まだ暗号化されていない (= enc:v1:
プレフィックスのない) 平文の行はそのまま読み込めます。decrypt は
プレフィックスのない値を素通しするため、legacy データと暗号化データが
混在していても動作します。
既存の平文データを再暗号化する
暗号化を後から有効にした場合、それ以前に保存された機密値は平文のまま
残っています。これらをまとめて暗号化し直すには、管理画面の暗号化
設定画面 (/admin/crypto) を使います。
状態の確認
/admin/crypto を開くと、マスターキーが設定されているか、暗号化済みの値と
平文のまま残っている値がそれぞれ何件あるか、どの機密キーがどちらの状態かが
表示されます。
再暗号化の実行
画面から再暗号化を実行すると、平文のまま残っている値だけが暗号化されます。
- マスターキーが未設定の場合はエラーになります。先に
CROWI_ENCRYPTION_KEYを設定してください。 - すでに暗号化済みの値はスキップされるため、何度実行しても安全です。
- 実行後に、書き換えた件数・すでに暗号化済みだった件数・値が存在しなかった 件数が表示されます。
Tip: 再暗号化は何度実行しても安全 (冪等) です。新しい OAuth 設定を 平文で投入してしまったときなど、必要に応じていつでも実行できます。
鍵のローテーションについて
現状の実装では、CROWI_ENCRYPTION_KEY は単一の固定鍵を前提と
しています。鍵を別の値に変更すると、それ以前に暗号化された値は
復号できなくなります (GCM の認証タグ検証に失敗します)。鍵を変更する
必要がある場合は、変更前に該当の機密設定を管理画面から再入力できるよう
準備しておいてください。