MySQL 8.0 リファレンスマニュアル


MySQL 8.0 リファレンスマニュアル  /  ...  /  部分取消しを使用した権限の制限

6.2.12 部分取消しを使用した権限の制限

MySQL 8.0.16 より前は、特定のスキーマを除き、グローバルに適用される権限を付与することはできません。 MySQL 8.0.16 では、これは partial_revokes システム変数が有効な場合に可能です。 具体的には、グローバルレベルの権限を持つユーザーの場合、partial_revokes では、特定のスキーマの権限を取り消しながら、他のスキーマの権限をそのままにすることができます。 したがって、権限の制限は、グローバル権限を持つが、特定のスキーマへのアクセスを許可しないアカウントの管理に役立つ場合があります。 たとえば、mysql システムスキーマ内のテーブルを除く任意のテーブルの変更をアカウントに許可できます。

注記

簡潔にするために、ここに示す CREATE USER ステートメントにはパスワードは含まれていません。 本番で使用する場合は、常にアカウントパスワードを割り当てます。

部分失効の使用

partial_revokes システム変数は、アカウントに権限制限を設定できるかどうかを制御します。 デフォルトでは、partial_revokes は無効になっており、グローバル権限を部分的に取り消そうとするとエラーが発生します:

mysql> CREATE USER u1;
mysql> GRANT SELECT, INSERT ON *.* TO u1;
mysql> REVOKE INSERT ON world.* FROM u1;
ERROR 1141 (42000): There is no such grant defined for user 'u1' on host '%'

REVOKE 操作を許可するには、partial_revokes を有効にします:

SET PERSIST partial_revokes = ON;

SET PERSIST は、実行中の MySQL インスタンスの値を設定します。 また、値が保存され、その後のサーバーの再起動に引き継がれます。 後続の再起動に引き継ぐことなく、実行中の MySQL インスタンスの値を変更するには、PERSIST ではなく GLOBAL キーワードを使用します。 セクション13.7.6.1「変数代入の SET 構文」を参照してください。

partial_revokes が有効になっている場合、部分的な取消しは成功します:

mysql> REVOKE INSERT ON world.* FROM u1;
mysql> SHOW GRANTS FOR u1;
+------------------------------------------+
| Grants for u1@%                          |
+------------------------------------------+
| GRANT SELECT, INSERT ON *.* TO `u1`@`%`  |
| REVOKE INSERT ON `world`.* FROM `u1`@`%` |
+------------------------------------------+

SHOW GRANTS の出力には、部分的な取消しが REVOKE ステートメントとしてリストされます。 この結果は、world スキーマのテーブルに対して INSERT を実行できないことを除き、u1 にグローバルな SELECT および INSERT 権限があることを示しています。 つまり、u1 による world テーブルへのアクセスは読取り専用です。

サーバーは、部分的な取消しによって実装された権限制限を mysql.user システムテーブルに記録します。 アカウントに部分的な失効がある場合、その User_attributes カラム値には Restrictions 属性があります:

mysql> SELECT User, Host, User_attributes->>'$.Restrictions'
       FROM mysql.user WHERE User_attributes->>'$.Restrictions' <> '';
+------+------+------------------------------------------------------+
| User | Host | User_attributes->>'$.Restrictions'                   |
+------+------+------------------------------------------------------+
| u1   | %    | [{"Database": "world", "Privileges": ["INSERT"]}] |
+------+------+------------------------------------------------------+
注記

部分的な取消しは任意のスキーマに適用できますが、mysql システムスキーマに対する権限制限は、通常のアカウントがシステムアカウントを変更できないようにする戦略の一環として特に役立ちます。 通常アカウントによる操作からのシステムアカウントの保護を参照してください。

部分的な取消し操作には、次の条件があります:

  • 部分的な取消しでは、スキーマに文字どおりの名前を付ける必要があります。 % または_ SQL ワイルドカード文字 (myschema% など) を含むスキーマ名は使用できません。

  • 部分的な取消しを使用して、存在しないスキーマに制限を設定できますが、取り消す権限がグローバルに付与されている場合のみです。 権限がグローバルに付与されていない場合、存在しないスキーマに対して権限を取り消すとエラーが発生します。

  • 部分的な取消しはスキーマレベルでのみ適用されます。 部分取消しは、グローバルにのみ適用される権限 (FILEBINLOG_ADMIN など)、またはテーブル、カラムまたはルーチン権限には使用できません。

前述のように、スキーマレベルの権限の部分的な取消しは、SHOW GRANTS 出力に REVOKE ステートメントとして表示されます。 これは、SHOW GRANTS「プレーン」スキーマレベルの権限を表す方法とは異なります:

  • 付与されると、スキーマレベルの権限は、出力内の独自の GRANT ステートメントによって表されます:

    mysql> CREATE USER u1;
    mysql> GRANT UPDATE ON mysql.* TO u1;
    mysql> GRANT DELETE ON world.* TO u1;
    mysql> SHOW GRANTS FOR u1;
    +---------------------------------------+
    | Grants for u1@%                       |
    +---------------------------------------+
    | GRANT USAGE ON *.* TO `u1`@`%`        |
    | GRANT UPDATE ON `mysql`.* TO `u1`@`%` |
    | GRANT DELETE ON `world`.* TO `u1`@`%` |
    +---------------------------------------+
  • 取り消すと、スキーマレベルの権限は単に出力から消えます。 これらは REVOKE ステートメントとしては表示されません:

    mysql> REVOKE UPDATE ON mysql.* FROM u1;
    mysql> REVOKE DELETE ON world.* FROM u1;
    mysql> SHOW GRANTS FOR u1;
    +--------------------------------+
    | Grants for u1@%                |
    +--------------------------------+
    | GRANT USAGE ON *.* TO `u1`@`%` |
    +--------------------------------+

ユーザーが権限を付与すると、権限受領者がその権限を持たない権限をすでに持っていないかぎり、権限受領者はその権限を継承します。 次の 2 人のユーザーについて考えてみます。いずれかのユーザーにグローバル SELECT 権限があります:

CREATE USER u1, u2;
GRANT SELECT ON *.* TO u2;

管理ユーザー admin に、グローバルだが部分的に取り消された SELECT 権限があるとします:

mysql> CREATE USER admin;
mysql> GRANT SELECT ON *.* TO admin WITH GRANT OPTION;
mysql> REVOKE SELECT ON mysql.* FROM admin;
mysql> SHOW GRANTS FOR admin;
+------------------------------------------------------+
| Grants for admin@%                                   |
+------------------------------------------------------+
| GRANT SELECT ON *.* TO `admin`@`%` WITH GRANT OPTION |
| REVOKE SELECT ON `mysql`.* FROM `admin`@`%`          |
+------------------------------------------------------+

admin によって SELECTu1 および u2 にグローバルに付与される場合、結果はユーザーごとに異なります:

  • adminSELECT 権限を持たない u1SELECT をグローバルに付与する場合、u1admin 権限制限を継承します:

    mysql> GRANT SELECT ON *.* TO u1;
    mysql> SHOW GRANTS FOR u1;
    +------------------------------------------+
    | Grants for u1@%                          |
    +------------------------------------------+
    | GRANT SELECT ON *.* TO `u1`@`%`          |
    | REVOKE SELECT ON `mysql`.* FROM `u1`@`%` |
    +------------------------------------------+
  • 一方、u2 は制限なしでグローバル SELECT 権限をすでに保持しています。 GRANT は、権限受領者の既存の権限にのみ追加でき、権限を減らすことはできないため、adminSELECTu2 にグローバルに付与する場合、u2admin の制限を継承しません:

    mysql> GRANT SELECT ON *.* TO u2;
    mysql> SHOW GRANTS FOR u2;
    +---------------------------------+
    | Grants for u2@%                 |
    +---------------------------------+
    | GRANT SELECT ON *.* TO `u2`@`%` |
    +---------------------------------+

GRANT ステートメントに AS user 句が含まれている場合、適用される権限制限は、ステートメントを実行するユーザーではなく、句で指定されたユーザー/ロールの組合せに対する権限制限です。 AS 句の詳細は、セクション13.7.1.6「GRANT ステートメント」 を参照してください。

アカウントに付与される新しい権限の制限は、そのアカウントの既存の制限に追加されます:

mysql> CREATE USER u1;
mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO u1;
mysql> REVOKE INSERT ON mysql.* FROM u1;
mysql> SHOW GRANTS FOR u1;
+---------------------------------------------------------+
| Grants for u1@%                                         |
+---------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO `u1`@`%` |
| REVOKE INSERT ON `mysql`.* FROM `u1`@`%`                |
+---------------------------------------------------------+
mysql> REVOKE DELETE, UPDATE ON db2.* FROM u1;
mysql> SHOW GRANTS FOR u1;
+---------------------------------------------------------+
| Grants for u1@%                                         |
+---------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO `u1`@`%` |
| REVOKE UPDATE, DELETE ON `db2`.* FROM `u1`@`%`          |
| REVOKE INSERT ON `mysql`.* FROM `u1`@`%`                |
+---------------------------------------------------------+

権限制限の集計は、権限が明示的に明示的に取り消された場合 (前述のとおり)、およびステートメントを実行するユーザーまたは AS user 句に指定されたユーザーから制限が暗黙的に継承された場合の両方に適用されます。

アカウントにスキーマに対する権限制限がある場合:

  • アカウントは、制限付きスキーマまたはその中のオブジェクトに対する権限を他のアカウントに付与することはできません。

  • 制限のない別のアカウントは、制限付きスキーマまたはその中のオブジェクトの制限付きアカウントに権限を付与できます。 無制限のユーザーが次のステートメントを実行するとします:

    CREATE USER u1;
    GRANT SELECT, INSERT, UPDATE ON *.* TO u1;
    REVOKE SELECT, INSERT, UPDATE ON mysql.* FROM u1;
    GRANT SELECT ON mysql.user TO u1;          -- grant table privilege
    GRANT SELECT(Host,User) ON mysql.db TO u1; -- grant column privileges

    結果のアカウントには次の権限があり、制限付きスキーマ内で制限付き操作を実行できます:

    mysql> SHOW GRANTS FOR u1;
    +-----------------------------------------------------------+
    | Grants for u1@%                                           |
    +-----------------------------------------------------------+
    | GRANT SELECT, INSERT, UPDATE ON *.* TO `u1`@`%`           |
    | REVOKE SELECT, INSERT, UPDATE ON `mysql`.* FROM `u1`@`%`  |
    | GRANT SELECT (`Host`, `User`) ON `mysql`.`db` TO `u1`@`%` |
    | GRANT SELECT ON `mysql`.`user` TO `u1`@`%`                |
    +-----------------------------------------------------------+

アカウントにグローバル権限の制限がある場合、その制限は次のいずれかのアクションによって削除されます:

  • 権限に対する制限のないアカウントによるアカウントへの権限のグローバルな付与。

  • スキーマレベルでの権限の付与。

  • 権限をグローバルに取り消します。

複数の権限をグローバルに保持しているが、INSERTUPDATE および DELETE に制限があるユーザー u1 について考えてみます:

mysql> CREATE USER u1;
mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO u1;
mysql> REVOKE INSERT, UPDATE, DELETE ON mysql.* FROM u1;
mysql> SHOW GRANTS FOR u1;
+----------------------------------------------------------+
| Grants for u1@%                                          |
+----------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO `u1`@`%`  |
| REVOKE INSERT, UPDATE, DELETE ON `mysql`.* FROM `u1`@`%` |
+----------------------------------------------------------+

制限のないアカウントから u1 にグローバルに権限を付与すると、権限制限が削除されます。 たとえば、INSERT の制限を削除するには:

mysql> GRANT INSERT ON *.* TO u1;
mysql> SHOW GRANTS FOR u1;
+---------------------------------------------------------+
| Grants for u1@%                                         |
+---------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO `u1`@`%` |
| REVOKE UPDATE, DELETE ON `mysql`.* FROM `u1`@`%`        |
+---------------------------------------------------------+

スキーマレベルで u1 に権限を付与すると、権限の制限がなくなります。 たとえば、UPDATE の制限を削除するには:

mysql> GRANT UPDATE ON mysql.* TO u1;
mysql> SHOW GRANTS FOR u1;
+---------------------------------------------------------+
| Grants for u1@%                                         |
+---------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO `u1`@`%` |
| REVOKE DELETE ON `mysql`.* FROM `u1`@`%`                |
+---------------------------------------------------------+

グローバル権限を取り消すと、その権限に対する制限も含めて権限が削除されます。 たとえば、DELETE の制限を削除するには、次のようにします (すべての DELETE アクセスを削除します):

mysql> REVOKE DELETE ON *.* FROM u1;
mysql> SHOW GRANTS FOR u1;
+-------------------------------------------------+
| Grants for u1@%                                 |
+-------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE ON *.* TO `u1`@`%` |
+-------------------------------------------------+

アカウントにグローバルレベルとスキーマレベルの両方の権限がある場合、部分的な取消しを有効にするには、スキーマレベルで 2 回取り消す必要があります。 u1 に次の権限があり、INSERT がグローバルおよび world スキーマの両方で保持されているとします:

mysql> CREATE USER u1;
mysql> GRANT SELECT, INSERT ON *.* TO u1;
mysql> GRANT INSERT ON world.* TO u1;
mysql> SHOW GRANTS FOR u1;
+-----------------------------------------+
| Grants for u1@%                         |
+-----------------------------------------+
| GRANT SELECT, INSERT ON *.* TO `u1`@`%` |
| GRANT INSERT ON `world`.* TO `u1`@`%`   |
+-----------------------------------------+

worldINSERT を取り消すと、スキーマレベルの権限が取り消されます (SHOW GRANTS にはスキーマレベルの GRANT ステートメントは表示されなくなります):

mysql> REVOKE INSERT ON world.* FROM u1;
mysql> SHOW GRANTS FOR u1;
+-----------------------------------------+
| Grants for u1@%                         |
+-----------------------------------------+
| GRANT SELECT, INSERT ON *.* TO `u1`@`%` |
+-----------------------------------------+

worldINSERT を再度取り消すと、グローバル権限の部分的な取消しが実行されます (SHOW GRANTS にはスキーマレベルの REVOKE ステートメントが含まれるようになりました):

mysql> REVOKE INSERT ON world.* FROM u1;
mysql> SHOW GRANTS FOR u1;
+------------------------------------------+
| Grants for u1@%                          |
+------------------------------------------+
| GRANT SELECT, INSERT ON *.* TO `u1`@`%`  |
| REVOKE INSERT ON `world`.* FROM `u1`@`%` |
+------------------------------------------+

部分的な取消しと明示的なスキーマ付与

一部のスキーマのアカウントへのアクセスを提供し、他のスキーマのアカウントへのアクセスを提供するために、部分的な取消しでは、グローバル権限を付与せずにスキーマレベルのアクセス権を明示的に付与する方法の代替方法が提供されます。 2 つのアプローチには、長所と短所があります。

グローバル権限ではなく、スキーマレベルの権限を付与します:

  • 新規スキーマの追加: デフォルトでは、スキーマには既存のアカウントからアクセスできません。 スキーマにアクセスできるアカウントの場合、DBA はスキーマレベルのアクセス権を付与する必要があります。

  • 新規アカウントの追加: DBA は、アカウントがアクセスできるスキーマごとにスキーマレベルのアクセス権を付与する必要があります。

部分的な取消しと組み合せたグローバル権限の付与:

  • 新規スキーマの追加: スキーマは、グローバル権限を持つ既存のアカウントからアクセスできます。 スキーマにアクセスできないアカウントの場合、DBA は部分的な取消しを追加する必要があります。

  • 新規アカウントの追加: DBA は、グローバル権限に加えて、各制限付きスキーマに対する部分的な取消しを付与する必要があります。

明示的なスキーマレベルの付与を使用するアプローチは、アクセスがいくつかのスキーマに制限されているアカウントでは便利です。 部分的な取消しを使用するアプローチは、少数を除くすべてのスキーマへの広範なアクセス権を持つアカウントではより便利です。

部分失効の無効化

一度有効にすると、アカウントに権限制限がある場合は partial_revokes を無効にできません。 そのようなアカウントが存在する場合、partial_revokes の無効化は失敗します:

  • 起動時に partial_revokes を無効にしようとすると、サーバーはエラーメッセージをログに記録し、partial_revokes を有効にします。

  • 実行時に partial_revokes を無効にしようとすると、エラーが発生し、partial_revokes 値は変更されません。

制限が存在する場合に partial_revokes を無効にするには、最初に制限を削除する必要があります:

  1. 部分的な失効があるアカウントを判別します:

    SELECT User, Host, User_attributes->>'$.Restrictions'
    FROM mysql.user WHERE User_attributes->>'$.Restrictions' <> '';
  2. このようなアカウントごとに、その権限制限を削除します。 前のステップで、アカウント u1 に次の制限があるとします:

    [{"Database": "world", "Privileges": ["INSERT", "DELETE"]

    制限の削除は様々な方法で実行できます:

    • 制限なしで権限をグローバルに付与します:

      GRANT INSERT, DELETE ON *.* TO u1;
    • スキーマレベルで権限を付与します:

      GRANT INSERT, DELETE ON world.* TO u1;
    • 権限をグローバルに取り消します (不要になった場合):

      REVOKE INSERT, DELETE ON *.* FROM u1;
    • アカウント自体を削除します (不要になった場合):

      DROP USER u1;

すべての権限制限を削除した後、部分的な取消しを無効にできます:

SET PERSIST partial_revokes = OFF;

部分的な取消しとレプリケーション

レプリケーションシナリオでは、partial_revokes が任意のホストで有効になっている場合、すべてのホストで有効にする必要があります。 それ以外の場合、グローバル権限を部分的に取り消す REVOKE ステートメントは、レプリケーションが発生するすべてのホストで同じ効果がないため、レプリケーションの不整合またはエラーが発生する可能性があります。


関連キーワード:  権限, スキーマ, アカウント, 制限, GRANT, INSERT, 部分, REVOKE, 付与, グローバル