Hébergement de fichiers statiques avec certificat SSL gratuit grâce à AWS S3 + CloudFront + Certificate Manager

Quand on héberge un site web, on peut séparer deux types de trafic : ce qui nécessite du traitement côté serveur (et donc du code en PHP, Python, ou autre), et les fichiers complètement statiques.
Le premier est assez délicat ; c’est là où se trouve tout le code applicatif, les bases de données, les frameworks et ainsi de suite.
Le second est comparativement plus simple ; tout ce qu’on veut, c’est rendre disponibles des fichiers (souvent des fichiers CSS, JS, et des images, mais possiblement aussi du son et de la vidéo).

J’ai expliqué dans mon précédent article comment générer des certificats SSL gratuits, pour sécuriser un hébergement utilisant le serveur Apache. Pour les fichiers statiques, il est souvent rentable de ne pas les héberger soi-même, mais de passer par une plate-forme cloud pour le stockage et un CDN pour délivrer le contenu de la manière la plus efficace possible.

Nous allons voir comment faire cela, en utilisant les outils proposés par Amazon Web Services. Pour commencer, vous devez évidemment avoir un compte AWS et pouvoir vous identifier sur la console web.

Imaginons que l’on souhaite créer un hébergement de fichiers qui seront servis depuis le sous-domaine static.toto.com. Assurez-vous que ce sous-domaine n’est pas déjà défini dans votre DNS.

AWS Certificate Manager

Nous allons commencer par créer le certificat SSL.
Pour la petite histoire, à une époque il n’y avait que deux possibilités pour créer un certificat SSL chez AWS : soit importer un certificat SSL généré par ailleurs (ce qui peut être pratique si on a acheté un certificat wildcard chez une autorité de certification classique), soit le créer sur AWS − sauf que cela n’était possible que pour les domaines gérés dans Route 53, le service de DNS d’Amazon.
Aujourd’hui, cette limitation n’existe plus. Il est possible de générer des certificats pour n’importe quel domaine, à partir du moment où on peut prouver que ce domaine nous appartient.

Dans la console AWS, sélectionnez le service Certificate Manager.

Cliquez sur le bouton “Demander un certificat”.

Laissez l’option “Demander un certificat public” et cliquez sur le bouton “Demander un certificat”.

Entrez le nom de domaine “static.toto.com”.
(Notez au passage que vous pouvez inclure plusieurs sous-domaines différents dans le même certificat.)
Cliquez sur le bouton “Suivant”.

Laissez l’option “Validation DNS”. Cliquez sur le bouton “Suivant”.

À l’étape “Ajouter des balises”, contentez-vous de cliquer sur le bouton “Vérification”.

À l’étape “Vérification”, cliquez sur le bouton “Confirmer et demander”.

Vous arrivez sur une étape “Validation”. Celle-ci affiche le domaine “static.toto.com” avec l’état “Validation en attente”. Cliquez sur le nom de domaine pour afficher les informations de DNS.
Vous pourrez y voir un champ CNAME à créer dans le DNS de votre domaine toto.com, avec la valeur associée.

Allez dans l’interface de votre registrar, et ajoutez un nouveau champ CNAME pour le domaine en question. Faites attention à saisir correctement les valeurs, aussi bien le nom du CNAME que sa valeur associée.

Revenez dans l’interface AWS, sur l’étape “Validation” où vous étiez. Cliquez sur le bouton “Continuer”.

Vous arrivez sur la liste des certificats. Celui que vous venez de créer apparaît, toujours avec le statut “Validation en attente”. Il va rester avec ce statut jusqu’à ce qu’Amazon ait vérifié que votre champ CNAME existe bien et contient les valeurs attendues. Cela peut prendre quelques dizaines de minutes, parfois plus si votre DNS est lent à se propager.

Par contre, une fois que le CNAME est vérifié, le certificat est validé et sa durée de validité est de 13 mois.

AWS S3

Dans la console AWS, sélectionnez le service S3.

Cliquez sur le bouton “Créer un compartiment”.

Dans le champ “Nom du compartiment”, entrez “static.toto.com”.
Pour la région, vous pouvez adopter plusieurs stratégies. Soit utiliser la région “UE (Paris)” pour avoir les données au plus près de vous et diminuer ainsi les latences ; soit vous dire que de toute façon c’est le CDN CloudFront qui délivrera les fichiers, et choisir une région où le stockage coûtera marginalement moins cher, comme “USA Est (Virginie du Nord)”.

À l’étape “Configurer des options”, ne touchez à rien et cliquez sur le bouton “Suivant”.

À l’étape “Définir des autorisations”, décochez la case “Bloquer tout l’accès public” puis cliquez sur “Suivant”.

À l’étape “Vérification”, cliquez sur le bouton “Créer un compartiment”.

Votre compartiment (aussi appelé “bucket” en anglais) est maintenant créé. Cliquez dessus pour entrer dedans (façon de parler, vous m’avez compris).

Pour déposer un (ou plusieurs) fichier, il suffit de cliquer sur le bouton “Charger”. Faites glisser les fichiers à envoyer, ou cliquez sur le bouton “Ajouter des fichiers” puis sélectionnez les fichiers.
L’étape “Sélectionner les fichiers” affiche la liste des fichiers que vous avez sélectionnés. Cliquez sur le bouton “Suivant”.
À l’étape “Définir des autorisations”, cliquez sur le menu déroulant placé sous le titre ”Gérer les autorisations publiques”, et sélectionnez l’option “Octroyer un accès en lecture public à ces objets”. Cliquez ensuite sur le bouton “Suivant”.
À l’étape “Définir les propriétés”, cliquez sur le bouton “Suivant”.
À l’étape “Vérification”, cliquez sur le bouton “Charger”.

Vous verrez alors une barre de progression indiquant le chargement des fichiers. Au terme de ce chargement, vous devriez voir vos fichiers listés dans le compartiment.

AWS CloudFront

Pour réaliser cette partie, il faut d’abord que le certificat créé précédemment ait été validé par Amazon. Si ce n’est pas encore le cas, attendez jusqu’à ce que ce soit bon (si ce n’est toujours pas validé au bout d’une heure, vérifiez que les noms saisis dans la console sont corrects, ainsi que les valeurs du CNAME).

Dans la console AWS, sélectionnez le service CloudFront.

Cliquez sur le bouton “Créer une distribution”.

Nous allons utiliser le mode de livraison “Web”. Cliquez sur le bouton “Mise en route” qui est juste en dessous. Vous arrivez sur une page intitulée “Créer une distribution”.

Dans le champ “Nom du domaine d’origine”, commencez à taper le nom “static.toto.com” ; l’interface vous proposera le compartiment S3 “static.toto.com.s3.amazonaws.com”, sélectionnez-le.

Dans le champ “Stratégie de protocole d’utilisateur”, sélectionnez “Rediriger HTTP vers HTTPS”.

Dans le champ “Autres noms de domaine (CNAME)”, entrez “static.toto.com”.

Pour la partie “Certificat SSL”, sélectionnez l’option “Certificat SSL personnalisé”. Cliquez dans la zone de texte juste en dessous ; l’interface devrait lister votre certificat (sous le nom “static.toto.com”, suivant d’un code hexadécimal entre parenthèses), cliquez dessus pour le sélectionner.

Pour la “Version minimale du protocole SSL”, vous pouvez laisser l’option par défaut. Pour ma part, je choisis l’option “TLSv1” pour assurer une compatibilité avec un plus grand nombre d’appareils (les autres versions du protocole ne sont supportées que depuis 2016 ou 2018).

Enfin, cliquez sur le bouton “Créer une distribution” en bas de la page.

Vous vous retrouverez alors sur la liste des distributions. Celle que vous venez de créer devrait apparaître, avec un statut en cours de déploiement.
Le déploiement peut prendre plusieurs dizaines de minutes.
Mais dans cette liste, vous pouvez voir qu’il y a une colonne nommée “Nom de domaine”. Pour votre distribution, vous y trouverez une chaîne de type “identifiant.couldfront.net” ; notez cette valeur.

En attendant, retournez dans l’interface de votre registrar. Vous allez pouvoir créer un nouvel enregistrement CNAME, pour le nom “static.toto.com” ; comme valeur pointée, entrez la valeur notée précédemment, sans oublier le point terminal (“identifiant.cloudfront.net.”).

Une fois que le déploiement est terminé dans CloudFront, et que la réplication DNS a eu le temps de se faire, votre hébergement est prêt à être utilisé.

Vérification

Vous pouvez maintenant taper dans votre navigateur l’adresse complète pointant vers l’un des fichiers que vous avez chargés dans le compartiment S3. Par exemple, si vous avez envoyé un fichier nommé “test.jpg”, vous pouvez vous rendre sur https://static.toto.com/test.jpg et l’image devrait s’afficher dans votre navigateur.

En cas de problème, vous pouvez utiliser un service de vérification de certificat SSL pour tenter de comprendre d’où vient le souci. Il en existe plusieurs, comme SSLChecker, DigiCert ou SSLShopper.

CORS

Tout le système expliqué ici prend son sens pour héberger des fichiers statiques (JS, CSS, images) qui sont ensuite utilisés dans un site ou une application web. Mais cela veut dire que les fichiers hébergés chez Amazon seront servis par un (sous-)domaine différent de celui qui hébergera le site.

Par exemple, la page web dont l’URL est https://www.toto.com/ aura peut-être besoin des fichiers https://static.toto.com/img/logo.png et https://static.toto.com/js/site.js.

Mais en HTTPS, faire ce genre de chose n’est pas aussi aisé qu’en HTTP. Au niveau du bucket S3, il faut ajouter des règles de Cross-Origin Resource Sharing, afin que les navigateurs acceptent d’utiliser ces fichiers.
Pour cela, dans la configuration du bucket, allez dans « Autorisations », puis dans « Configuration CORS ». Dans l’éditeur de configuration CORS, vous pouvez entrer le XML suivant :

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*.toto.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<MaxAgeSeconds>2592000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

En remplaçant évidemment « *.toto.com » par votre nom de domaine.

Du côté de votre site web, il faudra ajouter une balise meta dans l’en-tête HTML, pour que le navigateur sache qu’il est en droit d’aller chercher des fichiers sur le domaine qui héberge les fichiers statiques.
Par exemple :

<meta http-equiv="Content-Security-Policy" content="default-src 'self' static.toto.com">

Pour aller plus loin, vous pouvez vous référer à la documentation AWS.

CORS multi-domaines

Ce qu’on vient de voir juste au-dessus est utile pour le cas où les fichiers statiques sont hébergés sur le domaine static.toto.com, et chargés uniquement depuis le domaine www.toto.com.

Mais si vous souhaitez utiliser les fichiers statiques dans deux sites différents (par exemple www.toto.com et blog.toto.com), vous risquez d’avoir des problèmes. En effet, CloudFront va mettre en cache toutes les informations relatives aux fichiers statiques, y compris la valeur de l’en-tête HTTTP access-control-allow-origin. Donc si la première requête d’accès à un fichier se fait depuis www.toto.com, ça va coincer quand on essaiera de charger ce même fichier depuis blog.toto.com : le navigateur le refusera car la valeur de l’en-tête ne correspondra pas au domaine courant.

La solution se situe dans la configuration de CloudFront. Dans l’onglet « Comportements », sélectionnez la ligne existante, et cliquez sur le bouton « Modifier ».

Pour l’item « Réacheminer les en-têtes », sélectionnez « Liste blanche ». Une zone de sélection va apparaître en-dessous. Sélectionnez « Origin », puis cliquez sur le bouton « Ajouter >> ».
L’interface a changé : Dans la section « Demandes de clé de cache et d’origine », cochez le choix « Legacy cache settings ». Dans le menu déroulant « En-têtes », sélectionnez « Inclure les en-têtes suivants ». Dans le menu déroulant « Ajouter un en-tête », sélectionnez « Origin ».
Juste en dessous, pour le choix « Mise en cache d’un objet », sélectionnez « Use origin cache headers ».

Enfin, enregistrez la configuration en cliquant sur le bouton « Oui, Modifier » « Enregistrer les modification » en bas de la page.

Ajouter des fichiers

Nous venons de voir comment créer un hébergement statique en utilisant les outils Amazon Web Services, avec un certificat SSL généré gratuitement. Vous pouvez utiliser cette technique pour plusieurs sous-domaines différents, idéalement en les rassemblant dans le même certificat (mais vous pouvez générer un certificat par sous-domaine, si vous le souhaitez).

Tout ça donnera sa pleine valeur si vous automatisez la copie de fichiers vers votre compartiment S3. Vous pouvez faire cela en utilisant l’API S3 grâce à l’un des SDK fournis par Amazon, ou tout simplement en copiant les fichiers locaux vers S3 grâce à l’outil aws-cli en ligne de commande.
Important : Pensez bien à toujours donner les droits d’accès en lecture pour tout le monde (accès public) aux fichiers que vous ajouterez dans votre compartiment S3, sinon ils ne seront pas accessibles.

L’outil aws-cli permet de faire des synchronisation unidirectionnelles (depuis votre ordinateur vers un compartiment S3, mais pas dans l’autre sens ; donc aucun risque d’effacer des données). Pour recopier le contenu d’un répertoire vers le compartiment, il suffit de lancer la commande :

aws s3 sync dossier_local s3://static.toto.com --acl public-read --cache-control "max-age=31536000"

Vous pouvez voir que j’utilise les options suivantes :

  • --acl : Pour indiquer que le fichier est lisible par tous.
  • --cache-control : Pour que le fichier soit mis en cache par les navigateurs (ici avec une durée d’un an).

Comme ce sont des fichiers statiques, une longue durée de cache ne devrait pas être un soucis, au contraire. Si vous avez besoin de pouvoir modifier les fichiers, je conseille de versionner les fichiers, en les mettant dans des sous-répertoires (dont le nom correspond au numéro de version).
Ce qui donnerait quelque chose comme ça :

aws s3 sync dossier_local s3://static.toto.com/v1.2.3 --acl public-read --cache-control "max-age=31536000"

Il faut juste faire attention, par la suite, à ce que votre site ou application web pointe sur le bon chemin.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Notifiez-moi des commentaires à venir via email. Vous pouvez aussi vous abonner sans commenter.