MySQL道普請便り

第269回SUPER権限のその――MySQL 8.4/9.x時代の権限設計を見直す

MySQLの管理者権限といえば、やはりSUPERを思い浮かべる方が多いのではないかと思います。実際、少し前までの運用では、管理系の操作が必要になったときに「とりあえずSUPERを付ける」という場面はそれなりにあったはずです。

ただ、MySQL 8.4や9.xの時代に入ると、このあたりは少し整理し直したほうがよさそうです。MySQL 8.0以降では、以前SUPERがまとめて担っていたような役割が、かなり細かい権限に分かれてきているためです。代表的なものとしては、SYSTEM_VARIABLES_ADMIN、CONNECTION_ADMIN、SYSTEM_USER、ROLE_ADMIN、BINLOG_ADMIN、PERSIST_RO_VARIABLES_ADMIN、SET_ANY_DEFINER、ALLOW_NONEXISTENT_DEFINERなどがあります。

ここで大事なのは、SUPERは単に「昔ながらの強い権限」というだけではないことです。MySQLの公式マニュアルでは、SUPERはすでに非推奨とされており、将来のMySQLで削除される予定だと案内されています。つまり、これから権限設計を考えるなら、⁠まだ使えるから使う」というより、⁠消える前提でどう移していくか」を考えたほうがよい段階に来ています。

本稿では、SUPERに頼る前提から少し離れて、MySQL 8.4/9.xではどういうふうに権限設計を考えるとよさそうか、いくつかの例を見ながら整理してみます。

SUPER権限

SUPERが長く使われてきたのは、単純に便利だったからだと思います。管理系の操作をいろいろまとめて許可できるので、アカウント設計を細かく考えなくても、とりあえず作業は進みます。

ただ、その便利さの裏側では、本当はそこまで強い権限がいらないユーザーにも、かなり広い権限を渡してしまいやすい、という問題がありました。必要最小限の権限で設計したいと思っても、昔はあまりきれいに分けられなかったわけです。

その点、最近のMySQLでは、管理系の権限がかなり細かく分かれています。これは少し面倒に見える反面、設計としてはむしろやりやすくなっています。たとえば「システム変数の変更はさせたいが、接続制御まではさせたくない」とか、⁠アカウント管理はさせたいが、重要なシステムアカウントまでは触らせたくない」といったことを、以前よりだいぶ表現しやすくなりました。

なので、いま考えるべきなのは、⁠SUPERの代わりになる何か1個を探すこと」ではないはずです。そうではなくて、管理作業を少し分解して、それぞれに必要な権限をあてていくことだと思います。

システム変数

比較的わかりやすいのが、システム変数の変更です。以前は、運用担当者にパラメータ変更をさせたいとなると、かなり雑にSUPERを付けていたケースもあったのではないでしょうか。

現在は、このあたりをSYSTEM_VARIABLES_ADMINで考えられます。少なくとも、⁠グローバルなシステム変数を変更できるようにしたい」という目的に対しては、昔よりずっとまっすぐ権限を当てられるようになっています。MySQLのマニュアルでも、制限付きシステム変数の変更にはSYSTEM_VARIABLES_ADMINなどの適切な権限が必要であることが整理されています。

たとえば、実行時のパラメータ変更を行う運用担当向けには、次のようにロールを切り出せます。

CREATE ROLE role_ops_runtime;
GRANT SYSTEM_VARIABLES_ADMIN, CONNECTION_ADMIN ON *.* TO role_ops_runtime;

CREATE USER 'ops'@'10.%' IDENTIFIED BY 'strong-password';
GRANT role_ops_runtime TO 'ops'@'10.%';
SET DEFAULT ROLE role_ops_runtime TO 'ops'@'10.%';

ここではCONNECTION_ADMINも付けていますが、これは環境によっては不要かもしれません。たとえば本当に変数変更だけでよければ、そこまで持たせない設計もあると思います。逆に、保守作業の中で接続まわりの操作も想定するなら必要になることもあります。

このあたりで大事なのは、SUPERのときのように全部まとめて考えないことです。何をさせたいのかを少し切り分けるだけで、必要な権限の見え方がかなり変わってきます。

接続制御

実際に運用していると、設定変更と接続制御は同じではない、と感じる場面があると思います。たとえばoffline_modeのような操作は、単なるパラメータ変更というより、サービスの受け方に直接関わるものです。

この点は、権限の上でも分かれてきています。まず、グローバルなシステム変数を変更するには、基本的にSYSTEM_VARIABLES_ADMINが必要です。そしてoffline_mode=ONのように、接続の受け付け方そのものに関わる操作については、これに加えてCONNECTION_ADMINも関係します。MySQLの権限一覧でも、CONNECTION_ADMINは接続関連の制限を回避したり、offline_modeを有効にしたりするための権限として説明されています。

つまり、ここでは少なくとも2つの責務があります。1つは「システム変数を変更できること」で、これはSYSTEM_VARIABLES_ADMINの領域です。もう1つは「接続制御に関わる強い操作ができること」で、こちらはCONNECTION_ADMINの領域です。昔はこれらをSUPERがまとめて抱えていたため、あまり意識せず同じ箱で扱っていたかもしれません。実際、以前はoffline_mode有効時にもSUPERを持つ接続は影響を受けず、新規接続も許可される形でした。現在はその役割がCONNECTION_ADMINに整理されています。

これは少し地味ですが、運用上はかなり大きい変化だと思います。障害対応で一時的に接続制御まで必要な人、日常的な設定調整だけをする人、基盤全体を管理する人は、本来同じ権限でなくてもよいからです。SUPER1つでまとめてしまうと、その違いが見えにくくなります。逆に、SYSTEM_VARIABLES_ADMINとCONNECTION_ADMINを分けて考えると、⁠この人は実行時パラメータまでは触れるが、接続制御まではできない」といった線引きがしやすくなります。

SYSTEM_USER

SYSTEM_USERはユーザーアカウントカテゴリを分類するための権限です。権限を持つユーザーはシステムユーザー、持たないユーザーは通常のユーザーとして扱われ、他のアカウントに対して行える操作が変わってきます。

たとえば、CREATE USERやGRANTができるアカウントがあったとしても、それだけで重要なシステムアカウントまで自由に触れてしまうのは、あまりうれしくありません。複数チームで運用している環境なら、なおさらです。

そこでSYSTEM_USERを使うと、通常の運用アカウントと、基盤側の重要なアカウントを分けて扱いやすくなります。つまり、アカウント管理そのものにも段差をつけられるわけです。アカウントカテゴリの仕組みとしても、システムアカウントを通常アカウントとは分けて扱う考え方がマニュアルで説明されています。

CREATE ROLE role_platform_admin;
GRANT CREATE USER, SYSTEM_USER ON *.* TO role_platform_admin;

CREATE USER 'platform_admin'@'localhost' IDENTIFIED BY 'strong-password';
GRANT role_platform_admin TO 'platform_admin'@'localhost';
SET DEFAULT ROLE role_platform_admin TO 'platform_admin'@'localhost';

こういう分け方をしておくと、⁠触らないでください」という運用ルールだけで守るよりはかなり安全です。そもそも触れないようにしておけるからです。

SYSTEM_USERの詳細については以下をご覧ください。

DEFINER

権限の見直しが効いてくるのは、定常運用だけではありません。移行や復元のような作業でも、強い権限をどう扱うかは意外と重要です。

わかりやすいのが、DEFINERを持つオブジェクトです。ビュー、ストアドルーチン、トリガー、イベントなどを別環境に持っていくと、DEFINERに指定されたアカウントが復元先に存在しない、といったことが起きます。実際、ここでハマったことがある方も多いのではないでしょうか。

こういう場面で、昔の感覚のままSUPERで通してしまうと、移行用のアカウントが必要以上に強くなりがちです。8.0であれば、SET_USER_ID、8.4以降であれば、SET_ANY_DEFINERやALLOW_NONEXISTENT_DEFINERを移行用のロールに分けておくほうが、だいぶ整理しやすいと思います。

CREATE ROLE role_definer_migration;
GRANT SET_ANY_DEFINER, ALLOW_NONEXISTENT_DEFINER ON *.* TO role_definer_migration;

CREATE USER 'schema_migrator'@'192.168.%' IDENTIFIED BY 'strong-password';
GRANT CREATE, ALTER, DROP, CREATE ROUTINE, ALTER ROUTINE, EXECUTE ON appdb.* TO 'schema_migrator'@'192.168.%';
GRANT role_definer_migration TO 'schema_migrator'@'192.168.%';
SET DEFAULT ROLE role_definer_migration TO 'schema_migrator'@'192.168.%';

普段はいらないが、特定の作業では必要になる権限は意外とあります。そういうものほど、常設の強い管理権限に混ぜないほうがよさそうです。

PERSIST

もう1つ、見直しておきたいのが、実行時変更と永続化の違いです。SET GLOBALでその場の挙動を変えるのと、SET PERSISTで再起動後にも残るようにするのとでは、運用上の意味がかなり違います。

障害対応や一時的な性能調整で、その場だけ設定を変えたいことはあります。ただ、その変更が今後の再起動後も残ってよいかというと、必ずしもそうではありません。ここを同じ権限で扱うと、少し危うい場面が出てきます。

そこで、実行時変更用と、永続化までできるロールを分ける考え方が出てきます。

CREATE ROLE role_runtime_tuner;
GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO role_runtime_tuner;

CREATE ROLE role_persist_tuner;
GRANT SYSTEM_VARIABLES_ADMIN, PERSIST_RO_VARIABLES_ADMIN ON *.* TO role_persist_tuner;

こうしておくと、その場の調整はできるが、将来にも影響する設定までは変えられない、という役割を作れます。本番運用では、この違いはわりと大きいと思います。

SUPER権限棚卸し

SUPER権限から脱却するために何から始めるのがよいでしょうか。結局のところ、まずはSUPERを持っているアカウントを確認するところからだと思います。

しかもこれは、単なる整理ではなく、将来の削除に備える作業でもあります。公式マニュアルでも、SUPERを持つアカウントを洗い出し、適切な動的権限へ移行するよう案内されています。つまり、いまSUPERを棚卸しすること自体が、そのまま将来対応になります。

大事なのは、⁠このアカウントは何のためにSUPERを持っているのか」をちゃんと見ることです。設定変更がしたいだけなのか、接続制御も必要なのか、アカウント管理をしたいのか、移行作業専用なのか。目的を分けてみると、意外とSUPERである必要がないケースは多いはずです。

権限の確認にはSHOW GRANTSが便利です。

SHOW GRANTS FOR 'legacy_admin'@'%';
SHOW GRANTS FOR 'ops'@'10.%';
SHOW GRANTS FOR 'schema_migrator'@'192.168.%';

もちろん、いきなり全部置き換えるのは現実的ではないかもしれません。ただ、新しいアカウントではSUPERを使わないようにする、既存のものは用途ごとに少しずつ必要な権限だけを付与する、という進め方ならやりやすいのではないかと思います。

おわりに

SUPERは便利ですし、これまで長く使われてきた理由もよくわかります。ただ、SUPERにはあまりにも多くの権限が集約されてされておりとりあえずの管理者権限としては過剰な場合が多いです。

しかもSUPERはすでに非推奨で、将来のバージョンでは削除予定です。そう考えると、もはや「まだ使えるから当面このままでよい」とは言いにくくなっています。権限設計としても、運用の見通しとしても、早めに分解しておいたほうがよさそうです。

8.4/9.xの権限設計で大事なのは、⁠強い管理者を一人作る」ことよりも、⁠役割ごとに権限を分ける」ことです。設定変更、接続制御、アカウント管理、移行作業、永続化設定といったものを、少しずつ分けて考えるだけでも、権限の見通しはかなりよくなります。

アップグレードというと、新機能や非互換に目が向きがちです。ただ、そのタイミングは運用の前提を見直す機会でもあります。もしSUPERが惰性で残っているなら、この機会に一度棚卸ししてみるのは悪くないはずです。SUPERのその後を考えることは、そのまま、これからのMySQL運用を整えることにもつながるのではないでしょうか。

MySQLで提供されている権限については以下をご覧ください。

おすすめ記事

記事・ニュース一覧