MySQL道普請便り

第17回 MySQLのユーザー管理について[その1]

この記事を読むのに必要な時間:およそ 7 分

今回から何回かに分けて,MySQLのユーザー認証について説明します。今回はまず,⁠接続元ホスト名」⁠⁠ユーザー」⁠⁠パスワード」がどこに保管され,どのような順番で評価されるかを見ていきましょう。

今回のデモンストレーション環境はあえて「匿名ユーザー」を有効にしておくために,MySQL 5.6をyumリポジトリーからインストールしたものになっています。各バージョンのyum版, rpm版の構成の違いは第10回 yum, rpmインストールにおけるMySQL 5.6とMySQL 5.7の違いを参考にしてください。

筆者がCentOS 6.6上で今回の環境を作るために実行したコマンドは以下の通りです。

$ sudo yum install -y http://dev.mysql.com/get/mysql57-community-release-el6-7.noarch.rpm
$ sudo yum install -y --disablerepo=mysql57-community --enablerepo=mysql56-community mysql-community-server
$ sudo service mysqld start

MySQLのユーザー情報の格納先

MySQLにログインするためのアカウント情報は,各OSのアカウント情報とは独立しており,MySQLの内部に保管されています。このアカウント情報はmysqldのメモリ上に展開されています。またアカウント情報の本体とは別に,mysqlスキーマのuserテーブルに1ユーザー1レコードとしてスナップショットが永続化されています(後の段落で説明しますので,今のところはmysql.user=アカウント情報の実体,としておいてください)⁠

筆者が今回の環境として用意したMySQLサーバーを起動した直後の状態です(前の段落を参照してください)⁠この環境は"centos"というホスト名を持ち,IPアドレスは"172.17.1.67"でした。

$ mysql -uroot
mysql> SELECT user, host FROM mysql.user;
+------+-----------+
| user | host      |
+------+-----------+
| root | 127.0.0.1 |
| root | ::1       |
|      | centos    |
| root | centos    |
|      | localhost |
| root | localhost |
+------+-----------+
6 rows in set (0.00 sec)

mysqlスキーマのuserテーブルにはこの他にもたくさんのカラムがあります。少し長くなりますが,DESCRIBEステートメントでカラムの情報を表示してみましょう。

mysql> DESCRIBE mysql.user;
+------------------------+-----------------------------------+------+-----+-----------------------+-------+
| Field                  | Type                              | Null | Key | Default               | Extra |
+------------------------+-----------------------------------+------+-----+-----------------------+-------+
| Host                   | char(60)                          | NO   | PRI |                       |       |
| User                   | char(16)                          | NO   | PRI |                       |       |
| Password               | char(41)                          | NO   |     |                       |       |
| Select_priv            | enum('N','Y')                     | NO   |     | N                     |       |
| Insert_priv            | enum('N','Y')                     | NO   |     | N                     |       |
| Update_priv            | enum('N','Y')                     | NO   |     | N                     |       |
| Delete_priv            | enum('N','Y')                     | NO   |     | N                     |       |
| Create_priv            | enum('N','Y')                     | NO   |     | N                     |       |
| Drop_priv              | enum('N','Y')                     | NO   |     | N                     |       |
| Reload_priv            | enum('N','Y')                     | NO   |     | N                     |       |
| Shutdown_priv          | enum('N','Y')                     | NO   |     | N                     |       |
| Process_priv           | enum('N','Y')                     | NO   |     | N                     |       |
| File_priv              | enum('N','Y')                     | NO   |     | N                     |       |
| Grant_priv             | enum('N','Y')                     | NO   |     | N                     |       |
| References_priv        | enum('N','Y')                     | NO   |     | N                     |       |
| Index_priv             | enum('N','Y')                     | NO   |     | N                     |       |
| Alter_priv             | enum('N','Y')                     | NO   |     | N                     |       |
| Show_db_priv           | enum('N','Y')                     | NO   |     | N                     |       |
| Super_priv             | enum('N','Y')                     | NO   |     | N                     |       |
| Create_tmp_table_priv  | enum('N','Y')                     | NO   |     | N                     |       |
| Lock_tables_priv       | enum('N','Y')                     | NO   |     | N                     |       |
| Execute_priv           | enum('N','Y')                     | NO   |     | N                     |       |
| Repl_slave_priv        | enum('N','Y')                     | NO   |     | N                     |       |
| Repl_client_priv       | enum('N','Y')                     | NO   |     | N                     |       |
| Create_view_priv       | enum('N','Y')                     | NO   |     | N                     |       |
| Show_view_priv         | enum('N','Y')                     | NO   |     | N                     |       |
| Create_routine_priv    | enum('N','Y')                     | NO   |     | N                     |       |
| Alter_routine_priv     | enum('N','Y')                     | NO   |     | N                     |       |
| Create_user_priv       | enum('N','Y')                     | NO   |     | N                     |       |
| Event_priv             | enum('N','Y')                     | NO   |     | N                     |       |
| Trigger_priv           | enum('N','Y')                     | NO   |     | N                     |       |
| Create_tablespace_priv | enum('N','Y')                     | NO   |     | N                     |       |
| ssl_type               | enum('','ANY','X509','SPECIFIED') | NO   |     |                       |       |
| ssl_cipher             | blob                              | NO   |     | NULL                  |       |
| x509_issuer            | blob                              | NO   |     | NULL                  |       |
| x509_subject           | blob                              | NO   |     | NULL                  |       |
| max_questions          | int(11) unsigned                  | NO   |     | 0                     |       |
| max_updates            | int(11) unsigned                  | NO   |     | 0                     |       |
| max_connections        | int(11) unsigned                  | NO   |     | 0                     |       |
| max_user_connections   | int(11) unsigned                  | NO   |     | 0                     |       |
| plugin                 | char(64)                          | YES  |     | mysql_native_password |       |
| authentication_string  | text                              | YES  |     | NULL                  |       |
| password_expired       | enum('N','Y')                     | NO   |     | N                     |       |
+------------------------+-----------------------------------+------+-----+-----------------------+-------+
43 rows in set (0.00 sec)

HostカラムとUserカラムが複合プライマリキーとして定義されています。これはMySQLでは「接続元ホスト」「ユーザー」でユーザーを一意に識別している,ということです(以降,Hostに該当する部分を「接続元ホスト」⁠ホスト名,IPアドレス,ネットワークアドレスなどの形を含みます)⁠Userに該当する部分を「ユーザー」⁠(Host, User)で識別される部分を「アカウント」と呼びます)⁠

「rootユーザーのTCP経由の接続である root@127.0.0.1 アカウントと UNIXソケット経由の接続で主に使われる root@localhost アカウントは別のアカウントか?」という疑問に対する1つの答えがこれになります。この問いに対する答えは 理屈の上ではYes」となります。しかし,インストールしたままの今回のデモンストレーション環境では「理屈とは違ってNo」になります。これについてはまた別の回で説明しましょう。

Hostカラムはchar(64)Userカラムはchar(16)(MySQL 5.7ではchar(32)に拡張されました)ですので,この長さを超える接続元ホスト,ユーザーは登録できません。

Passwordカラム(MySQL 5.7ではauthentication_stringカラムに変更され,Passwordカラムは削除されました。MySQL 5.6とそれ以前のバージョンでは,authentication_stringカラムは存在しますが利用されていません(NULLまたは空文字列が入っています)⁠にはパスワードのハッシュ値が格納されます。

*_privカラムにはユーザーのグローバル権限GRANTステートメント上で許可する対象を*.*で指定したもの)が格納されています。GRANT SELECT, INSERT ON *.* TO ..でアカウントに権限を設定した場合,そのアカウントに対応するSelect_privInsert_privが'Y'に設定されます。

その他GRANTステートメントで指定することのできるアカウント単位の属性(SSL接続の強制や1時間あたりのクエリー回数の制限など)がそれぞれカラムとして定義されていますGRANTステートメントで指定可能なアカウント単位の属性の詳細はリファレンスマニュアルを参照してください)⁠

著者プロフィール

yoku0825

GMOメディア株式会社のDBA。日本MySQLユーザ会員。主に地雷担当。主食はMySQLだがPercona Server,MariaDB,InfiniDBにMroongaストレージエンジンなど,mysqldでありさえすれば雑食。

Twitter:@yoku0825

コメント

コメントの記入