Miniaturas de chat contornam s3_cdn_url e usam URLs brutas do bucket S3

Fiz uma configuração recente do bucket de uploads do Cloudflare R2 e as miniaturas de chat foram afetadas. Então, pesquisei um pouco, apliquei uma correção rápida na minha configuração e encontrei este tópico: Cloudflare R2 Image URL Display Issue: Detailed Explanation and Fix. De qualquer forma, analisei outras configurações de buckets de upload S3 e notei que o problema não era realmente específico do Cloudflare.


Descrição

Quando um armazenamento de objetos externo S3 ou compatível é configurado para uploads, as miniaturas de chat contornam a CDN e são carregadas diretamente a partir da URL do bucket.

Para buckets externos seguros e compatíveis com S3, como o Cloudflare R2, as miniaturas de chat ficam quebradas e não são exibidas.

O problema subjacente é que o serializador do chat não está aplicando a configuração s3_cdn_url às miniaturas. Em vez de rotear a imagem através da CDN configurada, ele está expondo diretamente a URL interna bruta do bucket S3 nas cargas úteis do navegador.

Passos para reproduzir

Isso é reproduzível no Meta e em outros sites que usam buckets de upload S3:

  1. Publique uma imagem no chat ou em um canal
  2. Inspecione a URL da imagem de miniatura no console
  3. Clique na imagem para obter a versão original maior e inspecione a URL
  4. Compare-a com a miniatura

Aqui está um exemplo de um chat do Meta:

URL da miniatura: do bucket

https://cdck-file-uploads-global.s3.dualstack.us-west-2.amazonaws.com/meta/optimized/4X/4/7/9/479815360e0e6e0cd9f4ba565891776e84aea532_2_375x500.jpeg

URL original: via CDN

https://global.discourse-cdn.com/meta/original/4X/4/7/9/479815360e0e6e0cd9f4ba565891776e84aea532.jpeg

No console, o HTML da miniatura <img... contém data-large-src = URL da CDN CloudFront, e src = URL do bucket AWS.

captura de tela

Impacto:

  • Para armazenamento compatível com S3, como o Cloudflare R2, que é seguro por padrão e bloqueia o acesso não autenticado aos endpoints brutos do bucket, as imagens de miniatura de chat (otimizadas) ficam quebradas.
  • Vazamento de banda para buckets de armazenamento de objetos AWS e outros compatíveis com S3 que permitem acesso aos endpoints brutos do bucket, já que o chat está contornando completamente a CDN; isso resulta em pagamento direto de taxas de egresso do S3 para todo o tráfego de miniaturas de chat.
  • Vazamento de infraestrutura: as URLs de armazenamento backend brutas (incluindo nomes internos de buckets e, às vezes, IDs de conta) estão sendo expostas nas cargas úteis JSON do cliente.

PR:

Tenho um PR para corrigir o problema aqui:

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

Parece que Sam adicionou o getURLWithCDN à prévia do compositor de chat — no entanto, não acho que isso chegue ao fluxo do chat?

Fico me perguntando se a correção do compositor pode ter falhado para algumas configurações S3 também, porque o getURLWithCDN trava em incompatibilidades de protocolo (// vs https://)? De qualquer forma, o PR acima simplesmente estende o trabalho de Sam adicionando os wrappers ao fluxo e tornando-o agnóstico ao protocolo.

Solução temporária:

Antes de perceber que isso era mais do que um problema do Cloudflare, criei um componente de tema leve. Ele intercepta os domínios brutos do S3 no DOM do Chat e os substitui pelo domínio correto da CDN antes que o navegador tente baixá-los. Isso roteia o tráfego corretamente e tapa o vazamento de banda. Adaptei-o para funcionar com qualquer armazenamento de objetos compatível com S3. São apenas duas configurações — URL bruta do bucket S3 e URL da CDN S3.

https://github.com/Lillinator/chat-s3-thumbnails-fix

(não sei por que os oneboxes do GitHub estão quebrados aqui) Corrigido agora

5 curtidas

Provavelmente relacionado à mudança do site… Acabei de refazer o bake.

2 curtidas

Olá, o PR já foi mesclado?

Obrigado

2 curtidas

agora só está aguardando a revisão de um membro da equipe humana, depois que meu amigo discourse-triage-bot corrigiu alguns testes :slight_smile:

https://github.com/discourse/discourse/pull/40419#issuecomment-4683409099

5 curtidas

parece que já foi mesclado.

4 curtidas

aberto a pedido do autor

Para sites com emojis personalizados adicionados, eles ficarão quebrados no chat agora que a correção foi mesclada.

Diferente das imagens padrão dos posts (que podem ser corrigidas com rake posts:rebake), os emojis personalizados do chat são passados para o front-end dinamicamente via /site.json.

Se o seu banco de dados contiver URLs da S3 que estão faltando com o protocolo (por exemplo, //bucket.endpoint...) ou que usam um domínio no estilo virtual-hosted que não corresponde perfeitamente às variáveis de ambiente do seu app.yml, o substituidor de CDN interno do Discourse falha silenciosamente. A URL bruta do bucket é passada para o navegador, quebrando os emojis personalizados no chat.

Como corrigir:

Para corrigir isso permanentemente, você precisa forçar o remapeamento das URLs brutas do bucket para a URL do seu CDN no banco de dados e, em seguida, limpar o cache do site para que o /site.json seja regenerado.

1. Entre no seu container:

Faça SSH no seu servidor e entre no container do Discourse (geralmente app, ou web_only se você tiver uma configuração de dois containers).

cd /var/discourse
./launcher enter app

2. Remapeie as URLs:

Execute a ferramenta interna do Discourse remap. Você deve executá-la duas vezes para capturar tanto a variação https:// quanto a variação sem protocolo // que o script de migração às vezes deixa para trás.

Substitua os placeholders pelas suas URLs reais do bucket bruto e da sua URL do CDN:

# Corrija as URLs padrão https://
discourse remap "https://<seu-bucket>.<seu-endpoint>.com" "https://cdn.seu-dominio.com"

# Corrija as URLs sem protocolo // (esta é a que geralmente quebra os emojis personalizados)
discourse remap "//<seu-bucket>.<seu-endpoint>.com" "https://cdn.seu-dominio.com"

3. Limpe o cache

Como o /site.json é fortemente armazenado em cache, você deve limpar o cache do Rails para forçar o fórum a servir as novas URLs:

Abra o console do Rails:

rails c

Execute estes comandos:

Rails.cache.clear
Site.clear_cache
exit

4. Atualize

Faça uma atualização forçada no seu navegador (e desative a solução alternativa do componente do tema, se ainda estiver usando). Os emojis personalizados no chat agora devem estar corrigidos e carregando corretamente pelo CDN.

3 curtidas

E aí, Lilly! Muito obrigado pelo seu ótimo trabalho. Agora, meus uploads antigos e as miniaturas estão funcionando normalmente após as duas reindexações. Antes disso, até as imagens de “/admin/config/customize/themes” não estavam funcionando. Agora está tudo resolvido. Que legal!

Obrigado!

1 curtida