Skip to content
StableAudienceOpsSécuritéAudit banqueOwner@platform-opsDernière revue2026-05-22

Infra de base — Réseau

Phases 1 à 3 du déploiement infrastructure : backend Terraform, VPC AWS, Security Groups. Pour la vue d'ensemble et la checklist globale, voir Infra de base — overview.

PHASE 1 — TERRAFORM STATE BACKEND

Objectif

Créer le stockage distant du state Terraform avant toute autre ressource. Sans ça, le state reste en local et ne peut pas être partagé ni verrouillé.

Instructions pour l'agent

Créer un dossier infrastructure/terraform/bootstrap/ séparé des environnements. Ce bootstrap est exécuté une seule fois, manuellement.

Ressources à créer :

  • Un bucket S3 nex-terraform-state-<AWS_ACCOUNT_ID> (ex: nex-terraform-state-009001720821) : versioning activé, encryption AES-256, block public access total. Le suffixe avec l'account ID garantit l'unicité globale du nom.
  • Une table DynamoDB nex-terraform-locks : clé primaire LockID (String). Utilisée pour le verrouillage concurrent — empêche deux terraform apply simultanés.

Recommandations :

  • Ce module ne doit PAS être géré par un backend distant (problème de l'œuf et de la poule). State local uniquement pour le bootstrap.
  • Tagger les deux ressources avec les tags projet.
  • Activer la suppression protection sur le bucket (prevent_destroy).

Configuration backend (dans infrastructure/terraform/staging/main.tf) :

hcl
terraform {
  backend "s3" {
    bucket         = "nex-terraform-state-009001720821"
    key            = "staging/terraform.tfstate"
    region         = "eu-west-3"
    dynamodb_table = "nex-terraform-locks"
    encrypt        = true
  }
}

Validation

bash
aws s3 ls | grep nex-terraform
aws dynamodb describe-table --table-name nex-terraform-locks --query "Table.TableStatus"

PHASE 2 — VPC & RÉSEAU

Objectif

Créer le réseau isolé dans lequel toute l'infrastructure vivra. C'est la fondation — une erreur ici impacte tout le reste.

Instructions pour l'agent

Créer le module infrastructure/terraform/modules/vpc/.

Architecture réseau :

VPC 10.0.0.0/16

├── Subnets publics (2 AZ)
│   ├── 10.0.1.0/24  (eu-west-3a) — ALB, NAT Gateway
│   └── 10.0.2.0/24  (eu-west-3b) — ALB, NAT Gateway

├── Subnets privés (2 AZ)
│   ├── 10.0.10.0/24 (eu-west-3a) — Pods EKS
│   └── 10.0.20.0/24 (eu-west-3b) — Pods EKS

└── Subnets données (2 AZ)
    ├── 10.0.100.0/24 (eu-west-3a) — RDS, Redis
    └── 10.0.200.0/24 (eu-west-3b) — RDS, Redis

Composants réseau :

  • Internet Gateway attaché au VPC.
  • NAT Gateway : 1 seul en staging (dans public-a pour économiser). 2 en production (un par AZ pour la haute dispo). Elastic IP associée.
  • Route tables : une publique (0.0.0.0/0 → IGW), une privée (0.0.0.0/0 → NAT), une data (0.0.0.0/0 → NAT).
  • DNS hostnames et DNS support activés sur le VPC.

Tags Kubernetes obligatoires sur les subnets — sans ça, EKS ne pourra pas créer les load balancers :

  • Subnets publics : kubernetes.io/role/elb = 1
  • Subnets privés : kubernetes.io/role/internal-elb = 1
  • Tous : kubernetes.io/cluster/nex-staging = shared

Recommandations :

  • 3 couches de subnets (public/privé/data) au lieu de 2. La couche data isole physiquement les bases de données des pods applicatifs. Même si un pod est compromis et qu'il a accès au réseau privé, il ne peut pas scanner le réseau data sauf si le Security Group l'autorise explicitement.
  • Le NAT Gateway coûte ~35 €/mois. En staging un seul suffit. Si la zone A tombe, les pods en zone B perdent leur accès internet sortant — acceptable en staging.

Validation

bash
# VPC existe
aws ec2 describe-vpcs --filters "Name=tag:Project,Values=nex" --query "Vpcs[0].VpcId" --region eu-west-3

# 6 subnets
aws ec2 describe-subnets --filters "Name=tag:Project,Values=nex" --query "length(Subnets)" --region eu-west-3
# Attendu : 6

# NAT Gateway actif
aws ec2 describe-nat-gateways --filter "Name=tag:Project,Values=nex" --query "NatGateways[0].State" --region eu-west-3
# Attendu : available

PHASE 3 — SECURITY GROUPS

Objectif

Définir la matrice de communication réseau. Le principe : tout est fermé par défaut, on ouvre uniquement ce qui est nécessaire.

Instructions pour l'agent

Créer dans infrastructure/terraform/modules/vpc/security_groups.tf un Security Group par composant :

sg-alb — Load Balancer (point d'entrée) :

  • Inbound : 443 depuis 0.0.0.0/0 (trafic HTTPS via Cloudflare)
  • Inbound : 80 depuis 0.0.0.0/0 (redirect HTTPS)
  • Outbound : tout vers les subnets privés

sg-eks-nodes — Nœuds Kubernetes :

  • Inbound : tout depuis sg-alb (le LB route vers les pods)
  • Inbound : tout depuis sg-eks-nodes (communication inter-pods)
  • Inbound : 443 depuis le CIDR VPC (API server ↔ kubelets)
  • Outbound : 5432 vers sg-rds
  • Outbound : 6379 vers sg-redis
  • Outbound : 443 vers 0.0.0.0/0 (pull images, appels API externes : Firebase, Resend)

sg-rds — PostgreSQL :

  • Inbound : 5432 depuis sg-eks-nodes uniquement
  • Outbound : aucun

sg-redis — Redis :

  • Inbound : 6379 depuis sg-eks-nodes uniquement
  • Outbound : aucun

ATTENTION — Piège EKS avec les Security Groups :

EKS crée automatiquement un Security Group cluster (différent de sg-eks-nodes défini dans Terraform). Ce SG auto-généré est celui réellement attaché aux nœuds du node group managé. Par conséquent, les règles inbound de sg-rds et sg-redis doivent autoriser à la fois sg-eks-nodes ET le SG cluster auto-généré par EKS.

Après la création du cluster (Phase 7), récupérer le SG cluster :

bash
aws eks describe-cluster --name nex-staging --region eu-west-3 \
  --query "cluster.resourcesVpcConfig.clusterSecurityGroupId" --output text

Puis ajouter ce SG en inbound sur sg-rds (port 5432) et sg-redis (port 6379). Sans ça, les pods ne pourront pas joindre RDS ni Redis (ETIMEDOUT / no pg_hba.conf entry... no encryption).

Recommandations :

  • Ne jamais ouvrir les SG RDS ou Redis à 0.0.0.0/0, même temporairement pour debug. Utiliser kubectl port-forward à la place.
  • En production on pourra restreindre le 443 inbound de sg-alb aux seules IPs Cloudflare (plages publiées par Cloudflare). En staging on laisse ouvert pour simplifier.
  • Chaque SG doit avoir une description claire et des tags.

Validation

bash
aws ec2 describe-security-groups --filters "Name=tag:Project,Values=nex" \
  --query "SecurityGroups[].GroupName" --region eu-west-3
# Attendu : sg-alb, sg-eks-nodes, sg-rds, sg-redis

# Vérifier que le SG cluster EKS est dans les inbound de sg-rds
aws ec2 describe-security-groups --group-ids <sg-rds-id> --region eu-west-3 \
  --query "SecurityGroups[0].IpPermissions"
# Attendu : le SG cluster EKS apparaît en source sur port 5432

Nex — Plateforme fintech CEMAC