보안 업로드

2월에 출시된 Discourse 2.4에는 Secure Uploads 기능이 추가되었습니다. 이 기능은 Discourse 인스턴스 내의 모든 업로드(이미지, 비디오, 오디오, 텍스트, PDF, ZIP 등)에 대해 더 높은 수준의 보안을 제공합니다.

사전 요구 사항

사이트에서 S3 업로드가 활성화되어 있어야 하며, 다음 설정을 채워 넣어야 합니다:

  • S3 액세스 키 ID
  • S3 시크릿 액세스 키
  • S3 리전
  • S3 업로드 버킷

또한 공개 버킷 정책(Public bucket policy)이 없는 S3 버킷을 사용해야 하며, 기존 모든 업로드에 public-read S3 ACL이 설정되어 있는지 확인해야 합니다. 자세한 내용은 아래 “Secure Uploads 활성화” 섹션을 참고하세요.

이러한 사전 요구 사항이 충족되면 “secure uploads” 사이트 설정을 활성화할 수 있습니다.

Secure Uploads 활성화

:dragon: :warning: 위험 구역 :warning: :dragon:

이것은 고급 기능이며, Enterprise 티어 외에는 지원이 제한적일 수 있습니다. 전문가 사용자만 Secure Uploads를 활성화하세요.


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” 사이트 설정이 활성화되어 있으면 모든 업로드가 보안으로 표시되며,匿名用户는 접근할 수 없습니다.
  • 개인 메시지(Personal Message) 내에서 무언가를 업로드하면 보안으로 표시됩니다.
  • 비공개 카테고리 내의 토픽에서 무언가를 업로드하면 보안으로 표시됩니다.

S3의 업로드는 private ACL을 가지므로, S3 파일에 대한 직접 링크는 403 접근 거부 오류를 발생시킵니다. 보안 업로드에 대한 모든 접근은 S3 presigned URL을 통해 이루어집니다. 그러나 사용자에게는 이것이 숨겨지며, 업로드가 보안이면 /secure-uploads/meta/ Discourse URL을 통해 참조됩니다.

권한 및 접근 제어

/secure-uploads/meta/ URL은 현재 사용자가 미디어에 접근할 수 있는지 여부를 결정하고, 허용되면 해당 미디어를 제공합니다. 업로드가 생성될 때, 해당 업로드가 처음 나타나는 게시물이 “접근 제어 게시물(access control post)”로 설정되며, 모든 권한은 해당 게시물을 기반으로 합니다.

  • “login required” 사이트 설정이 활성화되어 있으면,匿名用户는 URL에 접근할 때 항상 404 오류를 받게 됩니다.
  • 접근 제어 게시물이 개인 메시지인 미디어에 접근하려면, 사용자는 해당 개인 메시지 토픽의 구성원이어야 하며, 그렇지 않으면 403 오류를 받게 됩니다.
  • 접근 제어 게시물이 비공개 카테고리 내 토픽에 있는 미디어에 접근하려면, 사용자는 해당 카테고리에 대한 접근 권한이 있어야 하며, 그렇지 않으면 403 오류를 받게 됩니다.

/secure-uploads/meta/ URL을 게시물과 토픽 사이에서 복사해 붙여넣는 것은 지혜롭지 않습니다. Discourse 포럼 내의 사용자는 서로 다른 접근 권한을 가지고 있기 때문입니다. 새로운 업로드는 항상 Composer를 통해 생성해야 합니다. Oneboxes와 핫링크된 이미지도 Secure Uploads 규칙을 따릅니다. 사이트 설정 업로드, 이모지, 테마 업로드는 공개되어야 하므로 Secure Uploads의 영향을 받지 않습니다.

:warning: 접근 제어 게시물이 삭제되면, 첨부된 업로드는 더 이상 접근할 수 없게 됩니다. :warning:

Secure Uploads가 포함된 게시물 이동

“접근 제어 게시물”을 다른 보안 컨텍스트 사이에서 이동하면 첨부된 업로드가 보안으로 변경되거나 보안이 해제될 수 있습니다. 업로드의 보안 상태를 변경할 수 있는 상황은 다음과 같습니다:

  • 토픽 카테고리 변경. 토픽 내 모든 게시물을 순회하여 업로드 보안 상태를 그에 따라 업데이트합니다.
  • 공개 토픽과 개인 메시지 사이에서 토픽 변경. 위와 동일한 작업을 수행합니다.
  • 게시물을 다른 기존 또는 새 토픽으로 이동. 대상 토픽에 대해 위와 동일한 작업을 수행합니다.

이메일 내 Secure Uploads

이메일에 보안 이미지 임베드는 기본적으로 활성화되어 있습니다. 추가 제어를 위해 다음 사이트 설정을 구성할 수 있습니다:

  • secure_uploads_allow_embed_images_in_emails: 이메일 내 보안 이미지를 삭제(마스킹)하려면 이 설정을 비활성화합니다.
  • secure_uploads_max_email_embed_image_size_kb: 임베드할 보안 이미지의 크기 상한으로, 기본값은 1mb이며 이메일이 너무 커지지 않도록 합니다. 최대 10mb입니다. email_total_attachment_size_limit_kb와 함께 작동합니다.

보안 이미지는 이메일 첨부 파일로 추가되고 cid: URL 형식을 사용하여 임베드됩니다. 이는 이메일 클라이언트에서 base64 URL 지원이 여전히 불안정하기 때문입니다.

secure_uploads_allow_embed_images_in_emails가 활성화되어 있지 않거나 이미지가 크기 제한을 초과하기 시작하면, 보안 이미지(임베드되지 않는 보안 오디오 및 비디오 포함) 대신 다음을 보게 됩니다:

image

호스팅 고객

현재 Secure Uploads는 Enterprise 플랜 고객에게만 제공됩니다. 자세한 내용은 우리에게 문의하세요.

52개의 좋아요

이 기능은 :warning: 고급(ADVANCED) 기능으로, 심장이 약한 분들에게는 적합하지 않으므로 @martin 님, 이 기능 주변에 경고 표시를 많이 두는 것이 좋을 것 같습니다. 또한 엔터프라이즈 티어 외에는 지원 범위에 한계가 있으니, 관련 전문 지식을 직접 갖추고 사용해 주세요.

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를 허용하고 있다는 점으로, 이는 버킷 내의 모든 것을 아무나 다운로드할 수 있음을 의미합니다. 이 라벨은 해당 정책이 공개(Public)인지도 표시합니다:

이로 인해 혼란을 드려 죄송합니다. @AntiMetaman, @schleifer와 저는 이 오류를 재현하지 못했습니다:

S3/AWS 설정에 대해 더 많은 정보를 제공해 주시면 도움이 될 것입니다.

7개의 좋아요

@martin 감사합니다. 제 문제는 그 오류가 아니라, 익명 사용자가 페이지에 접근하지 못하는 것이었습니다. 업로드 버킷을 비공개로 설정하면 더 이상 그 오류가 발생하지 않고 업로드도 가능합니다. 제 사이트에는 로그인 필수 설정이 되어 있지 않습니다.

처음부터 버킷 설정에서 '모든 공개 접근 차단’을 활성화한 적이 없습니다. 익명 사용자는 여전히 토픽에 접근하고, 내용을 읽으며, 보안 이미지도 볼 수 있어야 한다는 말씀이시라면 다시 시도해 볼 수 있습니다. 미디어에 보안을 추가하는 것이 익명 사용자가 해당 이미지를 보는 것을 막는다면, 첨부파일만 보안 처리하는 쪽을 선호합니다.

도움이 된다면, 저는 BackBlaze B2와 BunnyCDN을 사용하고 있습니다. 현재 업로드 버킷 설정은 공개 상태입니다:

4개의 좋아요

네, 대략적인 내용은 그렇습니다. 비공개로 유지되어야 하는 항목에는 비공개 ACL이 설정되며, 사전 서명된 URL(presigned URL)을 사용하지 않는 한 액세스할 수 없습니다. 참고로 버킷 정책은 _공개(Public)_가 아닙니다. 그리고 네, 모든 “공개 액세스 차단(Block public access)” 설정은 해제되어 있어야 합니다. 업로드가 보안으로 결정되는 방식을 알고 싶으시다면 모든 규칙은 여기 discourse/lib/upload_security.rb at main · discourse/discourse · GitHub 와 여기 discourse/app/models/post.rb at main · discourse/discourse · GitHub 에 있습니다.

BackBlaze에 대해서는 잘 모르겠습니다, 죄송합니다. 표시된 설정이 버킷 정책으로 어떻게 변환되는지 정확히 알 수 없습니다. 기본적으로 버킷 정책을 공개(Public)로 설정하지 않고, "모든 공개 액세스 차단"도 켜지 않는 것이 좋습니다. 이렇게 하면 비공개 및 공개 ACL을 적절하게 설정할 수 있습니다. 로그인 요구 사항이 없다면, PM이나 비공개 카테고리에 있지 않은 토픽에서 이루어진 모든 업로드는 공개되어야 하며 익명 사용자가 액세스할 수 있어야 합니다. 익명 사용자가 액세스할 수 있는 토픽에서 이미지는 보안(secure) 상태가 아니어야 합니다.

5개의 좋아요

보안 미디어 구현은 Backblaze와 호환되지 않습니다. 사전 서명된 URL을 지원하나요?

1개의 좋아요

@riking

네, 사전 서명된 URL(Pre-signed URL)을 지원합니다: https://help.backblaze.com/hc/en-us/articles/360047815993-Does-the-B2-S3-Compatible-API-support-Pre-Signed-URLs-

@martin

네, 버킷을 공개에서 비공개로 변경하면 됩니다. 이렇게 했더니 업로드는 가능했지만, 비로그인 상태에서는 게시물을 볼 수 없었습니다.

4개의 좋아요

@martin 설명해 주셔서 감사합니다. 스크린샷과 같이 S3 설정을 Public으로 두고 모든 옵션을 해제한 상태(당신이 제안하신 방법)에서 커스텀 아바타/프로필 이미지가 마침내 정상 작동하는 것을 확인했습니다. 또한 토픽 보안 업로드 기능도 여전히 정상적으로 작동하고 있습니다. 감사합니다!

4개의 좋아요

이번 주에 이 PR을 병합했고, 원본 게시글(OP)에 다음 세부 내용을 추가합니다:


이메일에 보안 이미지가 임베드되도록 허용하려면 다음 사이트 설정을 구성할 수 있습니다:

  • secure_media_allow_embed_images_in_emails: 활성화하면 보안 이미지를 편집(블러 처리)하는 대신 이메일에 임베드합니다.
  • secure_media_max_email_embed_image_size_kb: 임베드할 보안 이미지의 최대 크기를 제한하며, 기본값은 1MB입니다. 이메일 용량이 과도하게 커지지 않도록 하기 위한 것입니다. 최대값은 10MB입니다. email_total_attachment_size_limit_kb 설정과 함께 작동합니다.

이메일 클라이언트에서 base64 URL 지원이 아직 불안정하기 때문에, 보안 이미지는 cid: URL 형식을 사용하여 임베드되며 이메일 첨부 파일로 추가됩니다.

secure_media_allow_embed_images_in_emails가 활성화되어 있지 않거나 이미지가 크기 제한을 초과하기 시작하면, 보안 이미지(임베드되지 않는 보안 오디오 및 비디오 포함) 대신 다음과 같은 내용이 표시됩니다:

image

10개의 좋아요

이전 게시물에 대한 추가 사항입니다. 이 PR에서:

https://github.com/discourse/discourse/pull/10688

이제 기본적으로 안전한 미디어 이미지 임베딩을 활성화합니다.

5개의 좋아요

안전한 미디어 업로드 설정을 완료한 후(OP 가이드를 따랐습니다) 모든 기능이 잘 작동합니다(첨부 파일, 이미지 등). 하지만 주제 첨부 파일이 아닌 업로드(예: 사이트 로고, 프로필 아바타)는 Discourse에서 “Access Denied” 팝업을 표시합니다.
어떤 설정을 잘못 설정한 걸까요?

게시글을 잘 읽어보시기 바랍니다. 질문하신 내용은 이 글보다 몇 개 위 게시글에서 다루고 있습니다.

3개의 좋아요

모든 내용을 주의 깊게 읽었습니다. 위에서 몇 포스트 전에 말씀하신 정확한 의미가 무엇인지 알려 주실 수 있을까요? 해당 문제를 확인하지 못하겠습니다.
수정:
여기서 뉘앙스를 읽으려 보니, 이 스레드가 원래는 더 길었지만 일부 주요 답변이 삭제된 것 같습니다. 존재하지 않는 답변에 대한 참조와 스레드에 표시되지 않는 스크린샷 언급을 볼 수 있습니다.
제 이해가 맞다면, 권장 사항은 S3 버킷에 대해 공개 액세스를 전혀 차단하지 않도록 설정하라는 것입니다. 이것이 맞는지 확인하고, 그렇게 하는 것이 안전한지 묻고 싶습니다.

1개의 좋아요

맞습니다.

원래 게시물은 실제로 사라졌지만, 문제와 해결책은 여전히 남아 있습니다.

6개의 좋아요

보안 미디어를 사용할 때 버그를 발견했습니다. https://meta.discourse.org/t/knowledge-base-plugin/115288

지식 베이스의 첨부 파일 링크가 새 창에서 열리도록 강제되지 않으면 열리지 않습니다(404 페이지로 리다이렉트됨).

더 이상한 점은 지식 베이스 항목과 연결된 디스코urse 토픽에서는 동일한 첨부 파일을 아무 문제 없이 열 수 있다는 것입니다.

수정:
한 답변에서 다른 답변으로 첨부 파일 링크를 복사할 때도 동일한 버그가 발생합니다. 물론 링크 자체는 정확히 동일하지만, 새 창에서 열리도록 강제하지 않는 한 원래 답변에서만 작동합니다.

1개의 좋아요

S3를 사용하지 않는 경우 보안 미디어는 어떻게 되나요?
현재 상태로는 업로드된 파일의 직접 링크를 가지고 있으면 로그인 없이도 해당 파일을 다운로드할 수 있는 것 같습니다. 이는 보안 문제가 될 수 있습니다…

보안 미디어는 s3를 필수로 요구합니다.
이 기능 전체는 직접 링크를 공유하고 접근하는 것을 불가능하게 만들기 위해 개발되었습니다.

11개의 좋아요

훌륭한 기능입니다. 개발해 주셔서 감사합니다. S3의 무료 대체품인 Minio는 ACL을 지원하지 않으며 앞으로도 지원할 계획이 없습니다. 그 이유는 ACL이 유용한 기능이 아니며, 두 번째 쓰기 작업을 요구하기 때문에 성능에 부정적인 영향을 미친다는 것입니다. 이는 꽤 설득력 있는 논리입니다. 안전한 미디어 업로드는 Discourse에서 작동합니다. uploads:secure_upload_analyse_and_update 작업은 마지막 단계에서 오류가 발생하지만, 무시해도 되는 것 같습니다. 그렇다면 Discourse가 ACL 호출을 수행해야 할 이유가 무엇일까요?

3개의 좋아요

네, OP의 설정에 따르면 S3 버킷이 비공개이므로, 비보안 업로드의 ACL을 공개로 설정해야 하고, 보안 업로드는 S3 URL에 직접 접근할 수 있도록 비공개 ACL을 유지합니다. 현재 이 작동 방식을 변경할 계획은 없는 것으로 보입니다. S3 대체 수단에서 ACL 사용을 완전히 피하려면 상당한 작업이 필요할 것으로 생각됩니다.

7개의 좋아요