MySQL :: MySQL 5.7 Reference Manual :: 5.1.8.4 Version Tokens
サーバーの持ってるトークンとクライアントが持ってるトークンを比較して、一致しなければエラーにしてくれる仕組み。
取り敢えず何はなくともインストール。version_token.soはバンドルされてるので、ドキュメントの通りにINSTALL PLUGINとCREATE FUNCTIONを貼り付ければOK。
mysql> INSTALL PLUGIN version_tokens SONAME 'version_token.so'; Query OK, 0 rows affected (0.00 sec) mysql> CREATE FUNCTION version_tokens_set RETURNS STRING SONAME 'version_token.so'; Query OK, 0 rows affected (0.00 sec) mysql> CREATE FUNCTION version_tokens_show RETURNS STRING SONAME 'version_token.so'; Query OK, 0 rows affected (0.00 sec) mysql> CREATE FUNCTION version_tokens_edit RETURNS STRING SONAME 'version_token.so'; Query OK, 0 rows affected (0.00 sec) mysql> CREATE FUNCTION version_tokens_delete RETURNS STRING SONAME 'version_token.so'; Query OK, 0 rows affected (0.00 sec) mysql> CREATE FUNCTION version_tokens_lock_shared RETURNS INT SONAME 'version_token.so'; Query OK, 0 rows affected (0.00 sec) mysql> CREATE FUNCTION version_tokens_lock_exclusive RETURNS INT SONAME 'version_token.so'; Query OK, 0 rows affected (0.00 sec) mysql> CREATE FUNCTION version_tokens_unlock RETURNS INT SONAME 'version_token.so'; Query OK, 0 rows affected (0.00 sec) mysql> SHOW GLOBAL VARIABLES LIKE 'version_token_%'; +-------------------------------+-------+ | Variable_name | Value | +-------------------------------+-------+ | version_tokens_session | | | version_tokens_session_number | 0 | +-------------------------------+-------+ 2 rows in set (0.00 sec)
サーバー側のトークンを設定するにはUDFを使うので、剥き出しで使うにはSELECTステートメントを使う。サーバー側のトークンを設定したり読み出したりするにはSuper権限が必要。
mysql> SELECT version_tokens_set('MySQL=dolphin'); +-------------------------------------+ | version_tokens_set('MySQL=dolphin') | +-------------------------------------+ | 1 version tokens set. | +-------------------------------------+ 1 row in set (0.00 sec) mysql> SELECT version_tokens_show(); +-----------------------+ | version_tokens_show() | +-----------------------+ | MySQL=dolphin; | +-----------------------+ 1 row in set (0.00 sec)
クライアント側のトークンはSETステートメントで指定する…せめてConnector/Cにはmysql_optionsとか無いの?
mysql> SELECT CURRENT_USER(); +----------------+ | CURRENT_USER() | +----------------+ | yoku0825@% | +----------------+ 1 row in set (0.00 sec) mysql> SELECT @@version_tokens_session; +--------------------------+ | @@version_tokens_session | +--------------------------+ | NULL | +--------------------------+ 1 row in set (0.00 sec) mysql> SET version_tokens_session= 'MySQL=sealion!?'; Query OK, 0 rows affected (0.00 sec) mysql> SELECT CURRENT_USER(); ERROR 3136 (42000): Version token mismatch for MySQL. Correct value dolphin mysql> SELECT @@version_tokens_session; ERROR 3136 (42000): Version token mismatch for MySQL. Correct value dolphin
*クライアント側のバージョントークンが指定されていない場合はバージョントークンの比較はされない*
クライアント側でバージョントークンが指定されていて、かつ、サーバーのバージョントークンと違う場合はError: 3136が返される。
権限とかそういうレベルではなく、ステートメントそのものが拒否される状態。
mysql> SET version_tokens_session= 'MySQL=dolphin'; ERROR 3136 (42000): Version token mismatch for MySQL. Correct value dolphin
バージョントークンを設定し直そうとしてもバージョントークンのチェックに引っかかってSETステートメントが転ける。おとなしく繋ぎ直す他にない。
mysql> SET version_tokens_session= 'MariaDB=sealion'; Query OK, 0 rows affected (0.00 sec) mysql> SELECT CURRENT_USER(); ERROR 3137 (42000): Version token MariaDB not found.
存在しないトークンをセットした場合もステートメントが転ける。
最初にチラ見した時に「これ使えば追加要素認証(ユーザー名、パスワードの他にトークンを使う)もできる?」とか思ったけど、クライアント側のトークンをセットしない場合は比較されないし、期待されている値をエラーメッセージに埋め込んでしまうのでそういう用途には使えない。
mysql> SELECT version_tokens_set('MariaDB=sealion'); +---------------------------------------+ | version_tokens_set('MariaDB=sealion') | +---------------------------------------+ | 1 version tokens set. | +---------------------------------------+ 1 row in set (0.00 sec) mysql> SELECT version_tokens_show(); +-----------------------+ | version_tokens_show() | +-----------------------+ | MariaDB=sealion; | +-----------------------+ 1 row in set (0.00 sec) mysql> SELECT version_tokens_edit('MySQL=dolphin'); +--------------------------------------+ | version_tokens_edit('MySQL=dolphin') | +--------------------------------------+ | 1 version tokens updated. | +--------------------------------------+ 1 row in set (0.00 sec) mysql> SELECT version_tokens_show(); +--------------------------------+ | version_tokens_show() | +--------------------------------+ | MariaDB=sealion;MySQL=dolphin; | +--------------------------------+ 1 row in set (0.00 sec)
version_tokens_setだとトークンを追加はできなくて上書かれる。セミコロン区切りで'MySQL=dolphin;MariaDB=sealion'と渡してやるか、version_tokens_editで指定する(editといいつつINSERT .. ON DUPLICATE UPDATEと同じような動き)
mysql> SET version_tokens_session= 'MariaDB=sealion'; Query OK, 0 rows affected (0.00 sec) mysql> SELECT CURRENT_USER(); +----------------+ | CURRENT_USER() | +----------------+ | yoku0825@% | +----------------+ 1 row in set (0.00 sec) mysql> SET version_tokens_session= 'MariaDB=sealion;sushi=beer'; Query OK, 0 rows affected (0.00 sec) mysql> SELECT CURRENT_USER(); ERROR 3137 (42000): Version token sushi not found.
サーバー側に複数のトークンがセットされている場合、クライアントが申告したトークンが全てサーバーに含まれていればステートメントは成功する。要らないものを付けると失敗する。
ドキュメント の例を見る限り、read_onlyを指定できないマルチマスターな環境下でそれでも特定の粒度でマスターを分ける、みたいな感じに使うことを想定されているんだろうか。Group Replicationですかそうですかわかりますん。
ぱっと思い付いたのは、WEBサービスのAPIをバージョンごとに公開している場合なんかにAPIのコードにSET SESSION version_tokens_session= 'v1=true'みたいなのを入れておいて、v2が作られたらサーバー側のトークンを'v1=true;v2=true'にして、v1が消し去られるタイミングでversion_tokens_edit('v1=false')ってやってやると、API v1から来るクエリーだけを転けさせられるようになる、みたいな感じだろうか。
ただ、サーバー側のトークンは揮発性(MySQLの再起動で消える)ので、ちょっと微妙な感じはする。どう使えるだろう。
あとこのプラグインの面白いところは、これAudit PluginなのでAudit Pluginの書き方のサンプルとして面白かった。 このへん。
0 件のコメント :
コメントを投稿