ホスト間の移行時にユーザーセッションを維持する

こんにちは!

Discourse インスタンスを新しいホスティング環境へ移行する準備を進めています。計画としては、旧サイトを読み取り専用モードに設定し、バックアップを取得してから新しいホスティング環境へ移動させ、DNS 設定(TTL を短く設定)を更新しながらリストアを行うというものです。この手順は、こちらや他のガイドを参考にしています。

このプロセスのドライランを /etc/hosts ファイルをいじることで DNS 更新をシミュレートし(ブラウザでも DNS over HTTPS も無効化)、テストを行ってきました。現状、特に問題なく動作しています。

しかし、旧サイトではブラウザを完全に閉じ、移行完了後にのみ新サイトのブラウザを開くように注意しているにもかかわらず、ログイン状態が保持されません。

もちろん、移行を機にサイトメンバー全員がログアウトされてしまうのは避けたいところです。どこを確認すべきか、あるいは何が不足しているのでしょうか?

現在テストしているユーザーは管理者権限を持ち、2 段階認証(2FA)を使用しています。また、Discourse コンテナは SSL を終端する Nginx の背後に配置されています。これが問題に関連する可能性はありますか?

ご教示いただければ幸いです。よろしくお願いいたします!

私もこの問題に直面しており、解決したいと考えています。

何かヒントがあれば幸いです。

2FA(二要素認証)なしでテストアカウントを作成してみるつもりです。それが何か関係あるかもしれません。サイトメンバーのほとんどが2FAを使っていないので、もし問題がそのセッションの消失だけなら、許容範囲かもしれません。

また、ソースサーバーとデスティネーションサーバーがNTPと同期しているか確認します。今はせいぜい数秒のずれしかないと思いますが。

それ以外には、認証トークンに何が含まれていて、何が問題を引き起こしているのかをソースコードから突き止めるしかありませんね… :grimacing:

ユーザーにこの変更と、ログアウトされて再ログインが必要になることを伝えるのが最善です。

各サーバーには SSL が適用された独自の署名があります。

サーバー設定を変更しようとするよりも、ユーザーに再ログインしてもらう方がはるかに手間がかかりません。

ご迷惑をおかけして申し訳ありませんが、これはより良い方向のための変更であることをお伝えください。

しかし、実際にはそうなのでしょうか?

セッションクッキーは、SSL の「署名」によってどのように影響を受けますか(特に、私のケースでは、新旧のホストが同じドメイン名で、同じ SSL 証明書ファイルを使用している場合)?

メンバーに謝罪すること自体には問題ありません(:slightly_smiling_face:)が、以下のいくつかの望ましくない副作用を招く可能性を考えると、そのような状況は避けたいと考えています。

  1. メンバーが再度ログインしなくなり、将来のフォーラムへの参加意欲が低下する
  2. メンバーがパスワードを忘れ、リカバリのサポートを必要とする
  3. メンバーがパスワードを忘れ、新しいアカウントを作成する。これにより、フォーラムに多くの「ゾンビアカウント」が残り、ユーザーノートや投稿履歴などが欠落したままの重複・混乱した同一人物のアカウントが多数発生する

SSL の設定は、Discourse の前面(hosts ファイルのハックを含む)では正常に動作しています。これは、ロードバランサーが問題なく動作していることからも明らかな通りです。この構成では、SSL は Nginx で終端されるため、Discourse 自体は SSL の存在を認識していないはずです。

別の質問として、「Discourse サーバーを新しい IP アドレスに移行する際、すべてのユーザーをログアウトさせずに移行することは可能か?」という点です。私は可能だと想定していましたが、もしかしたらその前提が間違っていたのかもしれません… :frowning:

フォーラムセッションがバックアップとリストアを生き延びたことは確かにあります。ここでは何が起きているのか、本当にわかりません :frowning:

セッションクッキーは、ランダムに生成された秘密鍵を使用して暗号化されており、デフォルトでは Redis に保存されます。Redis のデータはバックアップに含まれないため、サイトを新しいサーバーに復元すると、新しい秘密鍵が再生成されます。

環境変数 DISCOURSE_SECRET_KEY_BASE を使用して、秘密鍵を手動で設定できます。これを app.yml ファイルに記述することで、セッションを維持しようとするには、以下のような手順を試してみてください。

  1. 既存のサーバーでコンソールに入り、Redis から秘密鍵を取得します。

    pry(main)> GlobalSetting.safe_secret_key_base
    => "5fb9dc98be368599e0a..."
    
  2. 旧サーバーの app.yml の env: セクションに、(1) で取得した値を使用して DISCOURSE_SECRET_KEY_BASE を追加し、アプリを再ビルドします。理論的には、すべてが正常に進めば、Discourse は app.yml の値を使用するようになり、ユーザーセッションが維持されます。環境変数が使用されているか確認するには、以下を実行します。

    GlobalSetting.secret_key_base
    
  3. 新サーバーの app.yml に同じ SECRET_KEY_BASE が設定されていることを確認してください。バックアップを復元すると、ユーザーセッションが維持されるはずです。

この手順はテストしていないため、本番環境のフォーラムで使用する場合は、事前に必ずテストしてください!

補足:複数の Discourse インスタンス間で秘密鍵を共有しては 絶対にいけません。秘密鍵が入手されると、セッションクッキーを復号化・改ざんされる可能性があり、深刻なセキュリティ上の問題を引き起こす恐れがあります。

素晴らしいですね。サンドボックス環境で試してみます。うまくいったかどうか後で報告できるか確認します :slight_smile:

承知しました。バックアップ時にこのキーをエクスポートするオプションを機能リクエストとして提出すべきか考えています。数千のアカウントを持つサイトにおいて、すべてのセッションが失われることは「非常に望ましくない事態」だと考えます。移行の練習を通じてこの問題が明らかになりましたが、マシンや Docker インスタンスが何らかの理由で失われた場合、キーも失われ、同じくセッションの喪失に直面することになるでしょう。

この「機能」について、移行に関するトピックにも注記があると良いでしょう:Move your Discourse Instance to a Different Server

セキュリティと利便性のバランスを慎重に取る必要があります。

現在、Discourse のバックアップが盗まれた場合、フォラムのすべてのデータが漏洩しますが、ライブフォラムにログインすることはできません。パスワードはハッシュ化され、API キーもハッシュ化され、セッションクッキーは暗号化されています。

もしシークレットをバックアップに含めると、バックアップを入手した誰でもライブフォラムにアクセスでき、フィッシングや詐欺などの行為が可能になってしまいます。

素晴らしいですね!Redis シークレットキーから app.yml シークレットキーへの移行方法を Meta でトピックとして作成することに完全に賛成です。「別のサーバーへ移動する」トピックからリンクさせることもできます。

私見ですが、デフォルトのバックアップのセキュリティも強化すべきだと考えます。パスワードやセッションがハッシュ化され保護されていても、プライベートメッセージなどに含まれる他の多くのデータは依然として機密性を保つ必要があります。特に、当コミュニティフォーラムでは、電話番号や住所を公開場所に記載するのではなく、連絡先の交換や売買・受け取りの調整のためにプライベートメッセージの利用を推奨しています。

私のバックアップへの取り組み方は、インスタンスにアクセスしてバックアップを生成し、直ちに gpg を使って公開鍵で暗号化するというものです。これにより、対応する秘密鍵を持たない者にはバックアップは無意味なものになります。その秘密鍵はサーバーから離して保管し、パスフレーズで保護しています。

とはいえ、セッションの秘密鍵が変わらないのであれば、一度だけバックアップすれば十分です。そのため、それを行うためのシンプルな手順があればよく、おそらく上記で説明されている通りでしょう。

試してみますので、そのトピックを作成できるか確認いたします :slight_smile:

非常に役立ちました、@david さん、ありがとうございます!

Discourse はプライベートメッセージを提供していません。その機能は「Personal Messages(個人メッセージ)」と呼ばれます。この区別は非常に重要であり、プライバシーの暗示はありません。

管理者は、暗号化が使用されていない限り、サイトのすべての PM を既に読むことができます。

なるほど。しかし、会員がプライベートメッセージを使って個人情報を共有したり、公開したくない事項をやり取りしたりする可能性が変わるわけではありません。そのため、可能な限りこのデータを保護することが重要です。

はい、私たちが利用するすべてのサイトの管理者を信頼する必要もあります。ProtonMail のようなサイトでも同様です

少し話題から外れますが、本格的な「プライベート」メッセージについては、Discourse Encrypt (deprecated) が参考になるかもしれません。暗号化されたプライベートメッセージのバックアップが漏洩したり盗まれたりしても、攻撃者には読み取れません。

(ただし、おっしゃる通り、管理者を信頼しているという前提は残ります)

@david - 以下の投稿を確認し、問題なければ分割して howto に移動してもらえますか?(私はそこでトピックを作成できません。それに加えて、Akismet が投稿を隠してしまったので、それも修正が必要です :blush:

@david - 問題を解決してくださり、アドバイスもいただき、本当にありがとうございます。この情報が他の皆様のお役に立てれば幸いです。セッションを維持したまま移行できるのは、私たちにとって大きな安堵です :partying_face: