Aller au contenu

Infrastructure Terraform

Terraform est un outil logiciel open-source d’infrastructure as code qui vous permet de créer, modifier et améliorer votre infrastructure de manière sûre et prévisible.

Le générateur d’infrastructure Terraform crée un projet d’infrastructure Terraform. L’application générée inclut les meilleures pratiques de sécurité grâce aux vérifications de sécurité Checkov.

Vous pouvez générer un nouveau projet Terraform de deux manières :

Exécuter ce générateur@aws/nx-plugin:terraform#project

pnpm nx g @aws/nx-plugin:terraform#project
Composez votre commande5

Requis

Options du générateur5 options
nameRequisstring

Le nom du projet.

typeenumPar défaut: application

Si c'est une bibliothèque terraform (modules réutilisables) ou une application (déployable).

applicationlibrary
directorystringPar défaut: packages

Le répertoire du nouveau projet.

subDirectorystring

Le sous-répertoire dans lequel le projet est placé. Par défaut, il s'agit du nom du projet.

preferInstallDependenciesbooleanPar défaut: true

Indique s'il faut privilégier l'installation des dépendances après l'exécution du générateur. Définir sur false pour différer l'installation lors de l'exécution de plusieurs générateurs en lot (une installation s'exécute quand même si nécessaire pour que les générateurs suivants puissent calculer le graphe de projet Nx) ; installer une seule fois à la fin.

Le générateur crée différentes structures de fichiers en fonction du type de projet :

type = application

Pour les projets d’application (--type=application), le générateur crée une application Terraform complète avec gestion de l’état distant :

  • Répertoiresrc
    • main.tf Fichier de configuration Terraform principal
    • providers.tf Configuration du fournisseur avec backend S3
    • variables.tf Définitions des variables d’entrée
    • outputs.tf Définitions des valeurs de sortie
    • Répertoireenv Fichiers de variables spécifiques à l’environnement
      • dev.tfvars Variables d’environnement de développement
  • Répertoirebootstrap Configuration de bootstrap pour l’état distant
    • main.tf Bucket S3 et politiques pour le stockage de l’état
    • providers.tf Configuration du fournisseur AWS
    • variables.tf Définitions des variables de bootstrap
  • Répertoirescripts Helpers Node exécutés par les cibles nx bootstrap, bootstrap-destroy et init
    • aws-config.ts Résout le compte + la région via la chaîne de credentials AWS SDK
    • bootstrap.ts Récupère/pousse le tfstate de bootstrap et exécute terraform apply
    • bootstrap-destroy.ts Vide le bucket d’état et exécute terraform destroy
    • init.ts Exécute terraform init avec la configuration du backend S3
    • env.ts Pointe terraform init vers le cache de fournisseurs partagé
  • checkov.yml Configuration Checkov, incluant les vérifications à ignorer
  • project.json Configuration du projet et cibles de build
type = library

Pour les projets de bibliothèque (--type=library), le générateur crée une structure plus simple pour les modules Terraform réutilisables :

  • Répertoiresrc
    • main.tf Fichier de module Terraform principal
  • checkov.yml Configuration Checkov, incluant les vérifications à ignorer
  • project.json Configuration du projet et cibles de build

Vous pouvez commencer à écrire votre infrastructure Terraform dans src/main.tf, par exemple :

src/main.tf
locals {
account_id = data.aws_caller_identity.current.account_id
aws_region = data.aws_region.current.id
}
resource "null_resource" "print_info" {
# triggers = {
# always_run = timestamp()
# }
provisioner "local-exec" {
command = "echo 'AWS Region: ${local.aws_region}, AWS Account: ${local.account_id}, Environment: ${var.environment}'"
}
}
# Declare your infrastructure here
resource "aws_s3_bucket" "my_bucket" {
bucket = "my-unique-bucket-name"
}

Notez que le bucket S3 ci-dessus échouerait à l’analyse de sécurité Checkov, qui vérifie que le bucket a les paramètres de sécurité appropriés activés.

Si vous souhaitez exécuter un module à partir d’un projet séparé (lib), vous pouvez le faire comme suit :

module "lib_module" {
source = "../../path/to/my-lib/src"
}

Cela mettra automatiquement à jour le graphe Nx pour ajouter une dépendance entre votre application consommatrice et votre lib.

Configurez les variables spécifiques à l’environnement dans les fichiers src/env/*.tfvars.

Pour ajouter de nouveaux environnements, créez un nouveau fichier src/env/<environment>.tfvars avec les variables spécifiques à l’environnement et ajoutez de nouvelles entrées pour apply, destroy, init, plan dans le project.json pour la nouvelle configuration d’environnement. Par exemple, supposons que nous voulions ajouter un environnement prod :

# Production environment variables
environment = "prod"
aws_region = "us-west-2"
type = application

Bootstrap de l’état distant (Projets d’application uniquement)

Section intitulée « Bootstrap de l’état distant (Projets d’application uniquement) »

Avant de déployer votre infrastructure, vous devrez initialiser le backend d’état distant. Cela crée un bucket S3 pour stocker vos fichiers d’état Terraform :

Terminal window
pnpm nx bootstrap tf-infra

Les cibles disponibles dépendent du type de votre projet :

Vous pouvez valider votre configuration Terraform en utilisant la cible validate :

Terminal window
pnpm nx validate tf-infra

Les projets Terraform utilisent terraform fmt pour vérifier le formatage.

Pour invoquer le linter afin de vérifier votre projet, vous pouvez exécuter la cible lint.

Terminal window
pnpm nx lint tf-infra

La majorité des problèmes de linting ou de formatage peuvent être corrigés automatiquement en exécutant avec l’argument --configuration=fix.

Terminal window
pnpm nx lint tf-infra --configuration=fix

De même, si vous souhaitez corriger tous les problèmes de lint dans tous les packages de votre espace de travail, vous pouvez exécuter :

Terminal window
pnpm nx run-many --target lint --all --configuration=fix

Pour éviter que les problèmes de linting ne vous ralentissent pendant le développement (en particulier si vous avez des problèmes non corrigeables automatiquement dans votre projet), vous pouvez exécuter un build avec la configuration skip-lint :

Terminal window
pnpm nx run-many --target build --configuration=skip-lint

Cela ignore complètement la vérification du format pendant le build.

Exécutez des vérifications de sécurité sur votre infrastructure en utilisant Checkov avec la cible checkov :

Terminal window
pnpm nx checkov tf-infra

Vous trouverez vos résultats de tests de sécurité dans le dossier dist racine, sous dist/packages/<my-terraform-project>/checkov.

Checkov s’exécute dans le cadre de build.

Les vérifications sont configurées dans le fichier checkov.yml du projet. Ajoutez un identifiant de vérification à skip-check pour le supprimer dans tout le projet :

checkov.yml
skip-check:
- CKV_AWS_115 # Concurrent execution limit
- CKV_AWS_116 # Dead Letter Queue

Pour supprimer une vérification pour une seule ressource, ajoutez un commentaire #checkov:skip=<id>:<reason> à l’intérieur du bloc de ressource :

resource "aws_s3_bucket" "example" {
#checkov:skip=CKV_AWS_18:Access logging not required for this bucket
bucket = "example"
}

La cible test exécute le framework de test natif de Terraform sur tous les fichiers .tftest.hcl de votre projet :

Terminal window
pnpm nx test tf-infra

Un projet sans fichiers de test est un succès sans opération, vous pouvez donc ajouter des tests quand vous en avez besoin. build exécute cette cible, donc vos tests s’exécutent dans le cadre d’un build normal.

Chaque bloc run évalue votre configuration. Utilisez command = plan pour vérifier ce que Terraform ferait (cela développe tout le graphe de modules, donc cela détecte les erreurs au moment de la planification que validate ne peut pas détecter), ou command = apply pour créer de vraies ressources et faire des assertions sur leurs sorties. Déclarer mock_provider signifie qu’aucun appel d’API n’est effectué et qu’aucune credential AWS n’est nécessaire, ce qui permet de garder les tests plan rapides et sûrs à exécuter en CI :

src/main.tftest.hcl
mock_provider "aws" {
mock_data "aws_caller_identity" {
defaults = { account_id = "123456789012" }
}
mock_data "aws_region" {
defaults = { region = "us-east-1" }
}
}
variables {
aws_region = "us-east-1"
environment = "dev"
}
run "plan_is_valid" {
command = plan
assert {
condition = data.aws_caller_identity.current.account_id == "123456789012"
error_message = "Unexpected account id"
}
}

Définissez chaque variable requise par votre configuration dans le bloc variables, sinon l’exécution échoue avec “has a required variable … with no set value”.

Chaque cible qui exécute terraform init réutilise un cache de fournisseurs sous .terraform/plugin-cache dans la racine de votre espace de travail, de sorte que les fournisseurs sont téléchargés une seule fois plutôt qu’à chaque exécution. Chaque projet obtient son propre répertoire là-bas : deux exécutions de terraform init remplissant un cache en même temps peuvent chacune calculer un hash différent pour le même fournisseur, que terraform rejette ensuite contre votre .terraform.lock.hcl. Consultez la documentation Terraform pour plus d’informations.

Définissez TF_PLUGIN_CACHE_DIR dans votre environnement pour pointer le script init fourni vers un cache que vous gérez vous-même — un volume partagé entre les espaces de travail, par exemple. Notez que la cible test lit son chemin depuis project.json, donc modifiez-le là aussi.

type = application

Les cibles suivantes ne sont disponibles que pour les projets de type application :

Avant d’appliquer des modifications, vous pouvez voir ce que Terraform va faire en exécutant la cible plan :

Terminal window
pnpm nx plan tf-infra

Cela créera un fichier de plan dans dist/packages/<my-terraform-project>/terraform/dev.tfplan.

plan dépend de assemble, donc il produit les artefacts que vos modules référencent, tels que les bundles Lambda et les métadonnées d’opérations générées, sans exécuter les contrôles de lint, test et vérification de type.

Initialisez votre répertoire de travail Terraform avec la cible init :

Terminal window
pnpm nx run tf-infra:init

Après la planification, vous pouvez déployer votre infrastructure sur AWS en utilisant la cible apply :

Terminal window
pnpm nx apply tf-infra

Récupérez les valeurs de sortie de votre configuration Terraform :

Terminal window
pnpm nx output tf-infra

Lorsque vous devez démanteler votre infrastructure, utilisez la cible destroy :

Terminal window
pnpm nx destroy tf-infra

Pour nettoyer les ressources de bootstrap (bucket S3 pour le stockage de l’état) :

Terminal window
pnpm nx bootstrap-destroy tf-infra

Cela vide le bucket d’état avant de le détruire, et résout la région à partir de la chaîne de credentials AWS SDK, de sorte qu’il s’exécute sans surveillance en CI.

Pour plus d’informations sur Terraform, veuillez vous référer à la Documentation Terraform et à la Documentation du fournisseur AWS.