アプリケーションは次のガイドラインを使用することで、データベースアクティビティーを MySQL アカウントに関連付ける SQL ベースの監査を実行できます。
MySQL アカウントは、mysql.user
システムテーブルの行に対応します。 クライアントが正常に接続すると、サーバーはこのテーブル内の特定の行にアクセスするクライアントを認証します。 この行の User
および Host
カラムの値は、アカウントを一意に識別し、アカウント名が SQL ステートメントに書き込まれる '
形式に対応します。
user_name
'@'host_name
'
クライアントを認証する際に使用されるアカウントによって、クライアントが持っている権限が特定されます。 通常、CURRENT_USER()
関数を呼び出すと、このアカウントがどのクライアントユーザー用であるかを特定できます。 その値は、アカウントの user
テーブル行の User
および Host
カラムで構成されています。
ただし、CURRENT_USER()
値がクライアントユーザーではなく、別のアカウントに対応するという状況もあります。 これは、権限チェックがクライアントのアカウントに基づいて実行されないコンテキストで発生します。
SQL SECURITY DEFINER
特性を使用して定義されたストアドルーチン (プロシージャーおよび関数)SQL SECURITY DEFINER
特性を使用して定義されたビュートリガーとイベント
このようなコンテキストでは、権限チェックは DEFINER
アカウントと照合して実行され、CURRENT_USER()
はそのアカウントを参照し、ストアドルーチンまたはビューを呼び出したクライアント、またはトリガーをアクティブにしたクライアントのアカウントは参照しません。 クライアントおよびクライアントの接続元ホストによって指定された実際のユーザー名を示す値を返す USER()
関数を呼び出すと、呼び出し元のユーザーを特定できます。 ただし、USER()
の値にはワイルドカードが含まれない一方で、(CURRENT_USER()
によって返される) アカウントの値にはユーザー名およびホスト名のワイルドカードが含まれる可能性があるため、この値は必ずしも、user
テーブル内のアカウントに直接対応するとはかぎりません。
たとえば、空白のユーザー名は任意のユーザーに一致するため、''@'localhost'
のアカウントを使用すると、クライアントは任意のユーザー名を持つローカルホストから匿名ユーザーとして接続できます。 この場合、クライアントがローカルホストから user1
として接続すると、USER()
と CURRENT_USER()
は異なる値を返します:
mysql> SELECT USER(), CURRENT_USER();
+-----------------+----------------+
| USER() | CURRENT_USER() |
+-----------------+----------------+
| user1@localhost | @localhost |
+-----------------+----------------+
アカウントのホスト名部分にワイルドカードを含めることもできます。 ホスト名に'%'
または'_'
パターン文字が含まれているか、ネットマスク表記法を使用している場合、アカウントは複数のホストから接続しているクライアントに使用でき、CURRENT_USER()
値はどちらかを示しません。 たとえば、アカウント 'user2'@'%.example.com'
を使用すると、user2
が example.com
ドメイン内の任意のホストから接続できます。 user2
が remote.example.com
から接続すると、USER()
と CURRENT_USER()
は別々の値を返します。
mysql> SELECT USER(), CURRENT_USER();
+--------------------------+---------------------+
| USER() | CURRENT_USER() |
+--------------------------+---------------------+
| user2@remote.example.com | user2@%.example.com |
+--------------------------+---------------------+
アプリケーションがユーザーを監査するために USER()
を呼び出す必要があるが (たとえば、トリガー内から監査を実行する場合)、USER()
の値を user
テーブル内のアカウントに関連付けることができる必要もある場合は、アカウントの User
または Host
カラムにワイルドカードが含まれることを回避する必要があります。 特に、User
を (匿名のユーザーアカウントが作成される) 空にすることは許可しないでください。また、Host
の値に、パターン文字またはネットマスク表記を使用することも許可しないでください。 すべてのアカウントには、空でない User
値とリテラルの Host
値を含める必要があります。
前述の例に関しては、ワイルドカードが使用されないように ''@'localhost'
および 'user2'@'%.example.com'
アカウントを変更するようにしてください。
RENAME USER ''@'localhost' TO 'user1'@'localhost';
RENAME USER 'user2'@'%.example.com' TO 'user2'@'remote.example.com';
user2
が example.com
ドメイン内の複数のホストから接続できる必要がある場合は、ホストごとに個別のアカウントにするべきです。
CURRENT_USER()
または USER()
の値からユーザー名またはホスト名の部分を抽出するには、SUBSTRING_INDEX()
関数を使用します。
mysql> SELECT SUBSTRING_INDEX(CURRENT_USER(),'@',1);
+---------------------------------------+
| SUBSTRING_INDEX(CURRENT_USER(),'@',1) |
+---------------------------------------+
| user1 |
+---------------------------------------+
mysql> SELECT SUBSTRING_INDEX(CURRENT_USER(),'@',-1);
+----------------------------------------+
| SUBSTRING_INDEX(CURRENT_USER(),'@',-1) |
+----------------------------------------+
| localhost |
+----------------------------------------+