セキュアなアップロード

2 月の Discourse 2.4 リリース で追加された「Secure Uploads(安全なアップロード)」機能により、Discourse インスタンス内のすべてのアップロード(画像、動画、音声、テキスト、PDF、ZIP など)のセキュリティが大幅に向上します。

前提条件

サイト上で S3 アップロードが有効になっている必要があります。そのためには、以下の設定を入力済みであることが必須です。

  • S3 access key id
  • S3 secret access key
  • S3 region
  • S3 upload bucket

また、パブリックバケットポリシーが設定されていない S3 バケットを使用している必要があります。さらに、既存のすべてのアップロードが public-read S3 ACL を持っていることを確認してください。詳細は後述の「Secure Uploads の有効化」をご覧ください。

これらの前提条件を満たした後、「secure uploads」サイト設定を有効にできます。

Secure Uploads の有効化

:dragon: :warning: HERE BE DRAGONS(危険地帯) :warning: :dragon:

これは高度な機能であり、エンタープライズプラン以外のサポートは限定的です。専門知識を持つユーザーのみが有効化してください。


Secure Uploads を有効にするには、以下の手順に従ってください。

  1. S3 アップロードが設定されていることを確認してください。
  2. S3 バケットにパブリックバケットポリシーが設定されているか確認してください。設定されている場合は、追加の手順(手順 4)が必要です。
  3. uploads:sync_s3_acls rake タスクを実行してください。これにより、すべてのアップロードが S3 で正しい ACL を持つようになります。これは非常に重要です。手順 4 をこのタスク実行前に実行すると、一部のアップロードにアクセスできなくなる可能性があります。
  4. 手順 1 で確認したように、バケットにパブリックバケットポリシーが設定されている場合は、それを削除してください。
  5. 「secure uploads」サイト設定を有効にしてください。オプションとして、「prevent anons from downloading files(匿名ユーザーによるファイルのダウンロードを防止)」サイト設定を有効にすると、匿名ユーザーが公開投稿からの添付ファイルをダウンロードするのを防げます。これ以降のアップロードは、以下の条件に応じて安全なものとしてマークされる可能性があります。
  6. 過去のすべてのアップロードを分析し、安全なものとしてマークし直す場合は、uploads:secure_upload_analyse_and_update rake タスクを実行してください。

:exclamation: S3 バケットポリシーに関する注意 :exclamation:

アップロード先のバケットに パブリック バケットポリシーが設定されていないことを確認してください。パブリックバケットポリシーには、以下のような記述が含まれます。

{
    "Version": "2012-10-17",
    "Id": "ComputedBucketPolicy",
    "Statement": [
        {
            "Sid": "AllowWorldRead",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::your-bucket-name/*"
        }
    ]
}

ここで重要なのは、* に対して GetObject を許可している点です。これは、バケット内のすべてのファイルを誰でもダウンロードできることを意味します。また、ポリシーがパブリックである場合は、このラベルにも表示されます。

これらの設定は 変更しないでください。以下は「Block public access(パブリックアクセスのブロック)」タブの理想的な状態です。

機能の説明

Secure Uploads を有効にすると、Composer 経由でアップロードされたファイルは、以下の基準に基づいて「安全」または「安全でない」としてマークされます。

  • 「login required(ログイン必須)」サイト設定が有効な場合、すべてのアップロードが安全としてマークされ、匿名ユーザーはアクセスできなくなります。
  • プライベートメッセージ内で何かをアップロードした場合、それは安全としてマークされます。
  • プライベートカテゴリ内のトピック内で何かをアップロードした場合、それは安全としてマークされます。

S3 上のアップロードはプライベートな ACL を持つため、S3 上のファイルへの直接リンクは 403 アクセス拒否エラーを返します。安全なアップロードへのアクセスはすべて、S3 の 署名付き URL を介して行われます。ただし、これはユーザーには非表示です。アップロードが安全な場合、その参照は /secure-uploads/meta/ という Discourse URL 経由で行われます。

権限とアクセス制御

/secure-uploads/meta/ URL は、現在のユーザーがメディアにアクセスする権限を持っているかを確認し、許可されている場合は提供します。アップロードが作成されるとき、それが最初に現れる投稿がその「アクセス制御投稿」として設定され、すべての権限はその投稿に基づきます。

  • 「login required」サイト設定が有効な場合、匿名ユーザーが URL にアクセスすると常に 404 エラーが表示されます。
  • アクセス制御投稿がプライベートメッセージであるメディアにアクセスする場合、ユーザーはそのプライベートメッセージトピックの一部でなければメディアにアクセスできず、そうでない場合は 403 エラーが表示されます。
  • アクセス制御投稿がプライベートカテゴリ内のトピック内にあるメディアにアクセスする場合、ユーザーはそのカテゴリにアクセスする権限を持っている必要があります。そうでない場合は 403 エラーが表示されます。

/secure-uploads/meta/ URL を投稿やトピック間でコピーして使用するのは避けてください。Discourse フォーラム内では、ユーザーごとにアクセスレベルが異なるためです。新しいアップロードは常に Composer 経由で作成してください。Onebox やホットリンクされた画像も、安全なアップロードのルールを尊重します。サイト設定によるアップロード、絵文字、テーマのアップロードは、公開されている必要があるため、安全なアップロードの影響 を受けません

:warning: アクセス制御投稿が削除された場合、添付されたアップロードは アクセスできなくなります:warning:

安全なアップロードを含む投稿の移動

「アクセス制御投稿」を異なるセキュリティコンテキスト間で移動すると、添付されたアップロードのセキュリティ状態が変更される可能性があります。アップロードのセキュリティが変更される可能性のある状況は以下の通りです。

  • トピックのカテゴリを変更する。トピック内のすべての投稿を循環させ、アップロードのセキュリティステータスを更新します。
  • トピックを公開トピックとプライベートメッセージの間で変更する。上記と同じ処理を行います。
  • 投稿をあるトピックから新しい、または既存の別のトピックに移動する。ターゲットトピックに対して上記と同じ処理を行います。

メール内の安全なアップロード

メールへの安全な画像の埋め込みはデフォルトで有効です。さらに制御するために、以下のサイト設定を構成できます。

  • secure_uploads_allow_embed_images_in_emails:これを無効にすると、メール内の安全な画像が抹消されます。
  • secure_uploads_max_email_embed_image_size_kb:埋め込む安全な画像のサイズ上限です。デフォルトは 1MB で、メールが大きくなりすぎないようにします。最大値は 10MB です。email_total_attachment_size_limit_kb と連携して動作します。

安全な画像は、メールクライアントでの base64 URL サポートがまだ不安定であるため、メール添付ファイルとして追加され、cid: URL 形式を使用して埋め込まれます。

secure_uploads_allow_embed_images_in_emails が有効になっていない場合、または画像がサイズ制限を超えた場合は、安全な画像の代わりに以下が表示されます(埋め込まれていない安全な音声や動画も同様です)。

image

ホスト型顧客について

現時点では、Secure Uploads はエンタープライズプランの顧客のみが利用可能です。詳細については、お問い合わせください

「いいね!」 51

この機能については、@martin さん、多くの警告を表示するべきでしょう。これは :warning: 高度な機能であり、初心者には向きません。また、エンタープライズティア以外でのサポートには限りがあります。ご自身の専門知識をお持ちください。

「いいね!」 9

セキュリティはアバターを対象として設計されたものではありません。これは私たちが想定していたユースケースではありません。

「いいね!」 13

注意:S3 バケットを「すべてのパブリックアクセスをブロック」に設定するのは正しくありません

@genachka @AntiMetaman @Hugh_Roberts @znedw @Thamer

元投稿を修正します。インフラチームのメンバーである @schleifer と話した結果、「すべてのパブリックアクセスをブロック」設定を有効にするよう助言したのは誤りだったことを確認しました。S3 バケットでこの設定を無効にし、その後 uploads:sync_s3_acls を実行して ACL が正しいことを確認してください。その上で、カスタムアバターの設定を再度お試しください。

また、全員が確認すべき重要な点として、アップロード先のバケットにパブリックバケットポリシーが存在しないようにしてください。パブリックバケットポリシーには、以下のような記述が含まれます。

{
    "Version": "2012-10-17",
    "Id": "ComputedBucketPolicy",
    "Statement": [
        {
            "Sid": "AllowWorldRead",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::your-bucket-name/*"
        }
    ]
}

ここで重要なのは、* に対して GetObject を許可している点です。これは、バケット内のあらゆるファイルを誰でもダウンロードできることを意味します。ポリシーがパブリックである場合、このラベルも表示されます。

ご迷惑をおかけして申し訳ありません。@AntiMetaman さん、@schleifer も私もこのエラーを再現できませんでした。

S3/AWS の設定について、より詳しい情報を提供していただければ幸いです。

「いいね!」 7

@martin ありがとうございます。私の問題はそのエラーではなく、匿名ユーザーがページにアクセスできないことでした。アップロードバケットをプライベートに設定すると、そのエラーは発生しなくなり、アップロードできるようになります。私のサイトでは「ログイン必須」は設定していません。

当初から、バケット設定で「すべての公開アクセスをブロック」を有効にしたことはありませんでした。匿名ユーザーがトピックにアクセスして読み、セキュリティ付きの画像を表示できる必要があるとおっしゃるなら、もう一度試してみます。メディアにセキュリティを適用することで匿名ユーザーが画像を見られなくなるなら、添付ファイルのみをセキュリティ保護する方がよいでしょう。

参考までに、私は BackBlaze B2 と BunnyCDN を使用しています。現在のアップロードバケット設定は公開です:

「いいね!」 4

その通りです。プライベートにする必要があるものはすべてプライベートな ACL が設定され、プレシグネッド URL を使用しない限りアクセスできません。なお、バケットポリシーはパブリックではありません。また、ご指摘の通り「すべてのパブリックアクセスのブロック」設定はすべてチェックを外す必要があります。アップロードがセキュアかどうかを当方がどのように判断するかに関心がある場合は、すべてのルールは以下の場所にあります:discourse/lib/upload_security.rb at main · discourse/discourse · GitHub および discourse/app/models/post.rb at main · discourse/discourse · GitHub

BackBlaze については詳しくありません。申し訳ありません。表示されている設定がバケットポリシーにどう反映されるか確信が持てません。基本的には、バケットポリシーをパブリックにしたくなく、「すべてのパブリックアクセスのブロック」もオンにしたくありません。そうすることで、プライベートおよびパブリックの ACL を適切に設定できます。ログインが必須でない場合、PM やプライベートカテゴリに含まれていないトピックで行われたアップロードはパブリックであり、匿名ユーザーからアクセス可能になります。匿名ユーザーがアクセス可能なトピック内の画像は、セキュアであるべきではありません。

「いいね!」 5

セキュアメディアの実装はBackblazeと互換性がありません。プレサイン付きURLをサポートしていますか?

「いいね!」 1

@riking

はい、プレシグンド URL はサポートされています:https://help.backblaze.com/hc/en-us/articles/360047815993-Does-the-B2-S3-Compatible-API-support-Pre-Signed-URLs-

@martin

はい、バケットを公開からプライベートに変更することでこの動作になります。私はこれを行ってアップロードは可能になりましたが、匿名ではトピックを表示できませんでした。

「いいね!」 4

@martin clarification ありがとうございます。私のスクリーンショットのように S3 の設定を「Public」に保ち、すべてのチェックを外す(あなたが提案した通り)ことで、カスタムアバターやプロフィール画像が正常に動作することを確認できました。また、トピックのセキュリティが保護されたアップロードも引き続き正常に動作しています。ありがとうございました!

「いいね!」 4

今週この PR をマージしましたので、オリジナル投稿にこれらの詳細を追加します:


メールに安全な画像を埋め込めるようにするには、以下のサイト設定を構成してください:

  • secure_media_allow_embed_images_in_emails:有効にすると、画像を削除する代わりに安全な画像をメールに埋め込みます。
  • secure_media_max_email_embed_image_size_kb:埋め込む安全な画像のサイズ上限です。デフォルトは 1MB で、メールが大きくなりすぎないようにします。最大値は 10MB です。email_total_attachment_size_limit_kb と連携して動作します。

安全な画像はメールの添付ファイルとして追加され、cid: URL 形式を使用して埋め込まれます。これは、メールクライアントにおける base64 URL のサポートがまだ不安定であるためです。

secure_media_allow_embed_images_in_emails が有効になっていない場合、または画像がサイズ制限を超えた場合は、安全な画像(埋め込まれない安全な音声や動画も含む)の代わりに以下のような表示になります:

image

「いいね!」 10

以前の投稿への追記;この PR より:

セキュリティを強化したメディア画像の埋め込みをデフォルトで有効化しました。

「いいね!」 5

安全なメディアアップロードの設定(OP ガイドに従って)を行った後、添付ファイルや画像などは問題なく動作しますが、トピックの添付ファイルではないアップロード(サイトロゴやプロフィールのアバターなど)では、Discourse で「アクセスが拒否されました」というポップアップが表示されます。
設定を間違えたのでしょうか?

トピックをお読みください。あなたの問題は、この投稿の数件上に記載されています。

「いいね!」 3

私はすべて注意深く読みました。上記の投稿で具体的に何を意味されているのか、お知らせください。この問題は確認できません。
編集:
行間を読むと、このスレッドは以前はもっと長かったようですが、いくつかの重要な返信が削除されているようです。存在しない返信への言及や、スレッド内に表示されないスクリーンショットの言及もあります。
もし私の理解が正しければ、S3 バケットに対して「パブリックアクセスを一切ブロックしない」設定を推奨されているということでしょうか。それを確認したいのと、それが安全かどうかお伺いしたいです。

「いいね!」 1

正しいです。

元の投稿は確かに削除されましたが、問題と解決策は残っています。

「いいね!」 6

セキュアメディアを使用する際にバグを見つけました:https://meta.discourse.org/t/knowledge-base-plugin/115288
ナレッジベース内の添付ファイルへのリンクが開かない(404 ページにリダイレクトする)問題が発生しています。ただし、新しいウィンドウで強制的に開く場合は例外です。
さらに奇妙なことに、ナレッジベース項目に関連付けられた Discourse トピックからは、全く同じ添付ファイルに問題なくアクセスできます。

追記:
同じバグが、返信から別の返信へ添付ファイルのリンクをコピーする際にも発生します。リンクは当然ながら同一ですが、元の返信からのみ機能し、新しいウィンドウで強制的に開かない限り動作しません。

「いいね!」 1

S3 を使用しない場合、セキュアなメディアはどうなるのでしょうか?
現在、アップロードされたファイルへの直接リンクがわかれば、ログインなしでファイルをダウンロードできてしまうようです。これはセキュリティ上の問題と言えます。

セキュアメディアは S3 を必須とします。
この機能全体は、直接リンクの共有やアクセスを不可能にするために開発されました。

「いいね!」 11

これは素晴らしい機能です。開発してくださりありがとうございます。S3 の無料の互換代替ソリューションである Minio は、ACL をサポートしていませんし、今後もサポートする予定もありません。彼らの主張は正当なもので、ACL は有用な機能ではなく、2 回目の書き込み操作を必要とするためパフォーマンスに悪影響を及ぼすという点です。Discourse とのセキュアなメディアアップロードは機能します。uploads:secure_upload_analyse_and_update タスクは最終ステップでエラーを発生させますが、これを無視できるようです。とはいえ、Discourse が ACL 呼び出しを行う必要がある理由はあるのでしょうか?

「いいね!」 3

はい、OP で設定されているように S3 バケットは非公開であるため、セキュアでないアップロードは ACL を公開に設定する必要があります。一方、セキュアなアップロードは ACL を非公開に設定し、S3 URL を直接アクセス可能にする必要があります。現時点では、この動作を変更する予定はないと考えています。S3 の代替手段として ACL を完全に使用しないようにするには、相当な作業が必要になるでしょう。

「いいね!」 7