Sécuriser et Déployer une Application Flask

Sécuriser et déployer une app Flask avec HTTPS, serveur et icônes SSL.

Flask est un framework Python léger conçu pour créer des applications web. Il permet aux développeurs de définir facilement des routes, de gérer les requêtes et réponses HTTP, et de générer du contenu dynamique à l’aide des templates Jinja2. Il prend également en charge diverses extensions pour intégrer des fonctionnalités comme l’accès à une base de données, la gestion des formulaires ou encore l’authentification des utilisateurs.

Dans cet article, nous allons apprendre à déployer une application Flask à l’aide de Gunicorn, tout en ajoutant une protection CSRF et des politiques de sécurité du contenu (CSP). Nous configurerons également un proxy inverse avec Nginx et mettrons en place le protocole HTTPS grâce à un certificat SSL gratuit fourni par Let’s Encrypt.

Ajoutez vos fichiers de code d'application de démonstration

Configurez un environnement virtuel Python

  • Installez le package python3-venv

    $ sudo apt install python3-venv
  • Créer un environnement virtuel.

$ python3 -m venv myenv
  • Activez l’environnement virtuel.

$ source myenv/bin/activate

Ajoutez les fichiers de code de l'application de démonstration

  • Clonez le dépôt Github.

    $ git clone https://github.com/mayankdebnath/flask-todo-demo.git
  • Naviguez jusqu’au répertoire du projet.

$ cd flask-todo-demo/sample/
  • Installez les packages Flask et Gunicorn.

$ cd flask-todo-demo/sample/
  • Installez les packages Flask et Gunicorn.

$ pip install flask gunicorn
  • Autoriser les connexions entrantes sur le port 5000

$ ufw allow 5000

Appliquer la protection CSRF et les politiques de sécurité du contenu

 Le Cross-Site Request Forgery (CSRF) est une vulnérabilité qui permet à quelqu’un d’exploiter et de tirer parti de la session connectée d’un utilisateur sur un site web de confiance pour effectuer des requêtes non autorisées vers ce site. WTForms est une extension Flask qui intègre par défaut la protection CSRF pour prévenir les attaques CSRF.

La politique de sécurité du contenu (CSP) est une couche supplémentaire de sécurité pour les applications web qui les protège contre les attaques malveillantes. CSP indique au navigateur quelles ressources sont autorisées à se charger sur une page web spécifique.
En général, l’administrateur du site configure une CSP en ajoutant un en-tête spécial à la réponse du serveur pour une page web, puis le navigateur reçoit cet en-tête CSP et comprend quelles ressources peuvent se charger. Talisman est une extension pour Flask qui simplifie le processus d’ajout de CSP aux applications Flask.

  • Installez les packages flask-wtf et talisman.

$ pip install flask-wtf talisman
  • Ouvrez le fichier app.py.

$ nano app.py
  • Modifiez le fichier app.py pour inclure des politiques de sécurité du contenu.

from talisman import Talisman
talisman = Talisman(
   app,
   content_security_policy={
       'default-src': ['\'self\''],

       'script-src': ['\'self\'', '\'unsafe-inline\'', 
       'https://code.jquery.com'],
'style-src': ['\'self\'', '\'unsafe-inline\''
'https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css',
'https://todoapp5.ddns.net/static/styles.css', 
'https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css'],
   },
 force_https=True,
session_cookie_secure=True,
frame_options='DENY',

)
  • Dans le fichier app.py, importez et configurez la protection CSRF.

from flask_wtf.csrf import CSRFProtect

app.config['SECRET_KEY'] = 'your_secret_key_here'

csrf = CSRFProtect(app)

csrf._csrf_request_token_key = 'X-CSRFToken'
Enregistrez et fermez le fichier.
Naviguez vers le répertoire des templates.
$ cd templates
Ouvrez le fichier index.html.
$ nano index.html
Modifiez la page HTML pour inclure la configuration CSRF 
  • Enregistrez et fermez le fichier.
  • Quittez le répertoire des templates.

$ cd ..

Configurez Nginx en tant que proxy inverse

Nginx agit comme un proxy inverse entre les clients et votre application Flask. Il reçoit les requêtes entrantes, gère les connexions HTTPS, et les redirige vers le serveur Gunicorn qui exécute l’application Flask. Cela améliore les performances, la sécurité et la gestion des requêtes.

Avant de configurer Nginx, vous devez relier un nom de domaine à votre serveur.

Lier un nom de domaine à votre serveur

  • Connectez-vous à l’interface de votre fournisseur de nom de domaine (par exemple : OVH, Gandi, Namecheap, Google Domains…).

  • Accédez à la section de gestion des DNS.

  • Créez un enregistrement de type A qui associe votre nom de domaine (votredomaine.com) à l’adresse IP publique de votre serveur.

  • (Facultatif) Ajoutez un enregistrement CNAME pour www.votredomaine.com qui pointe vers votredomaine.com.

  • Enregistrez les modifications et attendez que les DNS se propagent (cela peut prendre quelques minutes à plusieurs heures).
  • Installez Nginx.

$ sudo apt install nginx
  • Créez un nouveau fichier de configuration Nginx.

$ sudo nano /etc/nginx/sites-available/app.conf
  • Collez la configuration suivante dans le fichier.

server {

   listen 80;
   listen [::]:80;
   server_name ;
   location / {
       proxy_pass http://127.0.0.1:5000/;

       proxy_set_header Host $host;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Proto $scheme;

   }
}
  • Activez la configuration du virtual host.

$ sudo ln -s /etc/nginx/sites-available/app.conf /etc/nginx/sites-enabled/
  • Testez la configuration Nginx.

$ sudo nginx -t
  • Redémarrer Nginx

$ sudo systemctl reload nginx
  • Autoriser les connexions entrantes sur les ports 80 et 443.

$ sudo ufw allow 80/tcp && sudo ufw allow 443/tcp
  • Installez le package certbot.

$ sudo snap install --classic certbot
  • Demander un certificat SSL.

$ sudo certbot --nginx -d example.com -d www.example.com
  • Démarrer le serveur Gunicorn.

$ gunicorn -b 0.0.0.0:5000 app:app
  • Vous pouvez accéder à votre application Flask à l’adresse https://<votre_domaine>.

Résumé

Dans cet article, nous avons exploré comment déployer une application Flask en utilisant un proxy inverse Nginx et Gunicorn avec une protection CSRF et des CSPs. Nous avons également sécurisé l’application en ajoutant un certificat SSL et en activant l’accès HTTPS.

FAQ

Comment déployer une application Flask en production avec Gunicorn et Nginx ?

Pour déployer mon application Flask en production, j’utilise Gunicorn comme serveur d’application WSGI et Nginx comme proxy inverse. Gunicorn lance l’application Flask et gère les requêtes, tandis que Nginx agit comme un intermédiaire entre les utilisateurs et Gunicorn, améliorant la sécurité et les performances. Une fois mon code prêt, je démarre Gunicorn avec une commande comme gunicorn -b 0.0.0.0:5000 app:app, puis je configure Nginx pour rediriger les requêtes vers ce port.

Pour sécuriser mes formulaires contre les attaques CSRF (Cross-Site Request Forgery), j’installe l’extension Flask-WTF. Je configure une clé secrète dans mon application (app.config[‘SECRET_KEY’]) et j’utilise CSRFProtect(app) pour activer la protection. Dans mes templates HTML, j’ajoute le champ {{ form.csrf_token }} pour que le token soit intégré automatiquement dans chaque formulaire.

Utiliser Nginx comme proxy inverse me permet de mieux sécuriser mon application Flask. Il gère directement les connexions HTTPS, allège la charge de Flask, filtre les requêtes, compresse les réponses, et offre des performances accrues. Flask n’est pas conçu pour servir en production directement  c’est pourquoi je passe toujours par Nginx pour la stabilité et la sécurité.

Pour activer HTTPS sur mon site Flask, j’utilise Certbot de Let’s Encrypt, qui fournit gratuitement des certificats SSL. Après avoir installé Nginx et Certbot, j’exécute la commande sudo certbot –nginx -d monsite.com pour générer et configurer automatiquement le certificat. Cela active HTTPS sans intervention manuelle, et Certbot peut aussi renouveler le certificat automatiquement.

Je protège mon application Flask des attaques XSS en utilisant escape() ou les templates Jinja2 qui échappent les entrées par défaut. Pour éviter les injections SQL, j’utilise des ORM comme SQLAlchemy qui gèrent les requêtes de façon sécurisée. Contre les attaques DoS, je limite le nombre de requêtes avec des outils comme Flask-Limiter ou je configure un pare-feu via Nginx ou UFW.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *