This commit is contained in:
gastonchenet
2025-12-04 09:33:27 +01:00
parent be0ad3ca53
commit cff1cab940
12 changed files with 276 additions and 128 deletions

View File

@@ -0,0 +1,51 @@
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.0"
}
local = {
source = "hashicorp/local"
version = ">= 2.0"
}
}
}
provider "google" {
project = var.project_id
region = var.region
zone = var.zone
}
provider "local" {}
module "iam" {
source = "../../modules/iam"
project_id = var.project_id
sa_name = "tf-sa"
sa_display_name = "Terraform SA for TP"
}
module "compute" {
source = "../../modules/compute"
project_id = var.project_id
region = var.region
zone = var.zone
instance_type = var.instance_type
network = var.network
frontend_subnet_id = var.frontend_subnet_id
backend_subnet_id = var.backend_subnet_id
database_subnet_id = var.database_subnet_id
ssh_pub_key = var.ssh_pub_key
service_account_email = module.iam.service_account_email
}
module "network" {
source = "../../modules/network"
project_name = var.project_id
region = var.region
}

View File

@@ -0,0 +1,24 @@
output "frontend_public_ip" {
value = module.compute.frontend_public_ip
}
output "frontend_internal_ip" {
value = module.compute.frontend_internal_ip
}
output "backend_internal_ip" {
value = module.compute.backend_internal_ip
}
output "database_internal_ip" {
value = module.compute.database_internal_ip
}
output "service_account_email" {
value = module.iam.service_account_email
}
output "service_account_key" {
value = module.iam.service_account_key
sensitive = true
}

View File

@@ -0,0 +1,53 @@
variable "project_id" {
type = string
description = "GCP project id"
default = "school-478713"
}
variable "region" {
type = string
description = "The region of the VM"
default = "europe-west1"
}
variable "zone" {
type = string
description = "The zone of the VM"
default = "europe-west1-b"
}
variable "frontend_subnet_id" {
type = string
description = "self_link du subnet frontend"
default = "projects/my-gcp-project/regions/europe-west1/subnetworks/frontend-subnet"
}
variable "backend_subnet_id" {
type = string
description = "self_link du subnet backend"
default = "projects/my-gcp-project/regions/europe-west1/subnetworks/backend-subnet"
}
variable "database_subnet_id" {
type = string
description = "self_link du subnet database"
default = "projects/my-gcp-project/regions/europe-west1/subnetworks/database-subnet"
}
variable "network" {
type = string
description = "VPC network self_link or name"
default = "projects/my-gcp-project/global/networks/my-vpc"
}
variable "ssh_pub_key" {
type = string
description = "SSH public key to provision (optional)"
default = "ssh-ed25519 AAAA... user@example.com"
}
variable "instance_type" {
type = string
description = "Type of the VM instance"
default = "e2-minimal"
}

View File

@@ -1,74 +1,99 @@
# compute/main.tf
resource "google_compute_instance" "frontend" { resource "google_compute_instance" "frontend" {
name = "frontend-instance" name = "frontend-${substr(var.zone, -1, 2)}"
machine_type = var.instance_type project = var.project_id
zone = var.zone zone = var.zone
machine_type = var.instance_type
labels = merge({tier = "frontend"}, var.labels)
boot_disk { boot_disk {
initialize_params { initialize_params {
image = "debian-cloud/debian-11" image = "debian-cloud/debian-11"
size = 10 size = 10
type = "pd-standard"
} }
} }
network_interface { network_interface {
network = var.network
subnetwork = var.frontend_subnet_id subnetwork = var.frontend_subnet_id
access_config {} # IP publique access_config {}
} }
metadata = { metadata = {
enable-oslogin = "TRUE" enable-oslogin = "TRUE"
ssh-keys = var.ssh_pub_key
} }
tags = ["frontend", "ssh"] tags = ["frontend", "ssh"]
service_account {
email = var.service_account_email
scopes = ["userinfo-email", "compute-ro"]
}
} }
resource "google_compute_instance" "backend" { resource "google_compute_instance" "backend" {
name = "backend-instance" name = "backend-${substr(var.zone, -1, 2)}"
machine_type = var.instance_type project = var.project_id
zone = var.zone zone = var.zone
machine_type = var.instance_type
labels = merge({tier = "backend"}, var.labels)
boot_disk { boot_disk {
initialize_params { initialize_params {
image = "debian-cloud/debian-11" image = "debian-cloud/debian-11"
size = 10 size = 10
type = "pd-standard"
} }
} }
network_interface { network_interface {
network = var.network
subnetwork = var.backend_subnet_id subnetwork = var.backend_subnet_id
# Pas d'IP publique
} }
metadata = { metadata = {
enable-oslogin = "TRUE" enable-oslogin = "TRUE"
ssh-keys = var.ssh_pub_key
} }
tags = ["backend", "ssh"] tags = ["backend", "ssh"]
service_account {
email = var.service_account_email
scopes = ["userinfo-email", "compute-ro"]
}
} }
resource "google_compute_instance" "database" { resource "google_compute_instance" "database" {
name = "database-instance" name = "database-${substr(var.zone, -1, 2)}"
machine_type = var.instance_type project = var.project_id
zone = var.zone zone = var.zone
machine_type = var.instance_type
labels = merge({tier = "database"}, var.labels)
boot_disk { boot_disk {
initialize_params { initialize_params {
image = "debian-cloud/debian-11" image = "debian-cloud/debian-11"
size = 20 size = 20
type = "pd-standard"
} }
} }
network_interface { network_interface {
network = var.network
subnetwork = var.database_subnet_id subnetwork = var.database_subnet_id
# Pas d'IP publique
} }
metadata = { metadata = {
enable-oslogin = "TRUE" enable-oslogin = "TRUE"
ssh-keys = var.ssh_pub_key
} }
tags = ["database", "ssh"] tags = ["database", "ssh"]
}
service_account {
email = var.service_account_email
scopes = ["userinfo-email", "compute-ro"]
}
}

View File

@@ -1,27 +1,23 @@
# compute/outputs.tf output "frontend_internal_ip" {
value = google_compute_instance.frontend.network_interface[0].network_ip
# 1. IPs internes de toutes les instances
output "internal_ips" {
description = "IPs internes des instances"
value = {
frontend = google_compute_instance.frontend.network_interface[0].network_ip
backend = google_compute_instance.backend.network_interface[0].network_ip
database = google_compute_instance.database.network_interface[0].network_ip
}
} }
# 2. IP publique du frontend
output "frontend_public_ip" { output "frontend_public_ip" {
description = "IP publique de l'instance frontend" value = google_compute_instance.frontend.network_interface[0].access_config[0].nat_ip
value = google_compute_instance.frontend.network_interface[0].access_config[0].nat_ip
} }
# 3. Noms des instances output "backend_internal_ip" {
output "instance_names" { value = google_compute_instance.backend.network_interface[0].network_ip
description = "Noms des instances"
value = {
frontend = google_compute_instance.frontend.name
backend = google_compute_instance.backend.name
database = google_compute_instance.database.name
}
} }
output "database_internal_ip" {
value = google_compute_instance.database.network_interface[0].network_ip
}
output "instance_names" {
value = [
google_compute_instance.frontend.name,
google_compute_instance.backend.name,
google_compute_instance.database.name,
]
}

View File

@@ -1,27 +1,56 @@
# compute/variables.tf variable "project_id" {
variable "instance_type" {
description = "Type d'instance GCE à utiliser"
type = string type = string
description = "GCP project id"
}
variable "region" {
type = string
description = "GCP region"
} }
variable "zone" { variable "zone" {
description = "Zone dans laquelle déployer les instances"
type = string type = string
description = "GCP zone (ex: europe-west1-b)"
}
variable "instance_type" {
type = string
description = "Machine type for instances (ex: e2-medium)"
default = "e2-medium"
}
variable "network" {
type = string
description = "VPC network self_link or name"
} }
variable "frontend_subnet_id" { variable "frontend_subnet_id" {
description = "ID du sous-réseau frontend"
type = string type = string
description = "Frontend subnet self_link"
} }
variable "backend_subnet_id" { variable "backend_subnet_id" {
description = "ID du sous-réseau backend"
type = string type = string
description = "Backend subnet self_link"
} }
variable "database_subnet_id" { variable "database_subnet_id" {
description = "ID du sous-réseau database"
type = string type = string
description = "Database subnet self_link"
} }
variable "ssh_pub_key" {
type = string
description = "SSH public key to add as metadata for OS Login fallback (optional)"
default = ""
}
variable "service_account_email" {
type = string
description = "Service account email to attach to instances"
}
variable "labels" {
type = map(string)
default = {}
}

View File

@@ -1,36 +1,19 @@
# iam/main.tf
# 1. Compte de service pour Terraform
resource "google_service_account" "terraform_sa" { resource "google_service_account" "terraform_sa" {
account_id = "terraform-sa" account_id = var.sa_name
display_name = "Terraform Service Account"
project = var.project_id project = var.project_id
display_name = var.sa_display_name
} }
# 2. Clé pour ce compte de service
resource "google_service_account_key" "terraform_sa_key" { resource "google_service_account_key" "terraform_sa_key" {
service_account_id = google_service_account.terraform_sa.id service_account_id = google_service_account.terraform_sa.name
public_key_type = "TYPE_X509_PEM_FILE" keepers = {
} display_name = google_service_account.terraform_sa.display_name
}
# 3. Rôles IAM nécessaires
resource "google_project_iam_member" "terraform_sa_roles" {
for_each = toset([
"roles/compute.admin",
"roles/iam.serviceAccountUser",
"roles/oslogin.admin",
"roles/viewer"
])
project = var.project_id
role = each.value
member = "serviceAccount:${google_service_account.terraform_sa.email}"
}
# 4. Configuration OS Login avec clé SSH
resource "google_os_login_ssh_public_key" "terraform_sa_ssh" {
username = "terraform"
public_key = file("~/.ssh/id_rsa.pub")
project = var.project_id
} }
resource "google_project_iam_member" "sa_roles" {
for_each = toset(var.roles)
project = var.project_id
role = each.key
member = "serviceAccount:${google_service_account.terraform_sa.email}"
}

View File

@@ -1,15 +1,12 @@
# iam/outputs.tf
# 1. Email du compte de service
output "service_account_email" { output "service_account_email" {
description = "Email du compte de service Terraform" value = google_service_account.terraform_sa.email
value = google_service_account.terraform_sa.email
} }
# 2. Clé du compte de service (sensitive)
output "service_account_key" { output "service_account_key" {
description = "Clé privée du compte de service Terraform" value = google_service_account_key.terraform_sa_key.private_key
value = google_service_account_key.terraform_sa_key.private_key sensitive = true
sensitive = true
} }
output "service_account_key_id" {
value = google_service_account_key.terraform_sa_key.name
}

View File

@@ -1,7 +1,26 @@
# iam/variables.tf
variable "project_id" { variable "project_id" {
description = "ID du projet GCP"
type = string type = string
description = "GCP project id"
} }
variable "sa_name" {
type = string
description = "Service account name (id)"
default = "terraform-sa"
}
variable "sa_display_name" {
type = string
description = "Service account display name"
default = "Terraform Service Account"
}
variable "roles" {
type = list(string)
default = [
"roles/compute.instanceAdmin.v1",
"roles/iam.serviceAccountUser",
"roles/iam.serviceAccountKeyAdmin",
]
description = "Liste des roles à attribuer au compte de service"
}

View File

@@ -1,12 +1,9 @@
// 1. VPC personnalisé
resource "google_compute_network" "vpc" { resource "google_compute_network" "vpc" {
name = "${var.project_name}-vpc" name = "${var.project_name}-vpc"
project = var.project_name project = var.project_name
auto_create_subnetworks = false auto_create_subnetworks = false
} }
// 2. Sous-réseaux
resource "google_compute_subnetwork" "frontend" { resource "google_compute_subnetwork" "frontend" {
name = "${var.project_name}-frontend-subnet" name = "${var.project_name}-frontend-subnet"
project = var.project_name project = var.project_name
@@ -31,17 +28,12 @@ resource "google_compute_subnetwork" "database" {
ip_cidr_range = var.database_cidr ip_cidr_range = var.database_cidr
} }
// 3. Règles de firewall
// 3.1 HTTP/HTTPS vers frontend (depuis Internet)
resource "google_compute_firewall" "frontend_http_https" { resource "google_compute_firewall" "frontend_http_https" {
name = "${var.project_name}-fw-frontend-http-https" name = "${var.project_name}-fw-frontend-http-https"
project = var.project_name project = var.project_name
network = google_compute_network.vpc.name network = google_compute_network.vpc.name
description = "Autorise HTTP/HTTPS vers les instances frontend" description = "Autorise HTTP/HTTPS vers les instances frontend"
direction = "INGRESS"
direction = "INGRESS"
allow { allow {
protocol = "tcp" protocol = "tcp"
@@ -49,61 +41,46 @@ resource "google_compute_firewall" "frontend_http_https" {
} }
source_ranges = ["0.0.0.0/0"] source_ranges = ["0.0.0.0/0"]
target_tags = ["frontend"]
// Les instances frontend devront avoir ce tag
target_tags = ["frontend"]
} }
// 3.2 SSH vers toutes les instances (depuis la plage fournie)
resource "google_compute_firewall" "ssh_all" { resource "google_compute_firewall" "ssh_all" {
name = "${var.project_name}-fw-ssh-all" name = "${var.project_name}-fw-ssh-all"
project = var.project_name project = var.project_name
network = google_compute_network.vpc.name network = google_compute_network.vpc.name
description = "Autorise SSH vers toutes les instances du VPC" description = "Autorise SSH vers toutes les instances du VPC"
direction = "INGRESS"
direction = "INGRESS"
allow { allow {
protocol = "tcp" protocol = "tcp"
ports = ["22"] ports = ["22"]
} }
// Une seule CIDR passée en string, on l'enferme dans une liste
source_ranges = [var.ssh_source_ranges] source_ranges = [var.ssh_source_ranges]
} }
// 3.3 Port 8000 de frontend vers backend
resource "google_compute_firewall" "frontend_to_backend_8000" { resource "google_compute_firewall" "frontend_to_backend_8000" {
name = "${var.project_name}-fw-frontend-backend-8000" name = "${var.project_name}-fw-frontend-backend-8000"
project = var.project_name project = var.project_name
network = google_compute_network.vpc.name network = google_compute_network.vpc.name
description = "Autorise le trafic TCP 8000 des instances frontend vers backend" description = "Autorise le trafic TCP 8000 des instances frontend vers backend"
direction = "INGRESS"
direction = "INGRESS"
allow { allow {
protocol = "tcp" protocol = "tcp"
ports = ["8000"] ports = ["8000"]
} }
// Le trafic vient des instances taguées 'frontend'
source_tags = ["frontend"] source_tags = ["frontend"]
// Et cible les instances taguées 'backend'
target_tags = ["backend"] target_tags = ["backend"]
} }
// 3.4 Port 3306 de backend vers database
resource "google_compute_firewall" "backend_to_database_3306" { resource "google_compute_firewall" "backend_to_database_3306" {
name = "${var.project_name}-fw-backend-database-3306" name = "${var.project_name}-fw-backend-database-3306"
project = var.project_name project = var.project_name
network = google_compute_network.vpc.name network = google_compute_network.vpc.name
description = "Autorise le trafic TCP 3306 des instances backend vers database" description = "Autorise le trafic TCP 3306 des instances backend vers database"
direction = "INGRESS"
direction = "INGRESS"
allow { allow {
protocol = "tcp" protocol = "tcp"

View File

@@ -1,12 +1,8 @@
# output.tf
# 1. ID du VPC
output "vpc_id" { output "vpc_id" {
description = "ID du VPC personnalisé" description = "ID du VPC personnalisé"
value = google_compute_network.vpc.id value = google_compute_network.vpc.id
} }
# 2. IDs des sous-réseaux sous forme de map
output "subnet_ids" { output "subnet_ids" {
description = "Map des IDs des sous-réseaux (frontend, backend, database)" description = "Map des IDs des sous-réseaux (frontend, backend, database)"
value = { value = {

View File

@@ -1,13 +1,11 @@
variable "project_name" { variable "project_name" {
description = "Name of the project" description = "Name of the project"
type = string type = string
default = "school-478713"
} }
variable "region" { variable "region" {
description = "The region of the VM" description = "The region of the VM"
type = string type = string
default = "europe-west1"
} }
variable "frontend_cidr" { variable "frontend_cidr" {