docker compose up --build
: build + run appdocker compose up
: run app without rebuildingdocker ps
: list running docker containersdocker exec -it DOCKER_CONTAINER_ID /bin/bash
: access container shell (for debugging)- (web)
python manage.py migrate
: create tables (after each database schema change) - (db)
mysql -u MYSQL_USER -p MYSQL_PASSWORD
: access mysql shellmysql> show databases;
: list databasesmysql> use password_manager;
: select databasemysql> show tables;
: list tables in selected databasemysql> describe TABLE_NAME;
: show table structureselect * from TABLE_NAME;
: show table content
- (web)
the application can be accessible from localhost:8000
example of a valid .env file
(do not use such vulnerable passwords in production! this is for development purposes only)
MYSQL_DATABASE=password_manager_db
MYSQL_USER=user
MYSQL_PASSWORD=s3cret!
MYSQL_ROOT_PASSWORD=toor
DATABASE_URL=mysql://user:s3cret!@db:3306/password_manager_db
Ce guide explique comment héberger le service SonarQube sur une instance AWS EC2.
OS
: Ubuntu 22.04 / 20.04 LTSType d'instance
: t2.mediumSecurity Group
: Ports requis 9000 pour SonarQube, 22 pour SSH et 80 pou HTTP.
Note : Les spécifications ci-dessus sont les min recommandés. Vous pouvez les augmenter selon vos besoins.
-
Connectez-vous à votre serveur AWS EC2 en SSH en utiisant PUTTY:
citer adresse ip public
,connection >> data >> auto-login username >> ubuntu
,connection >> SSH >> AUTH >> credentials >> entrer private key for file configuration
-
Mettez à jour et améliorez les paquets :
sudo apt update
sudo apt upgrade -y
- Installation de Java OpenJDK 17
sudo apt install -y openjdk-17-jdk
java -version
- Installation et Configuration de PostgreSQL
- Ajoutez le dépôt PostgreSQL :
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
- Ajoutez la clé de signature PostgreSQL :
wget -q https://www.postgresql.org/media/keys/ACCC4CF8.asc -O - | sudo apt-key add -
- Installez PostgreSQL et l'initialiser :
sudo apt install postgresql postgresql-contrib -y
sudo systemctl enable postgresql
sudo systemctl start postgresql
sudo systemctl status postgresql
- Vérifiez la version :
psql --version
- Connectez-vous à PostgreSQL :
sudo -i -u postgres
psql
- Créez un utilisateur et un mot de passe sécurisés :
CREATE USER <nom_user> WITH ENCRYPTED PASSWORD 'mdp';
- Créez une base de données et assignez-lui cet utilisateur :
CREATE DATABASE sqube OWNER sona;
GRANT ALL PRIVILEGES ON DATABASE sqube TO <nom_user>;
- Vérifiez les utilisateurs et bases créés :
\du
\l
\q
exit
- Installez zip et téléchargez les fichiers SonarQube :
sudo apt install zip -y
sudo wget https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-10.4.1.88267.zip
sudo unzip sonarqube-10.4.1.88267.zip
sudo mv sonarqube-10.4.1.88267 /opt/sonarqube
- Créez un utilisateur dédié :
sudo groupadd <nom_user>
sudo useradd -d /opt/sonarqube -g <nom_user> <nom_user>
sudo chown -R <nom_user>:<nom_user> /opt/sonarqube
- Modifiez le fichier sonar.properties :
sudo nano /opt/sonarqube/conf/sonar.properties
- Ajoutez les lignes suivantes :
sonar.jdbc.username=<nom_user>
sonar.jdbc.password=<mdp>
sonar.jdbc.url=jdbc:postgresql://localhost:5432/sqube
- Modifiez le script sonar.sh pour exécuter SonarQube avec l’utilisateur dédié :
sudo nano /opt/sonarqube/bin/linux-x86-64/sonar.sh
Ajoutez :
RUN_AS_USER=<nom_user>
- Créez un fichier service :
sudo nano /etc/systemd/system/sonar.service
Contenu :
[Unit]
Description=SonarQube service
After=syslog.target network.target
[Service]
Type=forking
ExecStart=/opt/sonarqube/bin/linux-x86-64/sonar.sh start
ExecStop=/opt/sonarqube/bin/linux-x86-64/sonar.sh stop
User=<nom_user>
Group=<nom_user>
Restart=always
LimitNOFILE=65536
LimitNPROC=4096
[Install]
WantedBy=multi-user.target
Rechargez les services systemd et démarrez SonarQube :
sudo systemctl enable sonar
sudo systemctl start sonar
sudo systemctl status sonar
- Modifiez les paramètres du noyau pour Elasticsearch :
sudo nano /etc/sysctl.conf
Ajoutez :
vm.max_map_count=262144
fs.file-max=65536
ulimit -n 65536
ulimit -u 4096
- Redémarrez le système :
sudo reboot
- Accédez à SonarQube via : http://<IP_public>:9000
Identifiants par défaut :
Nom d’utilisateur :admin
Mot de passe :admin
Félicitations ! Vous avez installé SonarQube avec succès sur une instance EC2 Ubuntu. 🎉
Ce guide explique comment intégrer le service SonarQube hébergé sur une instance AWS EC2 dans un pipeline GitHub Actions pour l'analyse continue du code.
- Une instance AWS EC2 configurée avec Ubuntu 22.04/20.04 LTS et SonarQube installé (référez-vous au guide précédent pour l'installation de SonarQube).
- Une clé SSH pour accéder à l'instance EC2.
- Un dépôt GitHub contenant le code source à analyser.
- Une configuration correcte du projet token projectKey unique pour chaque projet.
- Assurez-vous que SonarQube est installé et accessible via l'URL
http://<IP-EC2>:9000
. - Générez un token d'authentification SonarQube :
- Connectez-vous à l'interface web de SonarQube.
- Allez dans Mon Compte > Tokens > Générer un Token.
- Notez le token généré.
Dans votre dépôt GitHub, configurez les secrets suivants :
SONAR_HOST_URL
: L'URL de votre serveur SonarQube (http://<IP-EC2>:9000
).SONAR_TOKEN
: Le token généré depuis SonarQube.SONAR_PROJECT_KEY
: La clé du projet dans Sonarqube.
3. modifier le fichier de configuration de sonar systemd service en /opt/sonarqube/conf/sonar.properties
sonar.branch.name=main
sonar.sources=.
sonar.sourceEncoding=UTF-8
sonar.language=py
sonar.exclusions=**/migrations/**, **/__pycache__/**, **/*.pyc, **/node_modules/**, **/venv/**
sudo systemctl restart sonar.service
dans fichier workflow dans .github/workflows
ajoutez ce job qui commence par tester la connectivité puis réalise le scan:
sonarq-integration:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Test SonarQube connectivity
run: |
curl -v ${{ secrets.SONAR_HOST_URL }}/api/system/status
- name: SonarQube Scan
uses: sonarsource/sonarqube-scan-action@v2
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
SONAR_PROJECT_KEY: ${{ secrets.SONAR_PROJECT_KEY }}
SONAR_PROJECT_NAME: "Microservice-Based-Password-Manager-with-a-Secure-CI-CD-Pipeline"
Poussez votre code sur la branche main (dans mon cas) ou ouvrez une Pull Request.
Accédez à l'onglet Actions de votre dépôt GitHub.
Suivez l'exécution du workflow et vérifiez les résultats dans SonarQube.
ce job crée une image Docker en local (cloud utilisé pargithub actions) avec le fichier Dockerfile.
La construction ne pousse pas encore l'image sur Docker Hub (push: false
).
Scanne l'image pour détecter des failles de sécurité ou des dépendances vulnérables.
Si des vulnérabilités critiques sont détectées, l'étape échoue, empêchant le push de l'image.
Le push n'est exécuté que si le scan Trivy réussit (aucune vulnérabilité bloquante).
Dans votre dépôt GitHub, configurez les secrets suivants :
DOCKERHUB_USERNAME
: Le nom utilisateur de votre compte Dockerhub.DOCKERHUB_TOKEN
: Le token généré depuis Dockerhub.
build-trivy-scan-and-push:
runs-on: ubuntu-latest
needs: sonarq-integration # Ensure SonarQube analysis completes before the build
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Log in to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Build Docker image
id: build-image
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
push: false
tags: ${{ secrets.DOCKERHUB_USERNAME }}/web:latest
- name: Scan image with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ secrets.DOCKERHUB_USERNAME }}/web:latest
- name: Push Docker image
if: success() # Push only if Trivy scan succeeds
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/web:latest
Félicitations ! Vous avez integré trivy pour scanner votre image. 🎉
si dessous les étapes exécutées dans la phase build-and-zap-scan
du pipeline CI/CD. Cette phase effectue les tâches suivantes :
- Récupération du code source.
- Vérification de l'installation de Docker Compose.
- Construction et exécution des services via Docker Compose.
- Inspection et vérification de l'état des conteneurs.
- Analyse de sécurité avec ZAP (Zed Attack Proxy) pour identifier les vulnérabilités de l'application.
- Téléchargement du rapport d'analyse ZAP comme artefact.
Le code du dépôt est récupéré dans l'environnement du runner à l'aide de l'action GitHub actions/checkout@v2.
- name: Checkout code
uses: actions/checkout@v2
Vérifie que Docker Compose est installé et affiche la version.
- name: Check Docker Compose version
run: docker compose --version
Construit et démarre les services définis dans le fichier docker-compose.yml
. Les variables d'environnement sont sécurisées avec les Secrets GitHub.
- name: Build and run Docker Compose
env:
MYSQL_DATABASE: ${{ secrets.MYSQL_DATABASE }}
MYSQL_USER: ${{ secrets.MYSQL_USER }}
MYSQL_PASSWORD: ${{ secrets.MYSQL_PASSWORD }}
MYSQL_ROOT_PASSWORD: ${{ secrets.MYSQL_ROOT_PASSWORD }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
run: |
docker compose up -d
sleep 15
Liste tous les conteneurs Docker en cours d'exécution pour vérifier que les services sont démarrés.
- name: Debug Docker containers
run: docker ps
Récupère l'adresse IP du conteneur nommé web
et vérifie que l'application est accessible.
- name: Get web container IP address and check accessibility
id: get_ip
run: |
CONTAINER_ID=$(docker ps -qf "name=web")
echo "Web Container ID: $CONTAINER_ID"
CONTAINER_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $CONTAINER_ID)
echo "Web Container IP: $CONTAINER_IP"
echo "container_ip=$CONTAINER_IP" >> $GITHUB_ENV
curl http://$CONTAINER_IP:8000
Utilise l'action ZAP Full Scan pour effectuer une analyse de vulnérabilités de l'application web.
- name: ZAP Scan
uses: zaproxy/[email protected]
with:
token: ${{ secrets.GITHUB_TOKEN }}
target: http://${{ env.container_ip }}:8000
artifact_name: "zap-alerts"
S'assure que le fichier de rapport d'analyse ZAP est généré avec succès.
- name: Verify ZAP Alerts File Generation
run: ls -l | grep report
Télécharge le rapport d'analyse ZAP dans les artefacts GitHub pour examen ultérieur.
- name: Upload ZAP Alerts as Artifact
uses: actions/upload-artifact@v4
with:
name: zap-alerts
path: ./report_html.html
- Docker et Docker Compose doivent être installés sur le runner.
- Le fichier
docker-compose.yml
doit définir les services de l'application. - Les Secrets GitHub doivent être configurés pour les variables d'environnement requises (
MYSQL_DATABASE
,MYSQL_USER
,MYSQL_PASSWORD
,MYSQL_ROOT_PASSWORD
,DATABASE_URL
).
- Un rapport d'analyse ZAP (
report_html.html
) est téléchargé comme artefact dans GitHub Actions comme suit, Les artefacts du dernier run du workflow peuvent être téléchargés depuis la page GitHub Actions.
- Allez sur la [page Actions] (https://github.com/halekammoun/Microservice-Based-Password-Manager-with-a-Secure-CI-CD-Pipeline/actions).
- Sélectionnez le dernier run.
- Faites défiler jusqu'à la section Artefacts et téléchargez l'artefact nommé
zap-alerts
.
- Extractes le Zip et consultes le rapport
report_html.html
- Ajustez la durée de
sleep
dans l'étape Docker Compose en fonction du temps de démarrage de vos services. - Assurez-vous que le nom du conteneur web correspond au nom défini dans votre fichier
docker-compose.yml
. - Examinez le rapport d'analyse ZAP pour résoudre les vulnérabilités identifiées.
Félicitations ! Vous avez integré zap pour scanner votre site web. 🎉
Nous avons automatisé le déploiement de notre application Kubernetes via un workflow GitHub Actions, qui s'exécute après la construction et le scan de sécurité du projet.
Voici les étapes clés du workflow :
Le code source est récupéré à partir du dépôt GitHub pour être déployé sur l'instance EC2.
- name: Checkout code
uses: actions/checkout@v2
La clé privée EC2 est récupérée à partir des secrets GitHub, puis elle est enregistrée et configurée avec les permissions appropriées pour se connecter à l'instance EC2.
- name: Configure SSH for EC2 and deploy
run: |
echo "${{ secrets.EC2_PRIVATE_KEY }}" > ec2_key.pem
chmod 600 ec2_key.pem
echo "Connecting to EC2 Host: ${{ secrets.K8S_HOST }}"
Une fois la connexion SSH établie, les fichiers YAML en local (configmap, secret, déploiements, et services) sont transférés sur l'instance EC2 avec scp.
Ensuite, la commande SSH est utilisée pour redémarrer Minikube et déployer les fichiers Kubernetes.
- name: SSH into EC2 and deploy
run: |
scp -o StrictHostKeyChecking=no -i ec2_key.pem configmap.yaml ubuntu@${{ secrets.K8S_HOST }}:/home/ubuntu/
scp -o StrictHostKeyChecking=no -i ec2_key.pem secret.yaml ubuntu@${{ secrets.K8S_HOST }}:/home/ubuntu/
scp -o StrictHostKeyChecking=no -i ec2_key.pem db-deployment.yaml ubuntu@${{ secrets.K8S_HOST }}:/home/ubuntu/
scp -o StrictHostKeyChecking=no -i ec2_key.pem web-deployment.yaml ubuntu@${{ secrets.K8S_HOST }}:/home/ubuntu/
scp -o StrictHostKeyChecking=no -i ec2_key.pem db-service.yaml ubuntu@${{ secrets.K8S_HOST }}:/home/ubuntu/
scp -o StrictHostKeyChecking=no -i ec2_key.pem web-service.yaml ubuntu@${{ secrets.K8S_HOST }}:/home/ubuntu/
ssh -v -o StrictHostKeyChecking=no -i ec2_key.pem ubuntu@${{ secrets.K8S_HOST }} << EOF
minikube stop
minikube start
kubectl create -f configmap.yaml
kubectl create -f secret.yaml
kubectl create -f db-deployment.yaml
kubectl create -f web-deployment.yaml
kubectl create -f db-service.yaml
kubectl create -f web-service.yaml
sleep 50
kubectl get pods
EOF
Pour permettre l'accès externe au service Kubernetes, nous avons configuré les règles iptables sur l'instance EC2 pour rediriger le trafic vers le port exposé par Minikube.
Redirection du port d'entrée :
Cette règle redirige le trafic entrant sur le port 30001 vers le port 30001 sur l'adresse IP interne de Minikube.
sudo iptables -A PREROUTING -t nat -i enX0 -p tcp --dport 30001 -j DNAT --to 192.168.49.2:30001
Autorisation de transfert de paquets :
Cette règle permet le transfert du trafic vers le service de l'application en autorisant le trafic sur le port 30001.
sudo iptables -A FORWARD -p tcp -d 192.168.49.2 --dport 30001 -j ACCEPT
Une fois les règles iptables appliquées, vous pouvez lister les services Minikube et exposer le service web en utilisant minikube tunnel. Voici les étapes :
Liste des services exposés par Minikube :
minikube service list
Tunnel Minikube pour accéder aux services externes :
Cette commande ouvre un tunnel réseau pour exposer les services Minikube à l'extérieur.
minikube tunnel
Accéder au service web : Vous pouvez maintenant accéder à votre application web en utilisant l'IP publique de votre instance EC2 et le port 30001 :
http://18.212.165.107:30001/
Cela vous permettra de voir la page web déployée depuis votre cluster Kubernetes exécuté sur Minikube sur EC2.
Félicitations ! Vous avez automtisé le déploiement vers minikube dans un EC2. 🎉