Skip to content
VDS · データベース

データベースのユーザーと権限

MySQLとPostgreSQLでアプリケーションごとに専用ユーザーを作成し、最小限の権限を付与して、余分な権限が許可されていないことを確認する方法を説明します。

更新日 2026年8月23日

root や postgres として動作するアプリケーションは、最初の脆弱性でマシン上のすべてのデータベースを攻撃者に引き渡してしまいます。自分のスキーマにのみ権限を持つ専用ユーザーであれば、被害を 1 つのプロジェクトに限定できます。

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;

最後の行は必須です。これがないと、権限を付与した後に作成されたテーブルをロールが認識できず、1 か月後にはレポートが新しいデータで壊れてしまいます。

確認:

\du
\l
\dp

必ず制限すべきこと

  • どのアプリケーションロールもスーパーユーザーではありません。
  • 各プロジェクトには専用のデータベースと専用のユーザーがあります。
  • パスワードは長くランダムで、プロジェクトごとに異なります。
  • 外部からのログインは、必要なアドレスのみに許可します — リモートアクセス。
  • MySQL には匿名ユーザーもテストデータベースもありません。mariadb-secure-installation がこれを行います。

よくある間違い

症状原因
正しいパスワードなのに Access denied別のホストルールが一致した。たとえば ''@'localhost'
権限を付与したのに SELECT が動作しないPostgreSQL に USAGE ON SCHEMA がない
新しいテーブルがロールから見えないDEFAULT PRIVILEGES が設定されていない
失敗したマイグレーション中にアプリケーションがすべて削除したアプリケーションロールに DROP 権限があった
パスワードがコマンド履歴に表示されるパスワードはファイルから設定し、~/.mysql_history を消去する

データベースのパスワードはコードではなく、600 権限のサービス環境ファイルに保存してください。漏洩した場合は、プロジェクト全体を再構築するのではなく、1 行を変更して再起動するだけですみます。