MySQL の GRANT にはワイルドカードが使える・・・意図せずに

## はじめに

`ore@localhost` ユーザーに `oreore` データベースへの権限を付与するには次のような GRANT を使いますが、

```console:console
$ mysql -u root -e 'grant all on oreore.* to ore@localhost'
```

データベースへの GRANT があると、データベースそのものを作成したり削除したりもできます。

```console:console
$ mysql -u ore -e 'create database oreore'
$ mysql -u ore -e 'show databases'
+--------------------+
| Database           |
+--------------------+
| information_schema |
| oreore             |
+--------------------+

$ mysql -u ore -e 'drop database oreore'
$ mysql -u ore -e 'show databases'
+--------------------+
| Database           |
+--------------------+
| information_schema |
+--------------------+
```

なぜか出来ないと思っていました。

もちろん他のデータベースを作ったり削除したりはできません。

```console:console
$ mysql -u ore -e 'create database areare'
ERROR 1044 (42000) at line 1: Access denied for user 'ore'@'localhost' to database 'areare'
```

## 本題

実は GRANT のデータベース名にはワイルドカードが使えます。

ワイルドカードと言っても、これ → `*.*` ← のことではありません。

MySQL の `%` とかのワイルドカードです。

ただし、次のように書いてもダメです。

```mysql:mysql
mysql> grant all on oreore%.* to ore@localhost;
ERROR 1064 (42000): You have an error in your SQL syntax; ...

mysql> grant all on 'oreore%'.* to ore@localhost;
ERROR 1064 (42000): You have an error in your SQL syntax; ...
```

バッククオートを使って識別子としてエスケープする必要があります。

```mysql:mysql
mysql> grant all on `oreore%`.* to ore@localhost;
Query OK, 0 rows affected (0.00 sec)
```

ワイルドカードを使うとパターンにマッチするすべてのデータベースに権限が与えられます。

```console:console
$ mysql -u ore -e 'create database oreore_a'
$ mysql -u ore -e 'create database oreore_b'
$ mysql -u ore -e 'create database oreore_c'
$ mysql -u ore -e 'show databases'
+--------------------+
| Database           |
+--------------------+
| information_schema |
| oreore_a           |
| oreore_b           |
| oreore_c           |
+--------------------+
```

（邪魔なので消します）

```console:console
$ mysql -u ore -e 'drop database oreore_a'
$ mysql -u ore -e 'drop database oreore_b'
$ mysql -u ore -e 'drop database oreore_c'
$ mysql -u root -e 'revoke all on `oreore%`.* from ore@localhost'
```

ところで、MySQL でワイルドカードといえば `%` だけではありません。`_` もです。しかも `_` の場合はバッククオートで囲う必要はないようです。

なので、次のようなありがちな GRANT だと・・・・

```mysql:mysql
mysql> grant all on oreore_test.* to ore@localhost;
```

**実は意図せず `oreore?test` なデータベースへ権限が付与されています。**

```console:console
$ mysql -u ore -e 'create database oreoreAtest'
$ mysql -u ore -e 'create database oreoreBtest'
$ mysql -u ore -e 'create database oreoreCtest'
$ mysql -u ore -e 'show databases'
+--------------------+
| Database           |
+--------------------+
| information_schema |
| oreoreAtest        |
| oreoreBtest        |
| oreoreCtest        |
+--------------------+
```

（邪魔なので消します）

```console:console
$ mysql -u ore -e 'drop database oreoreAtest'
$ mysql -u ore -e 'drop database oreoreBtest'
$ mysql -u ore -e 'drop database oreoreCtest'
$ mysql -u root -e 'revoke all on oreore_test.* from ore@localhost'
```

次のように `_` をエスケープする必要があります。

```mysql:mysql
mysql> grant all on `oreore\_test`.* to ore@localhost;
```

```console:console
$ mysql -u ore -e 'create database oreoreAtest'
ERROR 1044 (42000) at line 1: Access denied for user 'ore'@'localhost' to database 'oreoreAtest'

$ mysql -u ore -e 'create database oreore_test'
$ mysql -u ore -e 'show databases'
+--------------------+
| Database           |
+--------------------+
| information_schema |
| oreore_test        |
+--------------------+
```

## さいごに

`mysql_install_db` でデータディレクトリを作成した直後だと、以下のようにデータベース権限が設定されています。

```console:console
$ mysql -u root -e 'select User, Host, Db from mysql.db'
+------+------+---------+
| User | Host | Db      |
+------+------+---------+
|      | %    | test    |
|      | %    | test\_% |
+------+------+---------+
```

これを見てデータベース名にもワイルドカードが使えることを知ったのですが、普段はいつも `mysql_install_db` の後は余計な権限を消すために、

```mysql:mysql
mysql> delete from mysql.user;
mysql> delete from mysql.db;
mysql> grant all on *.* to root@localhost with grant option;
mysql> flush privileges;
```

とかやっていたので気づきませんでした・・・