PAM 認証プラグインは、商用の拡張機能です。商用の製品 (MySQL Enterprise Edition) についてさらに学習するには、https://www.mysql.com/products/ を参照してください。
MySQL 5.6.10 の時点で、MySQL の商用配布には、MySQL サーバーが PAM (Pluggable Authentication Module) を使用して MySQL ユーザーを認証できる認証プラグインが含まれています。PAM を使用すると、システムは標準インタフェースを使用して、さまざまな種類の認証方式 (Unix パスワードや LDAP ディレクトリなど) にアクセスできます。
PAM プラグインでは、MySQL
サーバーによって渡される情報
(ユーザー名、ホスト名、パスワード、認証文字列など)
に加えて、PAM
検索で使用可能な任意の方式が使用されます。このプラグインは、PAM
と照合してユーザー資格情報をチェックし、「Authentication
succeeded, Username is
またはuser_name
」「Authentication
failed」
を返します。
PAM 認証プラグインには、次のような機能が備わっています。
外部認証: このプラグインを使用すると、MySQL サーバーは、MySQL 付与テーブルの外部で定義されたユーザーからの接続を受け入れることができます。
プロキシユーザーのサポート: このプラグインは、外部ユーザーが属するグループおよび指定された認証文字列に基づいて、ログインユーザーとは異なるユーザー名を MySQL に返すことができます。つまり、このプラグインは、外部 PAM で認証されたユーザーが持つべき権限を定義する MySQL ユーザーを返すことができます。たとえば、
joe
という名前の PAM ユーザーは接続して、developer
という名前の MySQL ユーザーの権限を持つことができます。
次の表には、プラグインおよびライブラリファイルの名前を示します。ファイル名のサフィクスは、システムによって異なる場合があります。ファイルの場所は、plugin_dir
システム変数で指定されたディレクトリである必要があります。インストールについては、セクション6.3.8.5.1「PAM 認証プラグインのインストール」を参照してください。
表 6.11 MySQL PAM 認証プラグイン
サーバー側のプラグイン名 | authentication_pam |
クライアント側のプラグイン名 | mysql_clear_password |
ライブラリオブジェクトファイル名 | authentication_pam.so |
ライブラリファイルには、サーバー側のプラグインのみが含まれています。クライアント側のプラグインは、libmysqlclient
クライアントライブラリに組み込まれています。セクション6.3.8.7「クライアント側のクリアテキスト認証プラグイン」を参照してください。
サーバー側の PAM 認証プラグインは、商用配布にのみ含まれています。MySQL コミュニティー配布には含まれていません。サーバー側のプラグインと通信するクライアント側のクリアテキストプラグインは、MySQL クライアントライブラリに組み込まれ、コミュニティー配布を含むすべての配布に含まれています。これにより、5.6.10 以降の任意の配布から、サーバー側のプラグインがロードされたサーバーに接続することがクライアントに許可されます。
PAM 認証プラグインは、Linux および Mac OS X 上でテストされています。これには、MySQL Server 5.6.10 以降が必要です。
MySQL のプラガブル認証に関する一般的な情報については、セクション6.3.7「プラガブル認証」を参照してください。プロキシユーザーについては、セクション6.3.9「プロキシユーザー」を参照してください。
PAM 認証プラグインは、MySQL
プラグインディレクトリ
(plugin_dir
システム変数で指定されたディレクトリ)
に配置する必要があります。必要に応じて、サーバーの起動時に、プラグインディレクトリの場所をサーバーに指示する
plugin_dir
の値を設定します。
プラグインを有効にするには、--plugin-load
オプションを付けてサーバーを起動します。たとえば、my.cnf
ファイルに次の行を挿入します。オブジェクトファイルのサフィクスがシステム上の
.so
と異なる場合は、正しいサフィクスに置き換えてください。
[mysqld]
plugin-load=authentication_pam.so
このプラグインを使用して認証するべき MySQL
アカウントには、CREATE
USER
または GRANT
ステートメントの IDENTIFIED WITH
句の authentication_pam
というプラグイン名を使用します。
プラグインのインストールを確認するには、INFORMATION_SCHEMA.PLUGINS
テーブルを調査するか、または
SHOW PLUGINS
ステートメントを使用します。セクション5.1.8.2「サーバープラグイン情報の取得」を参照してください。
このセクションでは、PAM 認証プラグインを使用して、MySQL クライアントプログラムからサーバーに接続する方法について説明します。サーバー側のプラグインが有効になっていて、クライアント側のプラグインを追加するのに十分新しいクライアントプログラムであることが前提となっています。
PAM プラグインの通信相手であるクライアント側のプラグインは、PAM に渡すことができるように、単純にパスワードをクリアテキストでサーバーに送信します。これにより、一部の構成でセキュリティーの問題が発生する可能性がありますが、サーバー側の PAM ライブラリを使用するためには必要です。パスワードが傍受される可能性がある場合に、問題を回避するには、クライアントは SSL を使用して MySQL サーバーに接続するようにしてください。セクション6.3.8.7「クライアント側のクリアテキスト認証プラグイン」を参照してください。
CREATE USER
または
GRANT
ステートメントの
IDENTIFIED WITH
句で PAM
認証プラグインを参照するには、authentication_pam
という名前を使用します。例:
CREATE USER user
IDENTIFIED WITH authentication_pam
AS 'authentication_string';
認証文字列には、次のタイプの情報が指定されます。
PAM では、システム管理者が特定のアプリケーション用の認証方式を構成する際に使用できる名前である「サービス名」の概念がサポートされています。このような複数の「アプリケーション」が単一のデータベースサーバーインスタンスに関連付けられている可能性もあるため、サービス名の選択は SQL アプリケーションの開発者に任されます。PAM を使用して認証するべきアカウントを定義する際は、認証文字列でサービス名を指定します。
PAM では、ログイン時に指定されたログイン名以外の MySQL ユーザー名を PAM モジュールからサーバーに返すための方法が提供されています。認証文字列を使用して、ログイン名と MySQL ユーザー名とのマッピングを制御します。プロキシユーザーの機能を活用するには、この種類のマッピングを認証文字列に含める必要があります。
たとえば、サービス名が mysql
であり、root
および
users
PAM グループ内のユーザーを
developer
および
data_entry
ユーザーにマップする必要がある場合は、それぞれ次のようなステートメントを使用します。
CREATE USER user
IDENTIFIED WITH authentication_pam
AS 'mysql, root=developer, users=data_entry';
PAM 認証プラグインでの認証文字列の構文は、次のようなルールに従っています。
-
文字列は PAM サービス名で構成され、それぞれグループ名と SQL ユーザー名を指定する 1 つ以上のキーワードと値のペアで構成されるグループマッピングリストがオプションで続きます。
pam_service_name[,group_name=sql_user_name]...
の各ペアの前には、カンマを付ける必要があります。group_name
=sql_user_name
二重引用符で囲まれていない先頭および末尾の空白文字は、無視されます。
引用符で囲まれていない
pam_service_name
、group_name
、およびsql_user_name
の値には、等号、カンマ、または空白文字を除く、任意の文字を含めることができます。pam_service_name
、group_name
、またはsql_user_name
の値を二重引用符で囲むと、引用符間のすべての文字が値の一部となります。たとえば、値に空白文字が含まれている場合は、これが必要です。二重引用符およびバックスラッシュ ('\'
) を除く、すべての文字が有効です。どちらかの文字を含めるには、バックスラッシュを使用してエスケープします。
このプラグインは、各ログインチェック時に認証文字列を解析します。オーバーヘッドを最小限に抑えるには、できるだけ文字列を短く保ちます。
プラグインが正常にログイン名を認証すると、認証文字列でグループマッピングリストを検索し、そのリストを使用して外部ユーザーがメンバーになっているグループに基づいて MySQL サーバーに別のユーザー名を返します。
認証文字列にグループマッピングリストが含まれていない場合は、プラグインはログイン名を返します。
認証文字列にグループマッピングリストが含まれている場合は、プラグインはリスト内の各
ペアを左から右へと調査し、認証済みのユーザーに割り当てられたグループの MySQL 以外のディレクトリ内で、group_name
=sql_user_name
group_name
値の一致を見つけようとし、最初に見つかった一致に対応するsql_user_name
を返します。プラグインが任意のグループの一致を見つけた場合は、ログイン名を返します。プラグインがディレクトリ内のグループを検索できない場合は、グループマッピングリストを無視し、ログイン名を返します。
次のセクションでは、PAM 認証プラグインを使用するいくつかの認証シナリオを設定する方法について説明します。
-
プロキシユーザーなし。ここでは、ログイン名とパスワードをチェックする際にのみ PAM が使用されます。MySQL サーバーへの接続が許可されている外部ユーザーはすべて、外部 PAM 認証を使用するように定義されている一致する MySQL アカウントを持つべきです。PAM でサポートされているさまざまな方式で、認証を実行できます。この説明では、従来の Unix パスワードおよび LDAP を使用する方法を示します。
PAM 認証では、プロキシユーザーまたはグループを介して実行されない場合に、MySQL アカウントは Unix アカウントと同じユーザー名を持つ必要があります。MySQL ユーザー名は 16 文字に制限されているため (セクション6.2.2「権限システム付与テーブル」を参照してください)、PAM の非プロキシ認証は、最長で 16 文字の名前を持つ Unix アカウントに制限されます。
プロキシログインのみ、およびグループマッピング。このシナリオでは、さまざまな権限セットを定義する数個の MySQL アカウントを作成します。(理想は、これらを使用して直接ログインしないようにすることです。)そのあと、権限セットを保持している数個の MySQL アカウントに、すべての外部ログインをマップする一部のマッピングスキームが (通常は、ユーザーが属する外部グループによって) 使用される PAM を使用して、デフォルトのユーザー認証を定義します。ログインする任意のユーザーは、MySQL アカウントのいずれかにマップされ、その権限を使用します。この説明では、Unix パスワードを使用してこれを設定する方法を示しますが、代わりに LDAP などのその他の PAM 方式が使用される可能性もあります。
これらのシナリオでは、ばらつきがある可能性があります。たとえば、一部のユーザーに直接ログインすることを許可するが、その他のユーザーにはプロキシユーザーを介して接続するように要求できます。
この例は、次のことが前提となっています。システムが異なる方法で設定されている場合は、多少の調整が必要になることもあります。
PAM 構成ディレクトリは
/etc/pam.d
です。PAM サービス名は
mysql
です。これは、PAM 構成ディレクトリ内にmysql
という名前の PAM ファイル (存在しない場合はファイルを作成します) を設定する必要があることを意味します。別のサービス名を使用する場合は、ファイル名が異なるため、CREATE USER
およびGRANT
ステートメントのAS
句で別の名前を使用する必要があります。この例では、
antonio
というログイン名とverysecret
というパスワードが使用されています。認証するユーザーに対応するように、これらを変更します。
PAM 認証プラグインは、初期化時に
AUTHENTICATION_PAM_LOG
環境の値が設定されているかどうかをチェックします。その場合、プラグインを使用すると、標準出力への診断メッセージのロギングが有効になります。これらのメッセージは、プラグインが認証を実行するときに発生する
PAM
関連の問題をデバッグする際に役立つことがあります。詳細については、セクション6.3.8.5.3「PAM 認証プラグインのデバッグ」を参照してください。
この認証シナリオでは、Unix ユーザーのログイン名とパスワードをチェックする際にのみ PAM が使用されます。MySQL サーバーへの接続が許可されている外部ユーザーはすべて、外部 PAM 認証を使用するように定義されている一致する MySQL アカウントを持つべきです。
PAM の Unix 認証で、パスワード
verysecret
を使用してantonio
としてログインすることが許可されていることを確認します。-
mysql
サービスを認証するように PAM を設定します。/etc/pam.d/mysql
に次の行を挿入します。#%PAM-1.0 auth include password-auth account include password-auth
-
Unix ログイン名と同じユーザー名を持つ MySQL アカウントを作成し、PAM プラグインを使用して認証するように定義します。
CREATE USER 'antonio'@'localhost' IDENTIFIED WITH authentication_pam AS 'mysql'; GRANT ALL PRIVILEGES ON mydb.* TO 'antonio'@'localhost';
-
mysql コマンド行クライアントを使用して、MySQL サーバーへの接続を試みます。例:
mysql --user=antonio --password=verysecret --enable-cleartext-plugin mydb
サーバーは接続を許可し、以降のクエリーは次に示すような出力を返すはずです。
mysql> SELECT USER(), CURRENT_USER(), @@proxy_user; +-------------------+-------------------+--------------+ | USER() | CURRENT_USER() | @@proxy_user | +-------------------+-------------------+--------------+ | antonio@localhost | antonio@localhost | NULL | +-------------------+-------------------+--------------+
これは、
antonio
がantonio
MySQL アカウントに付与された権限を使用し、プロキシ処理が発生していないことを示します。
この認証シナリオでは、LDAP ユーザーのログイン名とパスワードをチェックする際にのみ PAM が使用されます。MySQL サーバーへの接続が許可されている外部ユーザーはすべて、外部 PAM 認証を使用するように定義されている一致する MySQL アカウントを持つべきです。
PAM の LDAP 認証で、パスワード
verysecret
を使用してantonio
としてログインすることが許可されていることを確認します。-
LDAP を使用して
mysql
サービスを認証するように PAM を設定します。/etc/pam.d/mysql
に次の行を挿入します。#%PAM-1.0 auth required pam_ldap.so account required pam_ldap.so
PAM オブジェクトファイルのサフィクスがシステム上の
.so
と異なる場合は、正しいサフィクスに置き換えてください。 MySQL アカウントの作成およびサーバーへの接続は、セクション6.3.8.5.2.1「プロキシユーザーを使用しない Unix パスワード認証」ですでに説明したものと同じです。
この認証スキームでは、さまざまな権限セットを定義する数個の MySQL アカウント上に、PAM を使用して MySQL サーバーに接続するユーザーをマップするグループマッピング、およびプロキシ処理が使用されます。ユーザーは、権限を定義するアカウントを使用して直接接続しません。代わりに、権限を保持している数個の MySQL アカウントに、すべての外部ログインをマップするマッピングスキームが使用される PAM を使用して、デフォルトのプロキシユーザー認証を使用して接続します。接続する任意のユーザーは、MySQL アカウントのいずれかにマップされ、その権限を使用します。
ここに示す手順では、Unix パスワード認証が使用されます。代わりに LDAP を使用するには、前半で示したセクション6.3.8.5.2.2「プロキシユーザーを使用しない LDAP 認証」の手順を参照してください。
PAM の Unix 認証で、パスワード
verysecret
を使用してantonio
としてログインすることが許可されること、およびantonio
がroot
またはusers
のメンバーであることを確認します。-
mysql
サービスを認証するように PAM を設定します。/etc/pam.d/mysql
に次の行を挿入します。#%PAM-1.0 auth include password-auth account include password-auth
-
プロキシ対象アカウントに外部 PAM ユーザーをマップするデフォルトのプロキシユーザーを作成します。
root
PAM グループからdeveloper
MySQL アカウントに外部ユーザーをマップし、users
PAM グループからdata_entry
MySQL アカウントに外部ユーザーをマップします。CREATE USER ''@'' IDENTIFIED WITH authentication_pam AS 'mysql, root=developer, users=data_entry';
サービス名のあとのマッピングリストは、プロキシユーザーを設定する際に必要です。それ以外の場合、プラグインは適切なプロキシ対象ユーザー名に PAM グループの名前をマップする方法を指示できません。
-
データベースにアクセスする際に使用されるプロキシ対象アカウントを作成します。
CREATE USER 'developer'@'localhost' IDENTIFIED BY 'very secret password'; GRANT ALL PRIVILEGES ON mydevdb.* TO 'developer'@'localhost'; CREATE USER 'data_entry'@'localhost' IDENTIFIED BY 'very secret password'; GRANT ALL PRIVILEGES ON mydb.* TO 'data_entry'@'localhost';
これらのアカウント用のパスワードをだれにも通知できない場合、ほかのユーザーはこれらのパスワードを使用して、MySQL サーバーに直接接続できません。代わりに、ユーザーは PAM を使用して認証し、自分の PAM グループに基づいてプロキシによる
developer
またはdata_entry
アカウントを使用することが予想されます。 -
プロキシ対象アカウント用のプロキシアカウントに、
PROXY
権限を付与します。GRANT PROXY ON 'developer'@'localhost' TO ''@''; GRANT PROXY ON 'data_entry'@'localhost' TO ''@'';
-
mysql コマンド行クライアントを使用して、MySQL サーバーへの接続を試みます。例:
mysql --user=antonio --password=verysecret --enable-cleartext-plugin mydb
サーバーは
''@''
アカウントを使用して、接続を認証します。権限antonio
は、メンバーとして属する PAM グループによって異なります。antonio
がroot
PAM グループのメンバーである場合、PAM プラグインは、developer
MySQL ユーザー名にroot
をマップし、その名前をサーバーに返します。サーバーは、''@''
がdeveloper
に対するPROXY
権限を持っていることを確認し、接続を許可します。以降のクエリーは、次に示すような出力を返すはずです。mysql> SELECT USER(), CURRENT_USER(), @@proxy_user; +-------------------+---------------------+--------------+ | USER() | CURRENT_USER() | @@proxy_user | +-------------------+---------------------+--------------+ | antonio@localhost | developer@localhost | ''@'' | +-------------------+---------------------+--------------+
これは、
antonio
がdeveloper
MySQL アカウントに付与された権限を使用し、デフォルトのプロキシユーザーアカウントからプロキシ処理が発生していないことを示します。antonio
がroot
PAM グループのメンバーではないが、users
グループのメンバーである場合にも、同様のプロセスが発生しますが、プラグインはdata_entry
MySQL ユーザー名にuser
グループメンバーシップをマップし、その名前をサーバーに返します。この場合、antonio
はdata_entry
MySQL アカウントの権限を使用します。mysql> SELECT USER(), CURRENT_USER(), @@proxy_user; +-------------------+----------------------+--------------+ | USER() | CURRENT_USER() | @@proxy_user | +-------------------+----------------------+--------------+ | antonio@localhost | data_entry@localhost | ''@'' | +-------------------+----------------------+--------------+
PAM 認証プラグインは、初期化時に
AUTHENTICATION_PAM_LOG
環境の値が設定されているかどうかをチェックします
(値は問題ありません)。その場合、プラグインを使用すると、標準出力への診断メッセージのロギングが有効になります。これらのメッセージは、プラグインが認証を実行するときに発生する
PAM
関連の問題をデバッグする際に役立つことがあります。
一部のメッセージには、PAM プラグインソースファイルと行番号への参照が含まれています。これを使用すると、プラグインアクションをそれが発生するコード内の場所に、より緊密に関連付けることができます。
次のトランスクリプトでは、ロギングを有効にすると生成される情報の種類を示します。これは、正常なプロキシ認証の試行による結果です。
entering auth_pam_server
entering auth_pam_next_token
auth_pam_next_token:reading at [cups,admin=writer,everyone=reader], sep=[,]
auth_pam_next_token:state=PRESPACE, ptr=[cups,admin=writer,everyone=reader],
out=[]
auth_pam_next_token:state=IDENT, ptr=[cups,admin=writer,everyone=reader],
out=[]
auth_pam_next_token:state=AFTERSPACE, ptr=[,admin=writer,everyone=reader],
out=[cups]
auth_pam_next_token:state=DELIMITER, ptr=[,admin=writer,everyone=reader],
out=[cups]
auth_pam_next_token:state=DONE, ptr=[,admin=writer,everyone=reader],
out=[cups]
leaving auth_pam_next_token on
/Users/gkodinov/mysql/work/x-5.5.16-release-basket/release/plugin/pam-authentication-plugin/src/parser.c:191
auth_pam_server:password 12345qq received
auth_pam_server:pam_start rc=0
auth_pam_server:pam_set_item(PAM_RUSER,gkodinov) rc=0
auth_pam_server:pam_set_item(PAM_RHOST,localhost) rc=0
entering auth_pam_server_conv
auth_pam_server_conv:PAM_PROMPT_ECHO_OFF [Password:] received
leaving auth_pam_server_conv on
/Users/gkodinov/mysql/work/x-5.5.16-release-basket/release/plugin/pam-authentication-plugin/src/authentication_pam.c:257
auth_pam_server:pam_authenticate rc=0
auth_pam_server:pam_acct_mgmt rc=0
auth_pam_server:pam_setcred(PAM_ESTABLISH_CRED) rc=0
auth_pam_server:pam_get_item rc=0
auth_pam_server:pam_setcred(PAM_DELETE_CRED) rc=0
entering auth_pam_map_groups
entering auth_pam_walk_namevalue_list
auth_pam_walk_namevalue_list:reading at: [admin=writer,everyone=reader]
entering auth_pam_next_token
auth_pam_next_token:reading at [admin=writer,everyone=reader], sep=[=]
auth_pam_next_token:state=PRESPACE, ptr=[admin=writer,everyone=reader], out=[]
auth_pam_next_token:state=IDENT, ptr=[admin=writer,everyone=reader], out=[]
auth_pam_next_token:state=AFTERSPACE, ptr=[=writer,everyone=reader],
out=[admin]
auth_pam_next_token:state=DELIMITER, ptr=[=writer,everyone=reader],
out=[admin]
auth_pam_next_token:state=DONE, ptr=[=writer,everyone=reader], out=[admin]
leaving auth_pam_next_token on
/Users/gkodinov/mysql/work/x-5.5.16-release-basket/release/plugin/pam-authentication-plugin/src/parser.c:191
auth_pam_walk_namevalue_list:name=[admin]
entering auth_pam_next_token
auth_pam_next_token:reading at [writer,everyone=reader], sep=[,]
auth_pam_next_token:state=PRESPACE, ptr=[writer,everyone=reader], out=[]
auth_pam_next_token:state=IDENT, ptr=[writer,everyone=reader], out=[]
auth_pam_next_token:state=AFTERSPACE, ptr=[,everyone=reader], out=[writer]
auth_pam_next_token:state=DELIMITER, ptr=[,everyone=reader], out=[writer]
auth_pam_next_token:state=DONE, ptr=[,everyone=reader], out=[writer]
leaving auth_pam_next_token on
/Users/gkodinov/mysql/work/x-5.5.16-release-basket/release/plugin/pam-authentication-plugin/src/parser.c:191
walk, &error_namevalue_list:value=[writer]
entering auth_pam_map_group_to_user
auth_pam_map_group_to_user:pam_user=gkodinov, name=admin, value=writer
examining member root
examining member gkodinov
substitution was made to mysql user writer
leaving auth_pam_map_group_to_user on
/Users/gkodinov/mysql/work/x-5.5.16-release-basket/release/plugin/pam-authentication-plugin/src/authentication_pam.c:118
auth_pam_walk_namevalue_list:found mapping
leaving auth_pam_walk_namevalue_list on
/Users/gkodinov/mysql/work/x-5.5.16-release-basket/release/plugin/pam-authentication-plugin/src/parser.c:270
auth_pam_walk_namevalue_list returned 0
leaving auth_pam_map_groups on
/Users/gkodinov/mysql/work/x-5.5.16-release-basket/release/plugin/pam-authentication-plugin/src/authentication_pam.c:171
auth_pam_server:authenticated_as=writer
auth_pam_server: rc=0
leaving auth_pam_server on
/Users/gkodinov/mysql/work/x-5.5.16-release-basket/release/plugin/pam-authentication-plugin/src/authentication_pam.c:429