Automatiser avec GitHub Actions
Les GitHub actions permettent d’automatiser des workflows et notamment les CI/CD. Dans le cadre de Terraform les objectifs sont :
-
Valider le style et le format des fichiers
-
Effectuer l’analyse du code
-
Générer la planification
-
Déployer la configuration
Les actions effectuées par le workflow dépendent du contexte.
-
Un push sur une branche
-
Une création de Pull Requests
-
Un merge sur la branche
main
Un push sur main déclencherait la mise à jour de l’infrastructure sans validation. Le fait de rendre les PR obligatoires pour cette branche permet d’éviter cela ( puis Require a pull request before merging).
|
Push
Lors d’un push, le but est de vérifier que les modifications du code répondent aux standards de développement et ne cassent pas l’existant.
-
Checkout : récupération du repo dans l’espace de travail
- name: Checkout uses: actions/checkout@v3
-
Analyse de code statique : L’analyse statique du code peut être effectuée directement sur le code de configuration Terraform. Elle est utile pour détecter des problèmes de sécurité ou des incohérences. Ces tests ne nécessitent pas la création d’un plan d’exécution ou d’un déploiement, et s’exécutent rapidement. Ils sont généralement exécutés en premier dans le processus d’intégration continue. Différentes solutions existent : Checkov, Terrascan, tfsec, Deepsource
- name: Checkov id: checkov uses: bridgecrewio/checkov-action@master (1) with: quiet: true framework: terraform output_format: github_failed_only soft_fail: false skip_check: CKV_AZURE_35,CKV2_AZURE_8,CKV2_AZURE_18,CKV2_AZURE_1,CKV2_AZURE_21 (2)
1 Checkov GitHub action 2 Ignorer certaines recommandations -
Installation de la CLI Terraform
- name: Setup Terraform uses: hashicorp/setup-terraform@v2 with: terraform_version: '>=1.2.1'
-
Mise en forme : Vérifie que les fichiers sont correctement formatés
- name: Terraform Format id: fmt run: terraform fmt -check (1)
1 -check
retourne un code d’erreur si le format n’est pas correct -
Init : Initialisation de la configuration
- name: Terraform Init id: init env: ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }} ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }} ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }} ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }} run: terraform init -input=false -no-color (1) (2)
1 -input=false
Lève une erreur si une entrée est attendue2 -no-color
évite la mise en forme qui est mal gérée par GitHub -
Validate : Validation de la configuration (utilisation d’une propriété obsolète…)
- name: Terraform Validate id: validate run: terraform validate -no-color (1)
Pull request
Pour une Pull request on ajoute la génération du plan ainsi que la génération d’une synthèse directement dans la PR.
-
Plan : génération du plan
- name: Terraform Plan id: plan env: ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }} ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }} ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }} ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }} if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' && github.event_name == 'push' (1) run: terraform plan -out=tfplan -no-color -input=false <.> Etape exécutée lors d'une _PR_ ou d'un _push_ sur `main`
-
Commenter la PR : génération d’une synthèse dans les commentaires de la PR
- name: add-plan-comment id: comment uses: actions/github-script@v3 if: github.event_name == 'pull_request' && (success() || failure()) (1) env: PLAN: "terraform\n${{ steps.plan.outputs.stdout }}" (2) with: github-token: ${{ secrets.GITHUB_TOKEN }} (3) script: | const output =`#### Checkov 🧪\`${{ steps.checkov.outcome }}\` #### Terraform Format and Style 🖌\`${{ steps.fmt.outcome }}\` #### Terraform Initialization ⚙️\`${{ steps.init.outcome }}\` #### Terraform Validation 🤖\`${{ steps.validate.outcome }}\` #### Terraform Plan 📖\`${{ steps.plan.outcome }}\` <details><summary>Show Checkov Results</summary> \`\`\`\n ${process.env.CHECKOV_RESULTS} \`\`\` </details> <details><summary>Show Plan</summary> \`\`\`\n ${process.env.PLAN} \`\`\` </details> *Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`, Workflow: \`${{ github.workflow }}\`*`; github.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: output })
1 Etape exécutée même si les étapes précédentes ont échoué 2 Sortie de l’étape plan 3 Authentification avec token pré existant pour pouvoir commenter la PR
Merge sur main
La validation de la PR génère un push sur la branche cible. Dans le cas de la branche main
, on effectue la mise à jour de l’infrastructure.
main
-
Apply : mise à jour de l’infrastructure
- name: Terraform Apply if: github.ref == 'refs/heads/main' && github.event_name == 'push' env: ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }} ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }} ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }} ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }} run: terraform apply -input=false tfplan
En production il est conseillé de mettre en place une règle de protection sur la branche pour confirmer les déploiements. |