REVOKEの「*」はワイルドカード?

2019年10月11日

こんにちは!
2019年新卒入社!プチDBAを目指してOJT中の高橋です!
弊社のOJT制度についてはこちら


「*」はワイルドカード

というのは言わずもがなですが、

それはMySQLにおいても同じで、きちんと期待する動作をしてくれます。

mysql8017> GRANT SELECT ON *.* TO hoge@'%';

を実行すると、
全てのスキーマの全てのテーブルに権限を付与するという解釈ができるので、
直感的でわかりやすいです。

そして権限を取るときも、

mysql8017> REVOKE SELECT ON *.* FROM hoge@'%';

という感じで実行できます。

ここで疑問

mysql8017> SHOW GRANTS FOR hoge@'%';
+----------------------------------------------+
| Grants for hoge@%                            |
+----------------------------------------------+
| GRANT SELECT ON *.* TO `hoge`@`%`            |
| GRANT SELECT ON `s1`.* TO `hoge`@`%`         |
| GRANT ALL PRIVILEGES ON `s2`.* TO `hoge`@`%` |
| GRANT ALL PRIVILEGES ON `s3`.* TO `hoge`@`%` |
+----------------------------------------------+

hoge@'%'ユーザにこれだけの権限があったとして、

mysql8017> REVOKE SELECT ON *.* FROM hoge@'%';

を実行した場合、

ワイルドカードの在り方としてはスキーマレベルの権限も取れる方が正しい気がしますが、
実際には取れません。

まあMySQLの仕様としてそういうものだと覚えてしまえばもーまんたいですよね。

しかし!

MySQL8.0ではREVOKE ALLを実行した場合に限り、

全ての権限が取れた!?

という話が今回の内容です!

検証

早速MySQL8.0と5.7のインスタンスで検証してみましょう。

今回は8.0.17と5.7.27でやっていきます。

ユーザをつくる

mysql5727> CREATE USER hoge@'%' IDENTIFIED BY 'hoge';
Query OK, 0 rows affected (0.00 sec)
mysql8017> CREATE USER hoge@'%' IDENTIFIED BY 'hoge';
Query OK, 0 rows affected (0.01 sec)

次!

権限をつける

mysql5727> GRANT SELECT ON *.* TO hoge@'%';
Query OK, 0 rows affected (0.00 sec)

mysql5727> GRANT ALL ON s1.* TO hoge@'%';
Query OK, 0 rows affected (0.01 sec)
mysql8017> GRANT SELECT ON *.* TO hoge@'%';
Query OK, 0 rows affected (0.00 sec)

mysql8017> GRANT ALL ON s1.* TO hoge@'%';
Query OK, 0 rows affected (0.00 sec)

ここまでで一旦比較してみます。

mysql5727> SHOW GRANTS FOR hoge@'%';
+----------------------------------------------+
| Grants for hoge@%                            |
+----------------------------------------------+
| GRANT SELECT ON *.* TO 'hoge'@'%'            |
| GRANT ALL PRIVILEGES ON `s1`.* TO 'hoge'@'%' |
+----------------------------------------------+
2 rows in set (0.00 sec)
mysql8017> SHOW GRANTS FOR hoge@'%';
+----------------------------------------------+
| Grants for hoge@%                            |
+----------------------------------------------+
| GRANT SELECT ON *.* TO `hoge`@`%`            |
| GRANT ALL PRIVILEGES ON `s1`.* TO `hoge`@`%` |
+----------------------------------------------+
2 rows in set (0.00 sec)

同じですね〜
次!

ALLを使って権限をはがす

今回の肝となるSQLを実行していきます!

globalレベルのSELECT権限をALLでとります。

mysql5727> REVOKE ALL ON *.* FROM hoge@'%';
Query OK, 0 rows affected (0.01 sec)
mysql8017> REVOKE ALL ON *.* FROM hoge@'%';
Query OK, 0 rows affected (0.01 sec)

結果

mysql5727> SHOW GRANTS FOR hoge@'%';
+----------------------------------------------+
| Grants for hoge@%                            |
+----------------------------------------------+
| GRANT USAGE ON *.* TO 'hoge'@'%'             |
| GRANT ALL PRIVILEGES ON `s1`.* TO 'hoge'@'%' |  ← これ!!
+----------------------------------------------+
2 rows in set (0.00 sec)
mysql8017> SHOW GRANTS FOR hoge@'%';
+----------------------------------+
| Grants for hoge@%                |
+----------------------------------+
| GRANT USAGE ON *.* TO `hoge`@`%` |
+----------------------------------+
1 row in set (0.00 sec)

はいどうでしょう!

8.0の方はschemaレベルで付けていた権限まで取られてもうすっからかんですね。

いっぱいあっても関係ありません。

mysql8017> SHOW GRANTS FOR hoge@'%';
+----------------------------------------------+
| Grants for hoge@%                            |
+----------------------------------------------+
| GRANT USAGE ON *.* TO `hoge`@`%`             |
| GRANT SELECT ON `s1`.* TO `hoge`@`%`         |
| GRANT ALL PRIVILEGES ON `s2`.* TO `hoge`@`%` |
| GRANT ALL PRIVILEGES ON `s3`.* TO `hoge`@`%` |
+----------------------------------------------+
4 rows in set (0.00 sec)

mysql8017> REVOKE ALL ON *.* FROM hoge@'%';
Query OK, 0 rows affected (0.00 sec)

mysql8017> SHOW GRANTS FOR hoge@'%';
+----------------------------------+
| Grants for hoge@%                |
+----------------------------------+
| GRANT USAGE ON *.* TO `hoge`@`%` |
+----------------------------------+
1 row in set (0.00 sec)

\\ 無慈悲!//

まとめ

我らがyoku0825さんとのペアオペ中に発覚したこの事象。

挙動としては8.0の方が直感的で正しい気がしますが、

MySQL8.0のREVOKE ALLには気をつけましょう!

ちなみに

8.0でもALLを使わなければこれまで通り使えるようです。

mysql8017> SHOW GRANTS FOR hoge@'%';
+--------------------------------------+
| Grants for hoge@%                    |
+--------------------------------------+
| GRANT SELECT ON *.* TO `hoge`@`%`    |
| GRANT SELECT ON `t1`.* TO `hoge`@`%` |
+--------------------------------------+
2 rows in set (0.00 sec)

mysql8017> REVOKE SELECT ON *.* FROM hoge@'%';
Query OK, 0 rows affected (0.01 sec)

mysql8017> SHOW GRANTS FOR hoge@'%';
+--------------------------------------+
| Grants for hoge@%                    |
+--------------------------------------+
| GRANT USAGE ON *.* TO `hoge`@`%`     |
| GRANT SELECT ON `t1`.* TO `hoge`@`%` |
+--------------------------------------+
2 rows in set (0.00 sec)

GMOメディアでは仲間を募集しております

当社は、「For your Smile,with Internet.」という企業理念のもと、多くの笑顔と感動を生み出していくべく、インターネットメディア媒体を多ブランドでサービス展開しています。
募集内容について詳しくはコチラをご覧ください