はじめに
アクセスコントロールとユーザー管理は、システム内のユーザー数や異なるデータベースエンティティが増えるにつれて、急速に複雑になる可能性のある2つの領域です。さまざまなデータベースオブジェクトに対する多数の異なる権限を管理し、同じ責任を持つユーザーが同じレベルのアクセスを持つことを保証し、アクセスを監査して制限することは、時間が経つにつれてすべて難しくなります。
この問題に対処するため、MySQLには「ロール」という概念があり、複数の権限の束を特定の名前でグループ化し、設定を一括で割り当てたり変更したりできます。このガイドでは、MySQL内でロールがどのように機能するか、そしてユーザーのデータアクセス管理を容易にするためにそれらをどのように使用するかについて説明します。
コマンド
MySQLのロール管理に関連して議論する主要なSQLコマンドを以下に示します。
CREATE ROLE
:CREATE ROLE
コマンドは、データベースシステム内で新しいロールを定義します。DROP ROLE
:DROP ROLE
コマンドは、その逆を行い、既存のロールを削除します。GRANT
:GRANT
コマンドには、ロールに関連して2つの異なる目的があります。ロールに権限を追加することと、ユーザーアカウントをロールのメンバーとして追加することです。REVOKE
: ロールのコンテキストでは、REVOKE
コマンドはロールから権限を削除し、ユーザーアカウントからロールのメンバーシップも削除します。SHOW GRANTS
:SHOW GRANTS
コマンドは、指定されたユーザーアカウントまたはロールの権限を表示します。SET ROLE
:SET ROLE
コマンドは、ユーザーアカウントが現在アクティブに使用しているロールを変更します。これにより、セッションに適用される権限のセットを指示できます。SET DEFAULT ROLE
:SET DEFAULT ROLE
コマンドは、クライアントが特定のユーザーアカウントとしてログインしたときに自動的に適用されるロールを定義します。
必要な権限
このガイドに従うには、以下の権限が必要です
CREATE ROLE
GRANT OPTION
CREATE USER
(他のユーザーのデフォルトロールを設定するため)ROLE_ADMIN
(ロールの動作を変更するシステム変数を設定するため)SYSTEM_VARIABLES_ADMIN
(ロールの動作を変更するシステム変数を設定するため)
CREATE ROLE
権限は、ロールを作成および管理できるCREATE USER
権限の下位バージョンです。CREATE USER
権限を既に持っているアカウントは、ロールを管理するために必要なすべての機能を自動的に持っています。
ロールに権限を割り当てるには、GRANT OPTION
権限が必要です。ロールに割り当てたいすべての権限について、GRANT OPTION
を有効にする必要があります。
ロールとは?
MySQLでは、ロールは、権限のコンテナまたはコレクションとして機能するエンティティです。管理者は、ユーザーアカウントに権限を割り当てるのと同じ方法で、ロールに権限を割り当てることができます。その後、ユーザーアカウントをロールのメンバーとして追加し、それらのアカウントがロールに関連付けられた権限にアクセスできるようにすることができます。
基本的に、ロールは異なる関連する権限をまとめて権限管理を容易にする方法として機能します。個々の権限を割り当てることによって各ユーザーが必要とする正確なアクセスレベルを持っていることを確認する代わりに、名前付きの権限グループを使用することで、より少なく、理解しやすい割り当てを管理できます。
これにより、アクセスレベルを割り当てる際に明確な利点があります。数十の権限を個別に管理するよりも、ユーザーにdeveloper
、sysadmin
、またはfinanceteam
のロールを割り当てる方が簡単だからです。また、複数のアカウントへのアクセスを一度に素早く調整できます。営業チーム用に新しいデータベースを作成する場合、アクセス権を持つべきすべてのアカウントを追跡する代わりに、salesteam
ロールにアクセス権を付与できます。
ロールの作成
CREATE ROLE
権限を持つアカウントがある場合、CREATE ROLE
コマンドを使用してロールを管理できます。
MySQLのロールの構文とは?
MySQLがロール名を有効と見なすには、特定の形式に従う必要があります。多くの場合、これらはMySQLユーザーアカウントを定義するために使用される形式を反映していますが、いくつかの重要な違いがあります。
ロールは以下の形式に従います
'<role>'@'<host>'
ユーザーと同様に、ロールにはロール名とクライアントが接続しているホストの2つのコンポーネントがあります。ただし、MySQLがこれらのコンポーネントを解釈する方法は異なります。
ロールの場合、名前の'<role>'
部分は空白であってはなりません。ユーザーの場合のような「匿名」のロールという概念はありません。一方、'<host>'
部分を省略することは依然として許可されており、MySQLはホストとして%
を使用します。ただし、このコンテキストでの%
は、ワイルドカードではなく、リテラル文字として解釈されます。
事実上、これはロール名が表面上はユーザーアカウント名と同じ形式を共有しているにもかかわらず、ユーザーアカウントのようにいかなる種類の評価も受けず、2つのコンポーネントを持つ単なるラベルであることを意味します。名前が2つの部分を持つ理由は、ユーザーとしてもロールとしても機能できるユーザーアカウントを作成できるためです。ユーザーとして使用される場合、コンポーネントはユーザー管理の記事で説明されている特別な評価ルールに従い、ロールとして使用される場合、名前はリテラルコンポーネント名を使用して直接一致されます。
これらの規則のため、多くの場合、管理者は'<role>'
コンポーネントのみを使用してロールを定義することを選択します。これにより、MySQLは'<host>'
コンポーネントをリテラルな%
文字に置換し、結果としてその名前の部分が不可視で重要ではないものになります。名前をユーザーアカウントとロールの両方として使用する意図がない場合でも、同様に行うことができます。
ロールを作成するには?
新しいロールを作成するには、CREATE ROLE
コマンドを使用します。
基本的な構文は次のようになります
CREATE ROLE '<role>'@'<host>';
各ロール名をコンマで区切って、複数のロールを同時に作成することもできます
CREATE ROLE '<role_1>'@'<host>', '<role_2>'@'<host>', '<role_3>'@'<host>';
指定したロールのいずれかがシステムに既に存在する場合、コマンドはエラーで失敗します。
これを回避し、MySQLに警告のみを発行させるには、ロール名の前にCREATE ROLE
コマンドの後にIF NOT EXISTS
句を含めることができます
CREATE ROLE IF NOT EXISTS '<role>'@'<host>';
前述のとおり、多くの場合、管理者は簡素化のためにロール名の'<host>'
部分を省略し、暗黙的にリテラルな%
文字に設定します。そのため、実際には、多くのロール作成コマンドは次のようになるでしょう
CREATE ROLE '<role>';
ロールに権限を付与するには?
新しいロールを作成したら、通常、次に優先すべきことは、それらに権限を付与して意味のあるものにすることです。
ロールに権限を付与する方法は、ユーザーアカウントに権限を付与するのと同じです。付与したい正確な権限を指定し、その権限が有効なデータベースとデータベースオブジェクトを提供してスコープを指定し、そして権限が付与されるべきエンティティ(この場合はロール)を指定します
GRANT <privileges> ON <database>.<object> TO '<role>'@'<host>';
例えば、appdb
データベースとその中のすべてのオブジェクトに対して、readapp
というロールにSELECT
権限を付与するには、次のように入力します
GRANT SELECT ON appdb.* TO 'readapp';
同様に、writeapp
というロールに同じデータベースへの書き込み権限を付与するには、次のように入力します
GRANT SELECT,INSERT,UPDATE,DELETE ON appdb.* TO 'writeapp';
ユーザーアカウントに直接行うのとまったく同じように、ロールに権限を付与したり、ロールから権限を取り消したりできます。したがって、提供したいアクセスレベルを調整する必要がある場合は、ロールに関連付けられた権限をいつでも変更できます。
ユーザーにロールのメンバーシップを付与するには?
ロールに権限を追加したら、次にメンバーをロールに追加して、関連する権限を付与できます。
これを行うために、MySQLはユーザーやロールに権限を付与するのに使用するのと同じGRANT
の別の形式を使用します。ただし、この新しい形式では、ロールをユーザーに追加し、ユーザーアカウントがロールに与えられたすべての権限にアクセスできるようにします。
基本的な構文は次のようになります
GRANT '<role>'@'<host>' TO '<user>'@'<host>';
例えば、'reports'@'localhost'
ユーザーがレポートを生成するためにappdb
データベースからデータを読み取る必要がある場合、そのユーザーアカウントにreadapp
ロールを追加し、選択権限を付与できます
GRANT 'readapp' TO 'reports'@'localhost';
同様に、'appuser'@'localhost'
に同じデータベース内のデータを管理する機能を与えるには、そのユーザーをwriteapp
ロールのメンバーにすることができます
GRANT 'writeapp' TO 'appuser'@'localhost';
'appuser'@'localhost'
アカウントは、データベースへのデータの挿入、更新、および削除ができるようになります。writeapp
ロールに新しい権限が追加された場合、'appuser'@'localhost'
アカウントは直ちにそれらの権限を取得します。
すべてのユーザーに特定のロールを自動的に付与するには?
システム上のすべてのユーザーにアクセスさせたいロールがある場合があります。mandatory_roles
変数を設定することで、各アカウントに自動的に付与されるロールを定義できます。
mandatory_roles
変数を変更するには、ユーザーはROLE_ADMIN
およびSYSTEM_VARIABLES_ADMIN
権限を持っている必要があります。すべてのユーザーに与えたいロールを設定するには、次のように入力します
SET PERSIST mandatory_roles = '`<role_1>`@`<host>`, `<role_2>`@`<host>`, `<role_3>`@`<host>`';
ここでは、システム上の各ユーザーに自動的に3つのロールを与えます。システム変数を設定する際、mandatory_roles
の値は文字列である必要があるため、ロールリスト全体をシングルクォートで囲み、個々のロールコンポーネントをバッククォートで囲みます。
SYSTEM_USER
権限を持つロールをmandatory_roles
リストに追加することはできません。これは、システム上のすべてのセッションが自動的にシステムセッションになることを防ぐためのセキュリティ対策です。
ロールから権限を使用するには?
ユーザーアカウントにロールのメンバーシップを付与したら、どのようにそれらを使用しますか?ロールによってアカウントに付与された権限にアクセスするには、それをアクティブ化する必要があります。
現在アクティブなロールを表示する
新しいロールをアクティブ化する前に、現在のユーザーセッションでどのロールがアクティブになっているかを確認できます。
セッションのアクティブなロールを表示するには、次のように入力します
SELECT CURRENT_ROLE()
出力には、現在のセッションでアクティブな1つ以上のロールが表示されます。これらのロールに関連付けられた権限は、実行が許可されているアクションに追加されます。
セッションのロールをアクティブ化する方法
セッション中にアクティブなロールを変更するには、SET ROLE
コマンドを使用します。このコマンドはさまざまな方法で使用できます。
基本的な構文は次のようになります
SET ROLE '<rolename>'@'<host>';
これにより、対象のロールがアクティブ化されます。SET ROLE
コマンドで言及されていない以前アクティブだったロールは、現在非アクティブ化されることに注意することが重要です。
複数のロールを一度にアクティブ化するには、各ロールをコンマで区切ります
SET ROLE '<role_1>'@'<host>', '<role_2>'@'<host>', '<role_3>'@'<host>';
アカウントに付与されているすべてのロールをアクティブ化するには、特定のロールの代わりにALL
を指定できます
SET ROLE ALL;
また、ALL EXCEPT
を使用して、特定の例外を除いてすべてのロールをアクティブ化するようにMySQLに指示することもできます
SET ROLL ALL EXCEPT '<role_1>'@'<host>';
別のオプションとして、NONE
を指定してアカウントのすべてのロールを無効にすることもできます
SET ROLE NONE
これにより、セッション中のすべてのユーザーロールが非アクティブ化され、ユーザーアカウントにเฉพาะ的に割り当てられた権限のみが与えられます。
アカウントに定義されているデフォルトのロールリストに戻るには、DEFAULT
キーワードを使用します
SET ROLE DEFAULT
ユーザーアカウントのデフォルトロールを定義する方法
ユーザーとしてログインしたときに自動的にアクティブ化されるロール、およびSET ROLE DEFAULT
を使用するときに再アクティブ化されるロールは、設定可能です。
デフォルトでアクティブ化されるロールを定義するには、SET ROLE
コマンドを使用するのと同様に、SET DEFAULT ROLE
コマンドを使用します
SET DEFAULT ROLE '<role_1>'@'<host>';
これにより、ログイン時またはSET ROLE DEFAULT
使用時に、あなた自身のアカウントでアクティブ化されるデフォルトロールが設定されます。
あなたのユーザーがCREATE USER
権限を持っている場合、他のアカウントのデフォルトロールを設定できます
SET DEFAULT ROLE ALL TO '<user>'@'<host>';
ここでは、'<user>'@'<host>'
アカウントが認証時にすべてのロールを自動的にアクティブ化することを指定します。
この構文は、各ユーザーをコンマで区切ることで、複数のアカウントのデフォルトロールを定義するためにも使用できます
SET DEFAULT ROLE ALL TO '<user_1>'@'<host>', '<user_2>'@'<host>';
すべてのユーザーに対してデフォルトで全ロールをアクティブ化する
MySQLサーバー上のすべてのアカウントがデフォルトですべてのロールをアクティブ化するようにしたい場合は、システム設定を変更することで実現できます。
activate_all_roles_on_login
変数がtrueに設定されている場合、MySQLはログイン時にアカウントに関連付けられたすべてのロールを自動的にアクティブ化します。これは、SET DEFAULT ROLE
で指定された設定を上書きします。
この機能を有効にするには、SYSTEM_VARIABLES_ADMIN
およびROLE_ADMIN
権限が必要です。次のように入力して機能を有効にします
SET PERSIST activate_all_roles_on_login = ON;
これにより、ユーザーアカウントはログイン時にすべてのロールを自動的にアクティブ化します。ただし、SET ROLE DEFAULT
を使用すれば、アカウントに関連付けられたデフォルトロールのみをアクティブ化することも可能です。
ロールから取得した既存の権限を表示する
アカウントで利用可能な権限を理解するには、SHOW GRANTS
コマンドを使用できます。
ユーザーに対して有効になっている権限を確認するには、次のように入力します
SHOW GRANTS FOR '<user>'@'<host>';
出力には、ユーザーアカウントに直接割り当てられたすべての権限と、ユーザーがメンバーであるすべてのロールが表示されます。
アカウントがどのロールのメンバーであるかを知った後、そのロールがユーザーに提供する権限を次のように入力して確認できます
SHOW GRANTS FOR '<user>'@'<host>' USING '<role>'@'<host>';
例えば、'reports'@'localhost'
ユーザーの権限(readapp
ロールのメンバーシップによって付与されたものを含む)を確認するには、次を使用できます
SHOW GRANTS FOR 'reports'@'localhost' USING 'readapp';
これにより、'reports'@'localhost'
ユーザーアカウントに明示的に付与されたすべての権限と、readapp
ロールによって追加された権限が表示されます。
ユーザーからロールを取り消す
では、ユーザーからロールを削除したい場合はどうなりますか?GRANT
コマンドがユーザーまたはロールに新しい権限を追加したり、ユーザーにロールを追加したりできるのと同様に、REVOKE
コマンドはユーザーまたはロールから権限を削除したり、ユーザーからロールのメンバーシップを削除したりできます。
ユーザーアカウントからロールを削除するための基本的な構文は次のようになります
REVOKE '<role>' FROM '<user>'@'<host>';
このようなステートメントを実行すると、ユーザーはロールを通じて付与された権限にアクセスできなくなります。
例として、'appuser'@'localhost'
ユーザーアカウントからwriteapp
ロールを取り消すには、次のように入力します
REVOKE 'writeapp' FROM 'appuser'@'localhost';
ただし、ユーザーが他の方法(直接付与されたか、異なるロールのメンバーシップを通じて付与されたか)で権限を付与されている場合、その権限には引き続きアクセスできます。したがって、もし'appuser'@'localhost'
ユーザーが以前に付与したreadapp
ロールのメンバーでもあった場合、彼らはappdb
データベースに対して依然としてSELECT
権限を持つことになります。
結論
MySQLデータベースでロールを使用して権限を配布することは、アクセスコントロールシステムの管理オーバーヘッドと複雑さを簡素化するのに役立ちます。同じ責任を持つユーザーが同じ権限を持つことを保証することは、多数の異なる権限を直接付与するよりも、ロールを使用する方がはるかに簡単です。
同様に、ロールを使用すると、権限付与の意図を明確にすることができます。コメントなしでアカウントに大量の権限を付与するのではなく、慎重に選択されたロール名によって、アクセスするさまざまな理由を区別するのに役立ちます。事前に時間をかけてロールを作成し整理することで、データのさまざまな部分へのユーザーアクセスを管理する能力が長期的にはより簡単になります。
よくある質問
権限フラッシュ操作を実行し、サーバーに許可テーブルをリロードさせるには、FLUSH PRIVILEGES
ステートメントを発行します。
これは、mysqladmin flush-privilegesまたはmysqladmin reloadコマンドを実行することでも行えます。
特定のスコープでユーザーに全権限を割り当てるには、ALL
またはALL PRIVILEGES
の省略形を使用できます。
以下の構文は、sales
データベースに関連する、ユーザーが実行できるすべての権限を'salesadmin'@'localhost'
ユーザーに付与します。
GRANT ALL PRIVILEGES ON sales.* TO 'salesadmin'@'localhost';
ユーザーにグローバルな読み取り専用権限を付与するには、スコープコンポーネントのデータベース部分とデータベースオブジェクト部分の両方にワイルドカードを使用できます。
基本的な構文は次のようになります
GRANT SELECT ON *.* TO 'sally'@localhost';
読み取り専用の付与のスコープを単一のデータベースに限定するには、ドットの左側のワイルドカードをデータベース名に置き換えます
GRANT SELECT ON account.* TO 'meredith'@'localhost';
同様に、データベース内の特定のテーブルにのみアクセスを許可するには、以下を使用します
GRANT SELECT ON account.revenue TO 'meredith'@'localhost';
MySQLで新しいルート、またはスーパーユーザーアカウントを作成するには、GRANT ALL PRIVILEGES
ステートメントを使用して、データベース内のすべてに対する完全なルートアクセスを付与する必要があります。
基本的な構文は次のようになります
GRANT ALL PRIVILEGES ON *.* TO 'user_name'@'localhost' WITH GRANT OPTION;
アカウントで利用可能な権限を理解するには、SHOW GRANTS
コマンドを使用できます。
ユーザーに対して有効になっている権限を確認するには、次のように入力します
SHOW GRANTS FOR '<user>'@'<host>';
アカウントがどのロールのメンバーであるかを知った後、そのロールがユーザーに提供する権限を次のように入力して確認できます
SHOW GRANTS FOR '<user>'@'<host>' USING '<role>'@'<host>';