Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentes Révision précédente | |||
| eadl:bloc4:fm4:td3 [2026/06/24 08:10] – jcheron | eadl: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 = " | ||
| * ALB opérationnel, | * ALB opérationnel, | ||
| * 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' | + | Le TD3 est un projet Terraform indépendant. |
| + | |||
| + | Il ne modifie pas le code du TD2. | ||
| + | |||
| + | Il récupère | ||
| Fichier : `td3/ | Fichier : `td3/ | ||
| <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 | + | └── |
| - | └── modules/ | + | ├── main.tf |
| - | ├── secrets/ | + | ├── variables.tf |
| - | │ └── main.tf | + | ├── outputs.tf |
| - | ├── kms/ | + | └── modules/ |
| - | │ └── main.tf | + | ├── secrets/ |
| - | ├── storage/ | + | │ ├── main.tf |
| - | │ └── main.tf | + | |
| - | └── | + | │ |
| - | └── main.tf | + | |
| + | │ ├── main.tf | ||
| + | | ||
| + | │ | ||
| + | | ||
| + | │ ├── main.tf | ||
| + | | ||
| + | │ └── | ||
| + | └── logging/ | ||
| + | ├── main.tf | ||
| + | ├── variables.tf | ||
| + | └── outputs.tf | ||
| </ | </ | ||
| - | Le fichier `td3/main.tf` orchestre les quatre modules et récupère les ressources du TD2 via des data sources. | + | ===== 1. Récupération des ressources du TD2 ===== |
| - | ===== 1. Analyse de l' | + | Objectif : comprendre comment un projet Terraform peut interroger une infrastructure existante sans accéder à son state. |
| - | Lire le fichier `td2/ | + | 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 round question> | <WRAP round question> | ||
| - | Dans `td2/ | + | Pourquoi TD3 ne peut-il |
| - | + | ||
| - | Quelle est la valeur par défaut de ce paramètre dans AWS ? | + | |
| - | Comment vérifier l' | + | Quelle est la différence entre un data source |
| </ | </ | ||
| - | |||
| - | <WRAP round question> | ||
| - | Aucun service de logging n'est présent dans le TD2. | ||
| - | |||
| - | Citer deux situations concrètes en production où l' | ||
| - | </ | ||
| - | |||
| - | ===== 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/ | Fichier : `td3/ | ||
| <sxh js> | <sxh js> | ||
| - | terraform { | ||
| - | required_providers { | ||
| - | aws = { | ||
| - | source | ||
| - | version = "~> 5.0" | ||
| - | } | ||
| - | random = { | ||
| - | source | ||
| - | version = "~> 3.0" | ||
| - | } | ||
| - | } | ||
| - | } | ||
| - | |||
| provider " | provider " | ||
| region = " | region = " | ||
| } | } | ||
| - | # Recuperation du compte AWS courant | + | # Récupération |
| - | data " | + | data " |
| - | + | | |
| - | # Recuperation de la region courante | + | Name = " |
| - | data " | + | |
| - | + | ||
| - | # Recuperation | + | |
| - | data " | + | |
| - | | + | |
| - | | + | |
| - | values | + | |
| } | } | ||
| } | } | ||
| - | # Recuperation du Security Group backend | + | # Récupération |
| - | data "aws_security_group" "backend_sg" { | + | data "aws_subnet" "private" { |
| - | | + | |
| - | | + | Name = "td2-private" |
| - | values | + | |
| } | } | ||
| } | } | ||
| - | module | + | # Récupération du subnet privé secondaire créé dans TD2 |
| - | | + | data "aws_subnet" |
| + | | ||
| + | Name = "td2-private-b" | ||
| + | } | ||
| } | } | ||
| - | module | + | # Récupération du Security Group RDS créé dans TD2 |
| - | | + | data "aws_security_group" |
| - | | + | |
| - | region | + | Name = "td2-sg-rds" |
| + | | ||
| } | } | ||
| - | module | + | # Récupération du Security Group de l' |
| - | | + | data "aws_security_group" |
| - | | + | |
| + | Name = "td2-sg-app" | ||
| + | | ||
| } | } | ||
| + | </ | ||
| - | module | + | <WRAP round todo> |
| - | | + | Vérifier dans le code TD2 que chaque ressource est bien taguée avec les valeurs attendues ci-dessus. |
| - | | + | |
| - | | + | 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 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 ? | ||
| + | </ | ||
| + | |||
| + | ===== 2. Identification du problème ===== | ||
| + | |||
| + | Objectif : identifier les secrets en clair dans l' | ||
| + | |||
| + | Voici un extrait du fichier `instances.tf` tel qu'il existe après le TD2. | ||
| + | |||
| + | Fichier : `td2/ | ||
| + | <sxh js> | ||
| + | resource " | ||
| + | | ||
| + | | ||
| + | | ||
| + | allocated_storage = 20 | ||
| + | |||
| + | username = " | ||
| + | password = " | ||
| + | |||
| + | skip_final_snapshot = true | ||
| } | } | ||
| </ | </ | ||
| <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 |
| - | Que se passerait-il si on redéclarait | + | Pour chaque problème, expliquer la conséquence concrète en cas de fuite du fichier |
| </ | </ | ||
| - | ===== 3. Gestion des secrets avec Secrets Manager ===== | + | <WRAP round todo> |
| + | Ne pas appliquer ce fichier tel quel. | ||
| - | Objectif : supprimer | + | Ne pas modifier |
| - | <WRAP round todo> | + | La correction se fait uniquement dans TD3. |
| - | Créer le module secrets. | + | |
| </ | </ | ||
| - | Fichier : `td3/ | + | ===== 3. Création du module secrets ===== |
| + | |||
| + | Objectif : stocker les identifiants de la base de données dans AWS Secrets Manager. | ||
| + | |||
| + | Fichier : `td3/ | ||
| <sxh js> | <sxh js> | ||
| + | variable " | ||
| + | type = string | ||
| + | description = "Nom du secret dans Secrets Manager" | ||
| + | default | ||
| + | } | ||
| + | |||
| variable " | variable " | ||
| type = string | type = string | ||
| description = "Nom d' | description = "Nom d' | ||
| - | default | + | default |
| } | } | ||
| Ligne 183: | Ligne 205: | ||
| sensitive | sensitive | ||
| } | } | ||
| + | </ | ||
| + | Fichier : `td3/ | ||
| + | <sxh js> | ||
| resource " | resource " | ||
| - | name = "td3/db/ | + | name = var.secret_name |
| - | | + | recovery_window_in_days = 7 |
| + | |||
| + | tags = { | ||
| + | Name = "td3-secret-db" | ||
| + | | ||
| + | } | ||
| } | } | ||
| resource " | resource " | ||
| 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: | ||
| }) | }) | ||
| } | } | ||
| + | </ | ||
| + | Fichier : `td3/ | ||
| + | <sxh js> | ||
| output " | output " | ||
| value = aws_secretsmanager_secret.db_credentials.arn | value = aws_secretsmanager_secret.db_credentials.arn | ||
| - | description = "ARN du secret contenant les identifiants | + | description = "ARN du secret contenant les identifiants |
| } | } | ||
| - | </ | ||
| - | Fichier : `td3/ | + | output |
| - | <sxh js> | + | |
| - | variable | + | description = "Nom du secret dans Secrets Manager" |
| - | | + | |
| - | description = "Mot de passe initial de la base de donnees" | + | |
| - | sensitive | + | |
| } | } | ||
| </ | </ | ||
| - | Le mot de passe est transmis via une variable | + | <WRAP round question> |
| + | Le paramètre `sensitive = true` sur la variable | ||
| - | Pour appliquer, Terraform demandera la valeur au moment | + | Cela signifie-t-il que le mot de passe est chiffré dans le state Terraform ? |
| - | Fichier : `td3/ | + | Où le mot de passe est-il stocké en clair malgré ce paramètre ? |
| - | <sxh bash> | + | </WRAP> |
| - | # Appliquer en fournissant | + | |
| - | terraform apply -var=" | + | |
| - | + | ||
| - | # Ou via une variable d' | + | |
| - | export TF_VAR_db_password=" | + | |
| - | terraform apply | + | |
| - | </sxh> | + | |
| <WRAP round question> | <WRAP round question> | ||
| - | Pourquoi utilise-t-on | + | Le paramètre |
| - | Que change ce paramètre dans l' | + | 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, |
| </ | </ | ||
| - | <WRAP round question> | + | ===== 4. Erreur volontaire – secret |
| - | Pourquoi utilise-t-on un JSON pour stocker le secret | + | |
| - | Quel avantage cela apporte-t-il si l'application | + | Objectif : comprendre ce qui se passe quand une application |
| - | </ | + | |
| - | ===== 4. Problème volontaire – dépendance entre modules ===== | + | Voici un data source intentionnellement incorrect. |
| + | |||
| + | Fichier : `td3/ | ||
| + | <sxh js> | ||
| + | data " | ||
| + | name = " | ||
| + | } | ||
| + | </ | ||
| <WRAP round todo> | <WRAP round todo> | ||
| - | Tenter d' | + | Lire le code ci-dessus sans l' |
| - | terraform apply -target=module.secrets | + | Identifier l' |
| - | 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 round question> | + | Le nom du secret dans Secrets Manager est `td3/ |
| - | Terraform gère les dépendances implicites entre ressources | + | |
| - | Pourquoi cette dépendance implicite ne fonctionne-t-elle pas toujours entre modules différents | + | Le data source ci-dessus cherche `td3/ |
| + | |||
| + | L' | ||
| + | |||
| + | Fichier : `td3/ | ||
| + | <sxh bash> | ||
| + | Error: reading Secrets Manager Secret: ResourceNotFoundException: | ||
| + | Secrets Manager can't find the specified secret. | ||
| + | </ | ||
| + | |||
| + | <WRAP round question> | ||
| + | Ce type d' | ||
| - | 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. |
| </ | </ | ||
| - | ===== 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 |
| - | <WRAP round question> | + | Fichier : `td3/ |
| - | AWS propose deux types de clés KMS : | + | <sxh js> |
| - | | + | data " |
| - | * les clés Customer Managed Keys (CMK) | + | |
| - | 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 | ||
| + | ) | ||
| + | } | ||
| + | </ | ||
| - | Qui décide des droits d' | + | <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 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 ? | ||
| </ | </ | ||
| - | Fichier : `td3/ | + | Fichier : `td3/ |
| <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 | ||
| } | } | ||
| - | variable "region" { | + | variable "account_id" { |
| type = string | type = string | ||
| - | description = "Region | + | description = "ID du compte |
| } | } | ||
| + | </ | ||
| + | |||
| + | Fichier : `td3/ | ||
| + | <sxh js> | ||
| + | data " | ||
| - | resource " | + | resource " |
| - | description | + | description |
| - | deletion_window_in_days = 7 | + | deletion_window_in_days = 10 |
| enable_key_rotation | enable_key_rotation | ||
| Ligne 299: | Ligne 361: | ||
| Statement = [ | Statement = [ | ||
| { | { | ||
| - | Sid = "Acces administrateur au compte" | + | Sid = "EnableRootAccess" |
| Effect = " | Effect = " | ||
| Principal = { | Principal = { | ||
| Ligne 309: | Ligne 371: | ||
| ] | ] | ||
| }) | }) | ||
| + | |||
| + | tags = { | ||
| + | Name = " | ||
| + | TD = " | ||
| + | } | ||
| } | } | ||
| - | resource " | + | resource " |
| - | name = " | + | name = var.key_alias |
| - | target_key_id = aws_kms_key.td3.id | + | target_key_id = aws_kms_key.main.key_id |
| } | } | ||
| + | </ | ||
| + | Fichier : `td3/ | ||
| + | <sxh js> | ||
| output " | output " | ||
| - | 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 " | output " | ||
| - | 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" |
| } | } | ||
| </ | </ | ||
| <WRAP round question> | <WRAP round question> | ||
| - | Le paramètre `deletion_window_in_days | + | Le paramètre `enable_key_rotation |
| - | 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' |
| - | Pourquoi AWS impose-t-il un délai minimum avant la suppression effective d' | + | Les données chiffrées avec l' |
| </ | </ | ||
| <WRAP round question> | <WRAP round question> | ||
| - | Le paramètre | + | La policy KMS donne accès à `arn: |
| - | Que signifie la rotation d'une clé KMS concrètement | + | Pourquoi cette entrée est-elle obligatoire dans une policy |
| - | La rotation de la clé KMS invalide-t-elle | + | Que se passe-t-il si elle est absente |
| </ | </ | ||
| - | <WRAP round question> | + | ===== 7. Cré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 |
| - | Que se passerait-il si on supprimait cette règle et qu' | + | Fichier |
| - | </ | + | |
| - | + | ||
| - | ===== 6. Chiffrement de la base de données RDS ===== | + | |
| - | + | ||
| - | Objectif | + | |
| - | + | ||
| - | <WRAP round todo> | + | |
| - | Modifier | + | |
| - | </ | + | |
| - | + | ||
| - | Fichier : `td2/network/instances.tf` | + | |
| <sxh js> | <sxh js> | ||
| - | # Recuperation du secret cree dans le module TD3 | + | variable |
| - | data "aws_secretsmanager_secret_version" | + | |
| - | | + | description |
| + | } | ||
| - | depends_on | + | variable " |
| - | aws_secretsmanager_secret_version.db_credentials | + | type |
| - | | + | |
| } | } | ||
| - | locals | + | variable " |
| - | | + | |
| - | | + | |
| - | | + | |
| } | } | ||
| - | resource | + | variable |
| - | | + | |
| - | | + | |
| - | | + | } |
| - | vpc_security_group_ids = [aws_security_group.backend_sg.id] | + | |
| - | user_data = << | + | variable " |
| - | # | + | |
| - | yum install -y python3 | + | |
| - | python3 -m http.server 80 & | + | |
| - | | + | |
| - | + | ||
| - | | + | |
| - | Name = "td2-backend" | + | |
| - | } | + | |
| } | } | ||
| - | resource | + | variable |
| - | | + | |
| - | engine | + | |
| - | engine_version | + | |
| - | instance_class | + | |
| - | allocated_storage | + | |
| - | + | ||
| - | username = local.db_secret.username | + | |
| - | password = local.db_secret.password | + | |
| - | + | ||
| - | storage_encrypted = true | + | |
| - | kms_key_id | + | |
| - | + | ||
| - | | + | |
| - | vpc_security_group_ids = [aws_security_group.db_sg.id] | + | |
| - | skip_final_snapshot | + | |
| - | + | ||
| - | tags = { | + | |
| - | Name = "td3-db" | + | |
| - | } | + | |
| } | } | ||
| + | </ | ||
| + | Fichier : `td3/ | ||
| + | <sxh js> | ||
| resource " | resource " | ||
| name = " | name = " | ||
| - | subnet_ids = [aws_subnet.private.id, aws_subnet.public_b.id] | + | subnet_ids = var.subnet_ids |
| tags = { | tags = { | ||
| Name = " | Name = " | ||
| + | TD = " | ||
| } | } | ||
| } | } | ||
| - | variable | + | resource |
| - | | + | |
| - | | + | |
| - | } | + | |
| - | </ | + | |
| + | allocated_storage = 20 | ||
| - | <WRAP round question> | + | username = var.db_username |
| - | Le chiffrement `storage_encrypted | + | |
| - | Quel mécanisme protège les données en transit entre le backend et RDS ? | + | db_subnet_group_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 round question> | + | skip_final_snapshot = true |
| - | L' | + | |
| - | Que se passe-t-il si on tente de modifier `storage_encrypted` sur une instance RDS existante ? | + | tags = { |
| - | + | | |
| - | Pourquoi AWS impose-t-il cette contrainte ? | + | |
| - | </ | + | |
| - | + | ||
| - | ===== 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' | + | |
| - | </ | + | |
| - | + | ||
| - | <WRAP round question> | + | |
| - | Terraform indique qu'il doit détruire et recréer l' | + | |
| - | + | ||
| - | 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 ? | + | |
| - | </ | + | |
| - | + | ||
| - | ===== 8. Création d'un bucket S3 sécurisé ===== | + | |
| - | + | ||
| - | Objectif : créer un bucket S3 avec chiffrement SSE-KMS et blocage d' | + | |
| - | + | ||
| - | <WRAP round todo> | + | |
| - | Créer le module storage. | + | |
| - | </ | + | |
| - | + | ||
| - | Fichier : `td3/ | + | |
| - | <sxh js> | + | |
| - | variable | + | |
| - | | + | |
| - | description = "ARN de la cle KMS utilisee pour le chiffrement S3" | + | |
| } | } | ||
| - | resource " | + | resource " |
| - | byte_length = 4 | + | bucket = var.bucket_name |
| - | } | + | |
| - | + | ||
| - | resource " | + | |
| - | bucket = " | + | |
| tags = { | tags = { | ||
| - | Name = "td3-app-data" | + | Name = "td3-s3-app" |
| + | TD = "td3" | ||
| } | } | ||
| } | } | ||
| - | resource " | + | resource " |
| - | bucket = aws_s3_bucket.app_data.id | + | bucket = aws_s3_bucket.app.id |
| - | + | ||
| - | block_public_acls | + | |
| - | block_public_policy | + | |
| - | ignore_public_acls | + | |
| - | restrict_public_buckets = true | + | |
| - | } | + | |
| - | + | ||
| - | resource " | + | |
| - | bucket = aws_s3_bucket.app_data.id | + | |
| rule { | rule { | ||
| Ligne 512: | Ligne 508: | ||
| } | } | ||
| - | output | + | resource |
| - | | + | |
| - | | + | |
| + | | ||
| + | block_public_policy | ||
| + | ignore_public_acls | ||
| + | restrict_public_buckets = true | ||
| } | } | ||
| </ | </ | ||
| <WRAP round question> | <WRAP round question> | ||
| - | Dans ce TD la valeur de `sse_algorithm` est `aws:kms`. | + | Le chiffrement |
| - | Dans le TD précédent la valeur était `AES256`. | + | Quel mécanisme protège les données en transit entre l' |
| - | + | ||
| - | 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 round question> | <WRAP round question> | ||
| - | Le paramètre `bucket_key_enabled = true` est activé. | + | Le paramètre `bucket_key_enabled = true` est activé |
| - | Rechercher ce que fait ce paramètre. | + | Rechercher |
| - | Quel impact | + | Quel est l'impact sur les coûts |
| </ | </ | ||
| - | <WRAP round question> | + | ===== 8. Erreur 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. |
| - | </ | + | |
| - | ===== 9. Mise 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' |
| + | |||
| + | 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 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. | ||
| </ | </ | ||
| - | Fichier : `td3/ | + | ===== 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/ | ||
| <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 " | variable " | ||
| type = string | type = string | ||
| - | description = "ARN de la cle KMS utilisee | + | description = "ARN de la clé KMS pour chiffrer les logs CloudTrail" |
| } | } | ||
| - | resource | + | variable |
| - | | + | |
| + | description = "ID du compte AWS courant" | ||
| } | } | ||
| + | </ | ||
| - | resource " | + | Fichier : `td3/ |
| - | bucket = " | + | <sxh js> |
| + | resource " | ||
| + | bucket = var.bucket_name | ||
| tags = { | tags = { | ||
| - | Name = "td3-cloudtrail-logs" | + | Name = "td3-s3-cloudtrail" |
| + | TD = "td3" | ||
| } | } | ||
| } | } | ||
| - | resource " | + | resource " |
| - | bucket = aws_s3_bucket.cloudtrail_logs.id | + | bucket = aws_s3_bucket.cloudtrail.id |
| block_public_acls | block_public_acls | ||
| Ligne 585: | Ligne 596: | ||
| } | } | ||
| - | resource " | + | resource " |
| - | bucket = aws_s3_bucket.cloudtrail_logs.id | + | bucket = aws_s3_bucket.cloudtrail.id |
| policy = jsonencode({ | policy = jsonencode({ | ||
| Ligne 598: | Ligne 609: | ||
| } | } | ||
| Action | Action | ||
| - | Resource = aws_s3_bucket.cloudtrail_logs.arn | + | Resource = aws_s3_bucket.cloudtrail.arn |
| }, | }, | ||
| { | { | ||
| Ligne 607: | Ligne 618: | ||
| } | } | ||
| Action | Action | ||
| - | Resource = " | + | Resource = " |
| Condition = { | Condition = { | ||
| StringEquals = { | StringEquals = { | ||
| Ligne 620: | Ligne 631: | ||
| resource " | resource " | ||
| name = " | name = " | ||
| - | s3_bucket_name | + | s3_bucket_name |
| include_global_service_events = true | include_global_service_events = true | ||
| is_multi_region_trail | is_multi_region_trail | ||
| Ligne 626: | Ligne 637: | ||
| kms_key_id | kms_key_id | ||
| - | | + | |
| - | | + | |
| - | ] | + | TD = " |
| + | | ||
| + | |||
| + | depends_on = [aws_s3_bucket_policy.cloudtrail] | ||
| } | } | ||
| + | </ | ||
| + | Fichier : `td3/ | ||
| + | <sxh js> | ||
| output " | output " | ||
| value = aws_cloudtrail.main.arn | value = aws_cloudtrail.main.arn | ||
| description = "ARN du trail CloudTrail" | description = "ARN du trail CloudTrail" | ||
| + | } | ||
| + | |||
| + | output " | ||
| + | value = aws_s3_bucket.cloudtrail.bucket | ||
| + | description = "Nom du bucket contenant les logs CloudTrail" | ||
| } | } | ||
| </ | </ | ||
| <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' |
| - | Expliquer le rôle de chacun : | + | Quel problème cela permet-il |
| - | * `AWSCloudTrailAclCheck` | + | |
| - | * `AWSCloudTrailWrite` | + | |
| - | Que se passerait-il si cette policy était absente | + | Quel mécanisme technique AWS utilise-t-il pour garantir |
| </ | </ | ||
| <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 | + | Citer trois exemples d' |
| - | Dans quel scénario cette fonctionnalité est-elle particulièrement utile ? | + | Citer deux exemples d' |
| </ | </ | ||
| - | <WRAP round question> | + | ===== 10. Assemblage 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 |
| - | * création d'un Security Group | + | |
| - | * modification d'une règle IAM | + | |
| - | * upload d'un fichier | + | |
| - | * 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/ |
| - | </WRAP> | + | <sxh js> |
| + | variable " | ||
| + | type = string | ||
| + | description = "Mot de passe de la base de données – ne pas committer" | ||
| + | sensitive | ||
| + | } | ||
| - | ===== 10. Simulation d'un incident ===== | + | variable " |
| + | type | ||
| + | description | ||
| + | default | ||
| + | } | ||
| - | Objectif : utiliser CloudTrail | + | variable " |
| + | type = string | ||
| + | description = "Nom du bucket S3 pour les logs CloudTrail" | ||
| + | default | ||
| + | } | ||
| + | </ | ||
| - | <WRAP round todo> | + | Fichier : `td3/ |
| - | Réaliser une action volontairement suspecte dans AWS. | + | <sxh js> |
| + | data " | ||
| - | Modifier un Security Group existant du TD2 pour ouvrir temporairement le port 22 depuis `0.0.0.0/0` : | + | module " |
| + | source | ||
| + | account_id = data.aws_caller_identity.current.account_id | ||
| + | } | ||
| - | terraform apply -target=module.network | + | module |
| + | source | ||
| + | db_username = " | ||
| + | db_password = var.db_password | ||
| + | } | ||
| - | Attendre deux minutes, puis supprimer cette règle : | + | module " |
| + | source = " | ||
| - | | + | |
| - | </ | + | |
| - | <WRAP round todo> | + | db_username = module.secrets.db_username |
| - | Aller dans la console AWS. | + | |
| - | Naviguer vers : CloudTrail > Event history. | + | subnet_ids = [ |
| + | data.aws_subnet.private.id, | ||
| + | data.aws_subnet.private_b.id | ||
| + | ] | ||
| - | Rechercher l' | + | security_group_id = data.aws_security_group.rds.id |
| - | Identifier : | + | bucket_name = var.s3_app_bucket_name |
| - | | + | } |
| - | | + | |
| - | | + | module " |
| - | </WRAP> | + | |
| + | | ||
| + | | ||
| + | account_id | ||
| + | } | ||
| + | </sxh> | ||
| <WRAP round question> | <WRAP round question> | ||
| - | CloudTrail enregistre l' | + | 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/ |
| - | Quel principe de gestion des identités du TD1 est directement lié à cette problématique | + | Que faut-il ajouter sur l' |
| </ | </ | ||
| - | <WRAP round question> | + | Fichier : `td3/ |
| - | Les logs CloudTrail sont stockés dans S3. | + | <sxh js> |
| + | output " | ||
| + | value = var.db_username | ||
| + | description = "Nom d' | ||
| + | } | ||
| - | Par défaut, combien | + | output " |
| + | value = var.db_password | ||
| + | description = " | ||
| + | sensitive | ||
| + | } | ||
| + | </ | ||
| - | Pourquoi stocker les logs dans S3 permet-il une conservation plus longue ? | + | ===== 11. Déploiement et vérification ===== |
| - | </ | + | |
| - | ===== 11. Vérification globale ===== | + | Fichier : `td3/ |
| + | <sxh bash> | ||
| + | # Se placer dans le dossier td3 | ||
| + | cd tp-aws/td3 | ||
| - | <WRAP round todo> | + | # Initialiser |
| - | Vérifier les points suivants dans le code Terraform et dans la console AWS : | + | terraform init |
| - | * le mot de passe n' | + | # Vérifier |
| - | * 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 | + | |
| - | * 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` | + | |
| - | </ | + | |
| - | ===== Challenge final ===== | + | # Appliquer |
| + | terraform apply -var=" | ||
| - | **Axe secrets** | + | # Vérifier les outputs |
| + | terraform output | ||
| + | |||
| + | # Vérifier le secret dans AWS CLI | ||
| + | aws secretsmanager get-secret-value --secret-id td3/ | ||
| + | |||
| + | # 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 | ||
| + | </ | ||
| <WRAP round todo> | <WRAP round todo> | ||
| - | Répondre aux questions suivantes par écrit | + | Après le déploiement, |
| - | * Où est stocké physiquement | + | * Secrets Manager : le secret |
| - | * Qui peut lire ce secret | + | * KMS : la clé `alias/ |
| - | * 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' |
| - | * 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 | ||
| </ | </ | ||
| - | **Axe KMS** | + | ===== 12. Lecture des logs CloudTrail ===== |
| - | <WRAP round question> | + | Objectif : naviguer dans les logs CloudTrail |
| - | 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 |
| - | Comment organiserait-on les clés KMS dans un environnement de production avec plusieurs équipes et plusieurs applications ? | + | Retrouver l' |
| - | </ | + | |
| - | **Axe chiffrement** | + | Identifier les champs suivants dans l' |
| + | |||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | </ | ||
| <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, | + | Quelle requête effectuer dans CloudTrail |
| - | * 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 | + | Quels champs |
| </ | </ | ||
| - | **Axe traçabilité** | + | ===== Challenge final ===== |
| - | <WRAP round question> | + | L' |
| - | 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 |
| - | Comment aurait-on pu protéger cette ressource contre une suppression accidentelle ? | + | **Axe 1 – Secrets** |
| - | Rechercher | + | Expliquer comment les identifiants RDS sont maintenant gérés. |
| - | </WRAP> | + | |
| + | Comparer l' | ||
| + | |||
| + | Indiquer ce qui resterait à améliorer si l' | ||
| + | |||
| + | **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/ | ||
| + | <sxh bash> | ||
| + | | Ressource | ||
| + | |------------|---------------------|---------------------|---------------------------| | ||
| + | | RDS | SSE-KMS | ||
| + | | S3 app | SSE-KMS | ||
| + | | 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 | + | Produire un schéma de l'infrastructure TD3 complète |
| - | Le schéma doit inclure : | + | |
| - | | + | * 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 | ||