Пользователи и права в базе
Как завести отдельного пользователя под каждое приложение в MySQL и PostgreSQL, выдать минимальные права и проверить, что лишнего нет.
Обновлено 23 августа 2026 г.
Приложение, работающее от root или postgres, при первой же уязвимости отдаёт злоумышленнику все базы на машине. Отдельный пользователь с правами только на свою схему ограничивает ущерб одним проектом.
MySQL и MariaDB
Пользователь здесь — это пара «имя и хост», и это главный источник путаницы:
CREATE USER 'shop'@'localhost' IDENTIFIED BY 'длинный-случайный-пароль';
GRANT SELECT, INSERT, UPDATE, DELETE ON shop.* TO 'shop'@'localhost';
FLUSH PRIVILEGES;
'shop'@'localhost' и 'shop'@'%' — два разных пользователя с разными паролями. Записи с хостом % не создавайте без необходимости: она разрешает вход с любого адреса.
Права на структуру нужны только на время миграций:
GRANT CREATE, ALTER, DROP, INDEX, REFERENCES ON shop.* TO 'shop_migrate'@'localhost';
Разделять роль приложения и роль миграций — хорошая практика: обычный запрос тогда физически не может уронить таблицу.
Проверка:
SELECT user, host FROM mysql.user;
SHOW GRANTS FOR 'shop'@'localhost';
Смена пароля и удаление:
ALTER USER 'shop'@'localhost' IDENTIFIED BY 'новый-пароль';
DROP USER 'shop'@'localhost';
PostgreSQL
Роль и её права на базу и схему:
CREATE ROLE shop WITH LOGIN PASSWORD 'длинный-случайный-пароль';
CREATE DATABASE shop OWNER shop;
REVOKE ALL ON DATABASE shop FROM PUBLIC;
Для роли только на чтение (отчёты, аналитика, панель мониторинга):
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;
Последняя строка обязательна: без неё роль не увидит таблицы, созданные после выдачи прав, и через месяц отчёты сломаются на новых данных.
Проверка:
\du
\l
\dp
Что должно быть закрыто
- Ни одна прикладная роль не является суперпользователем.
- У каждого проекта своя база и свой пользователь.
- Пароли длинные и случайные, разные у разных проектов.
- Вход снаружи разрешён только тем адресам, которым он нужен — удалённое подключение.
- В MySQL нет анонимных пользователей и тестовой базы: это делает
mariadb-secure-installation.
Частые ошибки
| Симптом | Причина |
|---|---|
Access denied при верном пароле | Совпало другое правило по хосту, например ''@'localhost' |
Права выданы, но SELECT не работает | В PostgreSQL нет USAGE ON SCHEMA |
| Новая таблица не видна роли | Не заданы DEFAULT PRIVILEGES |
| Приложение всё удалило при сбое миграции | У прикладной роли были права DROP |
| Пароль виден в истории команд | Задавайте пароли из файла, чистите ~/.mysql_history |
Пароли базы храните в файле окружения службы с правами
600, а не в коде. При компрометации меняется одна строка и делается перезапуск, а не пересборка всего проекта.