Skip to content
VDS · Bases de données

Utilisateurs et permissions dans la base de données

Comment créer un utilisateur distinct pour chaque application dans MySQL et PostgreSQL, accorder des permissions minimales, et vérifier que rien de superflu n'est autorisé.

Mis à jour le 23 août 2026

Une application exécutée en tant que root ou postgres livre toutes les bases de données de la machine à un attaquant dès la première vulnérabilité. Un utilisateur dédié, disposant de privilèges uniquement sur son propre schéma, limite les dégâts à un seul projet.

MySQL et MariaDB

Ici, un utilisateur est une paire « nom et hôte », et c'est la principale source de confusion :

CREATE USER 'shop'@'localhost' IDENTIFIED BY 'long-random-password';
GRANT SELECT, INSERT, UPDATE, DELETE ON shop.* TO 'shop'@'localhost';
FLUSH PRIVILEGES;

'shop'@'localhost' et 'shop'@'%' sont deux utilisateurs différents avec des mots de passe différents. Ne créez pas d'enregistrements avec l'hôte % sauf si c'est nécessaire : cela autorise la connexion depuis n'importe quelle adresse.

Les privilèges sur la structure ne sont nécessaires que pendant les migrations :

GRANT CREATE, ALTER, DROP, INDEX, REFERENCES ON shop.* TO 'shop_migrate'@'localhost';

Séparer le rôle applicatif et le rôle de migration est une bonne pratique : une requête ordinaire ne peut alors physiquement pas supprimer une table.

Vérification :

SELECT user, host FROM mysql.user;
SHOW GRANTS FOR 'shop'@'localhost';

Changer le mot de passe et supprimer :

ALTER USER 'shop'@'localhost' IDENTIFIED BY 'new-password';
DROP USER 'shop'@'localhost';

PostgreSQL

Le rôle et ses privilèges sur la base de données et le schéma :

CREATE ROLE shop WITH LOGIN PASSWORD 'long-random-password';
CREATE DATABASE shop OWNER shop;
REVOKE ALL ON DATABASE shop FROM PUBLIC;

Pour un rôle en lecture seule (rapports, analyses, panneau de supervision) :

CREATE ROLE reader WITH LOGIN PASSWORD '...';
GRANT CONNECT ON DATABASE shop TO reader;
GRANT USAGE ON SCHEMA public TO reader;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO reader;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT ON TABLES TO reader;

La dernière ligne est obligatoire : sans elle, le rôle ne verra pas les tables créées après l'attribution des privilèges, et dans un mois les rapports casseront sur les nouvelles données.

Vérification :

\du
\l
\dp

Ce qu'il faut verrouiller

  • Aucun rôle applicatif n'est superutilisateur.
  • Chaque projet dispose de sa propre base de données et de son propre utilisateur.
  • Les mots de passe sont longs et aléatoires, et différents d'un projet à l'autre.
  • La connexion externe n'est autorisée que pour les adresses qui en ont besoin — accès distant.
  • MySQL ne comporte aucun utilisateur anonyme ni base de données de test : mariadb-secure-installation s'en charge.

Erreurs courantes

SymptômeCause
Access denied avec le bon mot de passeUne autre règle d'hôte a été appliquée, par exemple ''@'localhost'
Privilèges accordés, mais SELECT ne fonctionne pasPostgreSQL manque de USAGE ON SCHEMA
La nouvelle table n'est pas visible pour le rôleLes DEFAULT PRIVILEGES ne sont pas définis
L'application a tout supprimé lors d'une migration échouéeLe rôle applicatif disposait du privilège DROP
Le mot de passe est visible dans l'historique des commandesDéfinissez les mots de passe depuis un fichier, effacez ~/.mysql_history

Stockez les mots de passe des bases de données dans le fichier d'environnement du service avec des permissions 600, et non dans le code. En cas de compromission, vous modifiez une ligne et redémarrez, sans reconstruire tout le projet.