MySQL道普請便り

第152回 パスワード検証必須ポリシーとログイン失敗時のアカウントの一時ロック

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

第149回 MySQLのパスワード再利用ポリシーでは,MySQL 8.0に追加されたパスワードの再利用についての設定について説明しました。今回もMySQL 8.0で追加されたパスワード周りの機能として,バージョン8.0.13で追加されたパスワード検証必須ポリシーと,バージョン8.0.19で追加された,ログイン失敗時のアカウントの一時ロックについて説明します。なお,今回利用するMySQLはバージョン8.0.23,OSはCentOS 7を利用しています。

パスワード検証必須ポリシー(Password Verification-Required Policy)とは

パスワード検証必須ポリシーとは,パスワードを変更する際に現在のパスワードを要求するオプションになります。デフォルトはOFFになっており,my.cnfにpassword_require_currentを記述するか,SET (GLOBAL|PERSIST)で設定します。アカウント単位でも設定することができます。

[mysqld]
password_require_current

password_require_currentは,mysqlデータベースに対してCREATE USER権限またはUPDATE権限を持っている場合,そのアカウントに対しては有効とならないためご注意ください。

グローバルポリシー設定

実際に設定して動作を確認してみましょう。

グローバルポリシーに設定がされている場合はSHOW VARIABLES構文で確認することができます。lhfukamachi@%ユーザーを作成し,lhfukamachi@%ユーザーでログインしてみます。

root > show variables like 'password_require_current';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| password_require_current | ON    |
+--------------------------+-------+
1 row in set (0.06 sec)

root > CREATE USER 'lhfukamachi'@'%' IDENTIFIED BY 'lhfukamachi';
Query OK, 0 rows affected (0.01 sec)
$ mysql -u lhfukamachi -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
〈省略〉
lhfukamachi >

lhfukamachi@%ユーザーでログインすることができました。従来通りにパスワードを変更してみると,以下のようなエラーが出てパスワードの変更に失敗しました。password_require_currentがONの状態でパスワードを変更する場合は,REPLACE <現在のパスワード>をつけて変更します。

> SET PASSWORD = 'lhfukamachi_change_password';
ERROR 3892 (HY000): Current password needs to be specified in the REPLACE clause in order to change it.

> SET PASSWORD = 'lhfukamachi_change_password' REPLACE 'lhfukamachi';
Query OK, 0 rows affected (0.01 sec)

このように,パスワードを変更することができました。

アカウント個別に設定する

アカウント個別に設定する場合は,CREATE USER/ ALTER USER構文にPASSWORD REQUIRE CURRENTオプションを設定することで設定することができます。

PASSWORD REQUIRE CURRENTは以下3つの設定ができます。

PASSWORD REQUIRE CURRENT
パスワードを変更するときは現在のパスワードを指定する必要がある。
PASSWORD REQUIRE CURRENT OPTIONAL
パスワードの変更するときは現在のパスワードを指定する必要はない。
PASSWORD REQUIRE CURRENT DEFAULT
パスワードの変更するときに現在のパスワードが必要かどうかはpassword_require_currentの設定に依存する。
root > ALTER USER 'lhfukamachi'@'%' PASSWORD REQUIRE CURRENT OPTIONAL;
Query OK, 0 rows affected (0.00 sec)

また,アカウント個別に設定した場合は,グローバルで設定したpassword_require_currentをオーバーライドして設定されます。個別で設定している場合,各アカウントの設定の状態は,mysql.userテーブルのpassword_require_currentカラムで設定を確認することができます。

password_require_currentカラムはY/N/NULLの3つの値をとり,それぞれ順にPASSWORD REQUIRE CURRENT, PASSWORD REQUIRE CURRENT OPTIONAL, PASSWORD REQUIRE CURRENT DEFAULTとなっています。

root > SELECT user, host, password_require_current FROM mysql.user WHERE user = 'lhfukamachi';
+-------------+------+--------------------------+
| user        | host | password_require_current |
+-------------+------+--------------------------+
| lhfukamachi | %    | N                        |
+-------------+------+--------------------------+
1 row in set (0.00 sec)

各アカウントの設定状態と,グローバルポリシーの状態においてパスワードの変更時に現在のパスワードが必要かどうかは公式ドキュメント6.2.15 パスワード管理にテーブル形式でまとまっているので,こちらもご参照ください。

ログイン失敗時のアカウントの一時ロック

MySQL 8.0.19以降では,CREATE USER/ALTER USER時にFAILED_LOGIN_ATTEMPTS <試行回数> PASSWORD_LOCK_TIME <アカウントロック期間>を設定することで,各アカウントに対して失敗時の回数を記録して規定の試行回数を超えた場合に,一定期間アカウントをロックすることができるようになりました。

それぞれ回数は0~32767の範囲で設定することができます(0を指定するとオプションが無効になります⁠⁠。

root > CREATE USER 'lhfukamachi'@'%' IDENTIFIED BY 'lhfukamachi' FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 3;
Query OK, 0 rows affected (0.01 sec)

(3回目のログイン失敗時もエラーの場合はアカウントがロックされる)
$ mysql -u lhfukamachi -p
Enter password:
ERROR 3955 (HY000): Access denied for user 'lhfukamachi'@'localhost'. Account is blocked for 3 day(s) (3 day(s) remaining) due to 3 consecutive failed logins.

ただし,一時ロックの場合ではmysql.userテーブルのaccount_lockedは有効になっておりません。

ロックされたアカウントはALTER USER構文のACCOUNT UNLOCKオプションを指定して解除するか,アカウントロックの期間を超える必要があります。

また,mysqldの再起動を実施するか,FLUSH PRIVILEGESを実行することで,すべてのアカウントに対してアカウントの状態をリセットすることができます。

各アカウントの設定についてはmysql.userのuser_attributesカラムで確認することができます。

root > SELECT user, host, user_attributes FROM mysql.user WHERE user = 'lhfukamachi';
+-------------+------+----------------------------------------------------------------------------------+
| user        | host | User_attributes                                                                  |
+-------------+------+----------------------------------------------------------------------------------+
| lhfukamachi | %    | {"Password_locking": {"failed_login_attempts": 3, "password_lock_time_days": 3}} |
+-------------+------+----------------------------------------------------------------------------------+
1 row in set (0.00 sec)

まとめ

今回は,パスワード検証必須ポリシーとログイン失敗時のアカウントの一時ロックについて説明しました。MySQLのバージョンが上がるにつれてより強固な設定が可能となっているため,利用したい設定がある場合は,ぜひMySQLのバージョンアップをご検討ください。

著者プロフィール

深町日出海(ふかまちひでみ)

GMOメディア株式会社のデータベースエンジニア。主にOracleとMySQLを担当。得意なプログラム言語はJava。MySQLの好きなところはTABLEやINDEXの識別子に64byteまで使えるところ。

Twitter:@lhfukamachi