This commit is contained in:
James Boutaric
2025-12-04 10:15:36 +01:00
parent 540fb6c634
commit cfeee8df7f
13 changed files with 220 additions and 214 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -1,90 +0,0 @@
# TP : Gestion des Identités (IAM) et Accès SSH
Dans cette partie, vous allez configurer les accès pour que Terraform puisse interagir avec le projet et pour que vous puissiez vous connecter aux futures machines virtuelles.
## Objectifs
1. Créer une identité machine (Service Account).
2. Lui donner des droits sur le projet.
3. Configurer votre propre clé SSH via le service **OS Login** de GCP.
---
## Étape 1 : Créer l'identité machine
**Objectif :** Créer un compte de service (Service Account) qui sera utilisé par nos scripts d'automatisation.
* **Ressource à utiliser :** `google_service_account`
* **Consignes :**
* Donnez-lui l'ID `terraform`.
* Ajoutez un `display_name` explicite pour qu'on le reconnaisse dans la console GCP.
## Étape 2 : Générer une clé d'accès
**Objectif :** Pour utiliser ce compte de service depuis l'extérieur (ou via Terraform), nous avons besoin d'une clé.
* **Ressource à utiliser :** `google_service_account_key`
* **Consignes :**
* Vous devez lier cette ressource au compte de service créé à l'étape 1 via son attribut `name` (ex: `google_service_account.votre_nom.name`).
* Définissez le type de clé publique sur `"TYPE_X509_PEM_FILE"`.
## Étape 3 : Donner des droits (IAM)
**Objectif :** Un compte de service naît sans aucun droit. Vous devez lui donner le rôle de "Viewer" sur le projet pour qu'il puisse lire les ressources.
* **Ressource à utiliser :** `google_project_iam_binding`
* **Consignes :**
* **Project :** Utilisez votre variable `var.project_id`.
* **Role :** Le rôle cible est `"roles/viewer"`.
* **Members :** C'est une liste. Attention à la syntaxe spécifique GCP pour désigner un membre : `"serviceAccount:..."`. Vous devez concaténer ce préfixe avec l'email du service account créé à l'étape 1 (`.email`).
## Étape 4 : Récupérer votre identité
**Objectif :** Terraform doit savoir "qui" lance le script actuellement pour associer la clé SSH à la bonne personne.
* **Data Source à utiliser :** `data "google_client_openid_userinfo"`
* **Consignes :**
* Déclarez simplement ce bloc `data` avec le nom `me`. Il n'a pas besoin d'arguments à l'intérieur. Il servira juste à récupérer votre email dynamiquement.
## Étape 5 : Ajouter votre clé SSH (OS Login)
**Objectif :** Uploader votre clé publique SSH locale vers GCP pour permettre la connexion aux VMs sans gestion manuelle.
* **Ressource à utiliser :** `google_os_login_ssh_public_key`
* **Consignes :**
* **User :** Utilisez l'email récupéré grâce au data source de l'étape 4 (`.email`).
* **Key :** Vous devez lire le contenu de votre fichier de clé publique locale.
* **Fonction Terraform :** Utilisez la fonction `file("chemin/vers/la/clé")`.
* **Chemin recommandé :** `~/.ssh/id_ed25519.pub`.
> **Attention :** Vérifiez impérativement que vous avez bien généré une clé SSH sur votre poste local avant de lancer le `terraform apply`. Sinon, Terraform ne trouvera pas le fichier et plantera.
---
### Résumé des liens entre ressources
Assurez-vous que vos ressources se référencent correctement :
* La **Clé** référencie le **Service Account**.
* L'**IAM Binding** référencie le **Service Account**.
* L'**OS Login** référencie le **Data User Info**.
Voici la suite du document Markdown (MD) à ajouter à la suite de l'étape 5.
---
## Étape 6 : Exposer les résultats (Outputs)
**Objectif :** Une fois le déploiement terminé, Terraform masque par défaut certaines informations. Nous devons définir explicitement quelles valeurs nous voulons voir ou récupérer (notamment pour les utiliser dans d'autres scripts).
* **Fichier à utiliser :** `outputs.tf` (c'est une bonne pratique de séparer les outputs du `main.tf`).
### Consigne A : L'email du Service Account
Nous aurons besoin de connaître l'adresse email complète générée par Google pour ce compte.
* Créez un output nommé `service_account_email`.
* Dans la valeur (`value`), référencez l'attribut `.email` de la ressource créée à l'**Étape 1**.
### Consigne B : La Clé Privée (Attention Sécurité)
Nous devons récupérer la clé privée générée pour pouvoir authentifier des applications externes.
* Créez un output nommé `service_account_key`.
* Dans la valeur, référencez l'attribut `.private_key` de la ressource créée à l'**Étape 2**.
* **Important :** Terraform refusera d'afficher cette valeur ou l'affichera en clair dans vos logs si vous ne faites pas attention. Vous **devez** ajouter l'argument suivant dans ce bloc output pour masquer la valeur dans le terminal :
```hcl
sensitive = true
```

View File

@@ -1,3 +1,8 @@
# À vous de :
# 1. Configurer le provider google
# 2. Appeler les trois modules avec les bonnes variables
# 3. Créer le fichier de configuration Ansible (template)
terraform { terraform {
required_providers { required_providers {
google = { google = {
@@ -20,5 +25,18 @@ module "network" {
backend_cidr = var.backend_cidr backend_cidr = var.backend_cidr
database_cidr = var.database_cidr database_cidr = var.database_cidr
ssh_source_ranges = var.ssh_source_ranges ssh_source_ranges = var.ssh_source_ranges
}
module "compute" {
source = "../../modules/compute"
instance_type = var.instance_type
zone = var.zone
frontend_subnet_id = module.network.subnets.frontend
backend_subnet_id = module.network.subnets.backend
database_subnet_id = module.network.subnets.database
}
module "iam" {
source = "../../modules/iam"
project_id = var.project_id
} }

View File

@@ -1,13 +1,14 @@
# Commentaire # définissez toutes les variables nécessaires avec des valeurs par défaut appropriées.
variable "project_name" { variable "project_name" {
description = "Nom du projet"
type = string type = string
description = "but3-iac" default = "My First Project"
default = "Automaticsearch"
} }
variable "region" { variable "region" {
description = "Region du projet"
type = string type = string
description = "Région dans laquelle déployer les ressources"
default = "europe-west9" default = "europe-west9"
} }
@@ -30,17 +31,25 @@ variable "database_cidr" {
} }
variable "ssh_source_ranges" { variable "ssh_source_ranges" {
description = ""
type = string type = string
description = "Plages dadresses autorisées à se connecter en SSH" default = "0.0.0.0/0"
default = "0.0.0.0/0"
} }
variable "project_id" {
description = "ID du projet"
type = string
default = "plenary-plane-478713-q1"
}
variable "project_id"{ variable "instance_type" {
description = "id du projet" description = "type de l'instance"
type = string type = string
default = "plenary-plane-478713-q1" default = "e2-small"
}
variable "zone" {
description = "Nom de la zone"
type = string
default = "europe-west9-b"
} }

View File

@@ -1,5 +1,28 @@
# À vous de créer :
# 1. Instance frontend :
# - Image : debian-11
# - Disque : 10GB
# - IP publique
# - Tags : frontend, ssh
# - OS Login enabled
# 2. Instance backend :
# - Image : debian-11
# - Disque : 10GB
# - Pas d'IP publique (interne seulement)
# - Tags : backend, ssh
# - OS Login enabled
# 3. Instance database :
# - Image : debian-11
# - Disque : 20GB
# - Pas d'IP publique
# - Tags : database, ssh
# - OS Login enabled
resource "google_compute_instance" "vm_frontend" { resource "google_compute_instance" "vm_frontend" {
name = "frontend-instance" name = "vm-frontend"
machine_type = var.instance_type machine_type = var.instance_type
zone = var.zone zone = var.zone
@@ -10,14 +33,12 @@ resource "google_compute_instance" "vm_frontend" {
} }
} }
network_interface { network_interface {
access_config {} # IP publique
subnetwork = var.frontend_subnet_id subnetwork = var.frontend_subnet_id
access_config {}
} }
tags= ["frontend", "ssh"] tags = ["frontend", "ssh"]
metadata = { metadata = {
enable-oslogin = "TRUE" enable-oslogin = "TRUE"
@@ -25,7 +46,7 @@ resource "google_compute_instance" "vm_frontend" {
} }
resource "google_compute_instance" "vm_backend" { resource "google_compute_instance" "vm_backend" {
name = "backend-instance" name = "vm-backend"
machine_type = var.instance_type machine_type = var.instance_type
zone = var.zone zone = var.zone
@@ -36,24 +57,21 @@ resource "google_compute_instance" "vm_backend" {
} }
} }
network_interface { network_interface {
subnetwork = var.backend_subnet_id subnetwork = var.backend_subnet_id
} }
tags = ["backend", "ssh"] tags = ["backend", "ssh"]
metadata = { metadata = {
enable-oslogin = "TRUE" enable-oslogin = "TRUE"
} }
} }
resource "google_compute_instance" "vm_database" { resource "google_compute_instance" "vm_database" {
name = "database-instance" name = "vm-database"
machine_type = var.instance_type machine_type = var.instance_type
zone = var.zone zone = var.zone
boot_disk { boot_disk {
initialize_params { initialize_params {
@@ -62,15 +80,13 @@ resource "google_compute_instance" "vm_database" {
} }
} }
network_interface { network_interface {
subnetwork = var.database_subnet_id subnetwork = var.database_subnet_id
} }
tags = ["database", "ssh"] tags = ["database", "ssh"]
metadata = { metadata = {
enable-oslogin = "TRUE" enable-oslogin = "TRUE"
} }
} }

View File

@@ -1,3 +1,8 @@
# À vous d'exposer :
# 1. Les IPs internes de toutes les instances
# 2. L'IP publique du frontend
# 3. Les noms des instances
output "ip_internes" { output "ip_internes" {
value = { value = {
frontend = google_compute_instance.vm_frontend.network_interface[0].network_ip frontend = google_compute_instance.vm_frontend.network_interface[0].network_ip
@@ -16,4 +21,4 @@ output "nom_instances" {
backend = google_compute_instance.vm_backend.name backend = google_compute_instance.vm_backend.name
database = google_compute_instance.vm_database.name database = google_compute_instance.vm_database.name
} }
} }

View File

@@ -1,27 +1,31 @@
# À vous de définir les variables pour :
# - instance_type
# - zone
# - frontend_subnet_id
# - backend_subnet_id
# - database_subnet_id
variable "instance_type" { variable "instance_type" {
description = "Type de machine à utiliser pour les instances" description = "type de l'instance"
type = string type = string
} }
variable "zone" { variable "zone" {
description = "Zone où déployer les instances" description = "Nom de la zone"
type = string type = string
} }
variable "frontend_subnet_id" { variable "frontend_subnet_id" {
description = "ID du sous-réseau frontend" description = "id du frontend"
type = string type = string
} }
variable "backend_subnet_id" { variable "backend_subnet_id" {
description = "ID du sous-réseau backend" description = "id du backend"
type = string type = string
} }
variable "database_subnet_id" { variable "database_subnet_id" {
description = "ID du sous-réseau database" description = "id du database"
type = string type = string
} }

View File

@@ -0,0 +1,33 @@
# À vous de créer :
# 1. Un compte de service pour Terraform
# 2. Une clé pour ce compte de service
# 3. Les rôles IAM nécessaires
# 4. La configuration OS Login avec votre clé SSH
resource "google_service_account" "service_account" {
account_id = "terraform"
display_name = "terraform"
}
resource "google_service_account_key" "mykey" {
service_account_id = google_service_account.service_account.name
public_key_type = "TYPE_X509_PEM_FILE"
}
resource "google_project_iam_binding" "custom_service_account" {
project = var.project_id
role = "roles/viewer"
members = [
"serviceAccount:${google_service_account.service_account.email}",
]
}
data "google_client_openid_userinfo" "me" {
}
resource "google_os_login_ssh_public_key" "cache" {
user = data.google_client_openid_userinfo.me.email
key = file("~/.ssh/id_ed25519.pub")
project = var.project_id
}

View File

@@ -1,10 +1,14 @@
output "service_account_email"{ # À vous d'exposer :
description = "Service account email" # 1. L'email du compte de service
value = google.service.account.myaccount.email # 2. La clé du compte de service (sensitive = true)
output "email" {
description = "Service account email."
value = google_service_account.service_account.email
} }
output "service_account_key"{ output "key" {
description = "Service key" description = "Service account private key."
sensitive = true sensitive = true
value = google.service.account.mykey.private_key value = google_service_account_key.mykey.private_key
} }

View File

@@ -0,0 +1,7 @@
# À vous de définir :
# - project_id (string)
variable "project_id" {
description = "ID du projet"
type = string
}

View File

@@ -1,87 +1,88 @@
resource "google_compute_network" "vpc" { # À vous de créer :
name = "mon-vpc" # 1. Un VPC personnalisé avec auto_create_subnetworks = false
# 2. Trois sous-réseaux (frontend, backend, database)
# 3. Règles de firewall :
# - HTTP/HTTPS vers frontend
# - SSH vers toutes les instances
# - Port 8000 de frontend vers backend
# - Port 3306 de backend vers database
# VPC
resource "google_compute_network" "vpc_terraform" {
name = "vpc-terraform-2"
auto_create_subnetworks = false auto_create_subnetworks = false
} }
# Sous-réseau # Sous-réseau
resource "google_compute_subnetwork" "frontend_network" { resource "google_compute_subnetwork" "subnet_frontend" {
name = "mon-frontend" name = "frontend-2"
network = google_compute_network.vpc.id network = google_compute_network.vpc_terraform.id
ip_cidr_range = var.frontend_cidr ip_cidr_range = var.frontend_cidr
region = var.region region = var.region
} }
resource "google_compute_subnetwork" "backend_network" { resource "google_compute_subnetwork" "subnet_backend" {
name = "mon-backend" name = "backend-2"
network = google_compute_network.vpc.id network = google_compute_network.vpc_terraform.id
ip_cidr_range = var.backend_cidr ip_cidr_range = var.backend_cidr
region = var.region region = var.region
} }
resource "google_compute_subnetwork" "database_network" { resource "google_compute_subnetwork" "subnet_database" {
name = "mon-database" name = "database-2"
network = google_compute_network.vpc.id network = google_compute_network.vpc_terraform.id
ip_cidr_range = var.database_cidr ip_cidr_range = var.database_cidr
region = var.region region = var.region
} }
resource "google_compute_firewall" "ssh_firewall" { resource "google_compute_firewall" "allow_user_frontend" {
name = "mon-ssh" name = "allow-user-frontend-2"
network = google_compute_network.vpc.id network = google_compute_network.vpc_terraform.id
allow { allow {
protocol = "tcp"
ports = ["22"]
}
source_ranges = ["0.0.0.0/0"]
target_tags = ["ssh"]
}
resource "google_compute_firewall" "frontend_firewall" {
name = "frontend"
network = google_compute_network.vpc.id
allow {
protocol = "tcp" protocol = "tcp"
ports = ["80", "443"] ports = ["80", "443"]
} }
source_ranges = ["0.0.0.0/0"] source_ranges = ["0.0.0.0/0"]
target_tags = ["frontend"] target_tags = ["frontend"]
} }
resource "google_compute_firewall" "backend_firewall" { resource "google_compute_firewall" "allow_frontend_backend" {
name = "backend" name = "allow-frontend-backend-2"
network = google_compute_network.vpc.id network = google_compute_network.vpc_terraform.id
allow { allow {
protocol = "tcp" protocol = "tcp"
ports = ["8000"] ports = ["8000"]
} }
source_tags = ["frontend"] source_tags = ["frontend"]
target_tags = ["backend"] target_tags = ["backend"]
} }
resource "google_compute_firewall" "database_firewall" { resource "google_compute_firewall" "allow_ssh_all" {
name = "database" name = "allow-ssh-all-2"
network = google_compute_network.vpc.id network = google_compute_network.vpc_terraform.id
allow { allow {
protocol = "tcp"
ports = ["22"]
}
source_ranges = ["0.0.0.0/0"]
target_tags = ["ssh"]
}
resource "google_compute_firewall" "allow_backend_database" {
name = "allow-backend-database-2"
network = google_compute_network.vpc_terraform.id
allow {
protocol = "tcp" protocol = "tcp"
ports = ["3306"] ports = ["3306"]
} }
source_tags = ["backend"] source_tags = ["backend"]
target_tags = ["database"] target_tags = ["database"]
}
}

View File

@@ -1,17 +1,15 @@
output "vpc_terraform" { # À vous d'exposer :
description = "ID du VPC créé" # 1. L'ID du VPC
value = google_compute_network.vpc.id # 2. Les IDs des sous-réseaux sous forme de map
output "vpc" {
value = google_compute_network.vpc_terraform.id
} }
output "subnets" {
output "subnet_ids" {
description = "Map des IDs des sous-réseaux"
value = { value = {
frontend = google_compute_subnetwork.subnet_frontend.id
frontend = google_compute_subnetwork.frontend_network.id backend = google_compute_subnetwork.subnet_backend.id
backend = google_compute_subnetwork.backend_network.id database = google_compute_subnetwork.subnet_database.id
database = google_compute_subnetwork.database_network.id
} }
}
}

View File

@@ -1,36 +1,37 @@
# À vous de définir les variables pour :
# - project_name (string)
# - region (string)
# - frontend_cidr (string)
# - backend_cidr (string)
# - database_cidr (string)
# - ssh_source_ranges (string)
variable "project_name" { variable "project_name" {
description = "Nom du projet"
type = string type = string
description = "but3-iac"
} }
variable "region" { variable "region" {
description = "Region du projet"
type = string type = string
description = "Région dans laquelle déployer les ressources"
} }
variable "frontend_cidr" { variable "frontend_cidr" {
description = "CIDR for frontend subnet" description = "CIDR for frontend subnet"
type = string type = string
} }
variable "backend_cidr" { variable "backend_cidr" {
description = "CIDR for backend subnet" description = "CIDR for backend subnet"
type = string type = string
} }
variable "database_cidr" { variable "database_cidr" {
description = "CIDR for database subnet" description = "CIDR for database subnet"
type = string type = string
} }
variable "ssh_source_ranges" { variable "ssh_source_ranges" {
description = "Plages dadresses autorisées à se connecter en SSH" description = ""
type = string type = string
}
}