Користувачі та права в базі даних
Як створити окремого користувача для кожного застосунку в MySQL і PostgreSQL, надати мінімальні права та переконатися, що зайвого не дозволено.
Оновлено 23 серпня 2026 р.
Застосунок, що працює від root або postgres, віддає зловмиснику всі бази даних на машині вже за першої вразливості. Окремий користувач із правами лише на власну схему обмежує збитки одним проєктом.
MySQL і MariaDB
Користувач тут — це пара «ім'я та хост», і саме це найчастіше плутає:
CREATE USER 'shop'@'localhost' IDENTIFIED BY 'long-random-password';
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 'new-password';
DROP USER 'shop'@'localhost';
PostgreSQL
Роль та її права на базу даних і схему:
CREATE ROLE shop WITH LOGIN PASSWORD 'long-random-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, а не в коді. У разі компрометації ви змінюєте один рядок і перезапускаєте сервіс, а не перебудовуєте весь проєкт.