2018年1月24日水曜日

MySQL 8.0.4におけるデフォルト認証形式の変更


Incompatible Change: The caching_sha2_password and sha256_password authentication plugins provide more secure password encryption than the mysql_native_password plugin, and caching_sha2_password provides better performance than sha256_password. Due to these superior security and performance characteristics of caching_sha2_password, it is now the preferred authentication plugin, and is also the default authentication plugin rather than mysql_native_password. This change affects both the server and the libmysqlclient client library:

MySQLはそれぞれのアカウントが「どうやって認証されるべきか」をアカウント情報の中に持っている(5.6とそれ以降) mysql.user テーブルには plugin というカラムがあって、
mysql80 10> SELECT user, host, plugin FROM user;
+------------------+-----------+-----------------------+
| user             | host      | plugin                |
+------------------+-----------+-----------------------+
| mysql.infoschema | localhost | mysql_native_password |
| mysql.session    | localhost | mysql_native_password |
| mysql.sys        | localhost | mysql_native_password |
| root             | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
4 rows in set (0.00 sec)
この場合、 mysql.infoschema@localhost, mysql.session@localhost, mysql.sys@localhostmysql_native_password プラグイン、 root@localhostcaching_sha2_password で認証される、という設定になっている。
MySQLの認証はチャレンジ・レスポンス認証なので、クライアントとサーバーで同じ認証形式をサポートしている必要がある。
root@localhost でログインしようとする場合、クライアント側も caching_sha2_password プラグインをサポートしていないといけないが、MySQL 5.7(少なくとも5.7.21)とそれ以前のバージョンには存在しないので転ける。
$ /usr/mysql/5.7.21/bin/mysql -S /usr/mysql/8.0.4/data/mysql.sock -u root
ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded: /usr/mysql/5.7.21/lib/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory
それに対して mysql.sys@localhost などはそもそも今までの mysql_native_password プラグインを使おうとするので、5.7とそれ以前のクライアントから接続しようとしても「パスワードが違う」エラーだけで、認証プラグインがどうこうのエラーにはならない。
$ /usr/mysql/5.7.21/bin/mysql -S /usr/mysql/8.0.4/data/mysql.sock -u mysql.sys
ERROR 1045 (28000): Access denied for user 'mysql.sys'@'localhost' (using password: NO)
MySQL 8.0.4とそれ以降は、認証プラグインを指定しないでユーザーを作成した場合のデフォルトが caching_sha2_password になっているので、MySQL 8.0.4とそれ以降にアップグレードしてから(プラグインを指定せずに)新しく作ったユーザーに対して、5.7とそれ以前と caching_sha2_password をサポートしていないライブラリーで接続しようとすると炸裂する。
これを避けるにはサーバー側に default_authentication_plugin を設定しておけば良くて、
$ vim my.cnf
[mysqld]
default_authentication_plugin= mysql_native_password
これで認証プラグイン指定しなかった場合のデフォルトが mysql_native_password に変更できる。再起動が必要なので(少なくともPHPのmysqlndとかその他libmysqlclient使ってるやつでも8.0に追従するまでは)秘伝のタレに入れておいていいかと。
デフォルトは変えずにユーザー単位で指定する場合は、 WITH mysql_native_password を指定すればOK( mysqldumpmysqlpump にはこの WITH 指定が含まれているので、8.0.4とそれ以降に対してこれらをリストアしても大丈夫)

mysql80 13> CREATE USER yoku0825 IDENTIFIED WITH mysql_native_password BY 'hogehoge';
Query OK, 0 rows affected (0.02 sec)
パスワードはハッシュ形式で保管されるので、既に存在していてパスワードを設定してしまったアカウントを ALTER USER で変更してもパスワードハッシュは更新されず…というかそれどころか IDENTIFIED BY '' と同じ扱いになってパスワードがからっぽになる。
mysql80 23> SELECT user, host, plugin, authentication_string FROM user;
+------------------+-----------+-----------------------+-------------------------------------------+
| user             | host      | plugin                | authentication_string                     |
+------------------+-----------+-----------------------+-------------------------------------------+
| yoku0825         | %         | mysql_native_password | *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 |
| mysql.infoschema | localhost | mysql_native_password | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| mysql.session    | localhost | mysql_native_password | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| mysql.sys        | localhost | mysql_native_password | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| root             | localhost | mysql_native_password |                                           |
+------------------+-----------+-----------------------+-------------------------------------------+
5 rows in set (0.00 sec)

mysql80 23> ALTER USER yoku0825 IDENTIFIED WITH caching_sha2_password;
Query OK, 0 rows affected (0.00 sec)

mysql80 23> SELECT user, host, plugin, authentication_string FROM user;
+------------------+-----------+-----------------------+-------------------------------------------+
| user             | host      | plugin                | authentication_string                     |
+------------------+-----------+-----------------------+-------------------------------------------+
| yoku0825         | %         | caching_sha2_password |                                           |
| mysql.infoschema | localhost | mysql_native_password | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| mysql.session    | localhost | mysql_native_password | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| mysql.sys        | localhost | mysql_native_password | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| root             | localhost | mysql_native_password |                                           |
+------------------+-----------+-----------------------+-------------------------------------------+
5 rows in set (0.00 sec)
これちょっと誤発動すると痛いからパーサーでエラーにしてほしいなぁ…。。。

【2018/01/24 17:22】

IDENTIFIED WITH auth_plugin
..
In addition, the password is marked expired. The user must choose a new one when next connecting.

https://dev.mysql.com/doc/refman/8.0/en/alter-user.html

だそうで。


mysql80 25> CREATE USER yoku0825 IDENTIFIED WITH caching_sha2_password BY 'caching_sha2';
Query OK, 0 rows affected (0.01 sec)

mysql80 25> SELECT user, host, plugin, authentication_string, password_expired FROM user WHERE user = 'yoku0825';
+----------+------+-----------------------+------------------------------------------------------------------------+------------------+
| user     | host | plugin                | authentication_string                                                  | password_expired |
+----------+------+-----------------------+------------------------------------------------------------------------+------------------+
| yoku0825 | %    | caching_sha2_password | $A$005$feA!*,'z
LvMw1OqJfNOBC0z03D4plWGdAtRsSIxpQg7iDE1yowBB0 | N                |
+----------+------+-----------------------+------------------------------------------------------------------------+------------------+
1 row in set (0.00 sec)

mysql80 25> ALTER USER yoku0825 IDENTIFIED WITH mysql_native_password;
Query OK, 0 rows affected (0.01 sec)

mysql80 25> SELECT user, host, plugin, authentication_string, password_expired FROM user WHERE user = 'yoku0825';
+----------+------+-----------------------+-----------------------+------------------+
| user     | host | plugin                | authentication_string | password_expired |
+----------+------+-----------------------+-----------------------+------------------+
| yoku0825 | %    | mysql_native_password |                       | Y                |
+----------+------+-----------------------+-----------------------+------------------+
1 row in set (0.00 sec)

$ mysql80 -uyoku0825
mysql80 26> show databases;
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.



0 件のコメント :

コメントを投稿