eadl:bloc4:fm4:td3

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
eadl:bloc4:fm4:td3 [2026/06/24 08:10] jcheroneadl:bloc4:fm4:td3 [2026/06/25 03:35] (Version actuelle) jcheron
Ligne 10: Ligne 10:
   * Mettre en place une traçabilité avec CloudTrail   * Mettre en place une traçabilité avec CloudTrail
   * Identifier une action suspecte via les logs   * Identifier une action suspecte via les logs
 +  * Récupérer des ressources existantes via des data sources AWS
  
 ===== Contexte ===== ===== Contexte =====
Ligne 33: Ligne 34:
  
   * Projet Terraform du TD2 déployé et fonctionnel   * Projet Terraform du TD2 déployé et fonctionnel
 +  * Ressources TD2 taguées avec `Name = "td2-vpc"`, `Name = "td2-private"`, etc.
   * ALB opérationnel, Security Groups en place   * ALB opérationnel, Security Groups en place
   * Accès AWS avec droits suffisants : IAM, Secrets Manager, KMS, S3, RDS, CloudTrail   * Accès AWS avec droits suffisants : IAM, Secrets Manager, KMS, S3, RDS, CloudTrail
Ligne 39: Ligne 41:
 ===== Structure du projet ===== ===== Structure du projet =====
  
-Le TD3 s'appuie sur les ressources existantes du TD2 et ajoute quatre nouveaux modules.+Le TD3 est un projet Terraform indépendant. 
 + 
 +Il ne modifie pas le code du TD2. 
 + 
 +Il récupère les ressources existantes via des data sources AWS interrogeant l'API par tags.
  
 Fichier : `td3/structure.txt` Fichier : `td3/structure.txt`
 <sxh bash> <sxh bash>
-td3/ +tp-aws/ 
-├── main.tf +├── td1/                  # IAM – roles, policies 
-├── variables.tf +├── td2/                  # Réseau – VPC, subnets, ALB, Security Groups 
-├── outputs.tf +└── td3/                  # Secrets, KMS, chiffrement, logs 
-└── modules/ +    ├── main.tf 
-    ├── secrets/ +    ├── variables.tf 
-    │   ── main.tf +    ├── outputs.tf 
-    ├── kms/ +    └── modules/ 
-    │   ── main.tf +        ├── secrets/ 
-    ├── storage/ +        │   ── main.tf 
-    │   ── main.tf +        │   ├── variables.tf 
-    └── logging/ +        │   └── outputs.tf 
-        └── main.tf+        ├── kms/ 
 +        │   ── main.tf 
 +        │   ├── variables.tf 
 +        │   └── outputs.tf 
 +        ├── storage/ 
 +        │   ── main.tf 
 +        │   ├── variables.tf 
 +        │   └── outputs.tf 
 +        └── logging/ 
 +            ├── main.tf 
 +            ├── variables.tf 
 +            └── outputs.tf
 </sxh> </sxh>
  
-Le fichier `td3/main.tf` orchestre les quatre modules et récupère les ressources du TD2 via des data sources.+===== 1Récupération des ressources du TD2 =====
  
-===== 1Analyse de l'existant =====+Objectif : comprendre comment un projet Terraform peut interroger une infrastructure existante sans accéder à son state.
  
-Lire le fichier `td2/network/instances.tf` avant toute manipulation.+TD3 utilise des data sources AWS natifs.
  
-<WRAP round question> +Ces data sources envoient des requêtes directement à l'API AWS et filtrent les ressources par tags.
-Localiser la ligne où le mot de passe de la base de données est défini.+
  
-Répondre aux questions suivantes : +Cela suppose que les ressources TD2 ont été correctement taguées.
-  * Qui peut lire ce mot de passe concrètement ? +
-  * Ce fichier est-il souvent versionné dans Git en entreprise ? +
-  * Quelles sont les conséquences si ce dépôt est public ou partagé avec un prestataire ? +
-</WRAP>+
  
 <WRAP round question> <WRAP round question>
-Dans `td2/network/instances.tf`, la ressource `aws_db_instance` ne contient pas le paramètre `storage_encrypted`. +Pourquoi TD3 ne peut-il pas utiliser directement les outputs du TD2 sans configuration supplémentaire ?
- +
-Quelle est la valeur par défaut de ce paramètre dans AWS ?+
  
-Comment vérifier l'état du chiffrement d'une instance RDS existante dans la console AWS ?+Quelle est la différence entre un data source AWS et un `terraform_remote_state` ?
 </WRAP> </WRAP>
- 
-<WRAP round question> 
-Aucun service de logging n'est présent dans le TD2. 
- 
-Citer deux situations concrètes en production où l'absence de logs rend la gestion d'incident impossible. 
-</WRAP> 
- 
-===== 2. Récupération des ressources du TD2 ===== 
- 
-Le TD3 ne redéploie pas les ressources du TD2. 
- 
-Il les récupère via des data sources Terraform pour les réutiliser. 
  
 Fichier : `td3/main.tf` Fichier : `td3/main.tf`
 <sxh js> <sxh js>
-terraform { 
-  required_providers { 
-    aws = { 
-      source  = "hashicorp/aws" 
-      version = "~> 5.0" 
-    } 
-    random = { 
-      source  = "hashicorp/random" 
-      version = "~> 3.0" 
-    } 
-  } 
-} 
- 
 provider "aws" { provider "aws" {
   region = "eu-west-3"   region = "eu-west-3"
 } }
  
-Recuperation du compte AWS courant +Récupération du VPC créé dans TD2 
-data "aws_caller_identity" "current" {} +data "aws_vpc" "main" { 
- +  tags = 
-# Recuperation de la region courante +    Name = "td2-vpc"
-data "aws_region" "current" {} +
- +
-# Recuperation du VPC cree au TD2 +
-data "aws_vpc" "td2" { +
-  filter +
-    name   = "tag:Name+
-    values ["td2-vpc"]+
   }   }
 } }
  
-Recuperation du Security Group backend du TD2 +Récupération du subnet privé créé dans TD2 
-data "aws_security_group" "backend_sg" { +data "aws_subnet" "private" { 
-  filter +  tags = 
-    name   = "tag:Name+    Name = "td2-private"
-    values ["backend-sg"]+
   }   }
 } }
  
-module "secrets" { +# Récupération du subnet privé secondaire créé dans TD2 
-  source = "./modules/secrets"+data "aws_subnet" "private_b" { 
 +  tags = { 
 +    Name = "td2-private-b" 
 +  }
 } }
  
-module "kms" { +# Récupération du Security Group RDS créé dans TD2 
-  source     = "./modules/kms+data "aws_security_group" "rds" { 
-  account_id = data.aws_caller_identity.current.account_id +  tags = { 
-  region     = data.aws_region.current.name+    Name = "td2-sg-rds
 +  }
 } }
  
-module "storage" { +# Récupération du Security Group de l'application créé dans TD2 
-  source  = "./modules/storage+data "aws_security_group" "app" { 
-  kms_key_arn = module.kms.key_arn+  tags = { 
 +    Name = "td2-sg-app
 +  }
 } }
 +</sxh>
  
-module "logging" { +<WRAP round todo> 
-  source     = "./modules/logging+Vérifier dans le code TD2 que chaque ressource est bien taguée avec les valeurs attendues ci-dessus. 
-  account_id data.aws_caller_identity.current.account_id + 
-  kms_key_arn module.kms.key_arn+Si un tag est absent ou différent, le data source échouera avec une erreur `no matching resource found`. 
 + 
 +Corriger les tags dans TD2 si nécessaire avant de poursuivre. 
 +</WRAP> 
 + 
 +<WRAP round question> 
 +Que se passe-t-il si deux ressources AWS portent le même tag `Name` dans la même région ? 
 + 
 +Quel comportement Terraform adopte-t-il dans ce cas ? 
 +</WRAP> 
 + 
 +===== 2. Identification du problème ===== 
 + 
 +Objectif : identifier les secrets en clair dans l'infrastructure TD2. 
 + 
 +Voici un extrait du fichier `instances.tf` tel qu'il existe après le TD2. 
 + 
 +Fichier : `td2/instances.tf` — lecture seule, ne pas modifier 
 +<sxh js> 
 +resource "aws_db_instance" "db" { 
 +  identifier        = "td2-db
 +  engine            "postgres" 
 +  instance_class    "db.t3.micro" 
 +  allocated_storage = 20 
 + 
 +  username = "admin" 
 +  password = "S3cr3tP@ss!" 
 + 
 +  skip_final_snapshot = true
 } }
 </sxh> </sxh>
  
 <WRAP round question> <WRAP round question>
-Pourquoi utilise-t-on des data sources plutôt que de redéclarer les ressources du TD2 ?+Identifier au moins trois problèmes de sécurité dans ce bloc.
  
-Que se passerait-il si on redéclarait `aws_vpcavec le même CIDR dans un nouveau fichier Terraform ?+Pour chaque problème, expliquer la conséquence concrète en cas de fuite du fichier `.tfou du state Terraform.
 </WRAP> </WRAP>
  
-===== 3Gestion des secrets avec Secrets Manager =====+<WRAP round todo> 
 +Ne pas appliquer ce fichier tel quel.
  
-Objectif : supprimer le mot de passe en clair de `instances.tf`.+Ne pas modifier le TD2 non plus.
  
-<WRAP round todo> +La correction se fait uniquement dans TD3.
-Créer le module secrets.+
 </WRAP> </WRAP>
  
-Fichier : `td3/modules/secrets/main.tf`+===== 3. Création du module secrets ===== 
 + 
 +Objectif : stocker les identifiants de la base de données dans AWS Secrets Manager. 
 + 
 +Fichier : `td3/modules/secrets/variables.tf`
 <sxh js> <sxh js>
 +variable "secret_name" {
 +  type        = string
 +  description = "Nom du secret dans Secrets Manager"
 +  default     = "td3/db/credentials"
 +}
 +
 variable "db_username" { variable "db_username" {
   type        = string   type        = string
   description = "Nom d'utilisateur de la base de données"   description = "Nom d'utilisateur de la base de données"
-  default     = "admin"+  default     = "td3admin"
 } }
  
Ligne 183: Ligne 205:
   sensitive   = true   sensitive   = true
 } }
 +</sxh>
  
 +Fichier : `td3/modules/secrets/main.tf`
 +<sxh js>
 resource "aws_secretsmanager_secret" "db_credentials" { resource "aws_secretsmanager_secret" "db_credentials" {
-  name        = "td3/db/credentials+  name                    = var.secret_name 
-  description = "Identifiants de la base de donnees RDS TD3"+  recovery_window_in_days = 7 
 + 
 +  tags = { 
 +    Name = "td3-secret-db" 
 +    TD   = "td3" 
 +  }
 } }
  
 resource "aws_secretsmanager_secret_version" "db_credentials" { resource "aws_secretsmanager_secret_version" "db_credentials" {
   secret_id = aws_secretsmanager_secret.db_credentials.id   secret_id = aws_secretsmanager_secret.db_credentials.id
 +
   secret_string = jsonencode({   secret_string = jsonencode({
     username = var.db_username     username = var.db_username
Ligne 196: Ligne 227:
   })   })
 } }
 +</sxh>
  
 +Fichier : `td3/modules/secrets/outputs.tf`
 +<sxh js>
 output "secret_arn" { output "secret_arn" {
   value       = aws_secretsmanager_secret.db_credentials.arn   value       = aws_secretsmanager_secret.db_credentials.arn
-  description = "ARN du secret contenant les identifiants RDS"+  description = "ARN du secret contenant les identifiants de la base de données"
 } }
-</sxh> 
  
-Fichier : `td3/variables.tf` +output "secret_name" { 
-<sxh js> +  value       aws_secretsmanager_secret.db_credentials.name 
-variable "db_password" { +  description = "Nom du secret dans Secrets Manager"
-  type        string +
-  description = "Mot de passe initial de la base de donnees" +
-  sensitive   = true+
 } }
 </sxh> </sxh>
  
-Le mot de passe est transmis via une variable sensible, jamais écrit en dur.+<WRAP round question> 
 +Le paramètre `sensitive = true` sur la variable `db_password` masque la valeur dans les logs Terraform.
  
-Pour appliquer, Terraform demandera la valeur au moment de l'exécution :+Cela signifie-t-il que le mot de passe est chiffré dans le state Terraform ?
  
-Fichier : `td3/commandes/terraform.txt` +Où le mot de passe est-il stocké en clair malgré ce paramètre ? 
-<sxh bash> +</WRAP>
-# Appliquer en fournissant le mot de passe de maniere interactive +
-terraform apply -var="db_password=MonMotDePasse123!" +
- +
-# Ou via une variable d'environnement sans valeur dans le code +
-export TF_VAR_db_password="MonMotDePasse123!" +
-terraform apply +
-</sxh>+
  
 <WRAP round question> <WRAP round question>
-Pourquoi utilise-t-on `sensitive truesur la variable `db_password` ?+Le paramètre `recovery_window_in_days 7signifie que le secret n'est pas supprimé immédiatement.
  
-Que change ce paramètre dans l'affichage Terraform ?+Pourquoi AWS impose-t-il cette fenêtre de récupération par défaut ?
  
-Est-ce suffisant pour garantir que le mot de passe ne sera jamais visible ?+Comment forcer la suppression immédiate si nécessaire, et dans quel cas cela est-il risqué ?
 </WRAP> </WRAP>
  
-<WRAP round question> +===== 4. Erreur volontaire – secret introuvable =====
-Pourquoi utilise-t-on un JSON pour stocker le secret plutôt qu'une simple chaîne ?+
  
-Quel avantage cela apporte-t-il si l'application doit récupérer le secret programmatiquement ? +Objectif : comprendre ce qui se passe quand une application tente de lire un secret inexistant.
-</WRAP>+
  
-===== 4Problème volontaire – dépendance entre modules =====+Voici un data source intentionnellement incorrect. 
 + 
 +Fichier : `td3/debug/wrong_secret.tf` — ne pas appliquer 
 +<sxh js> 
 +data "aws_secretsmanager_secret" "db_credentials"
 +  name "td3/db/credential" 
 +
 +</sxh>
  
 <WRAP round todo> <WRAP round todo>
-Tenter d'appliquer uniquement le module secrets :+Lire le code ci-dessus sans l'appliquer.
  
-  terraform apply -target=module.secrets+Identifier l'erreur sans regarder la réponse ci-dessous.
  
-Puis observer ce qui se passe si on tente de lire le secret immédiatement dans le module storage sans `depends_on`.+Écrire la correction avant de lire la suite.
 </WRAP> </WRAP>
  
-<WRAP round question> +Le nom du secret dans Secrets Manager est `td3/db/credentials` avec un `s` final.
-Terraform gère les dépendances implicites entre ressources du même fichier.+
  
-Pourquoi cette dépendance implicite ne fonctionne-t-elle pas toujours entre modules différents ?+Le data source ci-dessus cherche `td3/db/credential` sans `s`. 
 + 
 +L'erreur retournée par Terraform sera : 
 + 
 +Fichier : `td3/debug/wrong_secret_error.txt` 
 +<sxh bash> 
 +Error: reading Secrets Manager Secret: ResourceNotFoundException: 
 +Secrets Manager can'find the specified secret. 
 +</sxh> 
 + 
 +<WRAP round question> 
 +Ce type d'erreur peut-il survenir en production alors que le secret existe bien ?
  
-Dans quels cas faut-il utiliser `depends_on` explicitement ?+Citer au moins deux situations réelles où cette erreur peut apparaître même si le nom est correct.
 </WRAP> </WRAP>
  
-===== 5. Création d'une clé KMS =====+===== 5. Récupération du secret dans RDS =====
  
-Objectif : créer une clé de chiffrement gérée par le client (CMK).+Objectif : utiliser le secret Secrets Manager dans la configuration RDS plutôt que des valeurs en clair.
  
-<WRAP round question+Fichier : `td3/modules/secrets/main.tf` — ajouter après les ressources existantes 
-AWS propose deux types de clés KMS : +<sxh js
-  * les clés AWS managées (aws/rds, aws/s3...) +data "aws_secretsmanager_secret_version" "db_credentials" { 
-  * les clés Customer Managed Keys (CMK)+  secret_id = aws_secretsmanager_secret.db_credentials.id
  
-Quelle est la différence concrète entre les deux en termes de contrôle ?+  depends_on = [aws_secretsmanager_secret_version.db_credentials] 
 +}
  
-Qui peut utiliser une clé AWS managée ?+locals { 
 +  db_secret = jsondecode( 
 +    data.aws_secretsmanager_secret_version.db_credentials.secret_string 
 +  ) 
 +
 +</sxh>
  
-Qui décide des droits d'accès sur une CMK ?+<WRAP round question> 
 +Pourquoi utilise-t-on `depends_on` ici ? 
 + 
 +Que se passerait-il si Terraform tentait de lire le secret avant que la version soit créée ?
 </WRAP> </WRAP>
  
-<WRAP round todo+===== 6. Création du module KMS ===== 
-Créer le module KMS.+ 
 +Objectif : créer une clé de chiffrement gérée par le client (Customer Managed Key) pour chiffrer les données au repos. 
 + 
 +<WRAP round question
 +Avant de créer la clé, répondre aux questions suivantes : 
 + 
 +Quelle est la différence entre une clé AWS managée et une CMK (Customer Managed Key) ? 
 + 
 +Dans quel cas une CMK est-elle obligatoire plutôt que recommandée ?
 </WRAP> </WRAP>
  
-Fichier : `td3/modules/kms/main.tf`+Fichier : `td3/modules/kms/variables.tf`
 <sxh js> <sxh js>
-variable "account_id" {+variable "key_alias" {
   type        = string   type        = string
-  description = "ID du compte AWS courant"+  description = "Alias de la clé KMS" 
 +  default     = "alias/td3-key"
 } }
  
-variable "region" {+variable "account_id" {
   type        = string   type        = string
-  description = "Region AWS courante"+  description = "ID du compte AWS courant"
 } }
 +</sxh>
 +
 +Fichier : `td3/modules/kms/main.tf`
 +<sxh js>
 +data "aws_caller_identity" "current" {}
  
-resource "aws_kms_key" "td3" { +resource "aws_kms_key" "main" { 
-  description             = "Cle KMS TD3 – chiffrement RDS et S3" +  description             = "Clé KMS TD3 – chiffrement RDS et S3" 
-  deletion_window_in_days = 7+  deletion_window_in_days = 10
   enable_key_rotation     = true   enable_key_rotation     = true
  
Ligne 299: Ligne 361:
     Statement = [     Statement = [
       {       {
-        Sid    = "Acces administrateur au compte"+        Sid    = "EnableRootAccess"
         Effect = "Allow"         Effect = "Allow"
         Principal = {         Principal = {
Ligne 309: Ligne 371:
     ]     ]
   })   })
 +
 +  tags = {
 +    Name = "td3-kms-key"
 +    TD   = "td3"
 +  }
 } }
  
-resource "aws_kms_alias" "td3" { +resource "aws_kms_alias" "main" { 
-  name          = "alias/td3-key" +  name          = var.key_alias 
-  target_key_id = aws_kms_key.td3.id+  target_key_id = aws_kms_key.main.key_id
 } }
 +</sxh>
  
 +Fichier : `td3/modules/kms/outputs.tf`
 +<sxh js>
 output "key_arn" { output "key_arn" {
-  value       = aws_kms_key.td3.arn +  value       = aws_kms_key.main.arn 
-  description = "ARN de la cle KMS TD3"+  description = "ARN de la clé KMS"
 } }
  
 output "key_id" { output "key_id" {
-  value       = aws_kms_key.td3.id +  value       = aws_kms_key.main.key_id 
-  description = "ID de la cle KMS TD3"+  description = "ID de la clé KMS"
 } }
 </sxh> </sxh>
  
 <WRAP round question> <WRAP round question>
-Le paramètre `deletion_window_in_days 7est défini sur la clé KMS.+Le paramètre `enable_key_rotation trueactive la rotation automatique de la clé.
  
-Que se passe-t-il si on supprime cette clé alors que des données RDS ou S3 sont chiffrées avec elle ?+Que signifie concrètement la rotation d'une clé KMS ?
  
-Pourquoi AWS impose-t-il un délai minimum avant la suppression effective d'une clé ?+Les données chiffrées avec l'ancienne version de la clé deviennent-elles inaccessibles après rotation ?
 </WRAP> </WRAP>
  
 <WRAP round question> <WRAP round question>
-Le paramètre `enable_key_rotation = trueest activé.+La policy KMS donne accès à `arn:aws:iam::ACCOUNT_ID:root`.
  
-Que signifie la rotation d'une clé KMS concrètement ?+Pourquoi cette entrée est-elle obligatoire dans une policy KMS ?
  
-La rotation de la clé KMS invalide-t-elle les données déjà chiffrées avec l'ancienne version ?+Que se passe-t-il si elle est absente ?
 </WRAP> </WRAP>
  
-<WRAP round question> +===== 7Création du module storage =====
-La key policy autorise `kms:*` pour le root du compte.+
  
-Pourquoi cette règle est-elle nécessaire dans une key policy ?+Objectif : déployer une instance RDS chiffrée et un bucket S3 chiffré en utilisant la clé KMS du module précédent.
  
-Que se passerait-il si on supprimait cette règle et qu'aucun autre principal n'était autorisé ? +Fichier : `td3/modules/storage/variables.tf`
-</WRAP> +
- +
-===== 6. Chiffrement de la base de données RDS ===== +
- +
-Objectif activer le chiffrement au repos sur RDS avec la CMK. +
- +
-<WRAP round todo> +
-Modifier `td2/network/instances.tf` pour activer le chiffrement et utiliser le secret Secrets Manager. +
-</WRAP> +
- +
-Fichier : `td2/network/instances.tf`+
 <sxh js> <sxh js>
-# Recuperation du secret cree dans le module TD3 +variable "kms_key_arn" { 
-data "aws_secretsmanager_secret_version" "db_credentials" { +  type        = string 
-  secret_id = "td3/db/credentials"+  description = "ARN de la clé KMS utilisée pour le chiffrement" 
 +}
  
-  depends_on +variable "db_username"
-    aws_secretsmanager_secret_version.db_credentials +  type        string 
-  ]+  description = "Nom d'utilisateur transmis depuis Secrets Manager"
 } }
  
-locals +variable "db_password" 
-  db_secret jsondecode( +  type        string 
-    data.aws_secretsmanager_secret_version.db_credentials.secret_string +  description = "Mot de passe transmis depuis Secrets Manager" 
-  )+  sensitive   = true
 } }
  
-resource "aws_instance" "backend" { +variable "subnet_ids" { 
-  ami                    "ami-0f61de2873e29e866" +  type        list(string) 
-  instance_type          = "t2.micro+  description = "Liste des IDs de subnets privés récupérés depuis TD2
-  subnet_id              = aws_subnet.private.id +}
-  vpc_security_group_ids = [aws_security_group.backend_sg.id]+
  
-  user_data = <<-EOF +variable "security_group_id" { 
-    #!/bin/bash +  type        = string 
-    yum install -y python3 +  description = "ID du Security Group RDS récupéré depuis TD2"
-    python3 -m http.server 80 & +
-  EOF +
- +
-  tags = { +
-    Name = "td2-backend" +
-  }+
 } }
  
-resource "aws_db_instance" "db" { +variable "bucket_name" { 
-  identifier             = "td3-db" +  type        string 
-  engine                 = "postgres" +  description = "Nom du bucket S3 applicatif"
-  engine_version         = "15" +
-  instance_class         = "db.t3.micro" +
-  allocated_storage      = 20 +
- +
-  username = local.db_secret.username +
-  password = local.db_secret.password +
- +
-  storage_encrypted = true +
-  kms_key_id        var.kms_key_arn +
- +
-  db_subnet_group_name   = aws_db_subnet_group.main.name +
-  vpc_security_group_ids = [aws_security_group.db_sg.id] +
-  skip_final_snapshot    = true +
- +
-  tags = { +
-    Name = "td3-db" +
-  }+
 } }
 +</sxh>
  
 +Fichier : `td3/modules/storage/main.tf`
 +<sxh js>
 resource "aws_db_subnet_group" "main" { resource "aws_db_subnet_group" "main" {
   name       = "td3-db-subnet-group"   name       = "td3-db-subnet-group"
-  subnet_ids = [aws_subnet.private.id, aws_subnet.public_b.id]+  subnet_ids = var.subnet_ids
  
   tags = {   tags = {
     Name = "td3-db-subnet-group"     Name = "td3-db-subnet-group"
 +    TD   = "td3"
   }   }
 } }
  
-variable "kms_key_arn" { +resource "aws_db_instance" "db" { 
-  type        string +  identifier        "td3-db" 
-  description = "ARN de la cle KMS utilisee pour le chiffrement RDS+  engine            = "postgres
-} +  engine_version    = "15" 
-</sxh>+  instance_class    = "db.t3.micro" 
 +  allocated_storage = 20
  
-<WRAP round question> +  username = var.db_username 
-Le chiffrement `storage_encrypted true` protège les données au repos.+  password var.db_password
  
-Quel mécanisme protège les données en transit entre le backend et RDS ?+  db_subnet_group_name   = aws_db_subnet_group.main.name 
 +  vpc_security_group_ids = [var.security_group_id]
  
-Le chiffrement au repos protège-t-il contre un accès non autorisé via SQL si les credentials sont compromis ? +  storage_encrypted = true 
-</WRAP>+  kms_key_id        = var.kms_key_arn
  
-<WRAP round question> +  skip_final_snapshot = true
-L'identifiant de la base est passé de `td2-db` à `td3-db`.+
  
-Que se passe-t-il si on tente de modifier `storage_encrypted` sur une instance RDS existante ? +  tags = { 
- +    Name "td3-db" 
-Pourquoi AWS impose-t-il cette contrainte ? +    TD   "td3" 
-</WRAP> +  }
- +
-===== 7. Problème volontaire – chiffrement RDS immuable ===== +
- +
-<WRAP round todo> +
-Tenter de modifier une instance RDS existante non chiffrée pour activer le chiffrement : +
- +
-  terraform apply +
- +
-Observer le message d'erreur Terraform. +
-</WRAP> +
- +
-<WRAP round question> +
-Terraform indique qu'il doit détruire et recréer l'instance RDS. +
- +
-Pourquoi le chiffrement d'une instance RDS ne peut-il pas être activé à chaud ? +
- +
-Quelles précautions prendre en production avant de forcer cette opération ? +
-</WRAP> +
- +
-===== 8. Création d'un bucket S3 sécurisé ===== +
- +
-Objectif : créer un bucket S3 avec chiffrement SSE-KMS et blocage d'accès public. +
- +
-<WRAP round todo> +
-Créer le module storage. +
-</WRAP> +
- +
-Fichier : `td3/modules/storage/main.tf` +
-<sxh js> +
-variable "kms_key_arn" { +
-  type        = string +
-  description = "ARN de la cle KMS utilisee pour le chiffrement S3"+
 } }
  
-resource "random_id" "bucket_suffix"+resource "aws_s3_bucket" "app" { 
-  byte_length = 4 +  bucket = var.bucket_name
-+
- +
-resource "aws_s3_bucket" "app_data" { +
-  bucket = "td3-app-data-${random_id.bucket_suffix.hex}"+
  
   tags = {   tags = {
-    Name = "td3-app-data"+    Name = "td3-s3-app" 
 +    TD   = "td3"
   }   }
 } }
  
-resource "aws_s3_bucket_public_access_block" "app_data"+resource "aws_s3_bucket_server_side_encryption_configuration" "app" { 
-  bucket = aws_s3_bucket.app_data.id +  bucket = aws_s3_bucket.app.id
- +
-  block_public_acls       = true +
-  block_public_policy     = true +
-  ignore_public_acls      = true +
-  restrict_public_buckets = true +
-+
- +
-resource "aws_s3_bucket_server_side_encryption_configuration" "app_data" { +
-  bucket = aws_s3_bucket.app_data.id+
  
   rule {   rule {
Ligne 512: Ligne 508:
 } }
  
-output "bucket_name" { +resource "aws_s3_bucket_public_access_block" "app" { 
-  value       = aws_s3_bucket.app_data.id +  bucket = aws_s3_bucket.app.id 
-  description "Nom du bucket S3 applicatif"+ 
 +  block_public_acls       true 
 +  block_public_policy     = true 
 +  ignore_public_acls      = true 
 +  restrict_public_buckets = true
 } }
 </sxh> </sxh>
  
 <WRAP round question> <WRAP round question>
-Dans ce TD la valeur de `sse_algorithmest `aws:kms`.+Le chiffrement `storage_encrypted = truesur RDS protège-t-il les données en transit ou au repos ?
  
-Dans le TD précédent la valeur était `AES256`. +Quel mécanisme protège les données en transit entre l'application et RDS ?
- +
-Quelle est la différence concrète entre ces deux modes de chiffrement S3 ? +
- +
-Quel mode offre le plus de contrôle sur la clé de chiffrement ?+
 </WRAP> </WRAP>
  
 <WRAP round question> <WRAP round question>
-Le paramètre `bucket_key_enabled = true` est activé.+Le paramètre `bucket_key_enabled = true` est activé sur le bucket S3.
  
-Rechercher ce que fait ce paramètre.+Rechercher dans la documentation AWS ce que cette option apporte.
  
-Quel impact a-t-il sur les coûts liés à KMS ?+Quel est l'impact sur les coûts et les performances ?
 </WRAP> </WRAP>
  
-<WRAP round question> +===== 8Erreur volontaire – chiffrement impossible =====
-Les quatre paramètres de `aws_s3_bucket_public_access_block` sont tous à `true`.+
  
-Expliquer ce que bloque concrètement chacun des quatre paramètres.+Objectif : comprendre pourquoi RDS ne peut pas chiffrer une instance existante non chiffrée.
  
-Pourquoi ce bloc est-il indépendant du chiffrement +Imaginer le scénario suivant : une instance RDS existe déjà en production sans chiffrement, et un ingénieur ajoute `storage_encrypted = true` et `kms_key_id` dans le fichier Terraform, puis applique le changement.
-</WRAP>+
  
-===== 9Mise en place du logging avec CloudTrail =====+<WRAP round question> 
 +Avant de chercher la réponse, réfléchir à ce qui va se passer.
  
-Objectif : tracer toutes les actions réalisées sur le compte AWS.+Est-ce que Terraform va modifier l'instance en place ? 
 + 
 +Est-ce que le chiffrement peut être activé sur une instance RDS existante sans interruption ? 
 + 
 +Quelle est la procédure correcte dans ce cas ? 
 +</WRAP>
  
 <WRAP round todo> <WRAP round todo>
-Créer le module logging.+Rechercher dans la documentation AWS RDS la section relative au chiffrement d'une instance existante. 
 + 
 +Décrire en cinq étapes la procédure à suivre pour migrer une instance non chiffrée vers une instance chiffrée.
 </WRAP> </WRAP>
  
-Fichier : `td3/modules/logging/main.tf`+===== 9. Création du module logging ===== 
 + 
 +Objectif : activer CloudTrail pour conserver une trace de toutes les actions réalisées sur le compte AWS. 
 + 
 +Fichier : `td3/modules/logging/variables.tf`
 <sxh js> <sxh js>
-variable "account_id" {+variable "bucket_name" {
   type        = string   type        = string
-  description = "ID du compte AWS courant"+  description = "Nom du bucket S3 destiné à recevoir les logs CloudTrail"
 } }
  
 variable "kms_key_arn" { variable "kms_key_arn" {
   type        = string   type        = string
-  description = "ARN de la cle KMS utilisee pour le chiffrement des logs"+  description = "ARN de la clé KMS pour chiffrer les logs CloudTrail"
 } }
  
-resource "random_id" "bucket_suffix" { +variable "account_id" { 
-  byte_length 4+  type        string 
 +  description = "ID du compte AWS courant"
 } }
 +</sxh>
  
-resource "aws_s3_bucket" "cloudtrail_logs" { +Fichier : `td3/modules/logging/main.tf` 
-  bucket = "td3-cloudtrail-${var.account_id}-${random_id.bucket_suffix.hex}"+<sxh js> 
 +resource "aws_s3_bucket" "cloudtrail" { 
 +  bucket = var.bucket_name
  
   tags = {   tags = {
-    Name = "td3-cloudtrail-logs"+    Name = "td3-s3-cloudtrail" 
 +    TD   = "td3"
   }   }
 } }
  
-resource "aws_s3_bucket_public_access_block" "cloudtrail_logs" { +resource "aws_s3_bucket_public_access_block" "cloudtrail" { 
-  bucket = aws_s3_bucket.cloudtrail_logs.id+  bucket = aws_s3_bucket.cloudtrail.id
  
   block_public_acls       = true   block_public_acls       = true
Ligne 585: Ligne 596:
 } }
  
-resource "aws_s3_bucket_policy" "cloudtrail_logs" { +resource "aws_s3_bucket_policy" "cloudtrail" { 
-  bucket = aws_s3_bucket.cloudtrail_logs.id+  bucket = aws_s3_bucket.cloudtrail.id
  
   policy = jsonencode({   policy = jsonencode({
Ligne 598: Ligne 609:
         }         }
         Action   = "s3:GetBucketAcl"         Action   = "s3:GetBucketAcl"
-        Resource = aws_s3_bucket.cloudtrail_logs.arn+        Resource = aws_s3_bucket.cloudtrail.arn
       },       },
       {       {
Ligne 607: Ligne 618:
         }         }
         Action   = "s3:PutObject"         Action   = "s3:PutObject"
-        Resource = "${aws_s3_bucket.cloudtrail_logs.arn}/AWSLogs/${var.account_id}/*"+        Resource = "${aws_s3_bucket.cloudtrail.arn}/AWSLogs/${var.account_id}/*"
         Condition = {         Condition = {
           StringEquals = {           StringEquals = {
Ligne 620: Ligne 631:
 resource "aws_cloudtrail" "main" { resource "aws_cloudtrail" "main" {
   name                          = "td3-cloudtrail"   name                          = "td3-cloudtrail"
-  s3_bucket_name                = aws_s3_bucket.cloudtrail_logs.id+  s3_bucket_name                = aws_s3_bucket.cloudtrail.id
   include_global_service_events = true   include_global_service_events = true
   is_multi_region_trail         = false   is_multi_region_trail         = false
Ligne 626: Ligne 637:
   kms_key_id                    = var.kms_key_arn   kms_key_id                    = var.kms_key_arn
  
-  depends_on [ +  tags { 
-    aws_s3_bucket_policy.cloudtrail_logs +    Name = "td3-cloudtrail" 
-  ]+    TD   = "td3" 
 +  
 + 
 +  depends_on = [aws_s3_bucket_policy.cloudtrail]
 } }
 +</sxh>
  
 +Fichier : `td3/modules/logging/outputs.tf`
 +<sxh js>
 output "cloudtrail_arn" { output "cloudtrail_arn" {
   value       = aws_cloudtrail.main.arn   value       = aws_cloudtrail.main.arn
   description = "ARN du trail CloudTrail"   description = "ARN du trail CloudTrail"
 +}
 +
 +output "cloudtrail_bucket" {
 +  value       = aws_s3_bucket.cloudtrail.bucket
 +  description = "Nom du bucket contenant les logs CloudTrail"
 } }
 </sxh> </sxh>
  
 <WRAP round question> <WRAP round question>
-La bucket policy pour CloudTrail contient deux statements distincts.+Le paramètre `enable_log_file_validation = true` active la validation de l'intégrité des fichiers de logs.
  
-Expliquer le rôle de chacun : +Quel problème cela permet-il de détecter ?
-  * `AWSCloudTrailAclCheck` +
-  * `AWSCloudTrailWrite`+
  
-Que se passerait-il si cette policy était absente ?+Quel mécanisme technique AWS utilise-t-il pour garantir cette intégrité ?
 </WRAP> </WRAP>
  
 <WRAP round question> <WRAP round question>
-Le paramètre `enable_log_file_validation = true` est activé.+CloudTrail trace les appels API AWS.
  
-Que permet concrètement la validation des fichiers de log ?+Citer trois exemples d'actions tracées par CloudTrail dans le cadre de ce TD.
  
-Dans quel scénario cette fonctionnalité est-elle particulièrement utile ?+Citer deux exemples d'actions qui ne sont pas tracées par CloudTrail.
 </WRAP> </WRAP>
  
-<WRAP round question> +===== 10Assemblage dans main.tf =====
-CloudTrail enregistre les appels API réalisés sur le compte AWS.+
  
-Cocher parmi ces actions celles qui sont tracées par CloudTrail : +Objectif relier tous les modules entre eux et injecter les data sources TD2 dans les modules TD3.
-  * création d'un Security Group +
-  * modification d'une règle IAM +
-  * upload d'un fichier dans S3 +
-  * requête SQL vers RDS +
-  * connexion SSH vers une instance EC2 +
-  * suppression d'un secret Secrets Manager+
  
-Justifier les réponses non évidentes+Fichier : `td3/variables.tf` 
-</WRAP>+<sxh js> 
 +variable "db_password"
 +  type        = string 
 +  description = "Mot de passe de la base de données – ne pas committer" 
 +  sensitive   = true 
 +}
  
-===== 10. Simulation d'un incident =====+variable "s3_app_bucket_name"
 +  type        string 
 +  description "Nom du bucket S3 applicatif" 
 +  default     "td3-app-bucket-demo" 
 +}
  
-Objectif : utiliser CloudTrail pour retracer une action suspecte.+variable "s3_logs_bucket_name"
 +  type        = string 
 +  description = "Nom du bucket S3 pour les logs CloudTrail" 
 +  default     = "td3-cloudtrail-logs-demo" 
 +
 +</sxh>
  
-<WRAP round todo+Fichier : `td3/main.tf` — compléter après les data sources 
-Réaliser une action volontairement suspecte dans AWS.+<sxh js
 +data "aws_caller_identity" "current" {}
  
-Modifier un Security Group existant du TD2 pour ouvrir temporairement le port 22 depuis `0.0.0.0/0` :+module "kms"
 +  source     = "./modules/kms" 
 +  account_id = data.aws_caller_identity.current.account_id 
 +}
  
-  terraform apply -target=module.network+module "secrets"
 +  source      = "./modules/secrets" 
 +  db_username = "td3admin" 
 +  db_password = var.db_password 
 +}
  
-Attendre deux minutes, puis supprimer cette règle :+module "storage"
 +  source = "./modules/storage"
  
-  terraform apply +  kms_key_arn = module.kms.key_arn
-</WRAP>+
  
-<WRAP round todo> +  db_username = module.secrets.db_username 
-Aller dans la console AWS.+  db_password = module.secrets.db_password
  
-Naviguer vers : CloudTrail > Event history.+  subnet_ids = [ 
 +    data.aws_subnet.private.id, 
 +    data.aws_subnet.private_b.id 
 +  ]
  
-Rechercher l'événement `AuthorizeSecurityGroupIngress`.+  security_group_id = data.aws_security_group.rds.id
  
-Identifier : +  bucket_name = var.s3_app_bucket_name 
-  * l'heure de l'action +
-  * l'identité qui a réalisé l'action + 
-  * les paramètres de la règle ajoutée +module "logging" { 
-</WRAP>+  source      = "./modules/logging" 
 +  bucket_name = var.s3_logs_bucket_name 
 +  kms_key_arn = module.kms.key_arn 
 +  account_id  = data.aws_caller_identity.current.account_id 
 +} 
 +</sxh>
  
 <WRAP round question> <WRAP round question>
-CloudTrail enregistre l'identité qui a réalisé chaque action.+Le module `secrets` expose `db_username` et `db_password` via ses outputs.
  
-Si plusieurs développeurs partagent le même utilisateur IAM, que perd-on en termes de traçabilité ?+Regarder la définition des outputs dans `td3/modules/secrets/outputs.tf`.
  
-Quel principe de gestion des identités du TD1 est directement lié à cette problématique ?+Que faut-il ajouter sur l'output `db_password` pour que la valeur ne s'affiche pas dans le terminal lors d'un `terraform output` ?
 </WRAP> </WRAP>
  
-<WRAP round question+Fichier : `td3/modules/secrets/outputs.tf` — ajouter les outputs manquants 
-Les logs CloudTrail sont stockés dans S3.+<sxh js
 +output "db_username"
 +  value       = var.db_username 
 +  description = "Nom d'utilisateur de la base de données" 
 +}
  
-Par défaut, combien de temps sont-ils conservés dans CloudTrail Event History ?+output "db_password"
 +  value       = var.db_password 
 +  description = "Mot de passe de la base de données" 
 +  sensitive   = true 
 +
 +</sxh>
  
-Pourquoi stocker les logs dans S3 permet-il une conservation plus longue ? +===== 11. Déploiement et vérification =====
-</WRAP>+
  
-===== 11Vérification globale =====+Fichier : `td3/commandes/terraform.txt` 
 +<sxh bash> 
 +# Se placer dans le dossier td3 
 +cd tp-aws/td3
  
-<WRAP round todo> +# Initialiser le projet 
-Vérifier les points suivants dans le code Terraform et dans la console AWS :+terraform init
  
-  * le mot de passe n'apparaît plus dans aucun fichier `.tf` +# Vérifier le plan – inspecter les ressources créées et les data sources résolus 
-  * la variable `db_password` est marquée `sensitive = true` +terraform plan -var="db_password=VotreMotDePasse123!"
-  * la base RDS a `storage_encrypted = true` et un `kms_key_id` renseigné +
-  * le bucket S3 applicatif a `sse_algorithm = "aws:kms"+
-  * le bucket S3 applicatif a les quatre paramètres `public_access_block` à `true` +
-  * CloudTrail est actif et écrit dans son bucket dédié +
-  * la clé KMS a `enable_key_rotation = true` +
-</WRAP>+
  
-===== Challenge final =====+# Appliquer 
 +terraform apply -var="db_password=VotreMotDePasse123!"
  
-**Axe secrets**+# Vérifier les outputs 
 +terraform output 
 + 
 +# Vérifier le secret dans AWS CLI 
 +aws secretsmanager get-secret-value --secret-id td3/db/credentials --region eu-west-3 
 + 
 +# Vérifier que le bucket S3 est bien chiffré 
 +aws s3api get-bucket-encryption --bucket td3-app-bucket-demo --region eu-west-3 
 + 
 +# Vérifier que CloudTrail est actif 
 +aws cloudtrail get-trail-status --name td3-cloudtrail --region eu-west-3 
 +</sxh>
  
 <WRAP round todo> <WRAP round todo>
-Répondre aux questions suivantes par écrit :+Après le déploiement, vérifier manuellement dans la console AWS :
  
-  * Où est stocké physiquement le secret de la base après le TD3 ? +  * Secrets Manager : le secret `td3/db/credentials` est visible et déchiffrable 
-  * Qui peut lire ce secret dans AWS ? +  * KMS : la clé `alias/td3-key` est active avec rotation activée 
-  * Que se passe-t-il si le secret Secrets Manager est lui-même chiffré avec la clé KMS TD3 et que cette clé est supprimée ? +  * RDS : l'instance `td3-db` indique `Encrypted: Yes` dans ses propriétés 
-  * Quelles seraient les trois premières actions à réaliser si le mot de passe de la base était compromis ?+  * S3 : le bucket applicatif indique `SSE-KMS` dans ses propriétés de chiffrement 
 +  * CloudTrail : le trail `td3-cloudtrail` est actif et envoie des logs dans le bucket
 </WRAP> </WRAP>
  
-**Axe KMS**+===== 12. Lecture des logs CloudTrail =====
  
-<WRAP round question> +Objectif : naviguer dans les logs CloudTrail pour retrouver une action spécifique.
-La clé KMS est utilisée à la fois pour RDS, S3 et CloudTrail.+
  
-Quels sont les avantages de centraliser sur une seule clé ?+<WRAP round todo> 
 +Dans la console AWS, ouvrir CloudTrail puis Event History.
  
-Quels sont les risques de cette approche ?+Filtrer les événements par type `CreateSecret`.
  
-Comment organiserait-on les clés KMS dans un environnement de production avec plusieurs équipes et plusieurs applications ? +Retrouver l'événement correspondant à la création du secret TD3.
-</WRAP>+
  
-**Axe chiffrement**+Identifier les champs suivants dans l'événement : 
 + 
 +  `userIdentity` : qui a réalisé l'action 
 +  `eventTime` : quand 
 +  `sourceIPAddress` : depuis quelle IP 
 +  `requestParameters` : quel secret a été créé 
 +</WRAP>
  
 <WRAP round question> <WRAP round question>
-Dresser un tableau récapitulatif avec les colonnes suivantes :+Un collègue vous signale qu'une clé KMS a été désactivée à 3h du matin sans explication.
  
-  * Ressource (RDS, S3, Secrets Manager, CloudTrail+Quelle requête effectuer dans CloudTrail pour retrouver cet événement ?
-  * Type de chiffrement (au repos, en transit, les deux) +
-  * Algorithme ou mécanisme utilisé +
-  * Clé utilisée (AWS managée ou CMK TD3)+
  
-Dans quel cas le chiffrement AES256 de S3 ne suffit-il pas à garantir la confidentialité des données ?+Quels champs de l'événement permettent d'identifier l'auteur de l'action ?
 </WRAP> </WRAP>
  
-**Axe traçabilité**+===== Challenge final =====
  
-<WRAP round question> +L'audit de sécurité est terminé.
-Un stagiaire supprime accidentellement la ressource CloudTrail via `terraform destroy` sur le module logging.+
  
-Quelles sont les conséquences immédiates pour la traçabilité du compte ?+Rédiger un rapport de remédiation qui couvre les quatre axes suivants.
  
-Comment aurait-on pu protéger cette ressource contre une suppression accidentelle ?+**Axe 1 – Secrets**
  
-Rechercher le paramètre Terraform qui permet de protéger une ressource contre la destruction+Expliquer comment les identifiants RDS sont maintenant gérés. 
-</WRAP>+ 
 +Comparer l'état avant TD3 et l'état après TD3. 
 + 
 +Indiquer ce qui resterait à améliorer si l'application backend devait récupérer elle-même le secret. 
 + 
 +**Axe 2 – Clés KMS** 
 + 
 +Décrire le cycle de vie de la clé créée dans ce TD. 
 + 
 +Expliquer ce qui se passe lors de la rotation automatique. 
 + 
 +Indiquer le délai de suppression et pourquoi il est important. 
 + 
 +**Axe 3 – Chiffrement des données** 
 + 
 +Compléter le tableau suivant : 
 + 
 +Fichier : `td3/rapport/chiffrement.md` 
 +<sxh bash> 
 +| Ressource  | Type de chiffrement | Clé utilisée        | Données protégées         | 
 +|------------|---------------------|---------------------|---------------------------| 
 +| RDS        | SSE-KMS             | CMK alias/td3-key   | Données au repos          | 
 +| S3 app     | SSE-KMS             | CMK alias/td3-key   | Objets stockés            | 
 +| S3 logs    | ?                   | ?                   | ?                         | 
 +| Transit RDS| ?                   | ?                   | ?                         | 
 +</sxh> 
 + 
 +**Axe 4 – Traçabilité** 
 + 
 +Décrire ce que CloudTrail trace dans le contexte de ce TD. 
 + 
 +Expliquer pourquoi le bucket de logs est lui-même protégé par une policy stricte.
  
-**Axe architecture**+Indiquer comment détecter une tentative de suppression des logs CloudTrail.
  
 <WRAP round todo> <WRAP round todo>
-Produire un schéma de l'architecture complète en prolongement du schéma réalisé au TD2.+Produire un schéma de l'infrastructure TD3 complète incluant :
  
-Le schéma doit inclure : +  toutes les ressources déployées dans TD3 
-  * les composants du TD2 : ALB, backend, Security Groups, subnets +  * les ressources récupérées en data sources depuis TD2
-  * les ajouts du TD3 : Secrets Manager, KMS, RDS chiffré, S3 applicatif, CloudTrail et son bucket+
   * les flux de données entre chaque composant avec les ports concernés   * les flux de données entre chaque composant avec les ports concernés
   * une légende distinguant les flux chiffrés et les flux non chiffrés   * une légende distinguant les flux chiffrés et les flux non chiffrés
  • eadl/bloc4/fm4/td3.1782281412.txt.gz
  • Dernière modification : il y a 3 semaines
  • de jcheron