diff --git a/01-introduction-concepts.md b/01-introduction-concepts.md new file mode 100644 index 0000000..94bc707 --- /dev/null +++ b/01-introduction-concepts.md @@ -0,0 +1,116 @@ +# 01 - Introduction à GitHub + +[🏠 Retour à l'accueil](README.md) | [02 - Premiers pas →](02-premiers-pas-ssh.md) + +--- + +## Objectifs de cette partie + +- Comprendre ce qu'est GitHub et son rôle en DevOps Azure +- Distinguer Git et GitHub +- Découvrir les concepts clés de la plateforme +- Situer GitHub dans la chaîne DevOps Azure +- Comparer GitHub et Azure DevOps + +--- + +## Qu'est-ce que GitHub ? + +**GitHub** est une plateforme web d'hébergement et de gestion de code source basée sur Git. Lancée en 2008 et rachetée par Microsoft en 2018, c'est la plus grande plateforme de développement collaboratif au monde avec plus de 100 millions de développeurs. + +Dans un contexte **DevOps Azure**, GitHub est bien plus qu'un simple hébergeur de code : c'est le **point de contrôle central** de toute modification d'infrastructure avant qu'elle n'atteigne Azure. + +### GitHub vs Git + +| Aspect | Git | GitHub | +|---|---|---| +| **Type** | Outil local de versionnage | Plateforme cloud collaborative | +| **Installation** | Sur votre machine | Hébergé par Microsoft | +| **Fonction principale** | Versionner du code / IaC | Héberger, collaborer, automatiser | +| **Interface** | Ligne de commande | Interface web + CLI + API | +| **Collaboration** | Possible mais limitée | Optimisée : PR, Reviews, Issues | + +**Git** est le moteur local. **GitHub** est la plateforme qui orchestre la collaboration et les déploiements Azure autour de ce moteur. + +--- + +## Pourquoi GitHub est central en DevOps Azure ? + +### 🏗️ Source de vérité pour l'infrastructure + +Tous vos fichiers Terraform, Bicep, manifests Kubernetes et scripts Azure CLI vivent dans GitHub. Personne ne modifie Azure directement via le portail — tout passe par un commit, une Pull Request et un pipeline automatisé. C'est le principe fondateur du **GitOps**. + +### 🔄 CI/CD intégré nativement + +**GitHub Actions** déclenche automatiquement `terraform plan` à chaque PR et `terraform apply` après merge sur `main`, sans outil externe. L'authentification avec Azure se fait via **OIDC** (sans stocker de credentials). + +### 🔒 Contrôle d'accès et traçabilité + +Les **Branch Rulesets** et **CODEOWNERS** garantissent qu'aucune modification d'infrastructure sensible n'est mergée sans la validation des bonnes personnes. Chaque action est auditée. + +### 🛡️ Sécurité proactive + +**Secret Scanning** bloque la publication accidentelle de credentials Azure. **Dependabot** maintient les versions des providers Terraform à jour. **CodeQL** détecte les failles dans les scripts. + +### 📊 Gestion de projet intégrée + +**Issues**, **Projects** et **Milestones** permettent de piloter les chantiers d'infrastructure (migration AKS, mise à jour providers, remédiation sécurité) sans quitter l'outil. + +--- + +## Les concepts clés de GitHub + +| Concept | Description en DevOps Azure | +|---|---| +| **Repository** | Dépôt contenant votre IaC, manifests K8s et pipelines CI/CD | +| **Fork** | Copie d'un module Terraform public pour le personnaliser | +| **Pull Request (PR)** | Validation obligatoire avant tout `terraform apply` en production | +| **Issue** | Ticket pour un incident infra, une évolution ou une faille de sécurité | +| **Actions** | Workflows CI/CD déclenchant les déploiements Azure | +| **Environments** | Représentation de dev/staging/prod avec leurs secrets et leurs gates | +| **CODEOWNERS** | Fichier définissant qui doit approuver chaque partie de l'infra | + +--- + +## GitHub dans la chaîne DevOps Azure + +``` +Ingénieur DevOps + │ + │ git push → Pull Request + ▼ + ┌──────────────────────────────────────┐ + │ GitHub │ + │ Branch Rulesets ── CODEOWNERS │ + │ Secret Scanning ── Dependabot │ + └────────────────┬─────────────────────┘ + │ GitHub Actions (OIDC) + ▼ + ┌──────────────────────────────────────┐ + │ Azure │ + │ terraform plan / apply → Resources │ + │ az acr build → ACR │ + │ kubectl apply → AKS │ + └──────────────────────────────────────┘ +``` + +--- + +## GitHub vs Azure DevOps + +Les deux plateformes appartiennent à Microsoft et s'intègrent avec Azure. Le choix dépend du contexte : + +| Critère | GitHub | Azure DevOps | +|---|---|---| +| **CI/CD** | GitHub Actions | Azure Pipelines | +| **Gestion de projet** | Projects (Kanban/Table/Roadmap) | Boards (plus complet, intégration Jira) | +| **Dépôts** | GitHub Repos | Azure Repos | +| **Intégration Azure** | Via OIDC + `azure/login` | Native (Service Connection) | +| **Communauté** | La plus grande, open source | Principalement entreprises | +| **Cas d'usage** | Équipes modernes, cloud-native | Organisations avec historique Microsoft | + +> 💡 **En pratique** : les deux coexistent souvent en entreprise. Le code et les pipelines sur GitHub, la gestion de backlog sur Azure DevOps Boards. + +--- + +[🏠 Retour à l'accueil](README.md) | [02 - Premiers pas →](02-premiers-pas-ssh.md) diff --git a/02-premiers-pas-ssh.md b/02-premiers-pas-ssh.md new file mode 100644 index 0000000..b32c242 --- /dev/null +++ b/02-premiers-pas-ssh.md @@ -0,0 +1,161 @@ +# 02 - Premiers pas sur GitHub + +[← 01 - Introduction](01-introduction-concepts.md) | [🏠 Accueil](README.md) | [03 - Pull Requests →](03-pull-requests-code-review.md) + +--- + +## Objectifs de cette partie + +- Créer un compte GitHub professionnel +- Configurer votre profil DevOps +- Mettre en place l'authentification SSH +- Créer votre premier dépôt IaC +- Pousser un projet existant vers GitHub + +--- + +## Créer un compte GitHub + +1. Rendez-vous sur [github.com](https://github.com) +2. Cliquez sur **Sign up** +3. Choisissez un nom d'utilisateur professionnel (visible sur toutes vos contributions) +4. Vérifiez votre email +5. Le plan **Free** est suffisant — GitHub Teams/Enterprise est géré par votre organisation + +### Configurer votre profil DevOps + +Un profil complet renforce votre crédibilité auprès des recruteurs et collègues : + +- **Photo de profil** : photo professionnelle +- **Nom complet** : votre vrai nom +- **Bio** : `Ingénieur DevOps Azure | Terraform · AKS · GitHub Actions · CI/CD` +- **Localisation** : ville, pays +- **Site web** : LinkedIn ou portfolio +- **Entreprise** : votre employeur actuel + +--- + +## Authentification SSH + +SSH est la méthode recommandée pour interagir avec GitHub depuis le terminal : plus sécurisée, pas de mot de passe à chaque push. + +### Étape 1 : Générer une clé SSH + +```bash +# Algorithme ED25519 — moderne et recommandé +ssh-keygen -t ed25519 -C "votre.email@example.com" + +# Acceptez le chemin par défaut (~/.ssh/id_ed25519) +# Définissez une passphrase (recommandé) +``` + +### Étape 2 : Démarrer l'agent SSH + +```bash +eval "$(ssh-agent -s)" +ssh-add ~/.ssh/id_ed25519 +``` + +### Étape 3 : Copier la clé publique + +```bash +cat ~/.ssh/id_ed25519.pub +# Sur macOS : pbcopy < ~/.ssh/id_ed25519.pub +``` + +### Étape 4 : Ajouter la clé sur GitHub + +1. **Settings** → **SSH and GPG keys** → **New SSH key** +2. Titre : `Laptop DevOps` (identifiez la machine) +3. Collez la clé publique +4. **Add SSH key** + +### Étape 5 : Tester la connexion + +```bash +ssh -T git@github.com +# Réponse attendue : +# Hi username! You've successfully authenticated... +``` + +--- + +## Créer votre premier dépôt IaC + +### Via l'interface web + +1. Cliquez sur **+** → **New repository** +2. Configurez : + - **Repository name** : `infra-azure-devops` + - **Description** : `Infrastructure Azure - Terraform + AKS` + - **Private** (par défaut pour l'infra) + - ✅ Add a README file + - **.gitignore** : choisissez **Terraform** +3. **Create repository** + +### Structure de dépôt recommandée + +``` +infra-azure-devops/ +├── modules/ +│ ├── aks/ +│ └── network/ +├── environments/ +│ ├── dev/ +│ └── prod/ +├── kubernetes/ +├── .github/ +│ ├── workflows/ +│ ├── CODEOWNERS +│ └── pull_request_template.md +├── .gitignore ← généré par GitHub (Terraform) +└── README.md +``` + +--- + +## Pousser un projet local existant vers GitHub + +```bash +# 1. Créer un repo VIDE sur GitHub (sans README ni .gitignore) + +# 2. Dans votre projet local +cd infra-azure-devops + +# 3. Lier le remote +git remote add origin git@github.com:votre-username/infra-azure-devops.git + +# 4. Vérifier +git remote -v + +# 5. Pousser +git branch -M main +git push -u origin main +``` + +--- + +## ⚠️ Avant de pousser : vérifiez votre .gitignore + +Un credential Azure commité sur GitHub est un credential compromis — même supprimé, il reste dans l'historique Git. + +```gitignore +# Terraform — généré automatiquement par GitHub +*.tfstate +*.tfstate.* +.terraform/ +.terraform.lock.hcl +*.tfplan + +# Secrets Azure +.env +*.pem +service-principal.json +terraform.tfvars # contient souvent des valeurs sensibles +``` + +> 💡 **Conseil** : activez dès maintenant **Secret Scanning** sur votre organisation GitHub (Settings → Code security). Il bloquera tout push contenant un pattern de credential Azure reconnu. + +--- + +[← 01 - Introduction](01-introduction-concepts.md) | [🏠 Accueil](README.md) | [03 - Pull Requests →](03-pull-requests-code-review.md) diff --git a/03-pull-requests-code-review.md b/03-pull-requests-code-review.md new file mode 100644 index 0000000..91849f3 --- /dev/null +++ b/03-pull-requests-code-review.md @@ -0,0 +1,227 @@ +# 03 - Pull Requests, CODEOWNERS et Templates + +[← 02 - Premiers pas](02-premiers-pas-ssh.md) | [🏠 Accueil](README.md) | [04 - Issues et Projects →](04-issues-gestion-projet.md) + +--- + +## Objectifs de cette partie + +- Maîtriser le workflow Pull Request pour l'infrastructure +- Configurer CODEOWNERS pour protéger les modules critiques +- Créer des templates de PR et d'Issue adaptés au DevOps +- Effectuer des code reviews constructives sur du code IaC +- Choisir la bonne stratégie de merge + +--- + +## Le rôle central de la Pull Request en DevOps Azure + +Une **Pull Request** n'est pas simplement un mécanisme de code review : c'est la **porte d'entrée obligatoire** avant tout changement d'infrastructure Azure. Chaque PR déclenche automatiquement `terraform plan` et affiche le diff des ressources Azure qui seront créées, modifiées ou supprimées. + +``` +feature/add-aks-nodepool + │ + │ git push + ▼ + ┌──────────┐ + │ PR │──── terraform plan (CI) ──── affiche le diff Azure + └────┬─────┘ + │ Approbations CODEOWNERS + tests verts + ▼ + main ──── terraform apply ──── Azure (prod) +``` + +--- + +## Workflow complet d'une PR d'infrastructure + +### Étape 1 : Créer une branche + +```bash +git switch main && git pull origin main +git switch -c feature/add-aks-nodepool +``` + +### Étape 2 : Développer et committer + +```bash +# Modifier modules/aks/main.tf +git add modules/aks/main.tf +git commit -m "feat(aks): add spot node pool for batch workloads" +git push -u origin feature/add-aks-nodepool +``` + +### Étape 3 : Ouvrir la PR sur GitHub + +GitHub affiche une bannière "Compare & pull request" dès que vous poussez une branche. + +### Étape 4 : Rédiger une description complète + +```markdown +## 🎯 Objectif + +Ajout d'un node pool Spot pour les workloads batch (coût réduit de 70%). + +## 📝 Changements Terraform + +- `modules/aks/main.tf` : ajout de la ressource `azurerm_kubernetes_cluster_node_pool` +- `modules/aks/variables.tf` : nouvelles variables `spot_node_count`, `spot_vm_size` +- `environments/prod/terraform.tfvars` : activation du node pool Spot en prod + +## 🔍 Terraform Plan + +``` +# azurerm_kubernetes_cluster_node_pool.spot will be created ++ resource "azurerm_kubernetes_cluster_node_pool" "spot" { + + name = "spot" + + node_count = 2 + + priority = "Spot" + + vm_size = "Standard_D4s_v3" + } + +Plan: 1 to add, 0 to change, 0 to destroy. +``` + +## ✅ Checklist + +- [x] `terraform validate` passe +- [x] `terraform plan` attaché ci-dessus +- [x] Pas de régression sur les ressources existantes +- [x] Variables documentées dans variables.tf + +## ⚠️ Points d'attention + +- Vérifier la disponibilité des VMs Spot dans la région West Europe +- Les nœuds Spot peuvent être évincés : les workloads doivent être tolerants + +Closes #87 +``` + +--- + +## CODEOWNERS : Protéger les modules critiques + +Le fichier `.github/CODEOWNERS` définit qui doit **obligatoirement** approuver les modifications dans chaque répertoire. En DevOps Azure, c'est indispensable : personne ne doit pouvoir modifier un module réseau ou les variables de production sans que le bon expert valide. + +### Créer `.github/CODEOWNERS` + +``` +# .github/CODEOWNERS +# Syntaxe : <@user ou @org/team> + +# Tout le dépôt : revue obligatoire de l'équipe infra +* @mon-org/infra-team + +# Modules réseau : validé par l'architecte réseau +/modules/network/ @alice-network-architect + +# Module AKS : validé par l'expert Kubernetes +/modules/aks/ @bob-k8s-lead + +# Environnement de production : double validation requise +/environments/prod/ @alice-network-architect @bob-k8s-lead + +# Pipelines CI/CD : validé par le lead DevOps +/.github/workflows/ @charlie-devops-lead + +# Fichiers de sécurité : validé par l'équipe sécurité +/modules/keyvault/ @mon-org/security-team +/.github/CODEOWNERS @mon-org/security-team +``` + +> ⚠️ **Important** : pour que CODEOWNERS soit appliqué, la branche `main` doit avoir une **branch protection rule** avec "Require review from Code Owners" activé (voir module 06). + +--- + +## Templates de PR et d'Issue + +Les templates standardisent les informations fournies par les équipes et réduisent les allers-retours. + +### Template de Pull Request : `.github/pull_request_template.md` + +```markdown +## 🎯 Objectif + + +## 📝 Changements IaC + + +## 🔍 Terraform Plan / az diff + + +## ✅ Checklist +- [ ] `terraform validate` et `terraform fmt` passent +- [ ] Pas de secrets dans les fichiers committés +- [ ] Variables documentées +- [ ] `.gitignore` à jour si nécessaire +- [ ] README mis à jour si l'interface du module change + +## ⚠️ Risques et points d'attention pour les reviewers + + +## 🔗 Issue liée +Closes # +``` + +### Template d'Issue : `.github/ISSUE_TEMPLATE/incident-infra.md` + +```markdown +--- +name: Incident Infrastructure +about: Signaler un incident ou une dégradation sur l'infrastructure Azure +labels: incident, priority:high +--- + +## 🚨 Description de l'incident + + +## Impact +- Environnement concerné : [ ] dev [ ] staging [ ] prod +- Services impactés : +- Depuis quand : + +## Symptômes observés + + +## Hypothèse de cause + + +## Actions de remédiation envisagées + +``` + +--- + +## Code Review IaC : bonnes pratiques + +### Pour l'auteur de la PR + +**À faire :** PR petite et focalisée sur une seule ressource ou décision. Toujours joindre le `terraform plan`. Répondre rapidement aux commentaires. + +**À éviter :** Mélanger un nouveau module AKS et une refactorisation réseau dans la même PR. Description vide. Push force sur une branche partagée. + +### Pour le reviewer + +**Checklist de review IaC :** + +- La ressource va-t-elle être **recréée** (`-/+`) alors qu'on voulait juste la modifier (`~`) ? +- Y a-t-il des `sensitive = true` manquants sur les outputs ? +- Les variables ont-elles des descriptions et des types explicites ? +- Le `.gitignore` couvre-t-il les nouveaux fichiers générés ? +- Les règles de sécurité (NSG, RBAC) respectent-elles le principe du moindre privilège ? + +--- + +## Stratégies de merge + +| Type | Comportement | Recommandé pour | +|---|---|---| +| **Merge commit** | Crée un commit de fusion, historique complet | Projets où l'audit trail est prioritaire | +| **Squash and merge** | Combine tous les commits en un seul propre | Historique lisible sur `main` ✅ | +| **Rebase and merge** | Historique linéaire strict | Équipes avec discipline de commit élevée | + +Pour la plupart des dépôts IaC, **Squash and merge** est le meilleur choix : un commit sur `main` = une fonctionnalité ou un fix = un déploiement Azure potentiel. + +--- + +[← 02 - Premiers pas](02-premiers-pas-ssh.md) | [🏠 Accueil](README.md) | [04 - Issues et Projects →](04-issues-gestion-projet.md) diff --git a/04-issues-gestion-projet.md b/04-issues-gestion-projet.md new file mode 100644 index 0000000..8c4be77 --- /dev/null +++ b/04-issues-gestion-projet.md @@ -0,0 +1,142 @@ +# 04 - Issues et Gestion de projet + +[← 03 - Pull Requests](03-pull-requests-code-review.md) | [🏠 Accueil](README.md) | [05 - GitHub Actions →](05-github-actions-cicd.md) + +--- + +## Objectifs de cette partie + +- Créer et gérer des Issues pour les incidents et évolutions d'infrastructure +- Organiser avec Labels et Milestones DevOps +- Maîtriser GitHub Projects pour piloter les chantiers d'infra +- Lier automatiquement Issues et Pull Requests + +--- + +## Les Issues en DevOps Azure + +Les **Issues** sont le système de tickets de GitHub. En DevOps Azure, elles servent à : + +- 🚨 Signaler un incident d'infrastructure (AKS en panne, quota dépassé) +- 💡 Proposer une évolution (nouveau module Terraform, migration vers Bicep) +- 🔒 Tracer une remédiation de sécurité (faille NSG, rotation de secrets) +- 📋 Planifier une mise à jour de provider Terraform +- 💬 Discuter d'une décision d'architecture + +### Exemple d'issue bien rédigée — Incident AKS + +```markdown +## 🚨 Incident : Node pool AKS saturé en production + +**Description** +Le node pool `default` du cluster `aks-cloudops-prod` est à 100% de capacité. +Les nouveaux pods sont en état `Pending` depuis 14h35. + +**Impact** +- Environnement : Production +- Services impactés : API backend, workers batch +- Depuis : 2024-03-15 14:35 UTC + +**Logs / Alertes** +``` +kubectl describe node aks-default-xxxxx + Allocatable: cpu: 1930m, memory: 5GiB + Allocated: cpu: 1920m (99%), memory: 5GiB (99%) +``` + +**Hypothèse de cause** +Augmentation soudaine de trafic suite au lancement marketing. Le HPA a atteint +maxReplicas mais les nodes sont insuffisants. + +**Actions envisagées** +- Court terme : augmenter manuellement `node_count` dans Terraform (PR #92) +- Long terme : activer le Cluster Autoscaler (Issue #93) +``` + +--- + +## Labels : Organiser les Issues DevOps + +Créez des labels adaptés à vos chantiers d'infrastructure : + +| Label | Usage | +|---|---| +| `incident` | Problème actif en production | +| `infrastructure` | Modification de ressources Azure | +| `security` | Faille, rotation de secrets, RBAC | +| `terraform` | Mise à jour provider, refacto IaC | +| `kubernetes` | AKS, manifests, Helm | +| `ci-cd` | Workflows GitHub Actions | +| `priority:critical` | À traiter dans l'heure | +| `priority:high` | À traiter dans la journée | +| `priority:low` | Backlog | +| `good-first-issue` | Bon pour les nouveaux membres | + +--- + +## Milestones : Planifier les releases d'infrastructure + +Les **Milestones** regroupent les Issues autour d'un objectif ou d'une version. + +**Exemple : Milestone "Infrastructure v2.0 — Migration AKS 1.29"** + +- Date cible : 30 juin 2025 +- Description : Migration du cluster AKS vers la version 1.29 avec activation du Cluster Autoscaler +- Issues liées : 12 issues (8 fermées, 4 ouvertes) +- Progression : 67% + +--- + +## GitHub Projects : Tableau Kanban DevOps + +**GitHub Projects** est le système de gestion de projet intégré. En DevOps Azure, il permet de visualiser l'avancement des chantiers d'infrastructure en temps réel. + +### Colonnes typiques pour un projet d'infra + +``` +┌───────────┬───────────┬─────────────┬──────────┬──────────┐ +│ Backlog │ To Do │ In Progress │ Review │ Done │ +│ │ │ │ │ │ +│ Issue #95 │ Issue #91 │ Issue #88 │ PR #90 │ Issue #85│ +│ Issue #96 │ Issue #92 │ Issue #89 │ │ Issue #86│ +└───────────┴───────────┴─────────────┴──────────┴──────────┘ +``` + +- **Backlog** : évolutions et idées non encore planifiées +- **To Do** : issues assignées, prêtes à démarrer +- **In Progress** : en cours de développement IaC +- **Review** : PR ouverte, en attente d'approbation CODEOWNERS +- **Done** : mergé et déployé sur Azure + +### Automatisation + +GitHub Projects peut déplacer automatiquement les items : +- Issue assignée → **To Do** +- PR créée → **Review** +- PR mergée → **Done** + ferme l'issue liée + +--- + +## Lier Issues et Pull Requests + +Utilisez des mots-clés dans la description de vos PR pour fermer automatiquement les issues au merge : + +```markdown +## Description + +Correction de la saturation du node pool AKS en augmentant la capacité +et en activant le Cluster Autoscaler. + +## Closes + +Closes #88 +Fixes #89 +``` + +Mots-clés reconnus : `closes`, `fixes`, `resolves` (insensible à la casse). + +Quand la PR est mergée dans `main`, les issues liées sont automatiquement fermées et passent en **Done** dans GitHub Projects. + +--- + +[← 03 - Pull Requests](03-pull-requests-code-review.md) | [🏠 Accueil](README.md) | [05 - GitHub Actions →](05-github-actions-cicd.md) diff --git a/05-github-actions-cicd.md b/05-github-actions-cicd.md new file mode 100644 index 0000000..8e069b5 --- /dev/null +++ b/05-github-actions-cicd.md @@ -0,0 +1,350 @@ +# 05 - GitHub Actions : CI/CD Azure + +[← 04 - Issues et Projects](04-issues-gestion-projet.md) | [🏠 Accueil](README.md) | [06 - Sécurité →](06-securite-bonnes-pratiques.md) + +--- + +## Objectifs de cette partie + +- Comprendre GitHub Actions et ses concepts clés +- Configurer l'authentification OIDC avec Azure (sans credentials long-lived) +- Créer un pipeline Terraform CI/CD complet +- Déployer sur AKS via GitHub Actions +- Gérer les secrets et variables d'environnement + +--- + +## Qu'est-ce que GitHub Actions ? + +**GitHub Actions** est un système d'automatisation intégré à GitHub. Chaque workflow est un fichier YAML dans `.github/workflows/` déclenché par des événements Git (push, PR, tag, schedule...). + +### Concepts clés + +| Concept | Description | +|---|---| +| **Workflow** | Processus automatisé défini dans un fichier YAML | +| **Job** | Ensemble d'étapes s'exécutant sur le même runner | +| **Step** | Commande ou action individuelle | +| **Runner** | Machine virtuelle (Ubuntu, macOS, Windows) ou self-hosted | +| **Action** | Composant réutilisable du marketplace | +| **Event** | Déclencheur : push, pull_request, schedule, workflow_dispatch... | + +--- + +## 1. Authentification Azure avec OIDC (recommandé) + +L'**OIDC (OpenID Connect)** est la méthode moderne pour authentifier GitHub Actions vers Azure **sans stocker de secrets long-lived**. GitHub génère un token JWT à chaque exécution ; Azure le valide directement. + +### Pourquoi OIDC plutôt qu'un Service Principal avec secret ? + +| | Service Principal (ancien) | OIDC (recommandé) | +|---|---|---| +| **Secret stocké dans GitHub** | Oui (`AZURE_CLIENT_SECRET`) | Non | +| **Rotation des credentials** | Manuelle, risque d'oubli | Automatique (token éphémère) | +| **Surface d'attaque** | Secret permanent volable | Token valable quelques minutes | +| **Conformité** | ❌ Déconseillé | ✅ Recommandé par Microsoft | + +### Configurer OIDC (une seule fois) + +**Étape 1 : Créer une App Registration Azure** + +```bash +# Créer l'App Registration +az ad app create --display-name "github-actions-infra-azure" + +# Récupérer l'appId +APP_ID=$(az ad app list --display-name "github-actions-infra-azure" --query "[0].appId" -o tsv) + +# Créer le Service Principal associé +az ad sp create --id $APP_ID + +# Récupérer l'Object ID du SP +SP_OBJECT_ID=$(az ad sp show --id $APP_ID --query "id" -o tsv) +``` + +**Étape 2 : Créer la Federated Credential** + +```bash +# Autoriser GitHub Actions à s'authentifier (branche main) +az ad app federated-credential create \ + --id $APP_ID \ + --parameters '{ + "name": "github-main", + "issuer": "https://token.actions.githubusercontent.com", + "subject": "repo:mon-org/infra-azure-devops:ref:refs/heads/main", + "audiences": ["api://AzureADTokenExchange"] + }' + +# Autoriser aussi les Pull Requests +az ad app federated-credential create \ + --id $APP_ID \ + --parameters '{ + "name": "github-pr", + "issuer": "https://token.actions.githubusercontent.com", + "subject": "repo:mon-org/infra-azure-devops:pull_request", + "audiences": ["api://AzureADTokenExchange"] + }' +``` + +**Étape 3 : Assigner les permissions Azure** + +```bash +SUBSCRIPTION_ID=$(az account show --query id -o tsv) + +# Rôle Contributor sur la subscription (ou scope plus restreint) +az role assignment create \ + --assignee $APP_ID \ + --role "Contributor" \ + --scope "/subscriptions/${SUBSCRIPTION_ID}" +``` + +**Étape 4 : Ajouter les secrets GitHub** (sans le `AZURE_CLIENT_SECRET` !) + +Dans **Settings → Secrets and variables → Actions** : + +| Secret | Valeur | +|---|---| +| `AZURE_CLIENT_ID` | `appId` de l'App Registration | +| `AZURE_TENANT_ID` | ID de votre tenant Azure | +| `AZURE_SUBSCRIPTION_ID` | ID de votre subscription | + +--- + +## 2. Pipeline Terraform CI/CD complet + +```yaml +# .github/workflows/terraform.yml +name: Terraform CI/CD Azure + +on: + pull_request: + branches: [main] + paths: + - 'environments/**' + - 'modules/**' + push: + branches: [main] + paths: + - 'environments/**' + - 'modules/**' + +permissions: + id-token: write # Requis pour OIDC + contents: read + pull-requests: write # Pour commenter le plan sur la PR + +env: + TF_VERSION: '1.7.0' + WORKING_DIR: ./environments/prod + +jobs: + terraform-validate: + name: 🔍 Validate + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: ${{ env.TF_VERSION }} + + - name: Login Azure (OIDC) + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Terraform Init + run: terraform init + working-directory: ${{ env.WORKING_DIR }} + + - name: Terraform Format Check + run: terraform fmt -check -recursive + + - name: Terraform Validate + run: terraform validate + working-directory: ${{ env.WORKING_DIR }} + + terraform-plan: + name: 📋 Plan + needs: terraform-validate + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + outputs: + plan_exitcode: ${{ steps.plan.outputs.exitcode }} + + steps: + - uses: actions/checkout@v4 + + - uses: hashicorp/setup-terraform@v3 + with: + terraform_version: ${{ env.TF_VERSION }} + + - name: Login Azure (OIDC) + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Terraform Init + run: terraform init + working-directory: ${{ env.WORKING_DIR }} + + - name: Terraform Plan + id: plan + run: | + terraform plan -no-color -detailed-exitcode -out=tfplan 2>&1 | tee plan_output.txt + echo "exitcode=${PIPESTATUS[0]}" >> $GITHUB_OUTPUT + working-directory: ${{ env.WORKING_DIR }} + continue-on-error: true + + # Publier le plan en commentaire sur la PR + - name: Comment PR with Plan + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + const plan = fs.readFileSync('${{ env.WORKING_DIR }}/plan_output.txt', 'utf8'); + const maxLen = 65000; + const truncated = plan.length > maxLen ? plan.substring(0, maxLen) + '\n...(tronqué)' : plan; + const body = `## 📋 Terraform Plan\n\`\`\`hcl\n${truncated}\n\`\`\``; + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body + }); + + - name: Fail if plan errored + if: steps.plan.outputs.exitcode == '1' + run: exit 1 + + terraform-apply: + name: 🚀 Apply + needs: terraform-validate + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/main' && github.event_name == 'push' + + steps: + - uses: actions/checkout@v4 + + - uses: hashicorp/setup-terraform@v3 + with: + terraform_version: ${{ env.TF_VERSION }} + + - name: Login Azure (OIDC) + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Terraform Init + run: terraform init + working-directory: ${{ env.WORKING_DIR }} + + - name: Terraform Apply + run: terraform apply -auto-approve + working-directory: ${{ env.WORKING_DIR }} +``` + +--- + +## 3. Déploiement sur AKS + +```yaml +# .github/workflows/deploy-aks.yml +name: Build and Deploy to AKS + +on: + push: + branches: [main] + paths: + - 'src/**' + - 'kubernetes/**' + +permissions: + id-token: write + contents: read + +jobs: + build-push: + name: 🐳 Build & Push ACR + runs-on: ubuntu-latest + outputs: + image_tag: ${{ steps.meta.outputs.version }} + + steps: + - uses: actions/checkout@v4 + + - name: Login Azure (OIDC) + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Build and push to ACR + id: meta + run: | + TAG=$(git rev-parse --short HEAD) + az acr build \ + --registry ${{ vars.ACR_NAME }} \ + --image mon-app:${TAG} \ + --image mon-app:latest . + echo "version=${TAG}" >> $GITHUB_OUTPUT + + deploy-aks: + name: ☸️ Deploy AKS + needs: build-push + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Login Azure (OIDC) + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Set AKS context + uses: azure/aks-set-context@v3 + with: + resource-group: rg-cloudops-prod + cluster-name: aks-cloudops-prod + + - name: Deploy to AKS + uses: azure/k8s-deploy@v4 + with: + manifests: kubernetes/deployment.yaml + images: ${{ vars.ACR_NAME }}.azurecr.io/mon-app:${{ needs.build-push.outputs.image_tag }} +``` + +--- + +## 4. Secrets et Variables + +### Hiérarchie + +| Niveau | Portée | Cas d'usage | +|---|---|---| +| **Repository secret** | Un seul repo | Credentials propres au projet | +| **Repository variable** | Un seul repo | Config non-sensible (`ACR_NAME`) | +| **Environment secret** | Un env (prod/staging) | Credentials par environnement | +| **Organization secret** | Tous les repos de l'org | Credentials partagés | + +### Bonnes pratiques + +- Ne jamais mettre de secret dans le YAML du workflow +- Utiliser OIDC plutôt que des secrets pour Azure +- Les secrets sont masqués dans les logs automatiquement +- Faites une rotation régulière des secrets résiduels + +--- + +[← 04 - Issues et Projects](04-issues-gestion-projet.md) | [🏠 Accueil](README.md) | [06 - Sécurité →](06-securite-bonnes-pratiques.md) diff --git a/06-securite-bonnes-pratiques.md b/06-securite-bonnes-pratiques.md new file mode 100644 index 0000000..10cfc91 --- /dev/null +++ b/06-securite-bonnes-pratiques.md @@ -0,0 +1,208 @@ +# 06 - Sécurité et Branch Protection + +[← 05 - GitHub Actions](05-github-actions-cicd.md) | [🏠 Accueil](README.md) | [07 - Fonctionnalités avancées →](07-fonctionnalites-avancees.md) + +--- + +## Objectifs de cette partie + +- Configurer les GitHub Rulesets pour protéger les branches +- Activer et comprendre GitHub Advanced Security (GHAS) +- Utiliser Dependabot pour les providers Terraform +- Configurer Secret Scanning avec push protection +- Créer un README professionnel pour un projet IaC + +--- + +## 1. GitHub Rulesets (Branch Protection moderne) + +Les **Rulesets** sont le successeur des Branch Protection Rules. Plus flexibles et exportables, ils permettent de définir des règles sur plusieurs branches à la fois. + +### Créer un Ruleset pour `main` + +**Settings → Rules → Rulesets → New ruleset** + +``` +Nom : protect-main +Enforcement : Active +Target : Branch name matches "main" + +Règles à activer : +✅ Restrict creations → personne ne peut créer/supprimer main +✅ Restrict deletions +✅ Require pull request → tout passe par une PR + ✅ Required approvals : 1 minimum + ✅ Dismiss stale reviews → re-approval si nouveau commit poussé + ✅ Require review from Code Owners +✅ Require status checks → CI doit passer avant le merge + Ajouter : "terraform-validate / 🔍 Validate" +✅ Block force pushes → interdit même pour les admins +✅ Require signed commits → traçabilité renforcée (optionnel) +``` + +> 💡 **Différence avec Branch Protection** : Les Rulesets s'appliquent par pattern (ex : `release/*`) et peuvent être exportés/importés entre dépôts. Ils supportent aussi les **bypass lists** pour les workflows automatisés. + +--- + +## 2. GitHub Advanced Security (GHAS) + +GHAS regroupe trois fonctionnalités de sécurité automatisées. Pour les dépôts publics, GHAS est gratuit. + +### Secret Scanning — Push Protection + +Bloque tout push contenant un secret reconnu (credential Azure, token GitHub, clé AWS...) **avant** qu'il n'atteigne GitHub. + +**Activer :** +Settings → Code security → Secret scanning → **Enable** + **Push protection → Enable** + +Si un secret est détecté lors d'un `git push` : +``` +remote: — Push Protection ———————————————————— +remote: Secrets detected in push: +remote: AZURE_CLIENT_SECRET in terraform.tfvars (line 3) +remote: Push blocked. Revoke the secret and remove it from your commits. +``` + +**Si vous commitez un secret par erreur :** +1. Révoquez-le immédiatement dans le portail Azure +2. Supprimez-le de l'historique avec `git filter-repo --path-glob '*.tfvars' --invert-paths` +3. Force-push (après avoir désactivé temporairement la protection) +4. Ne faites PAS qu'un simple commit de suppression — le secret reste dans l'historique ! + +### Dependabot — Providers Terraform à jour + +Dependabot crée automatiquement des PR pour mettre à jour les dépendances, y compris les providers Terraform. + +**Configurer `.github/dependabot.yml` :** + +```yaml +version: 2 +updates: + # Providers Terraform + - package-ecosystem: "terraform" + directory: "/environments/prod" + schedule: + interval: "weekly" + labels: + - "terraform" + - "dependencies" + + # GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + labels: + - "ci-cd" + - "dependencies" +``` + +> ⚠️ **Attention** : les mises à jour de providers Terraform peuvent introduire des breaking changes. Configurez toujours une branch protection pour que Dependabot passe par la CI avant de merger. + +### Code Scanning — CodeQL pour IaC + +CodeQL analyse votre code pour détecter des vulnérabilités. Pour l'IaC, des outils spécialisés comme **Checkov** ou **tfsec** sont plus adaptés. + +**Ajouter tfsec dans votre CI :** + +```yaml +# .github/workflows/security-scan.yml +name: IaC Security Scan + +on: + pull_request: + paths: ['**.tf', '**.bicep'] + +jobs: + tfsec: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: tfsec + uses: aquasecurity/tfsec-action@v1.0.3 + with: + soft_fail: false # Bloque la PR si des failles sont trouvées + + checkov: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Checkov + uses: bridgecrewio/checkov-action@master + with: + directory: environments/ + framework: terraform + soft_fail: false +``` + +--- + +## 3. README professionnel pour un projet IaC + +```markdown +# Infrastructure Azure — CloudOps Corp + +![Terraform CI](https://github.com/mon-org/infra-azure/workflows/Terraform%20CI%2FCD%20Azure/badge.svg) +![Security Scan](https://github.com/mon-org/infra-azure/workflows/IaC%20Security%20Scan/badge.svg) +![Terraform](https://img.shields.io/badge/Terraform-1.7-purple) +![Azure](https://img.shields.io/badge/Azure-AKS%20%7C%20ACR%20%7C%20KeyVault-blue) + +Infrastructure Azure gérée en IaC (Terraform) pour CloudOps Corp. + +## 🏗️ Architecture + +- **AKS** : Cluster Kubernetes pour les workloads applicatifs +- **ACR** : Registry Docker privé +- **Key Vault** : Gestion des secrets +- **Virtual Network** : Isolation réseau + +## 🚀 Déploiement + +### Prérequis + +- Azure CLI >= 2.50 (`az --version`) +- Terraform >= 1.7 (`terraform --version`) +- Accès Contributor sur la subscription Azure + +### Déployer un environnement + +```bash +az login +cd environments/prod +terraform init +terraform plan +terraform apply +``` + +## 📁 Structure + +``` +├── modules/ # Modules Terraform réutilisables +│ ├── aks/ +│ ├── network/ +│ └── keyvault/ +├── environments/ # Configuration par environnement +│ ├── dev/ +│ └── prod/ +└── .github/ # CI/CD et configuration GitHub + ├── workflows/ + ├── CODEOWNERS + └── pull_request_template.md +``` + +## 🔒 Sécurité + +- Authentification Azure via **OIDC** (pas de credentials long-lived) +- **CODEOWNERS** : toute modification prod nécessite 2 approbations +- **Secret Scanning** : push protection activée +- **tfsec + Checkov** : scan de sécurité à chaque PR + +## 📖 Documentation + +- Runbook AKS : `docs/runbook-aks.md` +- Procédure de rollback : `docs/rollback.md` +``` + +--- + +[← 05 - GitHub Actions](05-github-actions-cicd.md) | [🏠 Accueil](README.md) | [07 - Fonctionnalités avancées →](07-fonctionnalites-avancees.md) diff --git a/07-fonctionnalites-avancees.md b/07-fonctionnalites-avancees.md new file mode 100644 index 0000000..54bed3b --- /dev/null +++ b/07-fonctionnalites-avancees.md @@ -0,0 +1,256 @@ +# 07 - Fonctionnalités avancées + +[← 06 - Sécurité](06-securite-bonnes-pratiques.md) | [🏠 Accueil](README.md) | [08 - Exercices →](08-exercices.md) + +--- + +## Objectifs de cette partie + +- Maîtriser GitHub CLI pour automatiser les tâches du quotidien +- Configurer GitHub Codespaces comme environnement IaC +- Utiliser GitHub Container Registry (GHCR) pour les images Docker +- Comprendre GitHub Packages + +--- + +## 1. GitHub CLI (`gh`) + +**gh** est l'outil officiel en ligne de commande de GitHub. Il permet de gérer repos, PRs, Issues et workflows directement depuis le terminal — indispensable pour automatiser les tâches DevOps. + +### Installation + +```bash +# macOS +brew install gh + +# Linux (Ubuntu/Debian) +sudo apt install gh + +# Windows +winget install GitHub.cli +``` + +### Authentification + +```bash +gh auth login +# Choisissez GitHub.com → SSH → authentification navigateur +``` + +### Commandes DevOps du quotidien + +```bash +# ── Dépôts ───────────────────────────────────────── +gh repo create mon-org/infra-azure --private --clone +gh repo view mon-org/infra-azure + +# ── Pull Requests ─────────────────────────────────── +gh pr create \ + --title "feat(aks): add spot node pool" \ + --body "Closes #87" \ + --reviewer alice,bob \ + --label "infrastructure" + +gh pr list # Lister les PRs ouvertes +gh pr view 42 # Détail d'une PR +gh pr checkout 42 # Checkout local d'une PR (pour tester) +gh pr merge 42 --squash --delete-branch + +# ── Issues ────────────────────────────────────────── +gh issue create \ + --title "Incident: AKS node pool saturé" \ + --label "incident,priority:critical" \ + --assignee @me + +gh issue list --label "incident" +gh issue close 88 --comment "Résolu par PR #90" + +# ── Workflows GitHub Actions ──────────────────────── +gh workflow list +gh workflow run terraform.yml # Déclencher manuellement +gh run list --workflow=terraform.yml +gh run view 12345 --log # Voir les logs d'un run +gh run watch # Suivre un run en temps réel + +# ── Secrets ───────────────────────────────────────── +gh secret set AZURE_CLIENT_ID +gh secret list +``` + +### Exemple : script d'automatisation + +```bash +#!/bin/bash +# Script : créer une PR de hotfix et notifier l'équipe + +BRANCH="hotfix/$(date +%Y%m%d)-nsg-fix" +git switch -c "$BRANCH" + +# ... faire le fix ... + +git add . +git commit -m "fix(security): restrict NSG inbound rule to corp CIDR" +git push -u origin "$BRANCH" + +# Créer la PR via gh CLI +gh pr create \ + --title "🔒 Hotfix: NSG inbound restriction" \ + --body "Fixes #$(gh issue list --label security --json number -q '.[0].number')" \ + --reviewer @mon-org/security-team \ + --label "security,priority:critical" + +echo "PR créée : $(gh pr view --json url -q .url)" +``` + +--- + +## 2. GitHub Codespaces — Environnement IaC dans le cloud + +**Codespaces** est un environnement de développement complet dans le navigateur (VS Code). Configuré avec un `devcontainer.json`, il lance automatiquement un environnement avec Terraform, Azure CLI, kubectl et tous vos outils préinstallés. + +### Configurer `.devcontainer/devcontainer.json` + +```json +{ + "name": "DevOps Azure IaC", + "image": "mcr.microsoft.com/devcontainers/base:ubuntu-22.04", + + "features": { + "ghcr.io/devcontainers/features/terraform:1": { + "version": "1.7.0" + }, + "ghcr.io/devcontainers/features/azure-cli:1": { + "version": "latest" + }, + "ghcr.io/devcontainers/features/kubectl-helm-minikube:1": { + "version": "latest" + }, + "ghcr.io/devcontainers/features/git:1": {} + }, + + "customizations": { + "vscode": { + "extensions": [ + "hashicorp.terraform", + "ms-azuretools.vscode-azureterraform", + "ms-kubernetes-tools.vscode-kubernetes-tools", + "ms-vscode.azure-account", + "github.vscode-pull-request-github" + ], + "settings": { + "editor.formatOnSave": true, + "[terraform]": { + "editor.defaultFormatter": "hashicorp.terraform" + } + } + } + }, + + "postCreateCommand": "terraform --version && az --version && kubectl version --client" +} +``` + +### Avantages pour le DevOps + +- Environnement identique pour toute l'équipe (plus de "ça marche sur ma machine") +- Accessible depuis n'importe quel navigateur, y compris tablette +- Gratuit jusqu'à 60h/mois sur les comptes personnels +- Idéal pour l'onboarding de nouveaux membres d'équipe + +### Démarrer un Codespace + +``` +GitHub → votre repo → Code → Codespaces → Create codespace on main +``` + +--- + +## 3. GitHub Container Registry (GHCR) + +**GHCR** (`ghcr.io`) est le registry Docker intégré à GitHub. Alternative à ACR pour héberger vos images de base ou outils internes. + +### Publier une image sur GHCR + +```yaml +# .github/workflows/publish-image.yml +name: Build and Publish to GHCR + +on: + push: + tags: ['v*'] + +permissions: + contents: read + packages: write # Requis pour pusher sur GHCR + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} # Token automatique, pas de secret à créer ! + + - name: Build and push + uses: docker/build-push-action@v5 + with: + push: true + tags: | + ghcr.io/${{ github.repository }}/mon-app:${{ github.ref_name }} + ghcr.io/${{ github.repository }}/mon-app:latest +``` + +### Utiliser une image GHCR dans AKS + +```yaml +# kubernetes/deployment.yaml +spec: + containers: + - name: mon-app + image: ghcr.io/mon-org/infra-azure/mon-app:v1.2.0 + imagePullPolicy: IfNotPresent +``` + +Pour les images privées, créez un `imagePullSecret` avec un Personal Access Token GitHub. + +--- + +## 4. Aide-mémoire : Workflow DevOps quotidien + +```bash +# 1. Synchroniser main +git switch main && git pull origin main + +# 2. Créer une branche feature +git switch -c feature/add-keyvault-module + +# 3. Développer, valider, committer +terraform validate && terraform fmt +git add . && git commit -m "feat(keyvault): add Key Vault module with RBAC" + +# 4. Pousser et créer la PR +git push -u origin feature/add-keyvault-module +gh pr create --title "feat(keyvault): add Key Vault module" --body "Closes #95" + +# 5. Suivre la CI en temps réel +gh run watch + +# 6. Intégrer les feedbacks de review +git commit -m "fix: address review comments" +git push + +# 7. Merger après approbation +gh pr merge --squash --delete-branch + +# 8. Vérifier le déploiement Azure +gh run list --workflow=terraform.yml +``` + +--- + +[← 06 - Sécurité](06-securite-bonnes-pratiques.md) | [🏠 Accueil](README.md) | [08 - Exercices →](08-exercices.md) diff --git a/08-exercices.md b/08-exercices.md new file mode 100644 index 0000000..2ab799c --- /dev/null +++ b/08-exercices.md @@ -0,0 +1,62 @@ +# 08 - Exercices : GitHub pour le DevOps Azure + +[← 07 - Fonctionnalités avancées](07-fonctionnalites-avancees.md) | [🏠 Accueil](README.md) | [09 - GitHub Actions Avancées →](09-github-actions-avance.md) + +--- + +## 📝 Niveau 1 : Premiers pas + +1. Créez un compte GitHub et configurez votre profil avec une bio DevOps Azure. +2. Générez une clé SSH ED25519 et ajoutez-la à votre compte GitHub. Vérifiez la connexion avec `ssh -T git@github.com`. +3. Créez un dépôt privé `infra-azure-practice` avec le `.gitignore` Terraform généré par GitHub. +4. Clonez-le en SSH, créez un fichier `versions.tf` avec les contraintes de version Terraform et Azure, committez et poussez. +5. Installez GitHub CLI (`gh`) et connectez-vous avec `gh auth login`. + +--- + +## 🌿 Niveau 2 : Pull Requests et CODEOWNERS + +1. Dans votre dépôt `infra-azure-practice`, créez la structure suivante : + ``` + .github/ + ├── CODEOWNERS + └── pull_request_template.md + modules/ + ├── aks/main.tf + └── network/main.tf + ``` +2. Rédigez un fichier `CODEOWNERS` qui : + - Assigne votre propre compte (`@votre-username`) à tout le dépôt + - Assigne un second reviewer (un collègue ou un second compte) spécifiquement au dossier `modules/aks/` +3. Créez un template de PR avec les sections : Objectif, Changements, Terraform Plan, Checklist, Issue liée. +4. Créez une branche `feature/add-aks-module`, ajoutez du contenu à `modules/aks/main.tf`, ouvrez une PR avec une description complète en utilisant le template, puis mergez en **Squash and merge**. +5. Activez la protection de branche sur `main` (Rulesets) : PR obligatoire, 1 approbation, CI doit passer. + +--- + +## ⚙️ Niveau 3 : GitHub Actions CI/CD Azure + +1. Configurez l'authentification OIDC entre votre dépôt GitHub et votre subscription Azure : + - Créez une App Registration Azure + - Ajoutez une Federated Credential pour votre repo (branche `main` et `pull_request`) + - Ajoutez les 3 secrets GitHub : `AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, `AZURE_SUBSCRIPTION_ID` +2. Créez un workflow `.github/workflows/terraform.yml` qui : + - Sur **Pull Request** : exécute `terraform init`, `fmt -check`, `validate` et `plan`, puis poste le plan en commentaire + - Sur **merge dans main** : exécute `terraform apply -auto-approve` +3. Vérifiez que le workflow se déclenche en ouvrant une nouvelle PR. +4. Ajoutez un second workflow `.github/workflows/security.yml` qui lance `tfsec` sur vos fichiers `.tf` à chaque PR. + +--- + +## 🔒 Niveau 4 : Sécurité et GitOps + +1. Activez **Secret Scanning avec Push Protection** sur votre dépôt. Tentez de committer une fausse clé Azure (`AZURE_CLIENT_SECRET=abc123`) et vérifiez que le push est bloqué. +2. Configurez **Dependabot** pour mettre à jour les providers Terraform et les GitHub Actions chaque semaine. +3. Créez le fichier `.github/dependabot.yml` correspondant et vérifiez qu'il apparaît dans **Insights → Dependency graph**. +4. **Bonus GitOps** : simulez un principe GitOps en créant une règle dans votre workflow qui vérifie que tout `terraform apply` ne s'exécute **que** depuis une PR mergée dans `main` (jamais depuis une branche directe). + +[📖 Voir les solutions](11-solutions.md) + +--- + +[← 07 - Fonctionnalités avancées](07-fonctionnalites-avancees.md) | [🏠 Accueil](README.md) | [09 - GitHub Actions Avancées →](09-github-actions-avance.md) diff --git a/09-github-actions-avance.md b/09-github-actions-avance.md new file mode 100644 index 0000000..710c6e4 --- /dev/null +++ b/09-github-actions-avance.md @@ -0,0 +1,274 @@ +# 09 - GitHub Actions Avancées + +[← 08 - Exercices](08-exercices.md) | [🏠 Accueil](README.md) | [10 - GitOps →](10-gitops.md) + +--- + +## Objectifs de cette partie + +- Configurer des Environments avec Deployment Gates (approbation manuelle prod) +- Créer des Reusable Workflows pour centraliser la logique CI/CD +- Mettre en place des Self-hosted runners Azure +- Contrôler la concurrence pour éviter les `terraform apply` parallèles + +--- + +## 1. GitHub Environments et Deployment Gates + +Les **Environments** représentent vos environnements Azure (dev, staging, prod). Chaque environment peut avoir ses propres secrets et des règles de protection — notamment une **approbation manuelle obligatoire** avant tout déploiement en production. + +### Créer les Environments + +**Settings → Environments → New environment** + +| Environment | Protection rules | Secrets | +|---|---|---| +| `dev` | Aucune (déploiement automatique) | `AZURE_CLIENT_ID_DEV` | +| `staging` | Aucune | `AZURE_CLIENT_ID_STAGING` | +| `prod` | ✅ Required reviewers: `@alice @bob` | `AZURE_CLIENT_ID_PROD` | + +### Utiliser les Environments dans un workflow + +```yaml +# .github/workflows/deploy-multi-env.yml +name: Deploy Infrastructure — Multi-env + +on: + push: + branches: [main] + +permissions: + id-token: write + contents: read + +jobs: + deploy-dev: + name: 🟢 Deploy Dev + runs-on: ubuntu-latest + environment: dev # Déploiement automatique, pas de gate + + steps: + - uses: actions/checkout@v4 + + - name: Login Azure (OIDC — Dev) + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - uses: hashicorp/setup-terraform@v3 + - run: terraform init && terraform apply -auto-approve + working-directory: environments/dev + + deploy-staging: + name: 🟡 Deploy Staging + needs: deploy-dev + runs-on: ubuntu-latest + environment: staging # Démarre seulement si dev réussit + + steps: + - uses: actions/checkout@v4 + - name: Login Azure (OIDC — Staging) + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + - uses: hashicorp/setup-terraform@v3 + - run: terraform init && terraform apply -auto-approve + working-directory: environments/staging + + deploy-prod: + name: 🔴 Deploy Prod + needs: deploy-staging + runs-on: ubuntu-latest + environment: prod # ← PAUSE ICI : approbation manuelle requise ! + + steps: + - uses: actions/checkout@v4 + - name: Login Azure (OIDC — Prod) + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + - uses: hashicorp/setup-terraform@v3 + - run: terraform init && terraform apply -auto-approve + working-directory: environments/prod +``` + +Quand le job `deploy-prod` démarre, GitHub envoie une notification aux reviewers désignés. Le pipeline se met en pause jusqu'à ce que l'un d'eux approuve (ou rejette) le déploiement via l'interface GitHub. + +--- + +## 2. Reusable Workflows + +Les **Reusable Workflows** permettent de définir la logique CI/CD une seule fois dans un workflow "appelé" et de l'invoquer depuis n'importe quel autre workflow. Indispensable pour éviter de dupliquer la logique Terraform dans chaque repo. + +### Créer un workflow réutilisable + +```yaml +# .github/workflows/_terraform-deploy.yml (préfixe _ = interne) +name: Terraform Deploy (Reusable) + +on: + workflow_call: + inputs: + environment: + required: true + type: string + description: "Nom de l'environnement Azure (dev/staging/prod)" + working_directory: + required: true + type: string + description: "Chemin vers le dossier Terraform" + terraform_version: + required: false + type: string + default: '1.7.0' + secrets: + AZURE_CLIENT_ID: + required: true + AZURE_TENANT_ID: + required: true + AZURE_SUBSCRIPTION_ID: + required: true + +permissions: + id-token: write + contents: read + +jobs: + terraform: + name: Deploy ${{ inputs.environment }} + runs-on: ubuntu-latest + environment: ${{ inputs.environment }} + + steps: + - uses: actions/checkout@v4 + + - uses: hashicorp/setup-terraform@v3 + with: + terraform_version: ${{ inputs.terraform_version }} + + - name: Login Azure (OIDC) + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Terraform Init + run: terraform init + working-directory: ${{ inputs.working_directory }} + + - name: Terraform Apply + run: terraform apply -auto-approve + working-directory: ${{ inputs.working_directory }} +``` + +### Appeler le workflow réutilisable + +```yaml +# .github/workflows/deploy.yml +name: Full Deployment Pipeline + +on: + push: + branches: [main] + +jobs: + deploy-dev: + uses: ./.github/workflows/_terraform-deploy.yml + with: + environment: dev + working_directory: environments/dev + secrets: + AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID_DEV }} + AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} + AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + deploy-prod: + needs: deploy-dev + uses: ./.github/workflows/_terraform-deploy.yml + with: + environment: prod + working_directory: environments/prod + secrets: + AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID_PROD }} + AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} + AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} +``` + +--- + +## 3. Self-hosted Runners Azure + +Les runners GitHub-hosted n'ont pas accès aux ressources Azure privées (AKS en réseau privé, Key Vault sans accès public). Les **self-hosted runners** s'exécutent sur vos propres machines Azure. + +### Déployer un runner sur ACI (Azure Container Instances) + +```bash +# 1. Récupérer le token d'enregistrement depuis GitHub +REPO="mon-org/infra-azure-devops" +TOKEN=$(gh api repos/${REPO}/actions/runners/registration-token --jq .token) + +# 2. Lancer le runner dans ACI +az container create \ + --resource-group rg-github-runners \ + --name github-runner-01 \ + --image ghcr.io/actions/runner:latest \ + --cpu 2 \ + --memory 4 \ + --environment-variables \ + REPO_URL="https://github.com/${REPO}" \ + RUNNER_TOKEN="${TOKEN}" \ + RUNNER_NAME="azure-runner-01" \ + RUNNER_LABELS="azure,terraform" +``` + +### Utiliser le self-hosted runner dans un workflow + +```yaml +jobs: + terraform-private: + runs-on: [self-hosted, azure, terraform] # Labels du runner + steps: + - uses: actions/checkout@v4 + - run: terraform apply -auto-approve + working-directory: environments/prod + # Ce job a accès aux ressources Azure privées ! +``` + +> 💡 **Sécurité** : les self-hosted runners ont accès au réseau Azure. Utilisez des **managed identities** ACI plutôt que des secrets pour s'authentifier à Azure. + +--- + +## 4. Contrôle de la concurrence + +Deux `terraform apply` simultanés sur le même état Terraform provoquent des corruptions. La directive `concurrency` garantit qu'un seul job s'exécute à la fois. + +```yaml +# Empêcher deux apply simultanés sur le même environnement +concurrency: + group: terraform-prod + cancel-in-progress: false # false = attendre, true = annuler le précédent + +jobs: + apply: + runs-on: ubuntu-latest + # ... +``` + +### Concurrence par environment + +```yaml +concurrency: + group: terraform-${{ github.event.inputs.environment || 'prod' }} + cancel-in-progress: false +``` + +--- + +[← 08 - Exercices](08-exercices.md) | [🏠 Accueil](README.md) | [10 - GitOps →](10-gitops.md) diff --git a/10-gitops.md b/10-gitops.md new file mode 100644 index 0000000..baa2615 --- /dev/null +++ b/10-gitops.md @@ -0,0 +1,227 @@ +# 10 - GitOps avec GitHub + +[← 09 - GitHub Actions Avancées](09-github-actions-avance.md) | [🏠 Accueil](README.md) | [11 - Solutions →](11-solutions.md) + +--- + +## Objectifs de cette partie + +- Comprendre le paradigme GitOps et ses principes +- Appliquer GitOps à l'infrastructure Azure avec GitHub +- Structurer un dépôt GitOps multi-environnements +- Détecter et corriger le drift entre Git et Azure +- Distinguer GitOps "push" et "pull" + +--- + +## Qu'est-ce que le GitOps ? + +Le **GitOps** est un modèle opérationnel qui utilise Git comme **unique source de vérité** pour l'état désiré de votre infrastructure et de vos applications. Toute modification passe par Git — jamais par le portail Azure, la CLI ou un script manuel. + +### Les 4 principes du GitOps + +**1. Déclaratif** : l'état désiré du système est décrit en code (Terraform, Bicep, YAML Kubernetes), pas en procédures impératives. + +**2. Versionné et immuable** : toute l'histoire des changements est dans Git. Revenir à un état précédent = `git revert` + pipeline. + +**3. Récupéré automatiquement** : un agent ou un pipeline tire l'état de Git et l'applique automatiquement. + +**4. Réconcilié en continu** : si l'état réel diverge de l'état Git (drift), le système le détecte et le corrige. + +--- + +## GitOps en pratique sur Azure + +``` +┌─────────────────────────────────────────────────────────┐ +│ GitHub │ +│ │ +│ main branch = état DÉSIRÉ de l'infra Azure │ +│ │ +│ PR → Review → Merge → Pipeline → Azure │ +└──────────────────────────────┬──────────────────────────┘ + │ GitHub Actions (OIDC) + │ terraform apply / kubectl apply + ▼ +┌─────────────────────────────────────────────────────────┐ +│ Azure (état RÉEL) │ +│ AKS cluster · VNet · Key Vault · ACR │ +└─────────────────────────────────────────────────────────┘ +``` + +### Règle fondamentale + +> **On ne modifie jamais Azure directement.** Ni par le portail, ni par `az` en dehors d'un pipeline. Tout changement = une PR sur GitHub. + +Si un ingénieur fait un changement manuel en urgence, il doit immédiatement ouvrir une PR pour "coder" ce changement, sinon il sera écrasé au prochain `terraform apply`. + +--- + +## Structurer un dépôt GitOps multi-environnements + +``` +infra-azure-gitops/ +├── modules/ # Modules Terraform réutilisables +│ ├── aks/ +│ ├── network/ +│ └── keyvault/ +│ +├── environments/ # Un dossier = un environnement Azure +│ ├── dev/ +│ │ ├── main.tf # Appelle les modules +│ │ ├── terraform.tfvars # Valeurs dev (non sensibles) +│ │ └── backend.tf # Backend Terraform (Azure Storage) +│ ├── staging/ +│ └── prod/ +│ +├── kubernetes/ # Manifests K8s déployés sur AKS +│ ├── dev/ +│ └── prod/ +│ +├── .github/ +│ ├── workflows/ +│ │ ├── terraform.yml # Pipeline IaC +│ │ ├── k8s-deploy.yml # Pipeline K8s +│ │ └── drift-detection.yml # Vérification quotidienne du drift +│ ├── CODEOWNERS +│ └── pull_request_template.md +│ +└── .gitignore +``` + +### Backend Terraform dans Azure Storage + +Pour stocker l'état Terraform dans Azure (et non localement) : + +```hcl +# environments/prod/backend.tf +terraform { + backend "azurerm" { + resource_group_name = "rg-terraform-state" + storage_account_name = "stterraformstateprod" + container_name = "tfstate" + key = "prod.terraform.tfstate" + } +} +``` + +--- + +## GitOps "Push" vs "Pull" + +Il existe deux modèles d'application du GitOps : + +### Push GitOps (GitHub Actions) + +GitHub Actions **pousse** les changements vers Azure après chaque merge. + +``` +Git merge → GitHub Actions → terraform apply → Azure +``` + +✅ Simple à mettre en place +✅ Adapté à l'IaC (Terraform, Bicep) +⚠️ Le pipeline doit avoir des credentials Azure (OIDC) + +### Pull GitOps (ArgoCD / Flux) + +Un agent tourne **dans** le cluster AKS et **tire** en continu l'état depuis Git. + +``` +Git merge → ArgoCD/Flux (dans AKS) détecte le changement → applique +``` + +✅ Pas de credentials Azure dans GitHub +✅ Réconciliation continue (corrige le drift automatiquement) +✅ Idéal pour les manifests Kubernetes +⚠️ Plus complexe à installer + +**En pratique** : on utilise souvent les deux — GitHub Actions pour l'IaC Terraform (infrastructure), ArgoCD/Flux pour les déploiements Kubernetes (applications). + +--- + +## Détection de drift + +Le **drift** survient quand l'état réel d'Azure diverge de ce qui est dans Git (changement manuel, ressource supprimée accidentellement, quota Azure modifié). + +### Workflow de détection quotidienne + +```yaml +# .github/workflows/drift-detection.yml +name: Drift Detection + +on: + schedule: + - cron: '0 6 * * 1-5' # Tous les jours ouvrés à 6h + workflow_dispatch: # Déclenchement manuel possible + +permissions: + id-token: write + contents: read + issues: write # Pour créer une issue si drift détecté + +jobs: + detect-drift: + runs-on: ubuntu-latest + strategy: + matrix: + environment: [dev, staging, prod] + + steps: + - uses: actions/checkout@v4 + + - uses: hashicorp/setup-terraform@v3 + + - name: Login Azure (OIDC) + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Terraform Init + run: terraform init + working-directory: environments/${{ matrix.environment }} + + - name: Terraform Plan (drift check) + id: plan + run: | + terraform plan -detailed-exitcode -no-color 2>&1 | tee plan.txt + echo "exitcode=${PIPESTATUS[0]}" >> $GITHUB_OUTPUT + working-directory: environments/${{ matrix.environment }} + continue-on-error: true + + # exitcode 2 = des changements existent = drift détecté + - name: Create Issue if drift detected + if: steps.plan.outputs.exitcode == '2' + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + const plan = fs.readFileSync('environments/${{ matrix.environment }}/plan.txt', 'utf8'); + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: `🚨 Drift détecté sur ${{ matrix.environment }}`, + body: `Un drift a été détecté entre Git et Azure.\n\n\`\`\`\n${plan.substring(0, 3000)}\n\`\`\``, + labels: ['incident', 'infrastructure', 'priority:high'] + }); +``` + +--- + +## Bonnes pratiques GitOps + +**Jamais de changement manuel sur Azure** : toute modification par le portail ou la CLI doit être immédiatement codée dans Git. + +**Terraform State dans Azure Storage** : le state file ne doit jamais être versionné dans Git, uniquement dans un backend distant. + +**Un environnement = un dossier = un state** : facilite les déploiements progressifs et limite le rayon d'impact. + +**Les PR comme audit trail** : chaque PR représente une décision d'architecture. Utilisez des descriptions détaillées — elles servent de journal de bord à l'équipe. + +**Drift detection régulière** : planifiez un `terraform plan` quotidien pour détecter rapidement les écarts. + +--- + +[← 09 - GitHub Actions Avancées](09-github-actions-avance.md) | [🏠 Accueil](README.md) | [11 - Solutions →](11-solutions.md) diff --git a/11-solutions.md b/11-solutions.md new file mode 100644 index 0000000..ea11eb2 --- /dev/null +++ b/11-solutions.md @@ -0,0 +1,323 @@ +# 11 - Solutions des exercices + +[← 10 - GitOps](10-gitops.md) | [🏠 Accueil](README.md) + +--- + +## 📝 Solutions Niveau 1 : Premiers pas + +```bash +# 2. Générer la clé SSH et l'ajouter à GitHub +ssh-keygen -t ed25519 -C "votre.email@cloudops.com" +eval "$(ssh-agent -s)" +ssh-add ~/.ssh/id_ed25519 +cat ~/.ssh/id_ed25519.pub # Copier et coller dans GitHub → Settings → SSH keys + +# Tester +ssh -T git@github.com + +# 4. Cloner en SSH, créer versions.tf, committer +git clone git@github.com:votre-user/infra-azure-practice.git +cd infra-azure-practice + +cat > versions.tf << 'EOF' +terraform { + required_version = ">= 1.5.0" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 3.85" + } + } +} +EOF + +git add versions.tf +git commit -m "chore: add Terraform version constraints" +git push + +# 5. GitHub CLI +gh auth login # Suivre les instructions +gh repo view # Vérifier la connexion +``` + +--- + +## 🌿 Solutions Niveau 2 : Pull Requests et CODEOWNERS + +```bash +# 1. Créer la structure +mkdir -p .github modules/aks modules/network +touch .github/CODEOWNERS .github/pull_request_template.md +touch modules/aks/main.tf modules/network/main.tf +``` + +**`.github/CODEOWNERS`** : +``` +# Tout le dépôt +* @votre-username + +# Module AKS : second reviewer requis +/modules/aks/ @votre-username @collègue-username +``` + +**`.github/pull_request_template.md`** : +```markdown +## 🎯 Objectif + + +## 📝 Changements IaC + + +## 🔍 Terraform Plan + + +## ✅ Checklist +- [ ] terraform validate passe +- [ ] terraform fmt appliqué +- [ ] Pas de secrets dans les fichiers +- [ ] Variables documentées + +## 🔗 Issue liée +Closes # +``` + +```bash +# 4. Créer la branche, ouvrir la PR et merger +git switch -c feature/add-aks-module + +cat >> modules/aks/main.tf << 'EOF' +resource "azurerm_kubernetes_cluster" "main" { + name = "aks-practice" + location = "West Europe" + resource_group_name = "rg-practice" + dns_prefix = "aks-practice" + + default_node_pool { + name = "default" + node_count = 2 + vm_size = "Standard_D2_v2" + } + + identity { + type = "SystemAssigned" + } +} +EOF + +git add . +git commit -m "feat(aks): add AKS cluster resource" +git push -u origin feature/add-aks-module + +# Créer la PR via CLI +gh pr create \ + --title "feat(aks): add AKS cluster resource" \ + --body "Ajout du module AKS avec node pool par défaut." \ + --label "infrastructure" + +# Merger en Squash +gh pr merge --squash --delete-branch +``` + +**Ruleset `main`** (via Settings → Rules → Rulesets) : +- Target : branch `main` +- ✅ Require pull request (1 approval, dismiss stale reviews, require code owners) +- ✅ Require status checks +- ✅ Block force pushes + +--- + +## ⚙️ Solutions Niveau 3 : GitHub Actions CI/CD Azure + +```bash +# 1. Créer l'App Registration et la Federated Credential +APP_ID=$(az ad app create --display-name "github-actions-practice" --query appId -o tsv) +az ad sp create --id $APP_ID +SP_OID=$(az ad sp show --id $APP_ID --query id -o tsv) +SUB_ID=$(az account show --query id -o tsv) + +az role assignment create --assignee $APP_ID --role Contributor \ + --scope "/subscriptions/${SUB_ID}" + +# Federated credential pour main +az ad app federated-credential create --id $APP_ID --parameters '{ + "name": "github-main", + "issuer": "https://token.actions.githubusercontent.com", + "subject": "repo:votre-user/infra-azure-practice:ref:refs/heads/main", + "audiences": ["api://AzureADTokenExchange"] +}' + +# Federated credential pour pull_request +az ad app federated-credential create --id $APP_ID --parameters '{ + "name": "github-pr", + "issuer": "https://token.actions.githubusercontent.com", + "subject": "repo:votre-user/infra-azure-practice:pull_request", + "audiences": ["api://AzureADTokenExchange"] +}' + +# Récupérer les valeurs pour les secrets GitHub +echo "AZURE_CLIENT_ID: $APP_ID" +echo "AZURE_TENANT_ID: $(az account show --query tenantId -o tsv)" +echo "AZURE_SUBSCRIPTION_ID: $SUB_ID" +``` + +```bash +# Ajouter les secrets via gh CLI +gh secret set AZURE_CLIENT_ID --body "$APP_ID" +gh secret set AZURE_TENANT_ID --body "$(az account show --query tenantId -o tsv)" +gh secret set AZURE_SUBSCRIPTION_ID --body "$SUB_ID" +``` + +**`.github/workflows/terraform.yml`** : + +```yaml +name: Terraform CI/CD + +on: + pull_request: + branches: [main] + push: + branches: [main] + +permissions: + id-token: write + contents: read + pull-requests: write + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: hashicorp/setup-terraform@v3 + - name: Login Azure + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + - run: terraform init + - run: terraform fmt -check + - run: terraform validate + + plan: + needs: validate + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: hashicorp/setup-terraform@v3 + - uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + - run: terraform init + - id: plan + run: terraform plan -no-color 2>&1 | tee plan.txt + continue-on-error: true + - uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + const plan = fs.readFileSync('plan.txt', 'utf8'); + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: '## Terraform Plan\n```\n' + plan.substring(0, 10000) + '\n```' + }); + + apply: + needs: validate + if: github.ref == 'refs/heads/main' && github.event_name == 'push' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: hashicorp/setup-terraform@v3 + - uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + - run: terraform init && terraform apply -auto-approve +``` + +**`.github/workflows/security.yml`** : + +```yaml +name: IaC Security Scan +on: + pull_request: + paths: ['**.tf'] +jobs: + tfsec: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: aquasecurity/tfsec-action@v1.0.3 + with: + soft_fail: false +``` + +--- + +## 🔒 Solutions Niveau 4 : Sécurité et GitOps + +```bash +# 1. Tester le Push Protection +# Activer dans Settings → Code security → Secret scanning → Push protection + +# Tenter de committer un faux secret +echo "AZURE_CLIENT_SECRET=FakeSecret123!" > test-secret.env +git add test-secret.env +git commit -m "test: should be blocked" +git push +# → Push bloqué par GitHub Secret Scanning +git restore --staged test-secret.env +rm test-secret.env +``` + +**`.github/dependabot.yml`** : + +```yaml +version: 2 +updates: + - package-ecosystem: "terraform" + directory: "/environments/dev" + schedule: + interval: "weekly" + labels: ["terraform", "dependencies"] + + - package-ecosystem: "terraform" + directory: "/environments/prod" + schedule: + interval: "weekly" + labels: ["terraform", "dependencies"] + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + labels: ["ci-cd", "dependencies"] +``` + +**Bonus GitOps — Garantir que apply ne s'exécute que depuis main :** + +```yaml +# Dans le job apply du workflow terraform.yml +apply: + needs: validate + runs-on: ubuntu-latest + # Double condition : branche main ET event push (pas workflow_dispatch depuis une branche) + if: | + github.ref == 'refs/heads/main' && + github.event_name == 'push' && + github.event.base_ref == null + steps: + # ... +``` + +--- + +[← 10 - GitOps](10-gitops.md) | [🏠 Accueil](README.md) diff --git a/README.md b/README.md index fe3377d..2136eca 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,83 @@ -# cours-github -Cours GitHub - SIMPLON +# Formation GitHub : Maîtriser GitHub pour le DevOps Azure + +Bienvenue dans ce module complet dédié à GitHub. GitHub est la plateforme centrale du DevOps Azure : chaque modification d'infrastructure, chaque déploiement, chaque correctif de sécurité passe par un dépôt GitHub avant d'atteindre Azure. + +## 🎯 Objectifs de la formation + +- Comprendre GitHub et son rôle dans l'écosystème DevOps Azure +- Maîtriser les Pull Requests, CODEOWNERS et templates d'équipe +- Gérer les Issues et Projects pour piloter les projets d'infrastructure +- Automatiser avec GitHub Actions : OIDC, Terraform CI/CD, déploiements AKS +- Sécuriser les dépôts avec GitHub Rulesets et GHAS +- Maîtriser les GitHub Actions avancées : Environments, Reusable workflows, Self-hosted runners +- Comprendre et appliquer le paradigme GitOps sur Azure + +--- + +## 📚 Modules du cours + +### [01 - Introduction à GitHub](01-introduction-concepts.md) +Rôle de GitHub dans la chaîne DevOps Azure, différences Git/GitHub, concepts clés. + +### [02 - Premiers pas avec GitHub](02-premiers-pas-ssh.md) +Compte, profil DevOps, authentification SSH, premier dépôt IaC. + +### [03 - Pull Requests, CODEOWNERS et Templates](03-pull-requests-code-review.md) +Workflow collaboratif pour l'infrastructure, CODEOWNERS, templates PR/Issue, code review IaC. + +### [04 - Issues et Gestion de projet](04-issues-gestion-projet.md) +Suivi des incidents et évolutions d'infrastructure, Labels DevOps, GitHub Projects Kanban. + +### [05 - GitHub Actions : CI/CD Azure](05-github-actions-cicd.md) +OIDC / Workload Identity Federation, pipeline Terraform complet, déploiement AKS. + +### [06 - Sécurité et Branch Protection](06-securite-bonnes-pratiques.md) +GitHub Rulesets, GHAS, Secret Scanning, Dependabot pour providers Terraform. + +### [07 - Fonctionnalités avancées](07-fonctionnalites-avancees.md) +GitHub CLI, Codespaces pour IaC, GitHub Container Registry, packages. + +### [08 - Exercices Pratiques](08-exercices.md) +Mise en pratique DevOps Azure : IaC, CI/CD, sécurité, GitOps. + +### [09 - GitHub Actions Avancées](09-github-actions-avance.md) +Environments, Deployment Gates, Reusable workflows, Self-hosted runners Azure, Concurrency. + +### [10 - GitOps avec GitHub](10-gitops.md) +GitHub comme source de vérité pour Azure, workflows GitOps, détection de drift. + +### [11 - Solutions](11-solutions.md) +Corrigés détaillés de tous les exercices. + +--- + +## 📋 Progression recommandée + +``` +Session 1 (1h30) : +├─ Module 01 : Introduction (20min) +├─ Module 02 : Premiers pas SSH (30min) +└─ Module 03 : Pull Requests + CODEOWNERS (40min) + +Session 2 (1h30) : +├─ Module 04 : Issues et Projects (30min) +└─ Module 05 : GitHub Actions CI/CD Azure (60min) + +Session 3 (1h30) : +├─ Module 06 : Sécurité (30min) +├─ Module 07 : Fonctionnalités avancées (30min) +└─ Module 09 : GitHub Actions Avancées (30min) + +Session 4 (1h30) : +├─ Module 10 : GitOps (45min) +└─ Module 08 : Exercices (45min) +``` + +## 🎓 Prérequis + +- Bases de Git (voir cours-git) +- Notions de Terraform et Azure CLI +- Terminal / ligne de commande + +--- +**Academy** - Formation Ingénieur DevOps Azure