Automatiser le processus d’audit statique avec SonarCloud et le déploiement de votre application python (Github Actions)
Bonjour à tous, dans cet article nous allons voir comment nous prendre un peu la tête afin d’améliorer le processus d’audit et déploiement d’une application dans un environnement de préproduction/production. Je vous encourage à lire les deux articles de la section préambule si-ne vous n’avez qu’une connaissance limitée du monde du DevOps
I. Préambule
Je vous encourage vivement à lire ces deux articles :
- https://geekflare.com/fr/devops-basics/ (Explication de la philosophie DevOps)
- https://about.gitlab.com/blog/2019/07/12/guide-to-ci-cd-pipelines/ (Explication de certains termes comme stages,jobs, runner etc.)
Si-vous souhaitez mettre en place simplement une pipeline CI (continous integration) pour réaliser un audit de code statique avec sonarCloud, regardez cette vidéo :
Je n’explique pas cette première partie (cf vidéo). Si cela ne vous intéresse pas d’intégrer sonar, supprimez le bloc de code identifiant le job sonarcloud plus bas dans l’article.
Dans un premier temps, nous allons générer une paire de clef SSH afin de réaliser l’interconnexion entre nos deux instances. (Github runner et mon serveur de production)
Pour rappel un « runner » une machine (virtuelle) ou un container exécute des tâches orchestrées par des GitHub Actions (équivalent Gitlab CI). Sur Github, il existe deux type de runner :
- Shared Runners
- Self Hosted runners
Pour plus d’informations : https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions
II. Génération d’une paire de clé SSH
Reprenons. Comme je l’ai dis en début d’article, je dois générer une nouvelle paire de clés, pour que notre runner puisse se connecter à notre VPS :
ssh-keygen -t rsa -b 4096 -f $HOME/.ssh/github_action
Copiez votre clé publique sur votre serveur distant, par l’intermédiaire de la commande suivante, afin que votre serveur de production ait déjà en « mémoire » votre clé publique.
Note : Lorsque vous exécutez cette commande, votre clé publique est inscrite dans le fichier : ~/.ssh/authorized_keys
ssh-copy-id -i ~/.ssh/github_action.pub [email protected]
III. Créez deux « secrets » dans votre repository
Ajoutez le contenu de votre clé privé aux « secrets » de votre repository (SSH_PRIVATE_KEY). Pour cela allez dans votre repository sur Github et cliquez sur Settings , puis Secrets, Actions . Vous devriez voir un bouton indiquant New repository secret.
Ajoutez le contenu de votre clé privée, afin que le runner github puisse se connecter en ssh sans soucis à votre serveur de production.
- SSH_PRIVATE_KEY
Vous aurez également besoin du contenu de votre fichier ~/.ssh/known_hosts
. L’option la plus simple consiste à exécuter la commande suivante à partir de votre ordintauer qui héberge votre environnement de développement (kali linux dans mon cas) en remplaçant IP_ADDRESS par votre serveur de destination (mon VPS in my case).
Pour rappel : Le fichier known_hosts
est un fichier « côté client » contient la clé publique du serveur SSH (identifiant le serveur, pas un utilisateur !!!). Par défaut SSH en génère plusieurs dans un but d’interopérabilité. Je vais prendre celle qui utilise l’algorythme de condensat (hash) ssh-ed25519
ssh-keyscan -H IP_ADDRESS
Choisissez une des clés publique du serveur de « prod » (VPS). Dans mon cas, je vais copier celle utilisant l’algo ed25519.
|1|tNnxxxxxxxxxxxxxxxxxPcs=|o1bbxxxxxxxxxxxxxxxxxxxxxxQES8= ssh-ed25519 AAAAC3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxY
Ajoutez la valeur à un nouveau « secret » Github nommé comme ci-dessous :
Vous pouvez aussi utiliser ssh -o StrictHostKeyChecking=no [email protected] ‘blablabla’, au lieu de créer le secret SSH_KNOW_HOST, si vous rencontrez des difficultés à cette étape.
IV. Création de notre pipeline avec Github Actions
Nous allons maintenant créer notre workflow. Accédez à votre référentiel sur Github et cliquez sur l’onglet Actions , puis set up a workflow yourself. Choisissez un petit nom utile et utilisez le script en s’appuyant du modèle ci-dessous.
Exécutez la commande Git pull
afin de pouvoir recevoir les modifications (la création des deux dossiers et du fichier .yml par défaut) ou bien alors tenter d’éditer le fichier directement depuis Github. (Faite cela uniquement si votre code est à jour sur github)
Dans le fichier que je vais nommer pipeline.yml, insérez le snippet de code suivant, et adaptez le en fonction de votre contexte :
name: CI/CD - code analysis and if it's ok auto deploy
on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened]
jobs:
sonarcloud:
name: SonarCloud
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
deploy:
needs: sonarcloud
runs-on: ubuntu-latest
steps :
- name : Install private SSH Key
uses : shimataro/ssh-key-action@v2
with :
key : ${{ secrets.SSH_PRIVATE_KEY }} # copy and paste a private key to a github secret of your current repo
known_hosts : ${{ secrets.SSH_KNOW_HOST }} # optional, but add at the beggining of your line : ssh -o StrictHostKeyChecking=no [email protected]
if_key_exists: ignore
- name : Pull
run : |
ssh ${{ secrets.USER }}@${{ secrets.IP }} '/usr/bin/screen -X -S weathergilant quit'
ssh ${{ secrets.USER }}@${{ secrets.IP }} '
cd /home/${{ secrets.USER }}/weathergilannt
/usr/bin/git pull origin main
/usr/bin/screen -S weathergilant -d -m /usr/bin/python3 /home/${{ secrets.USER }}/weathergilannt/index.py'
- Le workflow est instancié par le runner uniquement si nous mettons la branche main
- Dans un premier temps, le premier job va s’exécuter (analyse statique du code depuis sonarcloud)
- Si le scan est réussi (que le code passe toutes les étapes), alors le job
sonarcloud
va renvoyé « True » à github runner, qui lui va se charger d’exécuter le second jobdeploy
- Le job
deploy
va :- Stopper l’exécution de ma session screen qui éxecute le script de mon projet (index.py) –> clé de voute de mon programme
- Récupérer les dernière mise à jour de mon code (
git pull
automatique réalisé dans le bon dossier) - Création d’une nouvelle session screen, en exécutant de nouveau mon programme index.py
Tout cela fait que l’interruption de service très courte (de l’ordre de moins de 5 secondes environ, en fonction du poids informatique de votre mise à jour)
Note : Vous pouvez utiliser aussi des sessions screen
, si-vous n’avez pas en place un système de « Logging » pour votre programme
Pour testez, enregistrez vos modifications (commit) et poussez-les sur votre branche affecté par la pipeline (dans mon cas main
)
Vu que notre pipeline ne comporte que deux jobs, nous n’avons réelement besoin de surcharger notre script .yml en définissant deux stages (groupe de jobs). Néanmoins, gardez à l’esprit, que si-vous deviez avoir plus de 4 jobs, cela serait plus clair de les compartimenter en stages.
Lors de vos différents tests, n’hésitez pas à
- Activer le mode debug et à lire les logs du runner (menu « … » cf photo).
- Ouvrir la console de vos jobs (SonarCloud, Deploy)
J’espère que cet article vous aura plus. Je ne suis clairement pas un expert DevOps (Heureusement, c’est trop fatiguant ^^, et éreintant), mais parfois il peut s’avérer plaisant d’automatiser certaines redondante et fastidieuse ^^. Comme je dis souvent : Le devops c’est comme le mayonnaise, c’est bon, mais il ne faut pas trop en abuser.
Si-vous n’avez pas tout compris, je vous encourage à visiter un de mes projets hébergés en public sur Github, qui utilisent les Github Actions :
++
Geoffrey
En savoir plus sur Le Guide Du SecOps
Subscribe to get the latest posts sent to your email.