Introduction

Pour pratiquer un peu AWS et terraform, je vais évaluer les différentes façons d’héberger un site statique. Dans ce premier opus, je vais donc tester le service S3. Comme Azure Storage Account, un compartiment S3 peut accueillir un site statique.

Quelques prérequis

Commençons par installer les quelques utilitaires qui vont nous servir

choco install awscli
choco install terraform
choco install hugo-extended

Evidemment, il faudra un compte AWS.

Création du blog statique

Pour cet exemple, je vais m’appuyer sur Hugo qui fournit un guide rapide pour générer très rapidement un blog.

Avec Hugo installé, voici les quelques commandes passées (sur Windows)

hugo new site hugo
cd hugo
echo theme = "ananke" >> config.toml
hugo new posts/my-first-post.md

J’ai supprimé le flag draft de l’article et copié le contenu de l’archive https://github.com/theNewDynamic/gohugo-theme-ananke/archive/master.zip dans le répertoire themes\ananke, et en avant :

hugo server

Création d’un compte

Pour créer un nouveau compte à partir de la console AWS, il faut se connecter à https://console.aws.amazon.com/iamv2/home#/users. On peut alors cliquer sur le bouton Ajouter des utilisateurs et suivre l’assistant pas-à-pas. On prendra soin de choisir un accès par "Clé d’accès - Accès par programmation" et récupérer l’ID et le secret de la clé d’accès.

Des droits sont nécessaires pour que ce nouvel utilisateur puisse créer des buckets S3. Pour faire simple, nous allons attacher la politique "AmazonS3FullAccess" à cet utilisateur. Pour ce faire aller dans Politiques, rechercher la politique "AmazonS3FullAccess", puis aller dans l’onglet "Utilisation de la stratégie" pour attacher la politique.

La console utilise le terme "politique" ou "stratégie" pour les policies AWS.

Configuration d’AWS CLI

Pour utiliser le compte, nous allons créer un compte profil. Pour ce faire, utilisons la commande suivante :

> aws configure --profile terraform-s3
AWS Access Key ID [None]: AKIAI44QH8DHBEXAMPLE
AWS Secret Access Key [None]: h3yCo8nvbEXAMPLEKEY
Default region name [None]: eu-west-3
Default output format [None]:

Configuration de Terraform et création des ressources

Pour utiliser Terraform avec AWS, il est nécessaire de définir le fournisseur. Par souci de réutilisation et de facilité de lecture, je mets cette configuration dans un fichier à part, provider.tf

provider.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.3.0"
    }
  }
  required_version = ">= 1.1.6"
}

provider "aws" {
  region = var.aws_region (1)
}
J’utilise ici le "nouveau" fournisseur 4.0 qui contient de nombreux changements, notamment dans la gestion des compartiments S3.
1 Il est possible d’ajouter des paramètres comme profile. J’ai fait le choix de définir mon profil grâce à la variable d’environnement AWS_PROFILE, ce qui évite d’avoir cette info dans le code source.

La création d’un compartiment S3 (S3 Bucket) est bien documentée dans la doc AWS. Pour autant, il est facile de tout automatiser avec Terraform, comme le fichier ci-dessous.

main.tf
resource "aws_s3_bucket" "site" {
  bucket = var.s3_name (1)
}

resource "aws_s3_bucket_website_configuration" "site" {
  bucket = aws_s3_bucket.site.id

  index_document {
    suffix = "index.html" (2)
  }

  error_document {
    key = "error.html" (3)
  }
}

resource "aws_s3_bucket_acl" "site" {
  bucket = aws_s3_bucket.site.id

  acl = "public-read" (4)
}

resource "aws_s3_bucket_policy" "site" {
  bucket = aws_s3_bucket.site.id

  policy = jsonencode({ (5)
    Version = "2012-10-17"
    Statement = [
      {
        Sid       = "PublicReadGetObject"
        Effect    = "Allow"
        Principal = "*"
        Action    = ["s3:GetObject"]
        Resource = [
          "${aws_s3_bucket.site.arn}/*"
        ]
      },
    ]
  })
}

La création d’un compartiment pour un site Web requiert de nombreuses étapes :

  1. Créer un compartiment (S3 Bucket) (cf. 1)

  2. Activer l’hébergement de site web statique

  3. Modifier les paramètres de blocage de l’accès public (cf. 4)

  4. Ajouter une stratégie de compartiment visant à rendre disponible publiquement le contenu du compartiment (cf. 5)

  5. Configurer un document d’index (cf. 2)

  6. Configurer un document d’erreur (cf. 3), sachant qu’il est facile de créer une page d’erreur 404 avec Hugo (cf. https://gohugo.io/templates/404/).

A des fins de réutilisation, il est possible de définir des variables qui sont utilisées dans les différents fichiers Terraform. Ici, j’utilise uniquement 2 variables pour la région et pour le nom du compartiment S3.

variables.tf
variable "aws_region" {
  type        = string
  description = "The AWS region to put the bucket into"
  default     = "eu-west-3"
}

variable "s3_name" {
  type        = string
  description = "The name to use for the static site"
}

Finalement, afin de récupérer plus facilement l’URL du site généré, j’utilise variables en sortie que je déclare dans un fichier dédié, outputs.tf.

outputs.tf
output "website_bucket_name" {
  description = "Name (id) of the bucket"
  value       = aws_s3_bucket.site.id
}

output "bucket_endpoint" {
  description = "Bucket endpoint"
  value       = aws_s3_bucket.site.website_endpoint
}

La valeur des variables peut être définie dans le fichier terraform.tfvars.

terraform.tfvars
s3_name = "monbuckets3"

Quelques commandes magiques terraform pour préparer l’infrastructure :

terraform init
terraform plan
terraform apply
terraform output

Avec la dernière commande, on obtient l’URL du compartiment S3.

Publication

Hugo prévoit nativement des mécanismes de publication. Nous allons voir ici comment publier manuellement.

Avec le site Hugo précédemment créé (cf. Création du blog statique), on génère les fichiers statiques en précisant l’URL cible

hugo -b http://monbuckets3.s3-website.eu-west-3.amazonaws.com

Les fichiers sont générés par défaut dans le répertoire public. A partir du répertoire du blog, il est possible de pousser les fichiers du site dans le compartiment S3 avec la commande suivante :

aws s3 cp public/ s3://monbuckets3/ --recursive
La ligne de commande aws réutilisera le profil configuré précédemment avec la variable d’environnement AWS_PROFILE.

Conclusion

En quelques minutes, il est possible de créer un compartiment S3. Malheureusement, il n’est pas possible d’avoir du HTTPS ou un nom de domaine personnalisé juste avec S3. Dans un prochain article, nous verrons comment muscler le jeu pour répondre à ce besoin.