Les miniatures de chat contournent s3_cdn_url et utilisent les URL brutes du bucket S3

J’ai récemment configuré un bucket de téléchargements Cloudflare R2 et mes miniatures de discussion ont été cassées. J’ai donc fait quelques recherches et apporté une correction rapide à ma configuration, puis j’ai trouvé ce sujet : Cloudflare R2 Image URL Display Issue: Detailed Explanation and Fix. Quoi qu’il en soit, j’ai examiné d’autres configurations de buckets de téléchargements S3 et constaté que le bug n’était pas vraiment spécifique à Cloudflare.


Description

Lorsqu’un stockage objet externe S3 ou compatible est configuré pour les téléchargements, les miniatures de discussion contournent le CDN et sont chargées directement depuis l’URL du bucket.

Pour un bucket S3 externe sécurisé et compatible, tel que Cloudflare R2, les miniatures de discussion sont cassées et ne s’affichent pas.

Le problème sous-jacent est que le sérialiseur de discussion échoue à appliquer le paramètre s3_cdn_url aux miniatures. Au lieu de router l’image via le CDN configuré, il expose directement l’URL brute interne du bucket S3 dans les charges utiles transmises au navigateur.

Étapes pour reproduire le problème

Ceci est reproductible sur Meta et d’autres sites utilisant des buckets de téléchargements S3 :

  1. Publiez une image dans une discussion ou un canal
  2. Inspectez l’URL de l’image miniature dans la console
  3. Cliquez sur l’image pour obtenir la version originale plus grande, puis inspectez l’URL
  4. Comparez-la à celle de la miniature

Voici un exemple provenant d’une discussion Meta

URL de la miniature : depuis le bucket

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

URL originale : via le CDN

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

Dans la console, le code HTML de la miniature <img... contient data-large-src = URL du CDN CloudFront, et src = URL du bucket AWS.

capture d'écran

Impact :

  • Pour les stockages compatibles S3 comme Cloudflare R2, qui sont sécurisés par défaut et bloquent l’accès non authentifié aux points de terminaison bruts du bucket, les miniatures de discussion (optimisées) sont cassées.
  • Fuites de bande passante pour AWS et d’autres buckets de stockage objet compatibles S3 autorisant l’accès aux points de terminaison bruts du bucket, car la discussion contourne entièrement le CDN ; cela entraîne le paiement de frais de sortie S3 directs pour tout le trafic de miniatures de discussion.
  • Fuite d’infrastructure : les URL brutes du stockage backend (y compris les noms de buckets internes et parfois les identifiants de compte) sont exposées dans les charges JSON du client.

PR :

J’ai une PR pour corriger le problème ici :

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

Il semble que Sam ait ajouté getURLWithCDN à l’aperçu du compositeur de discussion — cependant, je ne pense pas que cela atteigne le flux de discussion ?

Je me demande si la correction du compositeur a pu échouer pour certaines configurations S3, car getURLWithCDN plante en cas de mismatch de protocole (// vs https://) ? Quoi qu’il en soit, la PR ci-dessus étend simplement le travail de Sam en ajoutant des wrappers au flux et en rendant le tout indépendant du protocole.

Contournement temporaire :

Avant de réaliser que ce problème dépassait celui de Cloudflare, j’ai créé un composant de thème léger. Il intercepte les domaines S3 bruts dans le DOM de la discussion et les remplace par le bon domaine CDN avant que le navigateur ne tente de les télécharger. Cela route correctement le trafic et colmate la fuite de bande passante. Je l’ai adapté pour fonctionner avec n’importe quel stockage objet compatible S3. Il suffit de deux paramètres : URL brute du bucket S3 et URL CDN S3.

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

(je ne sais pas pourquoi les oneboxes GitHub sont cassées ici) corrigé maintenant

5 « J'aime »

Probablement lié au déplacement du site… Je viens de les recompiler.

2 « J'aime »

Bonjour, le PR est-il déjà fusionné ?

merci

2 « J'aime »

Cela attend maintenant l’examen d’un membre de l’équipe humaine, après que mon ami discourse-triage-bot ait corrigé certains tests :slight_smile:

5 « J'aime »

on dirait que c’est maintenant fusionné.

4 « J'aime »

ouvert sur demande de l’auteur

Pour les sites disposant d’emojis personnalisés, ceux-ci seront cassés dans le chat maintenant que la correction a été intégrée.

Contrairement aux images standard des messages (qui peuvent être corrigées avec rake posts:rebake), les emojis personnalisés du chat sont transmis dynamiquement au frontend via /site.json.

Si votre base de données contient des URLs S3 manquant du protocole (par exemple, //bucket.endpoint...) ou utilisant un domaine de style virtual-hosted qui ne correspond pas parfaitement à vos variables d’environnement app.yml, le remplaçant CDN interne de Discourse échoue silencieusement. L’URL brute du bucket est alors transmise au navigateur, ce qui casse les emojis personnalisés dans le chat.

Comment corriger :

pour résoudre ce problème de manière permanente, vous devez forcer la redirection des URLs brutes du bucket vers votre URL CDN dans la base de données, puis vider le cache du site afin que /site.json soit régénéré.

1. Accédez à votre conteneur :

Connectez-vous en SSH à votre serveur et entrez dans le conteneur Discourse (généralement app, ou web_only si vous avez une configuration à deux conteneurs).

cd /var/discourse
./launcher enter app

2. Redirigez les URLs :

exécutez l’outil intégré de Discourse remap. Vous devriez l’exécuter deux fois pour prendre en compte à la fois la variation https:// et la variation sans protocole // que le script de migration laisse parfois.

Remplacez les espaces réservés par vos vraies URLs de bucket brut et votre vraie URL CDN :

# Corrigez les URLs standard https://
discourse remap "https://<your-bucket>.<your-endpoint>.com" "https://cdn.your-domain.com"

# Corrigez les URLs sans protocole // (c'est celle qui casse généralement les emojis personnalisés)
discourse remap "//<your-bucket>.<your-endpoint>.com" "https://cdn.your-domain.com"

3. Videz le cache

Étant donné que /site.json est fortement mis en cache, vous devez vider le cache Rails pour forcer le forum à servir les nouvelles URLs :

ouvrez la console Rails :

rails c

exécutez ces commandes :

Rails.cache.clear
Site.clear_cache
exit

4. Actualisez

Effectuez un rechargement forcé de votre navigateur (et désactivez la solution de contournement du composant de thème si vous l’utilisez encore). Les emojis personnalisés dans le chat devraient maintenant être corrigés et se charger correctement via le CDN.

3 « J'aime »

Salut Lilly, merci beaucoup pour ton excellent travail. Maintenant, mes anciens uploads et mes vignettes fonctionnent comme prévu après les deux remappings. Avant cela, les images de “/admin/config/customize/themes” ne fonctionnaient même pas. Tout est désormais réparé. C’est top.

Merci

1 « J'aime »