MySQL ではプラガブルな認証がサポートされており、プラグインはクライアント接続を認証するために呼び出されます。認証プラグインを使用すると、mysql.user
テーブルに格納されているパスワードによる組み込み方式ではない認証方式を使用できます。たとえば、外部認証方式にアクセスするプラグインを作成できます。また、認証プラグインはプロキシユーザー機能をサポートできるため、接続するユーザーを別のユーザーのプロキシにして、(アクセス制御のために) 別のユーザーの権限を持つユーザーとして扱うことが可能になります。詳細は、セクション6.3.7「プラガブル認証」およびセクション6.3.9「プロキシユーザー」を参照してください。
認証プラグインでは、サーバー側およびクライアント側のプラグインを作成します。サーバー側プラグインは、全文パーサープラグイン、監査プラグインなどのほかの種類のサーバープラグインで使用されるものと同じプラグイン API を使用します (ただし、タイプ固有のディスクリプタは異なります)。クライアント側プラグインはクライアントプラグイン API を使用します。
いくつかのヘッダーファイルに、認証プラグインに関する情報が格納されています。
plugin.h
:MYSQL_AUTHENTICATION_PLUGIN
サーバープラグインタイプを定義します。client_plugin.h
: クライアントプラグインの API を定義します。これには、クライアントプラグインディスクリプタ、およびクライアントプラグイン C API を呼び出すための関数プロトタイプが含まれます (セクション23.7.14「C API クライアントプラグイン関数」を参照してください)。plugin_auth.h
: 認証プラグインに固有のサーバープラグイン API の一部を定義します。これにはサーバー側認証プラグインのタイプ固有のディスクリプタとMYSQL_SERVER_AUTH_INFO
構造体が含まれます。plugin_auth_common.h
: クライアント認証プラグインとサーバー認証プラグインの共通要素が格納されます。これには戻り値の定義とMYSQL_PLUGIN_VIO
構造体が含まれます。
認証プラグインを作成するには、プラグインのソースファイルに次のヘッダーファイルをインクルードします。プラグインの機能および要件によっては、ほかの MySQL のヘッダーファイルまたは一般的なヘッダーファイルが必要になることもあります。
-
サーバー認証プラグインを実装するソースファイルの場合、次のファイルをインクルードします。
#include <mysql/plugin_auth.h>
-
クライアント認証プラグインを実装するか、クライアントプラグインとサーバープラグインの両方を実装するソースファイルの場合、次のファイルをインクルードします。
#include <mysql/plugin_auth.h> #include <mysql/client_plugin.h> #include <mysql.h>
plugin_auth.h
は plugin.h
および plugin_auth_common.h
をインクルードするため、後者のファイルを明示的にインクルードする必要はありません。
このセクションでは、連係して動作するサーバー認証プラグインとクライアント認証プラグインのペアを作成する方法について説明します。
これらのプラグインは空でないあらゆるパスワードを受け入れ、パスワードは平文で送信されます。これは安全でないため、このプラグインは本番環境で使用しないでください。
ここで作成するサーバー側プラグインおよびクライアント側プラグインの名前は、両方とも auth_simple
です。セクション24.2.4.2「プラグインのデータ構造体」で説明したように、プラグインライブラリファイルはクライアントプラグインと同じベース名を持つ必要があるため、ソースファイル名は auth_simple.c
であり、auth_simple.so
という名前のライブラリが生成されます (システムで、ライブラリファイルのサフィクスとして .so
が使用されていることを想定しています)。
MySQL ソース配布では、認証プラグインのソースが plugin/auth
ディレクトリにあり、ほかの認証プラグインを作成するときのガイドとして参考にできます。また、組み込み認証プラグインが実装される方法を確認するには、MySQL サーバーに組み込まれるプラグインについては sql/sql_acl.cc
、およびlibmysqlclient
クライアントライブラリに組み込まれるプラグインについては sql-common/client.c
を参照してください。(組み込みクライアントプラグインの場合、使用される auth_plugin_t
構造体は、通常のクライアントプラグイン宣言マクロで使用される構造と異なります。特に、最初の 2 つのメンバーは、宣言マクロによって設定されるのではなく、明示的に指定されています。)
すべてのサーバープラグインタイプに使用される通常の一般ディスクリプタ形式を使用して、サーバー側プラグインを宣言します (セクション24.2.4.2.1「サーバープラグインライブラリおよびプラグインディスクリプタ」を参照してください)。auth_simple
プラグインの場合、ディスクリプタは次のようになります。
mysql_declare_plugin(auth_simple)
{
MYSQL_AUTHENTICATION_PLUGIN,
&auth_simple_handler, /* type-specific descriptor */
"auth_simple", /* plugin name */
"Author Name", /* author */
"Any-password authentication plugin", /* description */
PLUGIN_LICENSE_GPL, /* license type */
NULL, /* no init function */
NULL, /* no deinit function */
0x0100, /* version = 1.0 */
NULL, /* no status variables */
NULL, /* no system variables */
NULL, /* no reserved information */
0 /* no flags */
}
mysql_declare_plugin_end;
name
メンバー (auth_simple
) は、INSTALL PLUGIN
、UNINSTALL PLUGIN
などのステートメントでプラグインを参照するために使用する名前を指定します。これは、SHOW PLUGINS
または INFORMATION_SCHEMA.PLUGINS
によって表示される名前でもあります。
一般ディスクリプタの auth_simple_handler
メンバーはタイプ固有のディスクリプタを指しています。認証プラグインの場合、タイプ固有のディスクリプタは st_mysql_auth
構造体 (plugin_auth.h
で定義されます) のインスタンスです。
struct st_mysql_auth
{
int interface_version;
const char *client_auth_plugin;
int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info);
};
st_mysql_auth
構造体には 3 つのメンバー (タイプ固有の API バージョン番号、クライアントプラグイン名、およびクライアントと通信するメインのプラグイン関数へのポインタ) があります。client_auth_plugin
メンバーは、特定のプラグインが必要な場合にクライアントプラグインの名前を示すようにします。NULL
値は「任意のプラグイン」を意味します。後者の場合、クライアントは任意のプラグインを使用できます。これは、クライアントプラグイン、およびクライアントプラグインが送信するユーザー名またはパスワードが、サーバープラグインの処理に関与しない場合に役立ちます。たとえば、サーバープラグインがローカルのクライアントのみを認証し、クライアントプラグインによって送信される情報ではなくオペレーティングシステムのいくつかのプロパティーを使用する場合です。
auth_simple
の場合、タイプ固有のディスクリプタは次のようになります。
static struct st_mysql_auth auth_simple_handler =
{
MYSQL_AUTHENTICATION_INTERFACE_VERSION,
"auth_simple", /* required client-side plugin name */
auth_simple_server /* server-side plugin main function */
};
メインの関数は、I/O 構造体および MYSQL_SERVER_AUTH_INFO
構造体を表す 2 つの引数を受け取ります。この構造体の定義は plugin_auth.h
にあります。これは次のような定義です。
typedef struct st_mysql_server_auth_info
{
char *user_name;
unsigned int user_name_length;
const char *auth_string;
unsigned long auth_string_length;
char authenticated_as[MYSQL_USERNAME_LENGTH+1];
char external_user[512];
int password_used;
const char *host_or_ip;
unsigned int host_or_ip_length;
} MYSQL_SERVER_AUTH_INFO;
文字列メンバーの文字セットは UTF-8 です。文字列に関連付けられた _length
メンバーがある場合、これはバイト単位の文字列の長さを示します。文字列も NULL で終わります。
サーバーによって認証プラグインが呼び出されると、MYSQL_SERVER_AUTH_INFO
構造体メンバーが次のように解釈されます。これらの一部は、説明されているようにクライアントセッション内の SQL 関数またはシステム変数の値を設定するために使用されます。
user_name
: クライアントによって送信されたユーザー名。この値はUSER()
関数の値になります。user_name_length
:user_name
のバイト単位の長さ。-
auth_string
:mysql.user
テーブルの一致するアカウント名の行 (つまり、クライアントユーザー名およびホスト名が一致し、クライアントを認証する方法を判別するためにサーバーによって使用される行) のauthentication_string
カラムの値。次のステートメントを使用してアカウントを作成するとします。
CREATE USER 'my_user'@'localhost' IDENTIFIED WITH my_plugin AS 'my_auth_string';
my_user
がローカルホストから接続する場合、サーバーはmy_plugin
を呼び出し、'my_auth_string'
をauth_string
値として渡します。 auth_string_length
:auth_string
のバイト単位の長さ。authenticated_as
: サーバーはこれをユーザー名 (user_name
の値) に設定します。プラグインは、クライアントが別のユーザーの権限を持つことを示すように変更できます。たとえば、プラグインでプロキシユーザーがサポートされる場合、初期値は接続する (プロキシ) ユーザーの名前ですが、プラグインがこのメンバーをプロキシ設定されているユーザー名に変更できます。その後、サーバーはプロキシ設定されているユーザーの権限を持つものとしてプロキシユーザーを扱います (プロキシユーザーのサポートのためのほかの条件が満たされていることを想定しています。セクション24.2.4.9.4「認証プラグインでのプロキシユーザーサポートの実装」を参照してください)。この値は、最大MYSQL_USER_NAME_LENGTH
バイトの長さを持つ文字列、および終端の NULL として表されます。この値はCURRENT_USER()
関数の値になります。external_user
: サーバーは空の文字列 (NULL で終わります) をこれに設定します。この値はexternal_user
システム変数の値になります。プラグインでこのシステム変数が異なる値を持つようにするには、プラグインでそのようにこのメンバーを設定してください (たとえば、接続しているユーザー名を設定します)。この値は、最大 511 バイトの長さの文字列、および終端の NULL として表されます。-
password_used
: このメンバーは、認証に失敗したときに適用されます。プラグインは、これを設定するか、無視できます。この値は、Authentication fails. Password used: %s
という失敗のエラーメッセージを作成するために使用されます。password_used
の値によって、次の表に示すように、%s
の処理方法が決まります。password_used
%s
の処理0 行わない 1 行う 2 %s
がない host_or_ip
: 解決できる場合はクライアントのホスト名、または解決できない場合は IP アドレス。host_or_ip_length
:host_or_ip
のバイト単位の長さ。
auth_simple
のメイン関数 auth_simple_server()
は、クライアントからパスワード (NULL で終了する文字列) を読み取り、パスワードが空でない (先頭バイトが NULL でない) 場合に成功します。
static int auth_simple_server (MYSQL_PLUGIN_VIO *vio,
MYSQL_SERVER_AUTH_INFO *info)
{
unsigned char *pkt;
int pkt_len;
/* read the password as null-terminated string, fail on error */
if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
return CR_ERROR;
/* fail on empty password */
if (!pkt_len || *pkt == '\0')
{
info->password_used= PASSWORD_USED_NO;
return CR_ERROR;
}
/* accept any nonempty password */
info->password_used= PASSWORD_USED_YES;
return CR_OK;
}
メイン関数は、次の表に示すいずれかのエラーコードを返します。
エラーコード | 意味 |
---|---|
CR_OK |
成功 |
CR_OK_HANDSHAKE_COMPLETE |
ステータスパケットをクライアントに送信しない |
CR_ERROR |
エラー |
CR_AUTH_USER_CREDENTIALS |
認証エラー |
CR_AUTH_HANDSHAKE |
認証ハンドシェイクエラー |
CR_AUTH_PLUGIN_ERROR |
内部プラグインエラー |
ハンドシェイクが動作する方法の例については、plugin/auth/dialog.c
ソースファイルを参照してください。
CR_ERROR
に続くエラーコードは MySQL 5.6.5 から使用できます。サーバーは、MySQL 5.6.5 以降で使用可能なパフォーマンススキーマ host_cache
テーブル内のプラグインエラーをカウントします。
auth_simple_server_main()
は非常に基本的なものであるため、パスワードを受け取ったかどうかを示すメンバーを設定することを除き、認証情報構造体を使用しません。
プロキシユーザーをサポートするプラグインは、プロキシ設定されているユーザー (クライアントユーザーが取得する権限を持っている MySQL ユーザー) の名前をサーバーに返す必要があります。これを行うには、プラグインはプロキシ設定されているユーザー名を info->authenticated_as
メンバーに設定する必要があります。プロキシ設定については、セクション6.3.9「プロキシユーザー」およびセクション24.2.4.9.4「認証プラグインでのプロキシユーザーサポートの実装」を参照してください。
mysql_declare_client_plugin()
マクロおよび mysql_end_client_plugin
マクロを使用して、クライアント側プラグインディスクリプタを宣言します (セクション24.2.4.2.3「クライアントプラグインディスクリプタ」を参照してください)。auth_simple
プラグインの場合、ディスクリプタは次のようになります。
mysql_declare_client_plugin(AUTHENTICATION)
"auth_simple", /* plugin name */
"Author Name", /* author */
"Any-password authentication plugin", /* description */
{1,0,0}, /* version = 1.0.0 */
"GPL", /* license type */
NULL, /* for internal use */
NULL, /* no init function */
NULL, /* no deinit function */
NULL, /* no option-handling function */
auth_simple_client /* main function */
mysql_end_client_plugin;
プラグイン名からオプション処理関数までのディスクリプタメンバーは、すべてのクライアントプラグインタイプで共通しています。(説明については、セクション24.2.4.2.3「クライアントプラグインディスクリプタ」を参照してください。)共通メンバーに続いて、このディスクリプタには認証プラグインに固有の追加メンバーがあります。これは「メイン」の関数であり、サーバーとの通信を処理します。この関数は、I/O 構造体と接続ハンドラを表す 2 つの引数を取ります。任意のパスワードを指定できるこの単純なプラグインでは、メイン関数はユーザーが指定したパスワードをサーバーに書き込むだけです。
static int auth_simple_client (MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
{
int res;
/* send password as null-terminated string in clear text */
res= vio->write_packet(vio, (const unsigned char *) mysql->passwd,
strlen(mysql->passwd) + 1);
return res ? CR_ERROR : CR_OK;
}
メイン関数は、次の表に示すいずれかのエラーコードを返します。
エラーコード | 意味 |
---|---|
CR_OK |
成功 |
CR_OK_HANDSHAKE_COMPLETE |
成功、クライアント完了 |
CR_ERROR |
エラー |
CR_OK_HANDSHAKE_COMPLETE
は、クライアントが自分の役割を正常に完了し、最後のパケットを読み取ったことを示します。認証プロトコルのラウンドトリップ数が事前に知られておらず、認証が完了したかどうかを判別するためにプラグインが別のパケットを読み取る必要がある場合、クライアントプラグインが CR_OK_HANDSHAKE_COMPLETE
を返すことがあります。
プラグインライブラリのオブジェクトファイルをコンパイルおよびインストールするには、セクション24.2.4.3「プラグインライブラリのコンパイルおよびインストール」の手順を参照してください。ライブラリファイルを使用するには、ライブラリファイルがプラグインディレクトリ (plugin_dir
システム変数で指定されているディレクトリ) にインストールされている必要があります。
サーバー側プラグインをサーバーに登録します。たとえば、プラグインをサーバー起動時にロードするには、--plugin-load=auth_simple.so
オプションを使用します (システムで必要な場合はライブラリサフィクスを変更します)。
サーバーが認証のために auth_simple
プラグインを使用する対象となるユーザーを作成します。
mysql> CREATE USER 'x'@'localhost'
-> IDENTIFIED WITH auth_simple;
クライアントプログラムを使用して、ユーザー x
としてサーバーに接続します。サーバー側の auth_simple
プラグインはクライアント側の auth_simple
プラグインを使用するクライアントプログラムと通信し、後者はサーバーにパスワードを送信します。サーバーは空のパスワードを送信する接続を拒否し、空ではないパスワードを送信する接続を受け入れます。これを検証するために、それぞれの方法でクライアントプログラムを起動します。
shell> mysql --user=x --skip-password
ERROR 1045 (28000): Access denied for user 'x'@'localhost' (using password: NO)
shell> mysql --user=x --password=abc
mysql>
このサーバープラグインは空ではないパスワードをすべて受け入れるため、安全ではないとみなされます。プラグインをテストしてプラグインが機能することを検証したら、気づかずに安全でない認証プラグインがロードされたままの状態でサーバーが実行され続けないように、--plugin-load
オプションを指定せずにサーバーを再起動します。また、DROP USER 'x'@'localhost'
を使用してユーザーを削除します。
認証プラグインのロードおよび使用に関する追加情報については、セクション5.1.8.1「プラグインのインストールおよびアンインストール」およびセクション6.3.7「プラガブル認証」を参照してください。
認証プラグインの使用をサポートするクライアントプログラムを作成する場合、一般的にそのようなプログラムは、mysql_options()
を呼び出して MYSQL_DEFAULT_AUTH
オプションおよび MYSQL_PLUGIN_DIR
オプションを設定することによって、プラグインをロードします。
char *plugin_dir = "path_to_plugin_dir";
char *default_auth = "plugin_name";
/* ... process command-line options ... */
mysql_options(&mysql, MYSQL_PLUGIN_DIR, plugin_dir);
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, default_auth);
一般にプログラムは、ユーザーがデフォルト値をオーバーライドできるようにする --plugin-dir
および --default-auth
オプションも受け付けます。
クライアントプログラムで低レベルのプラグイン管理が必要である場合は、クライアントライブラリに st_mysql_client_plugin
引数を受け取る関数を含めます。セクション23.7.14「C API クライアントプラグイン関数」を参照してください。
プラガブルな認証によって使用できるようになる機能の 1 つはプロキシユーザーです (セクション6.3.9「プロキシユーザー」を参照してください)。サーバー側の認証プラグインでプロキシユーザーがサポートされるようにするには、次の条件を満たしている必要があります。
接続するクライアントをプロキシユーザーとして扱う場合、プラグインは
MYSQL_SERVER_AUTH_INFO
構造体のauthenticated_as
メンバー内に異なる名前を返して、プロキシ設定されているユーザー名を示す必要があります。external_user
システム変数の値を設定するために、必要に応じてexternal_user
メンバーを設定することもできます。プロキシユーザーのアカウントは、プラグインによって認証されるようにセットアップする必要があります。アカウントをプラグインに関連付けるには、
CREATE USER
ステートメントまたはGRANT
ステートメントを使用します。プロキシユーザーアカウントには、プロキシ設定されているアカウントに対する
PROXY
権限がある必要があります。この権限を付与するには、GRANT
ステートメントを使用します。
言い換えると、プラグインに必要なプロキシユーザーサポートの特性は、プロキシ設定されているユーザー名を authenticated_as
に設定することのみです。そのほかは、オプションであるか (external_user
の設定)、SQL ステートメントを使用して DBA が行います。
認証プラグインはプロキシユーザーが接続したときに返すプロキシ設定されているユーザーをどのように決定するのでしょうか。これはプラグインによって異なります。通常、プラグインはサーバーから渡された認証文字列に基づいて、クライアントをプロキシ設定されているユーザーにマップします。この文字列は、認証にプラグインを使用することを指定する CREATE USER
ステートメントの IDENTIFIED WITH
句の AS
部分に指定されます。
プラグイン開発者は認証文字列の構文ルールを決定し、これらのルールに従ってプラグインを実装します。外部ユーザーを MySQL ユーザーにマップするカンマ区切りのリストのペアをプラグインが受け取るとします。例:
CREATE USER ''@'%.example.com'
IDENTIFIED WITH my_plugin AS 'extuser1=mysqlusera, extuser2=mysqluserb'
CREATE USER ''@'%.example.org'
IDENTIFIED WITH my_plugin AS 'extuser1=mysqluserc, extuser2=mysqluserd'
サーバーがプラグインを起動してクライアントを認証するときに、適切な認証文字列をプラグインに渡します。プラグインには次の役割があります。
文字列を構文解析して構成要素に分解し、使用するマッピングを決定する
クライアントユーザー名とマッピングを比較する
適切な MySQL ユーザー名を返す
たとえば、example.com
ホストから extuser2
が接続する場合、サーバーは 'extuser1=mysqlusera, extuser2=mysqluserb'
をプラグインに渡し、プラグインは mysqluserb
に終端の NULL バイトを付加して authenticated_as
にコピーします。example.org
ホストから extuser2
が接続する場合、サーバーは 'extuser1=mysqluserc, extuser2=mysqluserd'
を渡し、プラグインは代わりに mysqluserd
をコピーします。
マッピングに一致するものがない場合のアクションはプラグインによって異なります。一致するものがある必要があるとき、多くの場合、プラグインはエラーを返します。または、プラグインが単純にクライアント名を返すこともあり、この場合、プラグインは authenticated_as
を変更せず、サーバーはクライアントをプロキシとして扱いません。
次の例では、auth_simple_proxy
という名前のプラグインを使用して、プロキシユーザーを処理する方法を示しています。前に示した auth_simple
プラグインのように、auth_simple_proxy
は空ではないすべてのパスワードを有効なものとして受け入れます (このため、本番環境で使用しないでください)。また、これは auth_string
認証文字列メンバーを検査し、次の非常に単純なルールを使用してこれを解釈します。
文字列が空の場合、プラグインは指定されたユーザー名を返し、プロキシ設定は行われません。つまり、プラグインは
authenticated_as
の値を変更せずにそのままにします。文字列が空ではない場合、プラグインはこれをプロキシ設定されているユーザーの名前として扱い、プロキシ設定が行われるようにこれを
authenticated_as
にコピーします。
テストを行うために、上記のルールに従ってプロキシ設定されていない 1 つのアカウントとプロキシ設定されている 1 つのアカウントをセットアップします。これは、一方のアカウントには AS
句がなく、他方のアカウントにはプロキシ設定されているユーザーを指定する AS
句があることを意味します。
CREATE USER 'plugin_user1'@'localhost'
IDENTIFIED WITH auth_simple_proxy;
CREATE USER 'plugin_user2'@'localhost'
IDENTIFIED WITH auth_simple_proxy AS 'proxied_user';
また、プロキシ設定されているユーザーのアカウントを作成し、そのアカウントに対する PROXY
権限を plugin_user2
に付与します。
CREATE USER 'proxied_user'@'localhost'
IDENTIFIED BY 'proxied_user_pass';
GRANT PROXY
ON 'proxied_user'@'localhost'
TO 'plugin_user2'@'localhost';
サーバーは、認証プラグインを呼び出す前に、authenticated_as
にクライアントユーザー名を設定します。ユーザーがプロキシであることを示すために、プラグインはプロキシ設定されているユーザー名を authenticated_as
に設定します。auth_simple_proxy
の場合、これは、auth_string
値を検査し、値が空でない場合は値を authenticated_as
メンバーにコピーして、プロキシ設定されているユーザーの名前としてそれを返す必要があることを意味します。また、プロキシ設定が行われる場合、プラグインは external_user
メンバーにクライアントユーザー名を設定し、これが external_user
システム変数の値になります。
static int auth_simple_proxy_server (MYSQL_PLUGIN_VIO *vio,
MYSQL_SERVER_AUTH_INFO *info)
{
unsigned char *pkt;
int pkt_len;
/* read the password as null-terminated string, fail on error */
if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
return CR_ERROR;
/* fail on empty password */
if (!pkt_len || *pkt == '\0')
{
info->password_used= PASSWORD_USED_NO;
return CR_ERROR;
}
/* accept any nonempty password */
info->password_used= PASSWORD_USED_YES;
/* if authentication string is nonempty, use as proxied user name */
/* and use client name as external_user value */
if (info->auth_string_length > 0)
{
strcpy (info->authenticated_as, info->auth_string);
strcpy (info->external_user, info->user_name);
}
return CR_OK;
}
接続が成功すると、USER()
関数は接続しているクライアントユーザーとホスト名を示し、CURRENT_USER()
はセッション中に適用される権限を持つアカウントを示します。後者の値は、プロキシ設定が行われない場合は接続するユーザーアカウント、およびプロキシ設定が行われた場合はプロキシ設定されているアカウントになります。
プラグインをコンパイルおよびインストールして、テストします。最初に、plugin_user1
として接続します。
shell> mysql --user=plugin_user1 --password=x
この場合、プロキシ設定は行われません。
mysql> SELECT USER(), CURRENT_USER(), @@proxy_user, @@external_user\G
*************************** 1. row ***************************
USER(): plugin_user1@localhost
CURRENT_USER(): plugin_user1@localhost
@@proxy_user: NULL
@@external_user: NULL
次に、plugin_user2
として接続します。
shell> mysql --user=plugin_user2 --password=x
この場合、plugin_user2
は proxied_user
に対してプロキシ設定されます。
mysql> SELECT USER(), CURRENT_USER(), @@proxy_user, @@external_user\G
*************************** 1. row ***************************
USER(): plugin_user2@localhost
CURRENT_USER(): proxied_user@localhost
@@proxy_user: 'plugin_user2'@'localhost'
@@external_user: 'plugin_user2'@'localhost'