第 6 章 セキュリティー

目次

6.1 一般的なセキュリティーの問題
6.1.1 セキュリティーガイドライン
6.1.2 パスワードをセキュアな状態にする
6.1.3 攻撃者に対する MySQL のセキュアな状態の維持
6.1.4 セキュリティー関連の mysqld オプションおよび変数
6.1.5 MySQL を通常ユーザーとして実行する方法
6.1.6 LOAD DATA LOCAL のセキュリティーの問題
6.1.7 クライアントプログラミングのセキュリティーガイドライン
6.2 MySQL アクセス権限システム
6.2.1 MySQL で提供される権限
6.2.2 権限システム付与テーブル
6.2.3 アカウント名の指定
6.2.4 アクセス制御、ステージ 1: 接続の検証
6.2.5 アクセス制御、ステージ 2: リクエストの確認
6.2.6 権限変更が有効化される時期
6.2.7 アクセス拒否エラーの原因
6.3 MySQL ユーザーアカウントの管理
6.3.1 ユーザー名とパスワード
6.3.2 ユーザーアカウントの追加
6.3.3 ユーザーアカウントの削除
6.3.4 アカウントリソース制限の設定
6.3.5 アカウントパスワードの割り当て
6.3.6 パスワードの期限切れとサンドボックスモード
6.3.7 プラガブル認証
6.3.8 MySQL で使用可能な認証プラグイン
6.3.9 プロキシユーザー
6.3.10 セキュアな接続のための SSL の使用
6.3.11 SSH を使用した Windows から MySQL へのリモート接続
6.3.12 MySQL Enterprise Audit ログプラグイン
6.3.13 SQL ベースの MySQL アカウントアクティビティーの監査

MySQL インストール内のセキュリティーについて検討するときは、可能性のあるさまざまなトピックについて考慮し、それらが MySQL サーバーおよび関連するアプリケーションのセキュリティーに及ぼす影響について考慮するようにしてください。

6.1 一般的なセキュリティーの問題

このセクションでは、留意するべき一般的なセキュリティーの問題と、攻撃または悪用に対して MySQL インストールをさらにセキュアな状態にするために実行可能なアクションについて説明します。ユーザーアカウントのセットアップおよびデータベースアクセスの検査のために MySQL が使用するアクセス制御システムについての詳細は、セクション2.10「インストール後のセットアップとテスト」を参照してください。

MySQL Server のセキュリティーの問題について、よくある質問のうちのいくつかに対する回答は、セクションA.9「MySQL 5.6 FAQ: セキュリティー」を参照してください。

6.1.1 セキュリティーガイドライン

インターネットに接続したコンピュータ上で MySQL を使用するすべてのユーザーは、セキュリティーに関するもっとも一般的な間違いを回避するために、このセクションを読むようにしてください。

セキュリティーについて検討する際、該当するすべての種類の攻撃 (盗聴、改変、プレイバック、およびサービス妨害) から、(MySQL サーバーだけでなく) サーバーホスト全体を完全に保護することを考慮する必要があります。ここでは可用性およびフォールトトレランスのすべての側面について扱うことはしません。

MySQL では、ユーザーが実行を試行できるすべての接続、クエリー、およびその他の操作に対して、アクセス制御リスト (ACL) に基づくセキュリティーが使用されています。また、MySQL クライアントとサーバーの間で SSL に対応した接続のサポートもあります。ここで説明されている多くの概念は MySQL に固有のものではなく、同じような一般的な考え方は、ほぼすべてのアプリケーションに該当します。

MySQL を実行するときは、次のガイドラインに従ってください。

  • mysql データベース内の user テーブルに対するアクセス権限を (MySQL root アカウント以外の) すべてのユーザーに絶対に付与しないでください。これはきわめて重要です。

  • MySQL アクセス権限システムのしくみについて学習してください (セクション6.2「MySQL アクセス権限システム」を参照してください)。MySQL へのアクセスを制御するには、GRANT および REVOKE ステートメントを使用します。必要以上の権限を付与しないでください。すべてのホストに権限を付与してはいけません。

    チェックリスト:

    • mysql -u root を試してください。パスワードを尋ねられずにサーバーへの接続に成功する場合、すべてのユーザーが、完全な権限を持つ MySQL root ユーザーとして MySQL サーバーに接続できます。root パスワードの設定に関する情報に特に注意して、MySQL インストール手順を見直してください。セクション2.10.2「最初の MySQL アカウントのセキュリティー設定」を参照してください。

    • SHOW GRANTS ステートメントを使用して、どのアカウントが何にアクセスできるかをチェックします。REVOKE ステートメントを使用して、不要な権限を削除します。

  • 平文パスワードをデータベースに保管しないでください。コンピュータのセキュリティーが損なわれた場合、侵入者はすべてのパスワードのリストを取得して使用することができます。代わりに、SHA2()SHA1()MD5()、またはその他の一方向のハッシュ機能を使用して、ハッシュ値を保管してください。

    レインボーテーブルを使用したパスワードのリカバリを避けるために、これらの関数をプレーンテキストパスワードに使用しないようにしてください。代わりに、ソルトとして使用する何らかの文字列を選択して、hash(hash(パスワード)+ソルト) 値を使用してください。

  • 辞書からパスワードを選択しないでください。パスワードを解読する特殊なプログラムが存在します。xfish98 のようなパスワードでさえも、非常に悪いものです。同じ fish という単語を、標準 QWERTY キーボードでキー 1 個分左にずらしてタイプした duag98 の方が、ずっと優れています。別の方法は、文の各単語の先頭文字を取ったパスワードを使用することです (たとえば、Four score and seven years ago からは Fsasya というパスワードができます)。パスワードは覚えやすく入力も簡単ですが、文を知らない人は推測が困難です。この事例で、数字を示す単語をさらに数値に置き換えて 4 score and 7 years ago という句を作成し、4sa7ya というさらに推測困難なパスワードを得ることができます。

  • ファイアウォールに投資します。これにより、あらゆる種類のソフトウェアの悪用のうち、少なくとも 50% から保護されます。MySQL をファイアウォールの背後または非武装地帯 (DMZ) に配置します。

    チェックリスト:

    • nmap などのツールを使用して、インターネットから自分のポートをスキャンしてみてください。MySQL はデフォルトでポート 3306 を使用します。このポートは信頼できないホストからアクセス可能であってはいけません。MySQL ポートが開いているかどうかを検査する簡単な方法として、いずれかのリモートマシンから次のコマンドを試行します。ここで、server_host は MySQL サーバーが実行しているホストのホスト名または IP アドレスです。

      shell> telnet server_host 3306

      telnet がハングするか、接続が拒否されれば、ポートはブロックされており、これは期待どおりの結果です。接続を取得して、何らかの文字化けした文字が得られた場合、ポートは開いているため、ポートを開いたままにしておく十分な理由が実際にある場合を除き、ファイアウォールまたはルーターで閉じるようにしてください。

  • MySQL にアクセスするアプリケーションは、ユーザーから入力されるすべてのデータを信頼しないようにし、適切な防御的プログラミング技術を使用して記述するようにします。セクション6.1.7「クライアントプログラミングのセキュリティーガイドライン」を参照してください。

  • プレーンの (暗号化されていない) データをインターネット経由で送信しないでください。この情報は、情報を傍受する時間と能力を持ち、自身の目的のために情報を使用するすべての人物からアクセスできます。代わりに、SSL や SSH などの暗号化されたプロトコルを使用してください。MySQL は、内部 SSL 接続をサポートします。別の技術として、SSH ポートフォワーディングを使用して、暗号化された (および圧縮された) 通信用トンネルを作成する方法があります。

  • tcpdumpstrings などのユーティリティーの使用法について学習します。ほとんどの場合、次のようなコマンドを発行することによって、MySQL データストリームが暗号化されていない状態であるかどうかを検査できます。

    shell> tcpdump -l -i eth0 -w - src or dst port 3306 | strings

    これは Linux で動作するほか、ほかのシステムでもわずかな変更を行うことで動作するはずです。

    警告

    平文データが表示されない場合、これは情報が実際に暗号化されていることを必ずしも意味しているわけではありません。セキュリティーを強化する必要がある場合、セキュリティーの専門家に相談してください。

6.1.2 パスワードをセキュアな状態にする

パスワードは MySQL のいくつかのコンテキストで現れます。次のセクションでは、エンドユーザーおよび管理者がこれらのパスワードをセキュアな状態にし、公開しないようにするためのガイドラインを提供します。また、MySQL がパスワードハッシュを内部で使用する方法や、厳密なパスワードを強制するために使用できるプラグインについても説明します。

6.1.2.1 パスワードセキュリティーのためのエンドユーザーガイドライン

MySQL ユーザーは、パスワードをセキュアな状態にするために次のガイドラインを使用することをお勧めします。

クライアントプログラムを実行して MySQL サーバーに接続する場合、ほかのユーザーからの検出によって公開されるような方法でパスワードを指定することはお勧めできません。クライアントプログラムを実行するときにパスワードを指定するために使用できる方法と、それぞれの方法のリスクの評価について、次の一覧で示します。簡単に言えば、もっとも安全な方法は、クライアントプログラムがパスワードを求めるプロンプトを出すようにするか、適切に保護されたオプションファイルにパスワードを指定する方法です。

  • mysql_config_editor ユーティリティーを使用します。これは、.mylogin.cnf という名前の暗号化されたログインファイルに認証情報を格納できます。このファイルは、MySQL Server に接続するための認証情報を取得するために、MySQL クライアントプログラムによってあとで読み取ることができます。セクション4.6.6「mysql_config_editor — MySQL 構成ユーティリティー」を参照してください。

  • コマンド行で -pyour_pass または --password=your_pass オプションを使用します。例:

    shell> mysql -u francis -pfrank db_name

    これは便利ですがセキュアではありません。一部のシステムでは、使用しているパスワードが、コマンド行を表示するためにほかのユーザーによって起動できる ps などのシステムステータスプログラムによって表示可能になります。MySQL クライアントは通常、クライアントの初期化シーケンス中にコマンド行パスワード引数をゼロで上書きします。ただし、まだ値が表示可能な短い期間があります。また、一部のシステムではこの上書きの方法には効果がなく、パスワードは ps から表示可能になったままになります。(SystemV Unix システムおよびおそらくほかのシステムでもこの問題の影響があります。)

    ターミナルウィンドウのタイトルバーに現在のコマンドを表示するようにオペレーティング環境がセットアップされている場合、コマンドがウィンドウのコンテンツ領域からスクロールアウトされて表示されなくなっても、コマンドが実行中であるかぎりパスワードが表示されたままになります。

  • コマンド行でパスワード値を指定せずに -p または --password オプションを使用します。この場合、クライアントプログラムはパスワードを対話的に要求します。

    shell> mysql -u francis -p db_nameEnter password: ********

    * 文字はパスワードを入力したことを示しています。パスワードは入力時に表示されません。

    この方法でパスワードを入力する方が、コマンド行でパスワードを指定するよりもセキュアです。これは、パスワードがほかのユーザーに表示されないためです。ただし、このパスワード入力方法は、対話的に実行するプログラムについてのみ適しています。非対話的に実行するスクリプトからクライアントを呼び出す場合、キーボードからパスワードを入力する機会はありません。一部のシステムでは、スクリプトの 1 行目が (誤って) パスワードとして読み取られて解釈されることすらあります。

  • パスワードをオプションファイルに保管します。たとえば Unix の場合、ホームディレクトリの .my.cnf ファイルの [client] セクションにパスワードを一覧表示することができます。

    [client]
    password=your_pass

    パスワードを安全に保持するには、自分以外のすべてのユーザーからファイルにアクセス可能にしてはいけません。このようにするには、ファイルのアクセスモードを 400 または 600 に設定します。例:

    shell> chmod 600 .my.cnf

    パスワードを格納する特定のオプションファイルをコマンド行から指定するには、--defaults-file=file_name オプションを使用します。ここで file_name はファイルへのフルパス名です。例:

    shell> mysql --defaults-file=/home/francis/mysql-opts

    セクション4.2.6「オプションファイルの使用」には、オプションファイルについてさらに詳しく記載されています。

  • MYSQL_PWD 環境変数にパスワードを保存します。セクション2.12「環境変数」を参照してください。

    この方法で MySQL パスワードを指定することは非常に危険であるため、使用するべきではありません。ps のバージョンによっては、実行プロセスの環境を表示するオプションがあります。一部のシステムで、MYSQL_PWD を設定した場合、パスワードは ps を実行するすべてのユーザーに公開されます。そのようなバージョンの ps を持たないシステムであっても、ユーザーが処理環境を調査できるほかの方法がないと想定することは賢明ではありません。

Unix の場合、mysql クライアントは実行済みステートメントを履歴ファイルに書き込みます (セクション4.5.1.3「mysql のロギング」を参照してください)。デフォルトでは、このファイルは .mysql_history という名前で、ユーザーのホームディレクトリに作成されます。パスワードは、CREATE USERGRANTSET PASSWORD などの SQL ステートメントではプレーンテキストとして書き込むことができるため、これらのステートメントを使用する場合、ステートメントは履歴ファイルに記録されます。このファイルを安全に保持するには、以前 .my.cnf ファイルについて説明したのと同じ方法である制限アクセスモードを使用します。

コマンドインタプリタが履歴を保持するように構成されている場合、コマンドが保存されるすべてのファイルには、コマンド行で入力された MySQL パスワードが格納されます。たとえば、bash~/.bash_history を使用します。そのようなすべてのファイルは、制限アクセスモードにするようにしてください。

6.1.2.2 パスワードセキュリティーについての管理者ガイドライン

データベース管理者は、パスワードをセキュアな状態にするための次のガイドラインを使用するようにしてください。

MySQL はユーザーアカウント用のパスワードを mysql.user テーブルに保管します。このテーブルへのアクセス権を、管理者以外のすべてのアカウントに決して付与しないでください。

アカウントパスワードは期限切れとなることがあり、ユーザーはそれらをリセットする必要があります。セクション6.3.6「パスワードの期限切れとサンドボックスモード」を参照してください。

validate_password プラグインを使用して、許容可能なパスワードについてのポリシーを強制することができます。セクション6.1.2.6「パスワード検証プラグイン」を参照してください。

プラグインディレクトリ (plugin_dir システム変数の値) またはプラグインディレクトリの場所を指定する my.cnf ファイルを変更するためのアクセス権を持つユーザーは、認証プラグインなどのプラグインを置換して、プラグインによって提供される機能を変更することができます。

パスワードが書き込まれる可能性があるログファイルなどのファイルを保護するようにしてください。セクション6.1.2.3「パスワードおよびロギング」を参照してください。

6.1.2.3 パスワードおよびロギング

パスワードは、CREATE USERGRANTSET PASSWORD などの SQL ステートメントや、PASSWORD() 関数を呼び出すステートメントにプレーンテキストとして書き込むことができます。これらのステートメントが MySQL サーバーによって、書き込まれたとおりにログに記録された場合、それらのパスワードはログにアクセス可能なすべてのユーザーから利用できるようになります。

MySQL 5.6.3 からステートメントロギングが変更され、次のステートメントについてはパスワードがプレーンテキストで表示されなくなりました。

CREATE USER ... IDENTIFIED BY ...
GRANT ... IDENTIFIED BY ...
SET PASSWORD ...
SLAVE START ... PASSWORD = ... (as of 5.6.4)
CREATE SERVER ... OPTIONS(... PASSWORD ...) (as of 5.6.9)
ALTER SERVER ... OPTIONS(... PASSWORD ...) (as of 5.6.9)

これらのステートメント内のパスワードは、一般クエリーログ、スロークエリーログ、およびバイナリログについて、ステートメントテキストの文字どおりに表示されないように書き換えられます。ほかのステートメントについては書き換えが適用されません。

一般クエリーログの場合、パスワードの書き換えは、--log-raw オプションを使用してサーバーを起動することによって抑制することができます。このオプションは、サーバーによって受け取られるステートメントの正確なテキストを表示する際の診断目的で役立つ場合がありますが、セキュリティー上の理由で本番用途では推奨されません。

監査ログプラグインによって生成される監査ログファイルの内容は、暗号化されません。セキュリティー上の理由から、このファイルは MySQL サーバーおよびログを表示する正当な理由を持つユーザーからのみアクセス可能なディレクトリに書き込むようにしてください。セクション6.3.12.2「監査ログプラグインのセキュリティーに関する考慮事項」を参照してください。

ログファイルが不当に公開されないよう保護するには、サーバーおよびデータベース管理者にのみアクセスを制限したディレクトリにログファイルを配置するようにしてください。mysql データベース内のテーブルにログを記録する場合、これらのテーブルへのアクセス権を、管理者以外のアカウントに決して付与してはいけません。

レプリケーションスレーブは、レプリケーションマスターのパスワードをマスター情報リポジトリに格納し、このリポジトリは、ファイルまたはテーブルのいずれかになります (セクション17.2.2「レプリケーションリレーおよびステータスログ」を参照してください)。このリポジトリはデータベース管理者からのみアクセス可能になるようにします。MySQL 5.6.4 の時点では、パスワードのファイルへの保管に代わる方法は、START SLAVE ステートメントを使用して、マスターに接続するための資格情報を指定する方法です。

パスワードを保管するテーブルまたはログファイルを含むデータベースバックアップは、制限アクセスモードを使用して保護するようにしてください。

6.1.2.4 MySQL でのパスワードハッシュ

MySQL では、mysql データベースの user テーブルにユーザーアカウントがリストされます。各 MySQL アカウントにパスワードを割り当てることができますが、user テーブルはパスワードの平文バージョンを格納せず、パスワードから計算されたハッシュ値を格納します。

MySQL では、クライアントとサーバーの通信の 2 つのフェーズでパスワードが使用されます。

  • クライアントがサーバーに接続しようとすると、初期認証ステップがあり、そのステップでは、クライアントが使用するアカウントについての user テーブルに格納されたハッシュ値に一致するハッシュ値を持つパスワードをクライアントが提供する必要があります。

  • クライアントが接続したあと、クライアントは (十分な権限がある場合に) user テーブルにリストされているアカウントについてのパスワードハッシュを設定または変更することができます。クライアントは、PASSWORD() 関数を使用してパスワードハッシュを生成するか、パスワード生成ステートメント (CREATE USERGRANT、または SET PASSWORD) を使用することによって、これを行うことができます。

言い換えると、クライアントが最初に接続しようとしたとき、サーバーは認証中にハッシュ値を検査します。接続されたクライアントが PASSWORD() 関数を呼び出すか、パスワード生成ステートメントを使用してパスワードを設定または変更する場合、サーバーはハッシュ値を生成します。

MySQL のパスワードハッシュ方式には、次に記述するような歴史があります。これらの変更は、パスワードハッシュ値を計算する PASSWORD() 関数からの結果と、パスワードが格納される user テーブルの構造の変更によって説明されます。

元の (4.1 より前の) ハッシュ方式

元のハッシュ方式では 16 バイト文字列が生成されていました。そのようなハッシュは、次のようになります。

mysql> SELECT PASSWORD('mypass');+--------------------+
| PASSWORD('mypass') |
+--------------------+
| 6f8c114b58f2ce9e |
+--------------------+

アカウントパスワードを格納するために、user テーブルの Password カラムは、この時点で 16 バイト長でした。

4.1 ハッシュ方式

MySQL 4.1 では、セキュリティーを高めてパスワードが傍受されるリスクを低下させる、パスワードハッシュが導入されました。この変更にはさまざまな側面がありました。

  • PASSWORD() 関数結果の形式の変更

  • Password カラムの拡張

  • デフォルトのハッシュ方式による制御

  • サーバーに接続しようとするクライアントについて、許可されたハッシュ方式による制御

MySQL 4.1 の変更は、2 段階で行われました。

  • MySQL 4.1.0 では 4.1 ハッシュ方式の予備バージョンが使用されていました。この方式は使用期間がたいへん短かったため、以後の説明ではこれについては言及しません。

  • MySQL 4.1.1 ではハッシュ方式が変更され、41 バイトの長いハッシュ値が生成されるようになりました。

    mysql> SELECT PASSWORD('mypass');+-------------------------------------------+
    | PASSWORD('mypass') |
    +-------------------------------------------+
    | *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |
    +-------------------------------------------+

    長いパスワードハッシュ形式は暗号化特性に優れ、長いハッシュに基づくクライアント認証の方が短いハッシュに基づく認証よりセキュアです。

    長いパスワードハッシュに対応するために、user テーブルの Password カラムはこの時点で現在の長さである 41 バイトに変更されました。

    拡張された Password カラムは、4.1 より前と 4.1 の両方の形式でパスワードハッシュを格納できます。特定のハッシュ値の形式は、2 つの方法で決定されます。

    • 長さ: 4.1 および 4.1 より前のハッシュは、それぞれ 41 バイトと 16 バイトです。

    • 4.1 形式のパスワードハッシュは常に * 文字で始まりますが、4.1 より前の形式のパスワードでそうなることはありません。

    4.1 より前のパスワードハッシュを明示的に生成できるようにするために、2 つの追加変更が行われました。

    • ハッシュ値を 16 バイト形式で返す OLD_PASSWORD() 関数が追加されました。

    • 互換性目的で、DBA およびアプリケーションがハッシュ方式を制御できるようにする old_passwords システム変数が追加されました。old_passwords 値がデフォルトの 0 のときは、ハッシュで 4.1 方式を使用し、(41 バイトのハッシュ値)、old_passwords=1 と設定すると、ハッシュで 4.1 より前の方式を使用します。この場合、PASSWORD() は 16 バイト値を生成し、OLD_PASSWORD() と同等です

    クライアントが接続できる方法を DBA が制御できるようにするために、secure_auth システム変数が追加されました。この変数を無効または有効にしてサーバーを起動することにより、クライアントが 4.1 より前の古いパスワードハッシュ方式を使用して接続することを許可または禁止します。MySQL 5.6.5 より前では、secure_auth はデフォルトで無効になっています。5.6.5 の時点では、よりセキュアなデフォルト構成を促進するために secure_auth はデフォルトで有効になっています (DBA は自らの裁量によりこれを無効化できますが、これは推奨されません)。4.1 より前のパスワードハッシュは非推奨であるため使用しないようにしてください。(アカウントのアップグレード手順については、セクション6.3.8.3「4.1 よりも前のパスワードハッシュ方式と mysql_old_password プラグインからの移行」を参照してください。)

    さらに、mysql クライアントは、secure_auth に類似した --secure-auth オプションをサポートしますが、これはクライアント側から指定します。これは 4.1 より前のパスワードハッシュを使用する、セキュアではないアカウントへの接続を防ぐために使用できます。このオプションは、MySQL 5.6.7 より前ではデフォルトで無効になっていますが、それ以降では有効になっています。

ハッシュ方式に関する互換性の問題

MySQL 4.1 での 16 バイトから 41 バイトへの Password カラムの拡張は、インストールまたはアップグレード操作に次のように影響します。

  • MySQL の新規インストールを実行する場合、Password カラムは自動的に 41 バイトの長さになります。

  • MySQL 4.1 以降から現在のバージョンの MySQL へのアップグレードでは、どちらのバージョンも同じカラム長とパスワードハッシュ方式を使用しているため、Password カラムに関して問題は何も発生しないはずです。

  • 4.1 より前のリリースから 4.1 以降へのアップグレードの場合、アップグレード後にシステムテーブルをアップグレードする必要があります。(セクション4.4.7「mysql_upgrade — MySQL テーブルのチェックとアップグレード」を参照してください。)

4.1 ハッシュ方式は MySQL 4.1 (およびそれ以降の) サーバーとクライアントによってのみ認識されるため、互換性の問題が発生する可能性があります。4.1 またはそれより新しいクライアントは、4.1 より前と 4.1 のパスワードハッシュ方式の両方を認識するため、4.1 より前のサーバーに接続できます。ただし、4.1 より前のクライアントが 4.1 またはそれより新しいサーバーに接続しようとすると、問題が発生することがあります。たとえば、4.0 の mysql クライアントは次のエラーメッセージを出して失敗することがあります。

shell> mysql -h localhost -u rootClient does not support authentication protocol requested
by server; consider upgrading MySQL client

この現象は、MySQL 4.1 以降にアップグレードしたあとで、古い PHP mysql 拡張を使用しようとしたときにも発生します。(Common Problems with MySQL and PHPを参照してください。)

次の説明では、4.1 より前と 4.1 のハッシュ方式の違いについて、およびサーバーをアップグレードしたが 4.1 より前のクライアントとの下位互換性を保持する必要がある場合にどうすればよいかについて記載します。(ただし、古いクライアントによる接続を維持することは推奨されず、可能な場合は避けるようにしてください。)セクションB.5.2.4「クライアントは認証プロトコルに対応できません」から追加情報を見つけることができます。この情報は、MySQL データベースを 4.1 より古いバージョンから 4.1 以降にマイグレーションを実行する PHP プログラマにとって特に重要です。

短いパスワードハッシュと長いパスワードハッシュの違いは、サーバーが認証中にパスワードを使用する方法と、パスワード変更操作を実行する接続対象のクライアントに対してサーバーがパスワードハッシュを生成する方法の両方に関係します。

サーバーが認証中にパスワードハッシュを使用する方法は、Password カラムの幅によって影響します。

  • カラムが短い場合、短いハッシュ認証のみが使用されます。

  • カラムが長い場合、短いハッシュまたは長いハッシュのいずれかを保持でき、サーバーはいずれかの形式を使用できます。

    • 4.1 より前のクライアントは接続できますが、4.1 より前のハッシュ方式のみ認識するため、短いハッシュを持つアカウントを使用してのみ認証できます。

    • 4.1 以降のクライアントは、短いハッシュまたは長いハッシュを持つアカウントを使用して認証できます。

短いハッシュのアカウントであっても、認証プロセスは、古いクライアントよりも 4.1 以降のクライアントの方が実際には少しセキュアです。セキュリティーの観点で、セキュアでないものからもっともセキュアなものの順に並べると、次のようになります。

  • 短いパスワードハッシュで認証する 4.1 より前のクライアント

  • 短いパスワードハッシュで認証する 4.1 以降のクライアント

  • 長いパスワードハッシュで認証する 4.1 以降のクライアント

接続対象のクライアントに対してサーバーがパスワードハッシュを生成する方法は、Password カラムの幅と、old_passwords システム変数に影響されます。4.1 以降のサーバーは、特定の条件が満たされた場合にのみ長いハッシュを生成し、この条件とは、Password カラムが長い値を保持するための十分な幅を持つこと、および old_passwords が 1 に設定されていてはいけないということです。

これらの条件は次のように適用されます。

  • Password カラムは、長いハッシュ (41 バイト) を保持するための十分な幅を持つ必要があります。カラムが更新されておらず、4.1 より前の 16 バイトの幅のままである場合、サーバーは長いハッシュがカラムに適合しないことを認識し、クライアントが PASSWORD() 関数またはパスワード生成ステートメントを使用してパスワード変更操作を実行したときに、サーバーは短いハッシュのみ生成します。これは、4.1 より古い MySQL バージョンから 4.1 以降にアップグレードしたが、Password カラムを拡張するための mysql_upgrade プログラムをまだ実行していない場合に発生する動作です。

  • Password カラムが広い場合、短いパスワードハッシュまたは長いパスワードハッシュのいずれかを格納できます。この場合は、代わりに短いパスワードハッシュを生成することをサーバーに強制するために old_passwords システム変数を 1 に設定してサーバーが起動されないかぎり、PASSWORD() 関数およびパスワード生成ステートメントは長いハッシュを生成します。

old_passwords システム変数の目的は、ほかの状況ではサーバーが長いパスワードハッシュを生成するような状況で、4.1 より前のクライアントとの下位互換性を許可することです。このオプションは認証に影響しませんが (4.1 以降のクライアントは、長いパスワードハッシュを持つアカウントを引き続き使用できます)、パスワード変更操作の結果として user テーブル内で長いパスワードハッシュが作成されないようにします。この発生が許される場合、アカウントは 4.1 より前のクライアントによって使用できなくなります。old_passwords を無効にすると、次のような好ましくないシナリオが発生する可能性があります。

  • 4.1 より前の古いクライアントが、短いパスワードハッシュを持つアカウントに接続します。

  • クライアントが自分のパスワードを変更します。old_passwords が無効なとき、これによりアカウントは長いパスワードハッシュを持つようになります。

  • 古いクライアントがアカウントに次回接続しようとしたとき、古いクライアントは接続できません。これはアカウントが、認証中に 4.1 ハッシュ方式を必要とする長いパスワードハッシュを持つためです。(アカウントがユーザーテーブルに長いパスワードハッシュを持つようになると、4.1 より前のクライアントは長いハッシュを認識しないため、4.1 以降のクライアントのみが認証できます。)

このシナリオでは、4.1 より前の古いクライアントをサポートする必要がある場合、old_passwords を 1 に設定しないで 4.1 またはそれより新しいサーバーを実行することは問題があるということを示しています。old_passwords=1 を指定してサーバーを実行することにより、パスワード変更操作は長いパスワードハッシュを生成せず、アカウントが古いクライアントからアクセスできなくなることはありません。(これらのクライアントは、自分のパスワードを変更し、長いパスワードハッシュを結局得ることによって誤って自分自身をロックアウトしてしまうことはありません。)

old_passwords=1 の欠点は、4.1 以降のクライアントについても、作成または変更されたすべてのパスワードが短いハッシュを使用することです。つまり、長いパスワードハッシュによって提供される追加のセキュリティーが失われます。長いハッシュ (たとえば 4.1 クライアントによって使用するためのもの) を持つアカウントを作成するか、長いパスワードハッシュを使用するための既存のアカウントを変更するために、管理者は old_passwords のセッション値を 0 に設定し、グローバル値を 1 に設定したままにすることができます。

mysql> SET @@session.old_passwords = 0;Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @@session.old_passwords, @@global.old_passwords;+-------------------------+------------------------+
| @@session.old_passwords | @@global.old_passwords |
+-------------------------+------------------------+
| 0 | 1 |
+-------------------------+------------------------+
1 row in set (0.00 sec)
mysql> CREATE USER 'newuser'@'localhost' IDENTIFIED BY 'newpass';Query OK, 0 rows affected (0.03 sec)
mysql> SET PASSWORD FOR 'existinguser'@'localhost' = PASSWORD('existingpass');Query OK, 0 rows affected (0.00 sec)

MySQL 4.1 以降では次のシナリオが発生する可能性があります。要因は、Password カラムが短いか長いかということと、長い場合、サーバーが old_passwords を有効または無効のいずれに指定して起動したかということです。

シナリオ 1: ユーザーテーブルの Password カラムが短い場合:

  • Password カラムには短いハッシュのみ格納できます。

  • サーバーはクライアント認証中に短いハッシュのみ使用します。

  • 接続対象のクライアントの場合、PASSWORD() 関数またはパスワード生成ステートメントを含むパスワードハッシュ生成操作では、短いハッシュだけが使用されます。アカウントのパスワードに何らかの変更を行うと、そのアカウントは短いパスワードハッシュを持つことになります。

  • Password カラムが短いと、サーバーは短いパスワードハッシュのみ生成するため、old_passwords の値は無関係です。

このシナリオは、4.1 より前の MySQL インストールが 4.1 以降にアップグレードされたが、mysql_upgrade がまだ実行されておらず、mysql データベース内のシステムテーブルがアップグレードされていない場合に発生します。(これはよりセキュアな 4.1 のパスワードハッシュを使用できなくなるため、推奨される構成ではありません。)

シナリオ 2:Password カラムが長く、サーバーは old_passwords=1 を指定して起動される場合:

  • Password カラムには短いハッシュまたは長いハッシュを格納できます。

  • 4.1 以降のクライアントは、短いハッシュまたは長いハッシュを持つアカウントについて認証できます。

  • 4.1 より前のクライアントは、短いハッシュを持つアカウントについてのみ認証できます。

  • 接続対象のクライアントの場合、PASSWORD() 関数またはパスワード生成ステートメントを含むパスワードハッシュ生成操作では、短いハッシュだけが使用されます。アカウントのパスワードに何らかの変更を行うと、そのアカウントは短いパスワードハッシュを持つことになります。

このシナリオでは、old_passwords=1 によって長いハッシュを生成できないため、新しく作成されるアカウントは短いパスワードハッシュを持ちます。また、old_passwords を 1 に設定する前に長いハッシュを持つアカウントを作成した場合、old_passwords=1 のときにアカウントのパスワードを変更すると、アカウントには短いパスワードが提供され、長いハッシュの持つセキュリティー上の利点を失うことになります。

長いパスワードハッシュを持つ新しいアカウントを作成するか、長いハッシュを使用するための既存のアカウントを変更するには、以前説明したように、まず old_passwords のセッション値を 0 に設定し、グローバル値を 1 に設定したままにします。

このシナリオでは、サーバーの Password カラムは最新状態ですが、サーバーは 4.1 より前のハッシュ値を生成するようにデフォルトのパスワードハッシュ方式を設定して実行されます。これは推奨される構成ではありませんが、4.1 より前のクライアントおよびパスワードが 4.1 以降にアップグレードされる移行期間に役立つことがあります。これが完了したら、old_passwords=0 および secure_auth=1 を指定してサーバーを実行することが推奨されます。

シナリオ 3:Password カラムが長く、サーバーは old_passwords=0 を指定して起動される場合:

  • Password カラムには短いハッシュまたは長いハッシュを格納できます。

  • 4.1 以降のクライアントは、短いハッシュまたは長いハッシュを持つアカウントを使用して認証できます。

  • 4.1 より前のクライアントは、短いハッシュを持つアカウントを使用する場合のみ認証できます。

  • 接続対象のクライアントの場合、PASSWORD() 関数またはパスワード生成ステートメントを含むパスワードハッシュ生成操作では、長いハッシュだけが使用されます。アカウントのパスワードに変更を行うと、そのアカウントは長いパスワードハッシュを持つことになります。

以前示したように、このシナリオの危険性は、短いパスワードハッシュを持つアカウントが 4.1 より前のクライアントからアクセスできなくなることがあるということです。PASSWORD() 関数またはパスワード生成ステートメントを使用して実行したそのようなアカウントのパスワードの変更により、アカウントに長いパスワードハッシュが提供されることになります。その時点以降では、4.1 より前のクライアントはそのアカウントを使用してサーバーに接続できなくなります。クライアントは 4.1 以降にアップグレードする必要があります。

これが問題になる場合、特別な方法でパスワードを変更することができます。たとえば、通常、アカウントのパスワード変更には、SET PASSWORD を次のように使用しています。

SET PASSWORD FOR 'some_user'@'some_host' = PASSWORD('mypass');

パスワードを変更するが、短いハッシュを作成する場合、代わりに OLD_PASSWORD() 関数を使用します。

SET PASSWORD FOR 'some_user'@'some_host' = OLD_PASSWORD('mypass');

OLD_PASSWORD() は、短いハッシュを明示的に生成する必要があるような状況で役立ちます。

前の各シナリオの欠点は、次のように要約できます。

シナリオ 1 では、よりセキュアな認証を提供する長いハッシュを活用することができません。

シナリオ 2 では、old_passwords=1 によって、短いパスワードを持つアカウントをアクセス不能にすることはできませんが、注意を払って old_passwords のセッション値を最初に 0 に変更しないかぎり、パスワード変更操作によって、長いハッシュを持つアカウントは短いハッシュに戻されます。

シナリオ 3 では、短いハッシュを使用するアカウントは OLD_PASSWORD() を明示的に使用せずにパスワードを変更した場合、4.1 より前のクライアントからアクセスできなくなります。

短いパスワードハッシュに関連する互換性の問題を回避するための最良の方法は、短いパスワードハッシュを使用しない方法です。

  • すべてのクライアントプログラムを MySQL 4.1 以降にアップグレードする。

  • old_passwords=0 を指定してサーバーを実行する。

  • 長いパスワードハッシュを使用するために、短いパスワードハッシュを持つすべてのアカウントについてのパスワードをリセットする。

  • セキュリティーを強化するために、secure_auth=1 を指定してサーバーを実行する。

6.1.2.5 MySQL 4.1 でのパスワードハッシュ変更がアプリケーションプログラムに及ぼす影響

アプリケーション固有の目的で PASSWORD() を使用してパスワードを生成するアプリケーションの場合、MySQL バージョン 4.1 以降にアップグレードすると互換性の問題が生じる可能性があります。PASSWORD() は MySQL アカウントのパスワード管理専用のものであるため、アプリケーションではこれを行うべきではありません。ただし、一部のアプリケーションではそれら固有の目的で PASSWORD() を使用しています。

4.1 より前の MySQL バージョンを 4.1 以降にアップグレードして、長いパスワードハッシュを生成する条件でサーバーを実行すると、アプリケーション固有のパスワード用に PASSWORD() を使用するアプリケーションは破損します。そのような状況で推奨される一連のアクションは、アプリケーションを変更して、ハッシュ値を生成する SHA2()SHA1()MD5() などの関数を使用するようにすることです。これが不可能な場合は、古い形式の短いハッシュを生成するために提供されている OLD_PASSWORD() 関数を使用することができます。ただし、OLD_PASSWORD() は将来サポートされなくなる可能性があることに留意してください。

サーバーが old_passwords=1 を指定して実行している場合、サーバーは短いハッシュを生成し、OLD_PASSWORD()PASSWORD() と同等になります。

MySQL データベースをバージョン 4.0 以前からバージョン 4.1 以降にマイグレーションを実行する PHP プログラマは、MySQL and PHPを参照してください。

6.1.2.6 パスワード検証プラグイン

validate_password プラグイン (MySQL 5.6.6 の時点で使用可能) は、パスワードをテストしてセキュリティーを向上させるために使用することができます。このプラグインは、2 つの機能を実装します。

  • 平文の値として指定されるパスワードを割り当てるステートメントで、値は現在のパスワードポリシーと照合して検査され、弱い場合は拒否されます (ステートメントは ER_NOT_VALID_PASSWORD エラーを返します)。これは、CREATE USERGRANT、および SET PASSWORD ステートメントに影響します。PASSWORD() および OLD_PASSWORD() 関数への引数として指定されるパスワードも検査されます。

  • パスワード候補の強さは、VALIDATE_PASSWORD_STRENGTH() SQL 関数を使用して評価でき、これはパスワード引数を取得して、0 (弱い) から 100 (強い) までの整数を返します。

たとえば、次のステートメントの平文パスワードが検査されます。デフォルトのパスワードポリシーではパスワードに最低 8 文字の長さが要求されるため、パスワードが弱いことからステートメントはエラーを生成します。

mysql> SET PASSWORD = PASSWORD('abc');ERROR 1819 (HY000): Your password does not satisfy the current policy
requirements

ハッシュ済みの値として指定されたパスワードは、元のパスワード値が得られないため検査されません。

mysql> SET PASSWORD = '*0D3CED9BEC10A777AEC23CCC353A8C08A633045E';Query OK, 0 rows affected (0.01 sec)

パスワード検査を制御するパラメータは、validate_password_xxx の形式の名前を持つシステム変数の値として利用できます。これらの変数を変更してパスワード検査を構成することができます。セクション6.1.2.6.2「パスワード検証プラグインのオプションおよび変数」を参照してください。

パスワード検査の 3 つのレベルは、LOWMEDIUM、および STRONG です。デフォルトは MEDIUM で、これを変更するには、validate_password_policy の値を変更します。これらのポリシーにより、実装されるパスワードテストはますます厳密になります。次の記述はデフォルトのパラメータ値を示しており、これらは適切なシステム変数を変更することによって変更できます。

  • LOW ポリシーは、パスワードの長さのみテストします。パスワードは少なくとも 8 文字の長さでなければなりません。

  • MEDIUM ポリシーは、パスワードが最低 1 つの数値文字を含み、1 つの小文字および大文字を含み、1 つの特殊文字 (英数字以外) を含む必要があるという条件を追加します。

  • STRONG ポリシーは、パスワードの 4 文字以上の部分文字列が、(辞書ファイルが指定された場合に) 辞書ファイル内の単語と一致してはならないという条件を追加します。

validate_password プラグインがインストールされていない場合、validate_password_xxx システム変数は利用できず、ステートメント内のパスワードは検査されず、VALIDATE_PASSWORD_STRENGTH() は常に 0 を返します。たとえば、アカウントに 8 文字より短いパスワードを割り当てることができます。

6.1.2.6.1 パスワード検証プラグインのインストール

パスワード検証プラグインの名前は validate_password です。サーバーから使用できるようにするには、プラグインライブラリのオブジェクトファイルが MySQL プラグインディレクトリ (plugin_dir システム変数によって指定されたディレクトリ) に存在する必要があります。必要に応じて、サーバーの起動時に、プラグインディレクトリの場所をサーバーに指示する plugin_dir の値を設定します。

サーバー起動時にプラグインをロードするには、--plugin-load オプションを使用して、プラグインを格納するオブジェクトファイルの名前を指定します。このプラグインのロード方式では、サーバーを起動するたびにオプションを指定する必要があります。たとえば、my.cnf ファイルに次の行を入力します。

[mysqld]
plugin-load=validate_password.so

システム上のオブジェクトファイルのサフィクスが .so とは異なる場合、正しいサフィクスに置き換えてください (たとえば Windows の場合は .dll)。

または、プラグインを実行時に登録するには (必要に応じて拡張子を変更して) 次のステートメントを使用します。

mysql> INSTALL PLUGIN validate_password SONAME 'validate_password.so';

INSTALL PLUGIN は、プラグインをロードします。また、後続の通常のサーバー起動のたびにプラグインがロードされるように、そのプラグインを mysql.plugins テーブルに登録します。

プラグインが INSTALL PLUGIN によって以前登録されているか、--plugin-load を指定してロードされた場合、--validate-password オプションをサーバー起動時に使用して、プラグインの有効化を制御できます。たとえば、プラグインをロードして、実行時に削除されないようにするには、次のオプションを使用します。

[mysqld]
plugin-load=validate_password.so
validate-password=FORCE_PLUS_PERMANENT

パスワード検証プラグインを使用せずにサーバーが実行することを回避することが望まれる場合、--validate-passwordFORCE または FORCE_PLUS_PERMANENT の値を指定して使用することで、プラグインが正常に初期化しない場合にサーバー起動を強制的に失敗させるようにします。

プラグインのインストールについての一般的な情報は、セクション5.1.8「サーバープラグイン」を参照してください。プラグインのインストールを検証するには、INFORMATION_SCHEMA.PLUGINS テーブルを調査するか、SHOW PLUGINS ステートメントを使用します。セクション5.1.8.2「サーバープラグイン情報の取得」を参照してください。

6.1.2.6.2 パスワード検証プラグインのオプションおよび変数

validate_password プラグインの有効化を制御するには、次のオプションを使用します。

  • --validate-password[=value]

    導入5.6.6
    コマンド行形式--validate-password[=value]
    許可されている値列挙
    デフォルトON
    有効な値ON
    OFF
    FORCE
    FORCE_PLUS_PERMANENT

    このオプションは、サーバーが起動時に validate_password プラグインをロードする方法を制御します。値はセクション5.1.8.1「プラグインのインストールおよびアンインストール」に記載されているような、プラグインロードオプション用に指定可能ないずれかの値とする必要があります。たとえば、--validate-password=FORCE_PLUS_PERMANENT の場合、プラグインをロードし、サーバーの実行中にプラグインが削除されないようにするようサーバーに指示します。

    このオプションは、validate_password プラグインが INSTALL PLUGIN で以前登録されていたか、--plugin-load でロードされている場合にのみ利用できます。セクション6.1.2.6.1「パスワード検証プラグインのインストール」を参照してください。

validate_password プラグインがインストールされている場合、パスワード検査を制御するパラメータを示すいくつかのシステム変数を公開します。

mysql> SHOW VARIABLES LIKE 'validate_password%';+--------------------------------------+--------+
| Variable_name | Value |
+--------------------------------------+--------+
| validate_password_dictionary_file | |
| validate_password_length | 8 |
| validate_password_mixed_case_count | 1 |
| validate_password_number_count | 1 |
| validate_password_policy | MEDIUM |
| validate_password_special_char_count | 1 |
+--------------------------------------+--------+

パスワードの検査方法を変更するために、これらの変数はいずれもサーバー起動時に設定でき、これらのほとんどは実行時にも設定できます。次のリストは、各変数の意味を説明したものです。

  • validate_password_dictionary_file

    導入5.6.6
    システム変数名前validate_password_dictionary_file
    変数スコープグローバル
    動的変数いいえ
    許可されている値ファイル名

    パスワードを検査するために validate_password プラグインによって使用される辞書ファイルのパス名。この変数は、そのプラグインがインストールされないかぎり利用できません。

    デフォルトでは、この変数は空の値を持ち、辞書検査は実行されません。辞書検査を有効にするには、この変数を空白でない値に設定する必要があります。ファイル名が相対パスとして指定された場合、サーバーのデータディレクトリを基準として解釈されます。この内容は小文字で記載し、1 行に 1 つの単語としてください。内容は、utf8 の文字セットを持つものとして処理されます。許可される最大のファイルサイズは 1M バイトです。

    パスワード検査中に辞書ファイルが使用されるようにするには、パスワードポリシーを 2 (STRONG) に設定する必要があります。validate_password_policy システム変数の説明を参照してください。これが true である場合、長さが 4 から 100 までのパスワードの各部分文字列が辞書ファイル内の単語と比較されます。いずれかが一致すると、パスワードが拒否されます。比較では大文字と小文字が区別されません。

    VALIDATE_PASSWORD_STRENGTH() の場合、パスワードは STRONG を含むすべてのポリシーと照合して検査されるため、強さの評価には validate_password_policy 値に関係なく辞書検査が含まれます。

    サーバーが実行中に辞書ファイルに変更を行なった場合、変更を認識させるにはサーバーの再起動が必要です。

  • validate_password_length

    導入5.6.6
    システム変数名前validate_password_length
    変数スコープグローバル
    動的変数はい
    許可されている値数値
    デフォルト8
    最小値0

    validate_password プラグインによって検査されるパスワードに必要な最小の文字数。この変数は、そのプラグインがインストールされないかぎり利用できません。

    validate_password_length の最小値は、関連するほかのいくつかのシステム変数の関数です。MySQL 5.6.10 の時点では、サーバーでは次の式の値より小さい値は設定されません。

    validate_password_number_count
    + validate_password_special_char_count
    + (2 * validate_password_mixed_case_count)

    前述の制約のため validate_password プラグインが validate_password_length の値を調整した場合、プラグインはエラーログファイルにメッセージを書き込みます。

  • validate_password_mixed_case_count

    導入5.6.6
    システム変数名前validate_password_mixed_case_count
    変数スコープグローバル
    動的変数はい
    許可されている値数値
    デフォルト1
    最小値0

    パスワードポリシーが MEDIUM またはそれより強い場合、validate_password プラグインによって検査されるパスワードに必要な小文字および大文字の最大数。この変数は、そのプラグインがインストールされないかぎり利用できません。

  • validate_password_number_count

    導入5.6.6
    システム変数名前validate_password_number_count
    変数スコープグローバル
    動的変数はい
    許可されている値数値
    デフォルト1
    最小値0

    パスワードポリシーが MEDIUM またはそれより強い場合、validate_password プラグインによって検査されるパスワードに必要な数値文字 (数字) の最大数。この変数は、そのプラグインがインストールされないかぎり利用できません。

  • validate_password_policy

    導入5.6.6
    システム変数名前validate_password_policy
    変数スコープグローバル
    動的変数はい
    許可されている値列挙
    デフォルト1
    有効な値0
    1
    2

    validate_password プラグインによって適用されるパスワードポリシー。この変数は、そのプラグインがインストールされないかぎり利用できません。

    validate_password_policy 値は、数値 0、1、2 または対応する記号値 LOWMEDIUMSTRONG を使用して指定できます。次の表では、それぞれのポリシーに対して実施されるテストについて説明します。長さテストの場合、必要な長さは validate_password_length システム変数の値です。同様に、ほかのテストについて必要な値は、ほかの validate_password_xxx 変数によって提供されます。

    ポリシー実施されるテスト
    0 または LOW長さ
    1 または MEDIUM長さ。数値、小文字、大文字、および特殊文字
    2 または STRONG長さ。数値、小文字、大文字、および特殊文字。辞書ファイル
    注記

    MySQL 5.6.10 以前では、validate_password_policy の名前は validate_password_policy_number でした。

  • validate_password_special_char_count

    導入5.6.6
    システム変数名前validate_password_special_char_count
    変数スコープグローバル
    動的変数はい
    許可されている値数値
    デフォルト1
    最小値0

    パスワードポリシーが MEDIUM またはそれより強い場合、validate_password プラグインによって検査されるパスワードに必要な英数字以外の文字の最大数。この変数は、そのプラグインがインストールされないかぎり利用できません。

6.1.3 攻撃者に対する MySQL のセキュアな状態の維持

MySQL サーバーに接続するときは、パスワードを使用するようにしてください。接続において、パスワードは平文で送信されません。クライアント接続シーケンス中のパスワード処理は、きわめてセキュアな状態を維持するように MySQL 4.1.1 でアップグレードされました。4.1.1 より前の形式のパスワードをまだ使用している場合、暗号化アルゴリズムは新しいアルゴリズムほど強くありません。クライアントとサーバーの間のトラフィックを傍受できる利口な攻撃者は、多少の労力をかければパスワードを解読することができます。(さまざまなパスワード処理方法についての説明は、セクション6.1.2.4「MySQL でのパスワードハッシュ」を参照してください。)

ほかのすべての情報はテキストとして送信され、接続を観察できるすべてのユーザーによって読み取ることができます。クライアントとサーバーの間の接続が、信頼できないネットワークを介して行われ、そのことに不安がある場合、圧縮されたプロトコルを使用して、トラフィックの解読をさらに困難にすることができます。また、MySQL の内部 SSL サポートを使用して、接続をさらにセキュアな状態にすることもできます。セクション6.3.10「セキュアな接続のための SSL の使用」を参照してください。または SSH を使用して、MySQL サーバーと MySQL クライアントの間で暗号化された TCP/IP 接続を実現します。オープンソース SSH クライアントは http://www.openssh.org/ から見つけることができ、オープンソースと商用の SSH クライアントの比較は http://en.wikipedia.org/wiki/Comparison_of_SSH_clients にあります。

MySQL システムをセキュアな状態にするには、次の推奨事項についてよく検討するようにしてください。

  • すべての MySQL アカウントがパスワードを持つことを要求します。クライアントプログラムは、それを実行中の人物の ID を必ずしも認識しているわけではありません。クライアント/サーバーアプリケーションでは、ユーザーがクライアントプログラムに任意のユーザー名を指定できることが一般的です。たとえば、other_user にパスワードがない場合、mysql プログラムを mysql -u other_userdb_name として呼び出すことによって、すべてのユーザーがこのプログラムを使用してほかのユーザーとして接続することができます。すべてのアカウントにパスワードがある場合、ほかのユーザーのアカウントを使用した接続は、もっと難しくなります。

    パスワードの設定方法についての説明は、セクション6.3.5「アカウントパスワードの割り当て」を参照してください。

  • データベースディレクトリ内の読み取りまたは書き込み権限を持つ Unix ユーザーアカウントのみが、mysqld の実行に使用されるアカウントであるようにしてください。

  • MySQL サーバーを Unix root ユーザーとして絶対に実行しないでください。これを行うと、FILE 権限を持つすべてのユーザーが、root としてサーバーにファイルを作成させることができるため (~root/.bashrc など)、非常に危険です。これを防ぐために、mysqld--user=root オプションを使用して明示的に指定された場合を除き、root として実行することを拒否します。

    mysqld は、権限のない普通のユーザーとしても実行できます (また、そのように実行するべきです)。mysql という名前の別の Unix アカウントを作成して、すべてをさらにセキュアな状態にすることができます。このアカウントは、MySQL の管理にのみ使用してください。mysqld を別の Unix ユーザーとして開始するには、サーバーオプションを指定した my.cnf オプションファイルの [mysqld] グループ内のユーザー名を指定する user オプションを追加します。例:

    [mysqld]
    user=mysql

    これにより、サーバーを手動で起動した場合も、mysqld_safe または mysql.server を使用して起動した場合も、指定のユーザーでサーバーが起動します。詳細は、セクション6.1.5「MySQL を通常ユーザーとして実行する方法」を参照してください。

    root 以外の Unix ユーザーとして mysqld を実行しても、user テーブル内の root ユーザー名を変更する必要があるということを意味するわけではありません。MySQL アカウントのユーザー名は、Unix アカウントのユーザー名とは何の関係もありません

  • 管理者以外のユーザーに FILE 権限を付与しないでください。この権限を持つすべてのユーザーは、mysqld デーモンの権限で、ファイルシステムのあらゆる場所のファイルに書き込むことができます。これは、権限テーブルを実装するファイルを格納するサーバーのデータディレクトリを含みます。FILE 権限の操作をもう少し安全にするために、SELECT ... INTO OUTFILE で生成されたファイルは既存のファイルを上書きせず、すべてのユーザーによって書き込み可能になります。

    FILE 権限は、すべてのユーザーが読み取り可能であるか、サーバーを実行している Unix ユーザーがアクセスできる、すべてのファイルを読み取る場合にも使用できます。この権限を使用して、すべてのファイルをデータベーステーブルに読み取ることができます。これは不正使用される可能性があり、たとえば LOAD DATA を使用して /etc/passwd をテーブルにロードし、次に SELECT を使用してこれを表示することができます。

    ファイルを読み取りおよび書き込みできる場所を制限するには、secure_file_priv システムを特定のディレクトリに設定します。セクション5.1.4「サーバーシステム変数」を参照してください。

  • 管理者以外のユーザーに PROCESS または SUPER 権限を付与しないでください。mysqladmin processlist および SHOW PROCESSLIST の出力には、現在実行されているすべてのステートメントのテキストが表示されるため、サーバープロセスリストを表示できるすべてのユーザーが、ほかのユーザーによって発行された UPDATE user SET password=PASSWORD('not_secure') などのステートメントを表示できる場合があります。

    mysqld は、SUPER 権限を持つユーザー用に特別な接続を確保しているため、通常の接続がすべて使用中の場合でも、MySQL root ユーザーはログインしてサーバーのアクティビティーを検査することができます。

    SUPER 権限は、クライアント接続を終了したり、システム変数の値を変更することによってサーバー操作を変更したり、レプリケーションサーバーを制御したりするために使用することができます。

  • テーブルへのシンボリックリンクを許可しないでください。(この機能は --skip-symbolic-links オプションで無効にできます。)このことは、mysqldroot として実行する場合に特に重要です。これは、サーバーのデータディレクトリへの書き込みアクセス権限があるすべてのユーザーは、システムのすべてのファイルを削除できることになるためです。セクション8.11.3.1.2「Unix 上の MyISAM へのシンボリックリンクの使用」を参照してください。

  • ストアドプログラムおよびビューは、セクション20.6「ストアドプログラムおよびビューのアクセスコントロール」に記載されているセキュリティーガイドラインを使用して記述するようにしてください。

  • DNS を信頼していない場合、付与テーブル内でホスト名の代わりに IP アドレスを使用するようにしてください。いずれの場合も、ワイルドカードを含むホスト名の値を使用して付与テーブルエントリを作成することについては、十分に注意するようにしてください。

  • 単一アカウントに対して許可される接続数を制限するには、mysqldmax_user_connections 変数を設定することによってこれを実行できます。GRANT ステートメントは、アカウントに対して許可されるサーバー使用の範囲を制限するためのリソース制御オプションもサポートします。セクション13.7.1.4「GRANT 構文」を参照してください。

  • プラグインディレクトリがサーバーによって書き込み可能な場合、ユーザーは SELECT ... INTO DUMPFILE を使用して、ディレクトリ内のファイルに実行可能コードを書き込むことができます。これを防ぐために、plugin_dir をサーバーに対して読み取り専用にしたり、SELECT 書き込みが安全に実行できるディレクトリに --secure-file-priv を設定したりできます。

6.1.4 セキュリティー関連の mysqld オプションおよび変数

次の表は、セキュリティーに影響する mysqld オプションおよびシステム変数を示します。これらの個別の説明は、セクション5.1.3「サーバーコマンドオプション」およびセクション5.1.4「サーバーシステム変数」を参照してください。

表 6.1 セキュリティーオプションと変数のサマリー

名前コマンド行オプションファイルシステム変数ステータス変数変数スコープ動的
allow-suspicious-udfsはいはい    
automatic_sp_privileges  はい グローバルはい
chrootはいはい    
des-key-fileはいはい    
local_infile  はい グローバルはい
old_passwords  はい 両方はい
safe-user-createはいはい    
secure-authはいはい  グローバルはい
- 変数: secure_auth  はい グローバルはい
secure-file-privはいはい  グローバルいいえ
- 変数: secure_file_priv  はい グローバルいいえ
skip-grant-tablesはいはい    
skip-name-resolveはいはい  グローバルいいえ
- 変数: skip_name_resolve  はい グローバルいいえ
skip-networkingはいはい  グローバルいいえ
- 変数: skip_networking  はい グローバルいいえ
skip-show-databaseはいはい  グローバルいいえ
- 変数: skip_show_database  はい グローバルいいえ

6.1.5 MySQL を通常ユーザーとして実行する方法

Windows 上では、通常のユーザーアカウントを使用して Windows サービスとしてサーバーを実行できます。

Unix では、MySQL サーバー mysqld を起動でき、すべてのユーザーが実行できます。しかし、セキュリティー上の理由から、Unix root ユーザーとしてサーバーを実行することは避けてください。mysqld を変更し、権限のない普通の Unix ユーザー user_name として実行するには、次のことを行う必要があります。

  1. サーバーが稼働していれば、サーバーを停止します (mysqladmin shutdown を使用します)。

  2. データベースディレクトリとファイルを変更して、user_name がそこのファイルの読み取りおよび書き込みを行う権限を与えます (この操作は Unix root ユーザーとして行う必要があります)。

    shell> chown -R user_name/path/to/mysql/datadir

    この操作を行わない場合、サーバーは user_name として実行するとき、データベースまたはテーブルにアクセスできません。

    MySQL データディレクトリ内のディレクトリまたはファイルがシンボリックリンクの場合、chown -R がシンボリックリンク先を参照しないことがあります。参照しない場合、それらのリンクを参照し、指定先のディレクトリおよびファイルを変更する必要もあります。

  3. user_name というユーザーでサーバーを起動します。代わりに、Unix root ユーザーとして --user=user_name オプションを使用して mysqld を起動する方法もあります。mysqld が起動すると、接続を受け入れる前に Unix ユーザー user_name としての実行に切り替わります。

  4. システム起動時に指定されたユーザーとしてサーバーを起動するには、/etc/my.cnf オプションファイルまたはサーバーのデータディレクトリに格納されている my.cnf オプションファイルの [mysqld] グループに、user オプションを追加することによってユーザー名を指定します。例:

    [mysqld]
    user=user_name

Unix マシン自体がセキュアな状態でない場合、付与テーブルの MySQL root アカウントにパスワードを割り当てるようにします。これをしないと、そのマシンのログインアカウントを持つすべてのユーザーが、--user=root オプションを使用して mysql クライアントを実行でき、あらゆる操作を行うことができます。(すべての場合に MySQL アカウントにパスワードを割り当てることはよい考えですが、ほかのログインアカウントがサーバーホスト上に存在する場合は特に重要です。)セクション2.10.2「最初の MySQL アカウントのセキュリティー設定」を参照してください。

6.1.6 LOAD DATA LOCAL のセキュリティーの問題

LOAD DATA ステートメントは、サーバーホストに配置されているファイルをロードしたり、LOCAL キーワードが指定された場合に、クライアントホストに配置されているファイルをロードしたりできます。

LOAD DATA ステートメントの LOCAL バージョンのサポートに関しては、セキュリティーについての潜在的な問題が 2 つあります。

  • クライアントホストからサーバーホストへのファイルの送信は、MySQL サーバーによって開始されます。理論的には、パッチ適用済みサーバーを構築して、LOAD DATA ステートメントでクライアントによって指定されたファイルでなく、サーバーが選択するファイルを転送するようサーバーがクライアントプログラムに指示するようにすることができます。そのようなサーバーは、クライアントユーザーが読み取りアクセス権を持つクライアントホスト上のすべてのファイルにアクセスできます。

  • クライアントが Web サーバーから接続する Web 環境で、ユーザーは LOAD DATA LOCAL を使用して、Web サーバープロセスが読み取りアクセス権を持つすべてのファイルを読み取ることができます (ユーザーが SQL Server に対してあらゆるコマンドを実行できる場合)。この環境では、MySQL サーバーを基準にしたときのクライアントは実際には Web サーバーであって、Web サーバーに接続するユーザーによって実行されているリモートプログラムではありません。

これらの問題に対処するために、MySQL 3.23.49 と MySQL 4.0.2 (Windows では 4.0.13) 以降で LOAD DATA LOCAL の処理方法が変更されました。

  • デフォルトでは、バイナリ配布内のすべての MySQL クライアントおよびライブラリは -DENABLED_LOCAL_INFILE=1 オプションでコンパイルされ、MySQL 3.23.48 以前との互換性が保持されています。

  • MySQL をソースからビルドしたが、-DENABLED_LOCAL_INFILE=1 オプションを指定して CMake を呼び出さない場合、LOAD DATA LOCALmysql_options(... MYSQL_OPT_LOCAL_INFILE, 0) を呼び出すように明示的に記述される場合を除いて、いずれのクライアントからも使用できません。セクション23.8.7.49「mysql_options()」を参照してください。

  • --local-infile=0 オプションを指定して mysqld を起動することによって、サーバー側からのすべての LOAD DATA LOCAL ステートメントを無効にすることができます。

  • mysql コマンド行クライアントの場合、--local-infile[=1] オプションを指定することによって LOAD DATA LOCAL を有効にするか、--local-infile=0 オプションを指定することによってこれを無効にします。mysqlimport の場合、ローカルデータファイルのロードはデフォルトでオフになっており、--local または -L オプションを使用してこれを有効にします。いずれの場合でも、ローカルロード操作を正常に使用するには、サーバーがこの操作を許可していることが必要。

  • オプションファイルから [client] グループを読み取る Perl スクリプトまたはその他のプログラムで LOAD DATA LOCAL を使用する場合、local-infile=1 オプションをそのグループに追加できます。ただし、local-infile を認識しないプログラムで問題が発生しないようにするために、loose- プリフィクスを使用してこれを指定します。

    [client]
    loose-local-infile=1
  • サーバーまたはクライアントのいずれかで LOAD DATA LOCAL が無効な場合、そのようなステートメントを発行しようとしたクライアントは次のエラーメッセージを受け取ります。

    ERROR 1148: The used command is not allowed with this MySQL version

6.1.7 クライアントプログラミングのセキュリティーガイドライン

MySQL にアクセスするアプリケーションは、ユーザーによって入力されるあらゆるデータを信頼しないようにしてください。ユーザーは Web フォーム、URL、または構築されたあらゆるアプリケーションに特殊文字またはエスケープ文字のシーケンスを入力することによってコードを欺くことを試すことができます。ユーザーが ; DROP DATABASE mysql; のような入力を行なっても、アプリケーションがセキュアな状態に保たれるようにしてください。これは極端な例ですが、同様の技術を使用するハッカーに備えていない場合、結果として大規模なセキュリティーリークおよびデータ損失が発生することがあります。

よくある過ちは、文字列データ値のみ保護することです。数値データも忘れずに検査してください。ユーザーが 234 という値を入力したとき、アプリケーションが SELECT * FROM table WHERE ID=234 のようなクエリーを生成する場合、ユーザーは 234 OR 1=1 という値を入力して、SELECT * FROM table WHERE ID=234 OR 1=1 というクエリーをアプリケーションに生成させることができます。その結果、サーバーはテーブル内のすべての行を取得します。これはすべての行を公開し、サーバーに過剰な負荷がかかります。この種類の攻撃から保護するためのもっとも簡単な方法は、数値定数を囲む単一引用符を使用して、SELECT * FROM table WHERE ID='234' とする方法です。ユーザーが余分の情報を入力すると、その情報はすべて文字列の一部となります。数値コンテキストでは、MySQL は自動的にこの文字列を数値に変換し、あとに続く数値以外のすべての文字を取り除きます。

データベースに格納されているデータが公開されているもののみであれば、保護は不要だと思われることもあります。これは正しくありません。データベース内のどの行も表示が許可されている場合であっても、サービス妨害攻撃 (前のパラグラフの技術に基づいた、サーバーにリソースを浪費させるものなど) から保護するべきです。そうしない場合、サーバーは正当なユーザーに対して応答不能になります。

チェックリスト:

  • 厳密な SQL モードを有効にして、サーバーが受け入れるデータ値の制限を厳しくするようサーバーに指示します。セクション5.1.7「サーバー SQL モード」を参照してください。

  • すべての Web フォームに単一引用符または二重引用符 (' および ") を入力してみます。何らかの種類の MySQL エラーが出る場合、すぐに問題を調査してください。

  • 動的 URL に %22 (")、%23 (#)、および %27 (') を追加して、これらを変更してみます。

  • 前の例で示した文字を使用して、動的 URL のデータ型を数値型から文字型に変更してみます。これらの攻撃や類似の攻撃に対してアプリケーションが安全であるようにしてください。

  • 数値フィールドに、数値でなく文字、スペース、および特殊記号を入力してみます。アプリケーションはこれらを MySQL に渡す前にこれらを削除するか、またはエラーを生成します。検査済みでない値を MySQL に渡すことは非常に危険です。

  • データを MySQL に渡す前にデータのサイズを検査してください。

  • アプリケーションがデータベースに接続するときは、管理目的で使用するものとは異なるユーザー名を使用するようにしてください。アプリケーションに不要なアクセス権限を付与しないでください。

多くのアプリケーションプログラミングインタフェースには、データ値の特殊文字をエスケープする手段が備わっています。適切に使用すれば、これにより、意図とは異なる効果を持つステートメントをアプリケーションに生成させる値を、アプリケーションユーザーが入力できないようにすることができます。

  • MySQL C API: mysql_real_escape_string() API コールを使用してください。

  • MySQL++: クエリーストリームに対して escape および quote 修飾子を使用してください。

  • PHP: mysqli または pdo_mysql 拡張子を使用し、古い ext/mysql 拡張子を使用しないでください。推奨される API は、プレースホルダを持つプリペアドステートメントのほかに、改善された MySQL 認証プロトコルおよびパスワードをサポートします。Choosing an APIも参照してください。

    古い ext/mysql 拡張子を使用する必要がある場合、エスケープのために、mysql_real_escape_string() 関数を使用し、mysql_escape_string() または addslashes() を使用しないでください。これは、mysql_real_escape_string() のみが文字セットを認識し、ほかの関数は、(無効な) マルチバイト文字セットを使用したときにバイパスされる可能性があるためです。

  • Perl DBI: プレースホルダまたは quote() メソッドを使用してください。

  • Ruby DBI: プレースホルダまたは quote() メソッドを使用してください。

  • Java JDBC: PreparedStatement オブジェクトおよびプレースホルダを使用してください。

ほかのプログラミングインタフェースも似たような機能を持っている場合があります。

6.2 MySQL アクセス権限システム

MySQL 権限システムの主な役割は、特定のホストから接続するユーザーを認証すること、およびそのユーザーを、SELECTINSERTUPDATEDELETE などのデータベースにおける権限に関連付けることです。追加機能として、匿名ユーザーを持つこと、そして、管理操作や LOAD DATA INFILE などの MySQL 特有の機能についての権限を与えることなどがあります。

MySQL 権限システムでは実行できないこともあります。

  • 特定ユーザーのアクセスを拒否するように明示的に指定することはできません。つまり、ユーザーを明示的に突き合わせて接続を拒否することはできません。

  • ユーザーがデータベースのテーブルを作成または削除できるが、データベース自体の作成または削除はできないような権限をユーザーが持つように指定することはできません。

  • パスワードはアカウントに対してグローバルに適用されます。データベース、テーブル、ルーチンなどの特定のオブジェクトにパスワードを関連付けることはできません。

MySQL 権限システムへのユーザーインタフェースは、CREATE USERGRANTREVOKE などの SQL ステートメントで構成されます。セクション13.7.1「アカウント管理ステートメント」を参照してください。

内部的には、サーバーは権限情報を mysql データベース (つまり mysql という名前のデータベース) の付与テーブルに格納します。MySQL サーバーはこれらのテーブルの内容を起動時にメモリーに読み取り、付与テーブルのインメモリーコピーに基づいてアクセス制御を決定します。

MySQL 権限システムによって、すべてのユーザーは自分に許可された操作のみ実行可能になります。ユーザーとして MySQL サーバーに接続すると、ユーザーの ID は、接続元のホストおよび指定したユーザー名によって決定されます。接続後にリクエストを発行すると、システムは、ユーザー ID と ユーザーが行う操作に応じて権限を付与します。

MySQL ではホスト名とユーザー名の両方を考慮に入れてユーザーを特定しますが、これは、特定のユーザー名がすべてのホストで同一人物に属すると想定する根拠がないためです。たとえば、office.example.com から接続したユーザー joe は、home.example.com から接続した joe と同一人物とは限りません。MySQL では、たまたま同じ名前を持った異なるホスト上のユーザーを識別できるようにすることによってこれを処理します。つまり、office.example.com からの joe による接続に対して 1 つの権限セットを付与し、home.example.com からの joe による接続に対して別の権限セットを提供することができます。特定のアカウントが持つ権限を表示するには、SHOW GRANTS ステートメントを使用します。例:

SHOW GRANTS FOR 'joe'@'office.example.com';
SHOW GRANTS FOR 'joe'@'home.example.com';

サーバーに接続するクライアントプログラムを実行するとき、MySQL アクセス制御には 2 つのステージがあります。

ステージ 1: サーバーは、ユーザーの ID および正しいパスワードを指定することによって ID を検証できるかどうかに基づいて、接続を受け入れるか拒否します。

ステージ 2: 接続できる場合、サーバーはユーザーが発行する各ステートメントを検査して、ステートメントを実行するだけの十分な権限をユーザーが持っているかどうかを判別します。たとえば、データベースのテーブルからレコードを選択したり、データベースのテーブルを削除したりしようとすると、サーバーはユーザーにそのテーブルの SELECT 権限があるかどうか、またはデータベースの DROP 権限があるかどうかを検証します。

各ステージで発生する動作の詳細な説明については、セクション6.2.4「アクセス制御、ステージ 1: 接続の検証」およびセクション6.2.5「アクセス制御、ステージ 2: リクエストの確認」を参照してください。

ユーザーの接続中に (ユーザー自身または別のだれかによって) 権限が変更された場合、それらの変更は、ユーザーが発行する次のステートメントで必ずしもすぐに有効になるわけではありません。サーバーが付与テーブルをリロードする条件についての詳細は、セクション6.2.6「権限変更が有効化される時期」を参照してください。

セキュリティーに関連する一般的な助言については、セクション6.1「一般的なセキュリティーの問題」を参照してください。権限に関連した問題の診断についての支援情報は、セクション6.2.7「アクセス拒否エラーの原因」を参照してください。

6.2.1 MySQL で提供される権限

MySQL では、さまざまなコンテキストおよびさまざまな動作レベルに適用される権限が提供されます。

  • 管理権限によって、ユーザーは MySQL サーバーの動作を管理できます。これらの権限は特定のデータベースに固有でないため、グローバルです。

  • データベース権限は、データベースおよびデータベース内のすべてのオブジェクトに適用されます。これらの権限は、特定のデータベースに付与したり、すべてのデータベースに適用されるようにグローバルに付与したりすることができます。

  • テーブル、インデックス、ビュー、ストアドルーチンなどのデータベースオブジェクト向けの権限は、データベース内の特定のオブジェクト、データベース内の特定タイプのすべてのオブジェクト (たとえばデータベース内のすべてのテーブル)、またはすべてのデータベース内の特定タイプのすべてのオブジェクトにグローバルに付与することができます。

アカウント権限に関する情報は、mysql データベース内の userdbtables_privcolumns_priv、および procs_priv テーブルに格納されます (セクション6.2.2「権限システム付与テーブル」を参照してください)。MySQL サーバーはこれらのテーブルの内容を起動時にメモリーに読み取り、セクション6.2.6「権限変更が有効化される時期」に示す条件でこれらを再ロードします。アクセス制御決定は、付与テーブルのインメモリーコピーに基づきます。

MySQL の一部のリリースでは、新たな権限や機能を追加するために付与テーブルの構造に変更を加えているものもあります。すべての新しい機能を確実に活用できるようにするには、新しいバージョンの MySQL に更新するときに常に付与テーブルを更新して、最新の構造を持つようにします。セクション4.4.7「mysql_upgrade — MySQL テーブルのチェックとアップグレード」を参照してください。

次の表には、GRANT および REVOKE ステートメント内で SQL レベルで使用される権限名のほか、付与テーブル内の各権限に関連付けられたカラムおよび権限が適用されるコンテキストが示されています。

表 6.2 GRANT および REVOKE に対して許容可能な権限

権限カラムコンテキスト
CREATECreate_privデータベース、テーブル、またはインデックス
DROPDrop_privデータベース、テーブル、またはビュー
GRANT OPTIONGrant_privデータベース、テーブル、またはストアドルーチン
LOCK TABLESLock_tables_privデータベース
REFERENCESReferences_privデータベースまたはテーブル
EVENTEvent_privデータベース
ALTERAlter_privテーブル
DELETEDelete_privテーブル
INDEXIndex_privテーブル
INSERTInsert_privテーブルまたはカラム
SELECTSelect_privテーブルまたはカラム
UPDATEUpdate_privテーブルまたはカラム
CREATE TEMPORARY TABLESCreate_tmp_table_privテーブル
TRIGGERTrigger_privテーブル
CREATE VIEWCreate_view_privビュー
SHOW VIEWShow_view_privビュー
ALTER ROUTINEAlter_routine_privストアドルーチン
CREATE ROUTINECreate_routine_privストアドルーチン
EXECUTEExecute_privストアドルーチン
FILEFile_privサーバーホストでのファイルアクセス
CREATE TABLESPACECreate_tablespace_privサーバー管理
CREATE USERCreate_user_privサーバー管理
PROCESSProcess_privサーバー管理
PROXYproxies_priv テーブルを参照サーバー管理
RELOADReload_privサーバー管理
REPLICATION CLIENTRepl_client_privサーバー管理
REPLICATION SLAVERepl_slave_privサーバー管理
SHOW DATABASESShow_db_privサーバー管理
SHUTDOWNShutdown_privサーバー管理
SUPERSuper_privサーバー管理
ALL [PRIVILEGES] サーバー管理
USAGE サーバー管理

次のリストには、MySQL で使用可能な各権限の一般的な説明が提供されています。特定の SQL ステートメントには、ここに示されているよりも具体的な権限要件がある場合もあります。そのような場合、該当するステートメントの説明で詳細を示します。

  • ALL または ALL PRIVILEGES 権限指定子は、短縮形です。これは、特定の権限レベルで使用可能なすべての権限 (GRANT OPTION を除く) を表します。たとえば、グローバルまたはテーブルレベルで ALL を付与すると、すべてのグローバル権限またはテーブルレベルのすべての権限が付与されます。

  • ALTER 権限は、テーブルの構造を変更するための ALTER TABLE の使用を可能にします。ALTER TABLE には CREATE および INSERT 権限も必要です。テーブルを名前変更するには、古いテーブル側で ALTER および DROP と、新しいテーブル側で ALTERCREATE、および INSERT 権限が必要です。

  • ストアドルーチン (プロシージャーおよび関数) を変更または削除するには、ALTER ROUTINE 権限が必要です。

  • CREATE 権限は、新規データベースおよびテーブルの作成を可能にします。

  • ストアドルーチン (プロシージャーおよび関数) を作成するには、CREATE ROUTINE 権限が必要です。

  • テーブルスペースおよびログファイルグループを作成、変更、または削除するには、CREATE TABLESPACE 権限が必要です。

  • CREATE TEMPORARY TABLES 権限は、CREATE TEMPORARY TABLE ステートメントを使用した一時テーブルの作成を可能にします。

    MySQL 5.6.3 の時点では、セッションによって一時テーブルが作成されると、サーバーはテーブル上の権限チェックを追加実行しません。セッションの作成によって、DROP TABLEINSERTUPDATESELECT などのあらゆる操作をテーブル上で実行できます。

    この動作の 1 つの影響として、現在のユーザーが一時テーブルを作成する権限を持たなくても、セッションが一時テーブルを操作できるということがあります。現在のユーザーが CREATE TEMPORARY TABLES 権限を持たないが、CREATE TEMPORARY TABLES を持つユーザーの権限で実行して一時テーブルを作成する、DEFINER コンテキストのストアドプロシージャーを実行できるとします。プロシージャーの実行中、セッションは定義側ユーザーの権限を使用します。プロシージャーが復帰したあと、有効な権限は現在のユーザーの権限に戻り、これによって引き続き一時テーブルを表示し、一時テーブルに対してあらゆる操作を実行できることになります。

    MySQL 5.6.3 より前では、INSERTUPDATESELECT などの一時テーブル上でのほかの操作には、一時テーブルを格納するデータベースに対する操作について、または同じ名前の非一時テーブルについての追加の権限が必要です。

    一時テーブルと非一時テーブルの権限を分離するための、この状況についての一般的な回避策は、一時テーブルを使用するための専用データベースを作成することです。そうすることで、そのデータベースについて、CREATE TEMPORARY TABLES 権限と、ユーザーによって実行される一時テーブル操作に必要なほかのすべての権限を、そのユーザーに付与することができます。

  • CREATE USER 権限は、CREATE USERDROP USERRENAME USER、および REVOKE ALL PRIVILEGES の使用を可能にします。

  • CREATE VIEW 権限は、CREATE VIEW の使用を可能にします。

  • DELETE 権限は、データベースのテーブルからの行の削除を可能にします。

  • DROP 権限は、既存のデータベース、テーブル、およびビューのドロップを可能にします。パーティション化されたテーブルで ALTER TABLE ... DROP PARTITION ステートメントを使用するには DROP 権限が必要です。DROP 権限は TRUNCATE TABLE のためにも必要です。mysql データベースに対する DROP 権限をユーザーに付与すると、MySQL アクセス権限が格納されているデータベースをユーザーが削除することができます。

  • イベントスケジューラについてのイベントを作成、変更、削除、または表示するには、EVENT 権限が必要です。

  • ストアドルーチン (プロシージャーおよび関数) を実行するには、EXECUTE 権限が必要です。

  • FILE 権限は、LOAD DATA INFILE および SELECT ... INTO OUTFILE ステートメントと LOAD_FILE() 関数を使用するサーバーホスト上でファイルの読み取りおよび書き込みを実行するための許可をユーザーに与えます。FILE 権限を持つユーザーは、すべてのユーザーから読み取り可能であるか、MySQL サーバーによって読み取り可能なサーバーホスト上のすべてのファイルを読み取ることができます。(このことは暗黙的に、データベースディレクトリ内のあらゆるファイルにサーバーからアクセスできるため、ユーザーはそれらのすべてのファイルを読み取ることができることを意味します。)さらに FILE 権限によって、ユーザーは MySQL サーバーが書き込みアクセス権限を持つあらゆるディレクトリに新しいファイルを作成できます。これは、権限テーブルを実装するファイルを格納するサーバーのデータディレクトリを含みます。セキュリティー対策として、サーバーは既存のファイルを上書きしません。

    ファイルを読み取りおよび書き込みできる場所を制限するには、secure_file_priv システムを特定のディレクトリに設定します。セクション5.1.4「サーバーシステム変数」を参照してください。

  • GRANT OPTION 権限によって、ユーザーは自分自身が所有する権限をほかのユーザーに付与したり、ほかのユーザーから削除したりすることができます。

  • INDEX 権限によって、ユーザーはインデックスを作成またはドロップできます。INDEX は既存のテーブルに適用されます。テーブルに対する CREATE 権限を持つ場合、CREATE TABLE ステートメントにインデックス定義を含めることも可能です。

  • INSERT 権限は、データベースのテーブルへの行の挿入を可能にします。ANALYZE TABLEOPTIMIZE TABLEREPAIR TABLE などのテーブル保守に関するステートメントにも、INSERT 権限が必要です。

  • LOCK TABLES 権限は、ユーザーが SELECT 権限を持つテーブルをロックするために、明示的な LOCK TABLES ステートメントの使用を可能にします。これには、ロックされたテーブルをほかのセッションから読み取らせないようにする書き込みロックの使用が含まれます。

  • PROCESS 権限は、サーバー内で実行するスレッドについての情報の表示に関係します (つまり、セッションによって実行されるステートメントについての情報)。この権限は、SHOW PROCESSLIST または mysqladmin processlist を使用して、ほかのアカウントに属するスレッドを表示することを可能にし、自分自身のスレッドを表示することもできます。PROCESS 権限は、SHOW ENGINE の使用も可能にします。

  • PROXY 権限によって、ユーザーは別のユーザーになりすましたり、別のユーザーとして認識されるようにしたりすることができます。セクション6.3.9「プロキシユーザー」を参照してください。

  • REFERENCES 権限は現在使用されていません。

  • RELOAD 権限は、FLUSH ステートメントの使用を可能にします。また、これは FLUSH 操作 (flush-hostsflush-logsflush-privilegesflush-statusflush-tablesflush-threadsrefresh、および reload) と同等な mysqladmin コマンドを使用可能にします。

    reload コマンドは、付与テーブルをメモリーにリロードするようにサーバーに指示します。flush-privilegesreload のシノニムです。refresh コマンドは、ログファイルを閉じて再オープンし、すべてのテーブルをフラッシュします。ほかの flush-xxx コマンドは refresh に類似した機能を実行しますが、より具体的であるため一部の状況では好ましい場合があります。たとえば、ログファイルだけをフラッシュするときは、refresh よりも flush-logs を選択することをお勧めします。

  • REPLICATION CLIENT 権限は、SHOW MASTER STATUS および SHOW SLAVE STATUS の使用を可能にします。MySQL 5.6.6 以降では、これは SHOW BINARY LOGS ステートメントの使用も可能にします。

  • REPLICATION SLAVE 権限は、マスターとしての現在のサーバーに接続するときにスレーブサーバーが使用するアカウントに対して与えるようにしてください。この権限がない場合、スレーブは、マスターサーバー上のデータベースに対して実行された更新をリクエストすることができません。

  • SELECT 権限によって、ユーザーはデータベース内のテーブルから行を選択できます。SELECT ステートメントで SELECT 権限が必要となるのは、ステートメントがテーブルから実際にレコードを取得する場合です。一部の SELECT ステートメントはテーブルにアクセスしないため、あらゆるデータベースへのアクセス権がなくても実行できます。たとえば、テーブルを参照しない式を評価するための単純な計算機として SELECT を使用することができます。

    SELECT 1+1;
    SELECT PI()*2;

    SELECT 権限は、カラム値を読み取るほかのステートメントについても必要です。たとえば、UPDATE ステートメントの代入 col_name=expr の右辺で参照されるカラムや、DELETE または UPDATE ステートメントの WHERE 句で指定されるカラムについて、SELECT が必要です。

  • SHOW DATABASES 権限によって、アカウントは SHOW DATABASE ステートメントを発行することでデータベース名を表示することができます。この権限を持たないアカウントには、アカウントが一部の権限を持つデータベースしか表示されず、サーバーが --skip-show-database オプションで起動されている場合はステートメントを一切使用できません。すべてのグローバル権限は、データベースに対する権限だということに注意してください。

  • SHOW VIEW 権限は、SHOW CREATE VIEW の使用を可能にします。

  • SHUTDOWN 権限は、mysqladmin shutdown コマンドの使用を可能にします。対応する SQL ステートメントはありません。

  • SUPER 権限によって、アカウントはほかのアカウントに属するスレッドを強制終了するための CHANGE MASTER TOKILL、または mysqladmin kill (自分のスレッドは常に強制終了できます)、PURGE BINARY LOGS、グローバルシステム変数を変更するための SET GLOBAL を使用した構成変更、mysqladmin debug コマンド、ロギングの有効化または無効化、read_only システム変数が有効な場合の更新の実行、スレーブサーバー上でのレプリケーションの開始と停止、ストアドプログラムおよびビューの DEFINER 属性内のすべてのアカウントの指定を使用することができ、ユーザーは max_connections システム変数によって制御される接続制限に達している場合でも (一度) 接続することができます。

    バイナリロギングを有効にした場合にストアドファンクションを作成または変更するとき、セクション20.7「ストアドプログラムのバイナリロギング」に記載されているように SUPER 権限がやはり必要になることがあります。

  • TRIGGER 権限はトリガー操作を有効にします。テーブルのトリガーを作成、削除、または実行するには、そのテーブルに対してこの権限を持つ必要があります。

  • UPDATE 権限は、データベース内のテーブルの行の更新を可能にします。

  • USAGE 権限指定子は、権限なしを表します。これは GRANT と一緒にグローバルレベルで使用されて、既存のアカウント権限に影響を及ぼすことなくリソース制限や SSL 特性などのアカウント属性を変更します。

アカウントには必要な権限のみを付与することをお勧めします。FILE 権限と管理権限の付与については十分に注意するようにしてください。

  • FILE 権限を悪用して、MySQL サーバーがサーバーホスト上で読み取ることができるあらゆるファイルをデータベーステーブルから読み取ることができます。これにはすべてのユーザーが読み取り可能なすべてのファイルと、サーバーのデータディレクトリ内のファイルが含まれます。そのあと、SELECT を使用してそのテーブルにアクセスし、テーブルの内容をクライアントホストに送信することができます。

  • GRANT OPTION 権限によって、ユーザーはほかのユーザーに権限を付与することができます。異なる権限を持つ 2 人のユーザーが GRANT OPTION 権限を持っていれば、権限を組み合わせることができます。

  • ALTER 権限を使用して、テーブルの名前を変更することによって権限システムを壊すことができます。

  • SHUTDOWN 権限を悪用して、サーバーを終了することによって、ほかのユーザーへのサービスを完全に妨害することができます。

  • PROCESS 権限は、パスワードの設定や変更を行うステートメントなどを含め、現在実行中のステートメントのプレーンテキストを表示することができます。

  • SUPER 権限は、ほかのセッションを終了したり、サーバーの動作方法を変更したりするために使用できます。

  • mysql データベース自体に付与した権限を使用して、パスワードおよびその他のアクセス権限情報を変更することができます。パスワードは暗号化されて保管されているため、悪意のあるユーザーは単純にそのパスワードを見てプレーンテキストパスワードを知ることはできません。ただし、user テーブルの Password カラムへの書き込みアクセス権限を持つユーザーは、アカウントのパスワードを変更し、そのアカウントを使用して MySQL サーバーに接続することができます。

6.2.2 権限システム付与テーブル

通常では、アカウントをセットアップして各アカウントで使用可能な権限を制御するためには、GRANTREVOKE などのステートメントを使用することによって、mysql データベース内の付与テーブルの内容を間接的に操作します。セクション13.7.1「アカウント管理ステートメント」を参照してください。ここでは付与テーブルの基本構造と、サーバーがクライアントと対話するときに付与テーブルの内容をどのように使用するかについて説明します。

次の mysql データベーステーブルには付与情報が格納されています。

  • user: ユーザーアカウント、グローバル権限、および権限以外のその他のカラムが含まれています。

  • db: データベースレベルの権限が格納されています。

  • host: 使用されなくなりました。MySQL 5.6.7 以降の新しい MySQL インストールではこのテーブルが作成されなくなりました。

  • tables_priv: テーブルレベルの権限が格納されています。

  • columns_priv: カラムレベルの権限が格納されています。

  • procs_priv: ストアドプロシージャーおよびストアドファンクションの権限が格納されています。

  • proxies_priv: プロキシユーザー権限が格納されています。

mysql データベース内のほかのテーブルには付与情報が保持されておらず、ほかの場所で説明されています。

注記

mysql データベース内のテーブルの変更は、CREATE USERGRANTCREATE PROCEDURE などのステートメントの応答としてサーバーによって通常実行されます。INSERTUPDATEDELETE などのステートメントを使用してこれらのテーブルを直接変更することは推奨されません。これらの変更の結果として誤った形式となった行を、サーバーは随意で無視します。

各付与テーブルにはスコープカラムと権限カラムがあります。

  • スコープカラムはテーブル内の各行 (エントリ) のスコープ、つまり行が適用されるコンテキストを決定します。たとえば、HostUser の値が 'thomas.loc.gov''bob' である user テーブル行は、bob というユーザー名を指定するクライアントによるホスト thomas.loc.gov からサーバーに対して実行する認証接続のために使用されます。同様に、HostUser、および Db カラム値が 'thomas.loc.gov''bob'、および 'reports' である db テーブル行は、bobthomas.loc.gov ホストから reports データベースに接続するときに使用されます。tables_priv テーブルおよび columns_priv テーブルには、それぞれの行に適用されるテーブルまたはテーブルとカラムの組み合わせを示すスコープカラムがあります。procs_priv スコープカラムは、それぞれの行に適用されるストアドルーチンを示します。

  • 権限カラムは、テーブル行によって付与される権限、つまり実行可能な操作を指定します。サーバーはさまざまな付与テーブル内の情報を組み合わせてユーザーの権限の完全な記述を構成します。この実行に使用されるルールの説明は、セクション6.2.5「アクセス制御、ステージ 2: リクエストの確認」にあります。

サーバーは次の方法で付与テーブルを使用します。

  • user テーブルのスコープカラムは、入接続を拒否または許可するかを決定します。許可される接続について、user テーブル内で付与されるすべての権限は、ユーザーのグローバル権限を示します。このテーブル内で付与されるすべての権限は、サーバー上のすべてのデータベースに適用されます。

    注記

    あらゆるグローバル権限は、すべてのデータベースに対する権限とみなされるため、あらゆるグローバル権限を持つユーザーは、SHOW DATABASES を使用したり、または INFORMATION_SCHEMASCHEMATA テーブルを調べたりすることで、すべてのデータベース名を表示できるようになります。

  • db テーブルのスコープカラムは、どのユーザーがどのホストからどのデータベースにアクセスできるかを決定します。権限カラムは、許可される操作を決定します。データベースレベルで付与される権限は、データベースのほかテーブルやストアドプログラムなどのデータベース内のすべてのオブジェクトに適用されます。

  • tables_priv および columns_priv テーブルは db テーブルと似ていますが、これらはさらに粒度が細かく、データベースレベルでなくテーブルレベルおよびカラムレベルに適用されます。テーブルレベルで付与される権限は、テーブルおよびそのすべてのカラムに適用されます。カラムレベルで付与される権限は、特定のカラムにのみ適用されます。

  • procs_priv テーブルはストアドルーチンに適用されます。ルーチンレベルで付与される権限は、単一ルーチンにのみ適用されます。

  • proxies_priv テーブルは、ほかのユーザーのプロキシの役割を担うことができるユーザーがだれか、およびプロキシユーザーが PROXY 権限をほかのユーザーに付与できるかどうかを指定します。

サーバーは mysql データベース内の user および db テーブルを、アクセス制御のステージ 1 とステージ 2 の両方で使用します (セクション6.2「MySQL アクセス権限システム」を参照してください)。userdb のテーブルのカラムをここで示します。

表 6.3 user テーブルおよび db テーブルのカラム

テーブル名userdb
スコープカラムHostHost
 UserDb
 PasswordUser
権限カラムSelect_privSelect_priv
 Insert_privInsert_priv
 Update_privUpdate_priv
 Delete_privDelete_priv
 Index_privIndex_priv
 Alter_privAlter_priv
 Create_privCreate_priv
 Drop_privDrop_priv
 Grant_privGrant_priv
 Create_view_privCreate_view_priv
 Show_view_privShow_view_priv
 Create_routine_privCreate_routine_priv
 Alter_routine_privAlter_routine_priv
 Execute_privExecute_priv
 Trigger_privTrigger_priv
 Event_privEvent_priv
 Create_tmp_table_privCreate_tmp_table_priv
 Lock_tables_privLock_tables_priv
 References_privReferences_priv
 Reload_priv 
 Shutdown_priv 
 Process_priv 
 File_priv 
 Show_db_priv 
 Super_priv 
 Repl_slave_priv 
 Repl_client_priv 
 Create_user_priv 
 Create_tablespace_priv 
セキュリティーカラムssl_type 
 ssl_cipher 
 x509_issuer 
 x509_subject 
 plugin 
 authentication_string 
 password_expired 
リソース制御カラムmax_questions 
 max_updates 
 max_connections 
 max_user_connections 

mysql.user テーブルの plugin および authentication_string カラムは認証プラグイン情報を格納します。

アカウント行の plugin カラムが空の場合、サーバーは Password カラムのパスワードハッシュの形式に応じて、mysql_native_password または mysql_old_password プラグインを暗黙的に使用してアカウントを認証します。Password 値が空または 4.1 のパスワードハッシュ (41 文字) である場合、サーバーは mysql_native_password を使用します。パスワード値が 4.1 より前のパスワードハッシュ (16 文字) の場合、サーバーは mysql_old_password を使用します。(これらのハッシュ形式についての追加情報は、セクション6.1.2.4「MySQL でのパスワードハッシュ」を参照してください。)クライアントは、アカウント行の Password カラム内のパスワードと一致する必要があります。

アカウント行で plugin カラムにプラグインが指定された場合、サーバーはこれを使用して、アカウントに対する接続の試行を認証します。プラグインが Password カラム内の値を使用するかどうかはプラグインによって異なります。

password_expired カラムは、DBA がアカウントパスワードを期限切れにして、ユーザーにパスワードをリセットするよう求めることができるようにするために、MySQL 5.6.6 で追加されました。デフォルトの password_expired 値は 'N' ですが、ALTER USER ステートメントを使用して 'Y' に設定できます。アカウントのパスワードの有効期限が切れたあと、サーバーへの以降の接続で、そのアカウントによって実行されるすべての操作は、ユーザーが SET PASSWORD ステートメントを発行して新しいアカウントパスワードを確立するまで、エラーになります。セクション13.7.1.1「ALTER USER 構文」を参照してください。

パスワードの有効期限が切れたあと、SET PASSWORD を使用してパスワードを現在の値に設定することによって、パスワードをリセットすることができます。適切なポリシーとして、別のパスワードを選択することをお勧めします。

注意

MySQL 5.6.6 で、ALTER USERPassword カラムを空の文字列に設定するため、このステートメントは 5.6.7 まで使用しないでください。

アクセス制御のステージ 2 で、サーバーはリクエスト検証を実行して、クライアントが発行した各リクエストに対してそれぞれのクライアントが十分な権限を持つことを確認します。user および db 付与テーブルに加えて、テーブルに関するリクエストの場合、サーバーは tables_priv および columns_priv テーブルを参照することもあります。後者のテーブルは、テーブルレベルおよびカラムレベルでの細かい権限制御を提供します。これらには、次の表に示すカラムがあります。

表 6.4 tables_priv テーブルおよび columns_priv テーブルのカラム

テーブル名tables_privcolumns_priv
スコープカラムHostHost
 DbDb
 UserUser
 Table_nameTable_name
  Column_name
権限カラムTable_privColumn_priv
 Column_priv 
その他のカラムTimestampTimestamp
 Grantor 

Timestamp カラムおよび Grantor カラムは、それぞれ現在のタイムスタンプおよび CURRENT_USER 値に設定されます。ただし、これらは未使用のため、ここではこれ以上説明しません。

ストアドルーチンに関するリクエストを検証するために、サーバーは procs_priv テーブルを参照することがあり、このテーブルには次の表に示すカラムがあります。

表 6.5 procs_priv テーブルのカラム

テーブル名procs_priv
スコープカラムHost
 Db
 User
 Routine_name
 Routine_type
権限カラムProc_priv
その他のカラムTimestamp
 Grantor

Routine_type カラムは、'FUNCTION' または 'PROCEDURE' の値を持つ ENUM カラムであり、その行が示すルーチンのタイプを指します。このカラムにより、同じ名前を持つ関数とプロシージャーに別々に権限を付与することができます。

Timestamp カラムと Grantor カラムは現在未使用のため、ここではこれ以上説明しません。

proxies_priv テーブルはプロキシユーザーについての情報を記録します。これには次のカラムがあります。

  • HostUser: これらのカラムは、プロキシ設定されるアカウントに対して PROXY 権限を持つユーザーアカウントを示します。

  • Proxied_hostProxied_user: これらのカラムは、プロキシ設定されるユーザーのアカウントを示します。

  • Grantor: 現在未使用です。

  • Timestamp: 現在未使用です。

  • With_grant: このカラムは、プロキシアカウントが PROXY 権限を別のアカウントに付与できるかどうかを示します。

付与テーブルのスコープカラムには文字列が格納されています。これらは次に示すように宣言され、それぞれのデフォルト値は空の文字列です。

表 6.6 付与テーブルのスコープカラムの型

カラム名
HostProxied_hostCHAR(60)
UserProxied_userCHAR(16)
PasswordCHAR(41)
DbCHAR(64)
Table_nameCHAR(64)
Column_nameCHAR(64)
Routine_nameCHAR(64)

アクセスチェックのために、UserProxied_userPasswordDb、および Table_name 値の比較は大文字小文字を区別します。HostProxied_hostColumn_name、および Routine_name 値の比較は大文字小文字を区別しません。

user および db テーブルでは、各権限は、ENUM('N','Y') DEFAULT 'N' として宣言される別個のカラムにリストされます。つまり、各権限は無効または有効にすることができ、デフォルトは無効です。

tables_privcolumns_priv、および procs_priv のテーブルでは、権限カラムは SET カラムとして宣言されます。これらのカラムの値は、テーブルによって制御されるあらゆる組み合わせの権限を含むことができます。カラム値にリストされている権限のみが入力されます。

表 6.7 Set タイプ権限のカラム値

テーブル名カラム名可能な Set 要素
tables_privTable_priv'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter', 'Create View', 'Show view', 'Trigger'
tables_privColumn_priv'Select', 'Insert', 'Update', 'References'
columns_privColumn_priv'Select', 'Insert', 'Update', 'References'
procs_privProc_priv'Execute', 'Alter Routine', 'Grant'

管理者権限 (RELOADSHUTDOWN など) は、user テーブルのみで指定されます。管理操作はサーバー自体での操作であって、データベース固有でないため、これらの権限をほかの付与テーブルにリストする理由はありません。したがって、ユーザーが管理操作を実行できるかどうかを判別するには、サーバーは user テーブルのみ参照する必要があります。

FILE 権限も、user テーブルでのみ指定されます。これはそもそも管理権限ではありませんが、サーバーホスト上のファイルを読み取りまたは書き込みするための能力は、アクセスするデータベースとは無関係です。

mysqld サーバーは、起動時に付与テーブルの内容をメモリーに読み取ります。FLUSH PRIVILEGES ステートメントを発行するか、mysqladmin flush-privileges または mysqladmin reload コマンドを実行することによって、テーブルをリロードするようサーバーに指示することができます。付与テーブルへの変更は、セクション6.2.6「権限変更が有効化される時期」で示すように反映されます。

アカウントの権限を変更するとき、変更によって権限が希望どおりにセットアップされるかどうかを確認することをお勧めします。特定のアカウントの権限をチェックするには、SHOW GRANTS ステートメントを使用します (セクション13.7.5.22「SHOW GRANTS 構文」を参照してください)。たとえば、ユーザー名およびホスト名の値がそれぞれ bob および pc84.example.com のアカウントに付与された権限を調べるには、次のステートメントを使用します。

SHOW GRANTS FOR 'bob'@'pc84.example.com';

6.2.3 アカウント名の指定

MySQL アカウント名はユーザー名とホスト名で構成されます。これにより、別々のホストから接続可能な同じ名前を持つユーザーのためのアカウントを作成できます。このセクションでは、特殊な値やワイルドカードルールを含む、アカウント名の記述方法について説明します。

CREATE USERGRANTSET PASSWORD などの SQL ステートメントでは、次のルールを使用してアカウント名を記述してください。

  • アカウント名の構文は 'user_name'@'host_name' です。

  • ユーザー名のみで構成されるアカウント名は、'user_name'@'%' と同等です。たとえば、'me''me'@'%' と同等です。

  • ユーザー名およびホスト名は、それらが引用符なしの識別子として有効な場合、引用する必要はありません。引用符が必要なのは、user_name 文字列が特殊文字 (- など) を含んでいたり、host_name 文字列が特殊文字またはワイルドカード文字 (% など) を含んでいたりする場合で、たとえば 'test-user'@'%.com' のようになります。

  • ユーザー名およびホスト名は、逆引用符 (`)、単一引用符 (')、または二重引用符 (") のいずれかを使用して、識別子または文字列として引用符で囲みます。

  • ユーザー名およびホスト名の部分が引用符で囲まれる場合、別々に囲んでください。つまり、'me'@'localhost' と記述し、'me@localhost' とは記述しません。後者は 'me@localhost'@'%' と解釈されます。

  • CURRENT_USER または CURRENT_USER() 関数への参照は、現行クライアントのユーザー名およびホスト名の文字を指定することと同等です。

MySQL は、mysql データベースの付与テーブルにアカウント名を格納するとき、ユーザー名とホスト名の部分に別々のカラムを使用します。

  • user テーブルにはアカウントごとに 1 行が格納されます。User および Host カラムはユーザー名およびホスト名を格納します。このテーブルには、アカウントが持つグローバル権限も指定されます。

  • ほかの付与テーブルには、データベースおよびデータベース内のオブジェクトに対してアカウントが持つ権限が示されます。これらのテーブルにはアカウント名を格納するための User および Host カラムがあります。これらのテーブルの各行は、同じ User および Host の値を持つ user テーブル内のアカウントに関連付けられています。

付与テーブル構造に関する追加の詳細については、セクション6.2.2「権限システム付与テーブル」を参照してください。

ユーザー名およびホスト名は、次に示すような特殊な値が使用されたりワイルドカード規則が適用されたりします。

ユーザー名は、入接続を試行するユーザー名と文字が一致するブランクでない値であるか、あらゆるユーザー名と一致するブランク値 (空の文字列) です。ブランクのユーザー名を持つアカウントは匿名ユーザーです。SQL ステートメントで匿名ユーザーを指定するには、''@'localhost' のように引用符で囲んだ空のユーザー名部分を使用します。

アカウント名のホスト名部分は多くの形式を持つことができ、ワイルドカードが許可されます。

  • ホスト値はホスト名または IP アドレス (IPv4 または IPv6) とすることができます。'localhost' という名前はローカルホストを示します。IP アドレス '127.0.0.1' は IPv4 ループバックインタフェースを示します。IP アドレス '::1' は、IPv6 ループバックインタフェースを示します。

  • ワイルドカード文字 % および _ を、ホスト名または IP アドレスの値に使用できます。これらは LIKE 演算子で実行されるパターンマッチング演算と同じ意味を持ちます。たとえば、ホスト値 '%' はあらゆるホスト名に一致し、'%.mysql.com' という値は mysql.com ドメイン内のすべてのホストに一致し、'192.168.1.%' は 192.168.1 のクラス C ネットワークのあらゆるホストに一致します。

    IP ワイルドカード値をホスト値に使用できるため (サブネット上のすべてのホストに一致する '192.168.1.%' など)、一部のユーザーがホスト 192.168.1.somewhere.com を指定することによって、この機能を悪用しようとする可能性があります。このような試みを阻止するために、MySQL では、数字およびドットで始まるホスト名との一致が許可されていません。したがって、1.2.example.com のような名前を持つホストがある場合、その名前はアカウント名のホスト部分と決して一致しません。IP ワイルドカード値は、ホスト名でなく IP アドレスのみと一致することができます。

  • IPv4 アドレスで指定されるホスト値について、ネットワーク番号に使用するアドレスビットの数を示すネットマスクを指定することができます。ネットマスク表記は IPv6 アドレスについては使用できません。

    構文は host_ip/netmask です。例:

    CREATE USER 'david'@'192.58.197.0/255.255.255.0';

    これにより david は、次の条件が true となる IP アドレス client_ip を持つすべてのクライアントホストから接続できます。

    client_ip & netmask = host_ip

    つまり、次のような CREATE USER ステートメントがあるとします。

    client_ip & 255.255.255.0 = 192.58.197.0

    この条件を満たし、MySQL サーバーに接続できる IP アドレスは、192.58.197.0 から 192.58.197.255 までの範囲のものです。

    ネットマスクは、8、16、24、または 32 ビットのアドレスを使用するようサーバーに指示するためにのみ使用できます。例:

    • 192.0.0.0/255.0.0.0: 192 のクラス A ネットワーク上のすべてのホスト

    • 192.168.0.0/255.255.0.0: 192.168 のクラス B ネットワーク上のすべてのホスト

    • 192.168.1.0/255.255.255.0: 192.168.1 のクラス C ネットワーク上のすべてのホスト

    • 192.168.1.1: この特定の IP アドレスを持つホストのみ

    次のネットマスクは 28 ビットをマスクしますが、28 は 8 の倍数でないため機能しません。

    192.168.0.1/255.255.255.240

サーバーは、クライアントホスト名または IP アドレス用のシステム DNS リゾルバによって返された値を使用して、アカウント名のホスト値の突き合わせをクライアントホストに対して実行します。アカウントホスト値がネットマスク記法を使用して指定される場合を除き、この比較は IP アドレスとして指定されるアカウントホスト値であっても文字列の突き合わせとして実行されます。つまり、DNS によって使用されるのと同じ形式でアカウントホスト値を指定しなければならないということを意味します。留意するべき問題の例を次に示します。

  • ローカルネットワーク上のホストの完全修飾名が host1.example.com だとします。DNS がこのホストの名前参照を host1.example.com として返す場合、アカウントホスト値にこの名前を使用します。ただし、DNS が host1 のみを返す場合、代わりに host1 を使用します。

  • DNS が特定のホストの IP アドレスとして 192.168.1.2 を返す場合、これはアカウントホスト値 192.168.1.2 と一致しますが 192.168.01.2 とは一致しません。同様に、これは 192.168.1.% のようなアカウントホストパターンに一致しますが 192.168.01.% には一致しません。

このような問題を避けるために、DNS がホスト名およびアドレスを返す際の形式を確認し、同じ形式の値を MySQL アカウント名に使用するようにすることをお勧めします。

6.2.4 アクセス制御、ステージ 1: 接続の検証

ユーザーが MySQL サーバーに接続しようとすると、サーバーはユーザーの ID と、正しいパスワードを指定することでユーザーが自分の ID を検証できるかどうかに基づいて、接続を受け入れるか拒否します。できない場合、サーバーはアクセスを完全に拒否します。それ以外の場合、サーバーは接続を受け入れてステージ 2 に進み、リクエストを待機します。

ユーザーの ID は 2 つの部分の情報に基づきます。

  • 接続元のクライアントホスト

  • MySQL ユーザー名

ID チェックは、user テーブルの 3 つのスコープカラム (HostUserPassword) を使用して実施されます。サーバーは、一部の user テーブル行の Host および User カラムがクライアントホスト名およびユーザー名と一致し、その行に指定されているパスワードがクライアントから提供された場合のみ、接続を受け入れます。許容可能な Host および User 値についてのルールは、セクション6.2.3「アカウント名の指定」にあります。

User カラム値がブランクでない場合、入接続のユーザー名は正確に一致する必要があります。User 値がブランクの場合、これはすべてのユーザー名と一致します。入接続と一致する user テーブル行のユーザー名がブランクである場合、ユーザーはクライアントが実際に指定した名前を持つユーザーでなく、名前のない匿名ユーザーとみなされます。つまり、接続期間中の (つまりステージ 2 での) 今後のすべてのアクセスチェックでブランクのユーザー名が使用されることを意味します。

Password カラムはブランクにできます。これはワイルドカードではなく、あらゆるパスワードが一致するという意味ではありません。これは、ユーザーはパスワードを指定せずに接続しなければならないことを意味します。サーバーがプラグインを使用してクライアントを認証する場合、プラグインが実装する認証方式で、Password カラムのパスワードが使用される場合もそうでない場合もあります。この場合、MySQL サーバーへの認証を行う際に、外部パスワードも使用される可能性があります。

user テーブル内のブランクでない Password 値は暗号化パスワードを表します。MySQL は、すべてのユーザーが表示できるプレーンテキスト形式のパスワードを格納しません。代わりに、接続しようとしたユーザーが入力したパスワードは (PASSWORD() 関数を使用して) 暗号化されます。そのあと、暗号化パスワードは、接続プロセス中にパスワードが正しいかどうかをチェックするときに使用されます。これは、暗号化パスワードが接続を介してやりとりされずに実行されます。セクション6.3.1「ユーザー名とパスワード」を参照してください。

MySQL から見ると、暗号化パスワードが実際のパスワードであるため、暗号化パスワードへのアクセス権限をすべてのユーザーに付与しないようにしてください。特に、管理者以外のユーザーに、mysql データベース内のテーブルへの読み取りアクセス権限を付与しないでください

次の表では、user テーブルエントリの Host 値および User 値のさまざまな組み合わせが入接続にどのように適用されるかを示しています。

HostUser許容される接続
'thomas.loc.gov''fred'thomas.loc.gov から接続する fred
'thomas.loc.gov'''thomas.loc.gov から接続するすべてのユーザー
'%''fred'任意のホストから接続する fred
'%'''任意のホストから接続する任意のユーザー
'%.loc.gov''fred'loc.gov ドメイン内の任意のホストから接続する fred
'x.y.%''fred'x.y.netx.y.comx.y.edu などから接続する fred。おそらく有用ではありません
'144.155.166.177''fred'IP アドレス 144.155.166.177 のホストから接続する fred
'144.155.166.%''fred'144.155.166 のクラス C サブネットの任意のホストから接続する fred
'144.155.166.0/255.255.255.0''fred'前の例と同じ

入接続のクライアントホスト名およびユーザー名が user テーブルの複数行と一致することもあります。このことは前の一連の例で示されており、示されている複数のエントリが、fred による thomas.loc.gov からの接続に一致します。

複数の一致が可能な場合、サーバーはいずれを使用するかを決定する必要があります。この問題は、次のように解決されます。

  • サーバーが user テーブルをメモリーに読み取るとき、行を毎回ソートします。

  • クライアントが接続しようとすると、サーバーは行をソート順に参照します。

  • サーバーは、クライアントホスト名およびユーザー名が一致した最初の行を使用します。

サーバーは、具体性がもっとも高い Host 値が先になるように行を並べるソートルールを使用します。リテラルのホスト名および IP アドレスは具体性がもっとも高くなります。(リテラルの IP アドレスの具体性は IP アドレスがネットマスクを持つかどうかによって影響されないため、192.168.1.13192.168.1.0/255.255.255.0 の具体性は同等とみなされます。)パターン '%'任意のホストを意味するため、具体性はもっとも低くなります。空の文字列 ''任意のホストを意味しますが、'%' のあとにソートされます。同じ Host 値を持つ行は、もっとも具体的な User 値が最初になるよう並べられます (ブランクの User 値は 任意のユーザーを意味し、具体性がもっとも低くなります)。Host および User 値の具体性が等しい行については、順序は不確定です。

user テーブルが次の内容であると仮定して、これがどのように作用するかを説明します。

+-----------+----------+-
| Host | User | ...
+-----------+----------+-
| % | root | ...
| % | jeffrey | ...
| localhost | root | ...
| localhost | | ...
+-----------+----------+-

サーバーがテーブルをメモリーに読み取るとき、サーバーは前に記載したルールを使用して行をソートします。ソート後の結果は次のようになります。

+-----------+----------+-
| Host | User | ...
+-----------+----------+-
| localhost | root | ...
| localhost | | ...
| % | jeffrey | ...
| % | root | ...
+-----------+----------+-

クライアントが接続しようとすると、サーバーはソート済みの行を参照し、見つかった最初の一致を使用します。jeffrey による localhost からの接続の場合、テーブルの 2 つの行が一致し、すなわち Host および User 値が 'localhost' および '' であるものと、値が '%' および 'jeffrey' であるものが一致します。ソート順では 'localhost' 行が最初になるため、サーバーはこの行を使用します。

次に別の例を示します。user テーブルが次のようになっていると仮定します。

+----------------+----------+-
| Host | User | ...
+----------------+----------+-
| % | jeffrey | ...
| thomas.loc.gov | | ...
+----------------+----------+-

ソート済みテーブルは次のようになります。

+----------------+----------+-
| Host | User | ...
+----------------+----------+-
| thomas.loc.gov | | ...
| % | jeffrey | ...
+----------------+----------+-

jeffrey による thomas.loc.gov からの接続は最初の行に一致しますが、jeffrey による任意のホストからの接続は 2 番目の行に一致します。

注記

よくある誤解として、ある特定のユーザー名についてサーバーが接続に対する一致を検出しようとしたとき、そのユーザーの名前を明示的に指定するすべての行が最初に使用されるという認識があります。これは正しくありません。このことは前述の例によって説明され、jeffrey による thomas.loc.gov からの接続は、User カラム値として 'jeffrey' を格納している行ではなく、ユーザー名のない行が最初に一致します。その結果、jeffrey は接続するときにユーザー名を指定したにもかかわらず、匿名ユーザーとして認証されます。

サーバーに接続できても権限が期待したものとは異なる場合、おそらくほかのアカウントとして認証されています。サーバーがユーザーの認識に使用したアカウントを見つけるには、CURRENT_USER() 関数を使用します。(セクション12.14「情報関数」を参照してください。)これは、一致する user テーブル行の User および Host 値を示す、user_name@host_name 形式の値を返します。たとえば、jeffrey が接続して、次のクエリーを発行したとします。

mysql> SELECT CURRENT_USER();+----------------+
| CURRENT_USER() |
+----------------+
| @localhost |
+----------------+

ここで表示された結果は、一致した user テーブル行の User カラム値がブランクであることを示しています。つまり、サーバーは jeffrey を匿名ユーザーとして扱っています。

認証の問題を診断するための別の方法は、user テーブルを出力し、テーブルを手作業でソートして、最初の一致が行われた行を確認する方法です。

6.2.5 アクセス制御、ステージ 2: リクエストの確認

接続が確立されたあと、サーバーはアクセス制御のステージ 2 に入ります。接続を介してユーザーが発行する各リクエストに対し、サーバーはユーザーが実行する操作を判別し、その操作を行う十分な権限をユーザーが持つかどうかを検査します。ここで、付与テーブルの権限カラムが役立ちます。これらの権限は、userdbtables_privcolumns_priv、または procs_priv テーブルから取得される可能性があります。(それぞれの付与テーブルにあるカラムの一覧を示す、セクション6.2.2「権限システム付与テーブル」を参照すると役立つことがあります。)

user テーブルは、ユーザーにグローバルに割り当てられ、デフォルトのデータベースに関係なく適用される権限を付与します。たとえば、user テーブルによってユーザーに DELETE 権限が付与された場合、そのサーバーホスト上のあらゆるデータベースのあらゆるテーブルの行を削除できてしまいます。user テーブルの権限は、データベース管理者などの権限を必要とするユーザーに対してのみ付与するのが賢明です。ほかのユーザーについては、user テーブルのすべての権限を 'N' に設定しておき、具体的なレベルでのみ権限を付与するようにします。特定のデータベース、テーブル、カラム、またはルーチンに対して権限を付与することができます。

db テーブルは、データベース固有の権限を付与します。このテーブルのスコープカラムの値は、次の形式を取ることができます。

  • ブランクの User 値は匿名ユーザーに一致します。ブランク以外の値は文字どおりに一致し、ユーザー名にワイルドカードはありません。

  • Host および Db カラム内でワイルドカード文字%および_を使用することができます。これらは LIKE 演算子で実行されるパターンマッチング演算と同じ意味を持ちます。権限を付与するときにいずれかの文字を文字どおりに使用する場合、文字をバックスラッシュでエスケープする必要があります。たとえば、データベース名の一部としてアンダースコア文字 (_) を含めるには、GRANT ステートメント内でこれを \_ と指定します。

  • '%' またはブランクの Host 値は、任意のホストを意味します。

  • '%' またはブランクの Db 値は、任意のデータベースを意味します。

サーバーは user テーブルを読み取るのと同時に、db テーブルをメモリーに読み取ってソートします。サーバーは、HostDb、および User スコープカラムに基づき db テーブルをソートします。user テーブルと同じように、ソートでは、もっとも具体的な値が最初に配置され、もっとも具体的でない値が最後に配置され、サーバーが一致するエントリを参照するときは、見つかった最初の一致が使用されます。

tables_privcolumns_priv、および procs_priv テーブルは、テーブル固有、カラム固有、およびルーチン固有の権限を付与します。これらのテーブルのスコープカラムの値は、次の形式を取ることができます。

  • Host カラム内でワイルドカード文字%および_を使用することができます。これらは LIKE 演算子で実行されるパターンマッチング演算と同じ意味を持ちます。

  • '%' またはブランクの Host 値は、任意のホストを意味します。

  • DbTable_nameColumn_name、および Routine_name カラムは、ワイルドカードを含めたり、ブランクにしたりすることができません。

サーバーは、HostDb、および User カラムに基づき、tables_privcolumns_priv、および procs_priv テーブルをソートします。これは db テーブルのソートと同様ですが、Host カラムのみワイルドカードを含めることができるため、よりシンプルです。

サーバーはソート済みテーブルを使用して、サーバーが受け取るリクエストを検証します。SHUTDOWNRELOAD などの管理権限が必要なリクエストでは、サーバーは user テーブル行のみチェックします。これは、管理権限を指定するのはこのテーブルだけであるためです。リクエストされた操作がその行によって許可される場合、サーバーはアクセス権限を付与し、そうでない場合はアクセスを拒否します。たとえば、ユーザーが mysqladmin shutdown を実行したいが、user テーブル行によって SHUTDOWN 権限がユーザーに付与されていない場合、サーバーは db テーブルさえもチェックせずにアクセスを拒否します。(これには Shutdown_priv カラムがないため、実行は不要です。)

データベース関連のリクエスト (INSERTUPDATE など) の場合、サーバーは user テーブル行を参照することによって、ユーザーのグローバル権限を最初にチェックします。リクエストされた操作が行で許可されている場合、アクセス権限が付与されます。user テーブル内のグローバル権限が不十分な場合、サーバーは db テーブルをチェックすることによってユーザーのデータベース固有の権限を調べます。

サーバーは、db テーブルを参照し HostDb、および User カラムの一致がないかチェックします。Host および User カラムは、接続するユーザーのホスト名および MySQL ユーザー名に突き合わせされます。Db カラムは、ユーザーがアクセスしようとしているデータベースに突き合わせされます。Host および User に該当する行がない場合、アクセスは拒否されます。

db テーブルエントリによって付与されるデータベース固有の権限を判別したあと、サーバーは user テーブルによって付与されるグローバル権限にそれらの権限を追加します。その結果、リクエストされた操作が許可される場合、アクセス権限が付与されます。そうでない場合、サーバーは続けて tables_priv および columns_priv テーブル内でユーザーのテーブル権限およびカラム権限をチェックし、これらをユーザーの権限に追加し、結果に基づいてアクセスを許可または拒否します。ストアドルーチン操作の場合、サーバーは tables_priv および columns_priv の代わりに procs_priv テーブルを使用します。

ブール条件によって表現すると、ユーザーの権限を計算する方法についての前述の説明は、次のように要約できます。

global privileges
OR (database privileges AND host privileges)
OR table privileges
OR column privileges
OR routine privileges

リクエストされた操作に対して user 行のグローバル権限が最初に十分ではないことがわかっている場合に、サーバーがそれらの権限をあとでデータベース権限、テーブル権限、およびカラム権限と組み合わせることの理由が明確でないかもしれません。この理由は、1 つのリクエストが複数のタイプの権限を必要とすることがあるためです。たとえば、INSERT INTO ... SELECT ステートメントを実行する場合、INSERT および SELECT 権限が両方必要です。使用する権限が、user テーブル行で 1 つの権限を付与し、db テーブル行でもう 1 つの権限を付与するようになっている場合があります。この状況で、リクエストを実行するために必要な権限はありますが、サーバーはいずれのテーブルから来たものかを見分けることができず、両方のテーブルのエントリによって付与される権限を組み合わせる必要があります。

6.2.6 権限変更が有効化される時期

mysqld を起動すると、すべての付与テーブルの内容がメモリーに読み取られます。インメモリーテーブルは、その時点でアクセス制御に有効になります。

ユーザーが GRANTREVOKESET PASSWORDRENAME USER などのアカウント管理ステートメントを使用して、付与テーブルを間接的に変更した場合、サーバーはそれらの変更を認識し、再びすぐに付与テーブルをメモリーにロードします。

INSERTUPDATEDELETE などのステートメントを使用して、付与テーブルを直接変更する場合、サーバーを再起動するか、テーブルをリロードするようサーバーに指示するまで、変更内容は権限チェックに影響しません。付与テーブルを直接変更したが、それらをリロードし忘れた場合、サーバーを再起動するまで変更は影響しません。このため、変更したのに違いが現れないことを不思議に思うことがあるかもしれません。

付与テーブルをリロードするようサーバーに指示するには、フラッシュ権限操作を実行します。これは、FLUSH PRIVILEGES ステートメントを発行するか、mysqladmin flush-privileges または mysqladmin reload コマンドを実行することによって行うことができます。

付与テーブルのリロードは、既存のクライアント接続のための権限に次のような影響を及ぼします。

  • テーブルおよびカラムの権限の変更は、クライアントの次回のリクエストで有効になります。

  • データベース権限の変更は、クライアントが次回 USE db_name ステートメントを実行したときに有効になります。

    注記

    クライアントアプリケーションがデータベース名をキャッシュしている場合があるため、この影響は、実際に別のデータベースに変更したり、権限をフラッシュしたりしないかぎり、クライアントアプリケーションに認識されないことがあります。

  • 接続済みクライアントについてのグローバルな権限およびパスワードは影響されません。これらの変更は、後続の接続についてのみ有効になります。

サーバーが --skip-grant-tables オプションを指定して起動された場合、サーバーは付与テーブルを読み取ったりアクセス制御を実装したりしません。すべてのユーザーが接続してあらゆることが可能であるため、セキュアではありません。そのように起動されたサーバーが、テーブルを読み取ってアクセスチェックを有効にするようにするには、権限をフラッシュします。

6.2.7 アクセス拒否エラーの原因

MySQL サーバーへの接続を試行したときに問題が発生した場合に問題を修正するために実行できる一連のアクションについて、次の項目で説明します。

  • サーバーが実行中であることを確認します。そうでない場合、クライアントは接続できません。たとえば、サーバーに接続しようとして次のいずれかのようなメッセージで失敗した場合、サーバーが実行中でないことが 1 つの原因であることがあります。

    shell> mysqlERROR 2003: Can't connect to MySQL server on 'host_name' (111)
    shell> mysqlERROR 2002: Can't connect to local MySQL server through socket
    '/tmp/mysql.sock' (111)
  • サーバーは実行しているが、サーバーが待機しているのと異なる TCP/IP ポート、名前付きパイプ、または Unix ソケットファイルを使用して接続しようとしている場合もあります。これを修正するには、クライアントプログラムを呼び出すときに、適切なポート番号を指すように --port オプションを指定するか、--socket で適切な名前付きパイプまたは Unix ソケットファイルを指定します。ソケットファイルがある場所を見つけるには、次のコマンドを使用できます。

    shell> netstat -ln | grep mysql
  • サーバーがネットワーク接続を無視するように構成されていないこと、または (リモート側から接続しようとする場合に) サーバーのネットワークインタフェース上でローカル側でのみ待機するように構成されていないことを確認します。サーバーが --skip-networking を指定して起動された場合、サーバーは TCP/IP 接続を受け入れません。サーバーが --bind-address=127.0.0.1 を指定して起動された場合、サーバーはローカルのループバックインタフェース上でのみ TCP/IP 接続を待機するためリモート接続を受け入れません。

  • ファイアウォールが MySQL へのアクセスをブロックしていないか確認します。ファイアウォールは、実行中のアプリケーションまたは MySQL によって通信用に使用されるポート番号 (デフォルトは 3306) を基準として構成されることがあります。Linux または Unix の場合、IP テーブル (または同様の機能の) 構成を調べてポートがブロックされていないことを確認します。Windows の場合、ZoneAlarm や Windows XP パーソナルファイアウォールなどのアプリケーションが MySQL ポートをブロックしないようにこれらを構成することが必要な場合があります。

  • 付与テーブルが適切にセットアップされており、サーバーがこれをアクセス制御に使用できるようになっていることが必要です。一部の配布タイプ (Windows のバイナリ配布または Linux の RPM 配布など) では、インストールプロセスで、付与テーブルがある mysql データベースが初期化されます。これを行わない配布の場合、mysql_install_db プログラムを実行して付与テーブルを手動で初期化する必要があります。詳細については、セクション2.10.1「Unix 類似システムでのインストール後の手順」を参照してください。

    付与テーブルの初期化が必要かどうかを判別するには、データディレクトリの下にある mysql ディレクトリを参照します。(通常、データディレクトリは data または var という名前で、MySQL のインストールディレクトリの下にあります。)mysql データベースディレクトリに user.MYD という名前のファイルがあることを確認してください。ない場合、mysql_install_db プログラムを実行します。このプログラムを実行してサーバーを起動したあと、次のコマンドを実行して初期の権限をテストします。

    shell> mysql -u root test

    サーバーはエラーを出さずにユーザーを接続するはずです。

  • 新規インストールのあと、サーバーに接続してユーザーおよびユーザーのアクセス権限をセットアップするようにします。

    shell> mysql -u root mysql

    MySQL root ユーザーには最初からパスワードがないため、サーバーはユーザーを接続するはずです。これにはセキュリティー面でのリスクが伴うため、別の MySQL アカウントをセットアップする際は、root アカウントのパスワードを設定することをお勧めします。初期パスワードの設定手順に関しては、セクション2.10.2「最初の MySQL アカウントのセキュリティー設定」を参照してください。

  • 既存の MySQL インストールを新しいバージョンに更新した場合、mysql_upgrade スクリプトを実行したかどうかを確認します。行なっていない場合は実行します。付与テーブルの構造は、新機能が追加されるときにしばしば変更されるため、アップグレードしたあとは常に、テーブルの構造が最新であることを確認することをお勧めします。その手順は、セクション4.4.7「mysql_upgrade — MySQL テーブルのチェックとアップグレード」を参照してください。

  • クライアントプログラムが接続しようとしたときに次のエラーメッセージを受け取る場合、サーバーはクライアントが生成可能なものよりも新しい形式のパスワードを予期していることを意味します。

    shell> mysqlClient does not support authentication protocol requested
    by server; consider upgrading MySQL client

    これに対処する方法については、セクション6.1.2.4「MySQL でのパスワードハッシュ」およびセクションB.5.2.4「クライアントは認証プロトコルに対応できません」を参照してください。

  • クライアントプログラムはオプションファイルまたは環境変数に指定された接続パラメータを使用することに留意してください。コマンド行に接続パラメータを指定しないときにクライアントプログラムが間違ったデフォルトの接続パラメータを送信していると思われる場合、該当するオプションファイルおよび環境を確認してください。たとえば、オプションなしでクライアントを実行するときに Access denied を受け取る場合、いずれかのオプションファイルで古いパスワードを指定していないか確認してください。

    --no-defaults を指定してクライアントプログラムを呼び出すことによって、オプションファイルの使用をクライアントプログラムによって抑制することができます。例:

    shell> mysqladmin --no-defaults -u root version

    クライアントが使用するオプションファイルの一覧は、セクション4.2.6「オプションファイルの使用」にあります。環境変数の一覧は、セクション2.12「環境変数」にあります。

  • 次のエラーが出る場合、誤った root パスワードを使用していることを示しています。

    shell> mysqladmin -u root -pxxxx verAccess denied for user 'root'@'localhost' (using password: YES)

    パスワードを指定していないのに前述のエラーが発生する場合、いずれかのオプションファイルに間違ったパスワードがリストされていることを意味します。前述の項目で説明したように、--no-defaults オプションを試してみてください。

    パスワードの変更に関する情報は、セクション6.3.5「アカウントパスワードの割り当て」を参照してください。

    root パスワードを紛失したか忘れた場合、セクションB.5.4.1「root のパスワードをリセットする方法」を参照してください。

  • SET PASSWORDINSERT、または UPDATE を使用してパスワードを変更する場合、PASSWORD() 関数を使用して、そのパスワードを暗号化する必要があります。これらのステートメントに対して PASSWORD() 関数を使用しないと、パスワードは機能しません。たとえば、次のステートメントはパスワードを割り当てますが、パスワードが暗号化されないため、ユーザーはあとで接続できません。

    SET PASSWORD FOR 'abe'@'host_name' = 'eagle';

    代わりに、パスワードを次のように設定します。

    SET PASSWORD FOR 'abe'@'host_name' = PASSWORD('eagle');

    CREATE USER または GRANT ステートメントまたは mysqladmin password コマンドを使用してパスワードを指定するときは、PASSWORD() 関数は不要です。これらはいずれも PASSWORD() を自動的に使用してパスワードを暗号化します。セクション6.3.5「アカウントパスワードの割り当て」およびセクション13.7.1.2「CREATE USER 構文」を参照してください。

  • localhost はローカルホスト名のシノニムで、ホストを明示的に指定しない場合にクライアントが接続を試行するデフォルトホストでもあります。

    そのようなシステムで前述の問題を回避するために、--host=127.0.0.1 オプションを使用して、サーバーホストを明示的に指定することができます。これにより、ローカルの mysqld サーバーへの TCP/IP 接続が作成されます。また、ローカルホストの実際のホスト名を使用する --host オプションを指定することによって TCP/IP を使用することもできます。この場合、サーバーと同じホスト上でクライアントプログラムを実行していても、ホスト名がサーバーホスト上の user テーブル行に指定されていなければなりません。

  • Access denied というエラーメッセージは、ログインしようとしているユーザー名、接続を試行しているクライアントホスト、およびパスワードを使用したかどうかを通知します。通常では、エラーメッセージ内で指定されたホスト名およびユーザー名に正確に一致する 1 つの行を user テーブル内に持つようにします。たとえば、using password: NO というメッセージを含むエラーメッセージを受け取る場合、パスワードなしでログインしようとしたことを意味します。

  • mysql -u user_name を使用してデータベースに接続しようとしたときに Access denied エラーを受け取った場合、user テーブルにおそらく問題があります。これをチェックするには、mysql -u root mysql を実行し、次の SQL ステートメントを発行します。

    SELECT * FROM user;

    この結果には、クライアントのホスト名および使用中の MySQL ユーザー名に一致する Host および User カラムを持つ行が含まれているはずです。

  • MySQL サーバーを実行しているホストではないホストから接続しようとして次のエラーが発生する場合、クライアントホストと一致する Host 値を持つ行が user テーブルにないということを意味しています。

    Host ... is not allowed to connect to this MySQL server

    これは、接続しようとするときに使用するクライアントホスト名およびユーザー名の組み合わせに対するアカウントをセットアップすることによって修正できます。

    接続元のマシンの IP アドレスまたはホスト名がわからない場合、Host カラム値が '%' の行を user テーブル内に作成するようにします。そして、そのクライアントマシンから接続しようとしたあとで、SELECT USER() クエリーを使用して、実際にどのように接続したかを確認します。そのあと、user テーブル行の '%' を、ログに表示されている実際のホスト名に変更します。そうしない場合、特定のユーザー名について任意のホストからの接続が可能になるため、システムはセキュアでない状態のままになります。

    Linux では、このエラーが発生する可能性がある別の理由として、使用中のバージョンとは異なるバージョンの glibc ライブラリでコンパイルされたバイナリ MySQL バージョンを使用しているということがあります。この場合、オペレーティングシステムまたは glibc をアップグレードするか、MySQL のソース配布バージョンをダウンロードして自分でコンパイルします。ソース RPM のコンパイルおよびインストールは通常簡単であるため、これは大きな問題ではありません。

  • 接続しようとしたときにホスト名を指定したが、ホスト名が非表示または IP アドレスとなっているエラーメッセージを受け取った場合、MySQL サーバーはクライアントホストの IP アドレスを名前に解決しようとしたときにエラーを受け取ったことを意味します。

    shell> mysqladmin -u root -pxxxx -h some_hostname verAccess denied for user 'root'@'' (using password: YES)

    root として接続しようとして次のエラーを受け取った場合、User カラム値が 'root' の行が user テーブルになく、mysqld がクライアントに対してホスト名を解決できないことを意味します。

    Access denied for user ''@'unknown'

    これらのエラーは DNS の問題を示しています。これを修正するには、mysqladmin flush-hosts を実行して内部 DNS ホストキャッシュをリセットします。セクション8.11.5.2「DNS ルックアップの最適化とホストキャッシュ」を参照してください。

    いくつかの永続的な解決策を次に示します。

    • DNS サーバーの問題を判別して修正します。

    • MySQL 付与テーブルにホスト名の代わりに IP アドレスを指定します。

    • クライアントマシン名に対するエントリを、Unix の場合は /etc/hosts に、Windows の場合は \windows\hosts に配置します。

    • mysqld--skip-name-resolve オプションで起動します。

    • mysqld--skip-host-cache オプションで起動します。

    • Unix で、サーバーとクライアントを同じマシンで実行している場合、localhost に接続します。localhost への Unix 接続は、TCP/IP ではなく Unix ソケットファイルを使用します。

    • Windows で、サーバーとクライアントを同じマシンで実行していて、サーバーが名前付きパイプ接続をサポートしている場合、ホスト名 . (ピリオド) に接続します。. への接続には、TCP/IP ではなく名前付きパイプが使用されます。

  • mysql -u root test は動作するが、mysql -h your_hostname -u root testAccess denied になる場合 (ここで、your_hostname はローカルホストの実際のホスト名)、ホスト名に対する正しい名前が user テーブル内にない可能性があります。このときよくある問題として、user テーブル行の Host 値は、修飾されていないホスト名を指定しているが、システムの名前解決ルーチンは完全修飾ドメイン名を返すということ (またはその逆) があります。たとえば、user テーブルにホスト 'pluto' のエントリがあるが、DNS が MySQL に対してホスト名が 'pluto.example.com' であると指示する場合、エントリは無効になります。ホストの IP アドレスを Host カラム値として格納するエントリを user テーブルに追加してみてください。(または、'pluto.%' などのワイルドカードを含む Host 値を持つエントリを user テーブルに追加することもできます。ただし、%で終わる Host 値を使用することは安全でないため推奨されません。)

  • mysql -u user_name test が動作するが、mysql -u user_nameother_db が動作しない場合、other_db という名前のデータベースについて、特定のユーザーにアクセス権限を付与していません。

  • mysql -u user_name をサーバーホスト上で実行したときに動作するが、mysql -h host_name -u user_name をリモートクライアントホスト上で実行したときに動作しない場合、特定のユーザー名についてリモートホストからサーバーへのアクセスを有効にしていません。

  • Access denied を受け取る理由がわからない場合、ワイルドカードを含む Host 値を持つすべてのエントリ ('%' または '_' 文字を含むエントリ) を user テーブルから削除します。非常によくある間違いは、Host='%' および User='some_user' という新しいエントリを挿入して、これにより、ユーザーは同じマシンから接続するよう localhost に指定できると思い込むことです。これが機能しない理由は、デフォルト権限に、Host = 'localhost' および User = '' というエントリを含むためです。このエントリには、'%' よりもさらに具体的な 'localhost' という Host 値があるため、localhost から接続するときは新しいエントリよりもこちらが優先して使用されます。正しい手順としては、Host = 'localhost' および User = 'some_user' という第 2 のエントリを挿入するか、Host = 'localhost' および User = '' のエントリを削除します。このエントリを削除したら、FLUSH PRIVILEGES ステートメントを発行して、付与テーブルのリロードを必ず行なってください。セクション6.2.4「アクセス制御、ステージ 1: 接続の検証」も参照してください。

  • MySQL サーバーに接続できるが、SELECT ... INTO OUTFILE または LOAD DATA INFILE ステートメントを発行するたびに Access denied メッセージを受け取る場合、user テーブル内のエントリで FILE 権限が有効になっていません。

  • 付与テーブルを直接 (たとえば、INSERTUPDATE、または DELETE ステートメントを使用して) 変更し、変更が無視されたように思われる場合、サーバーに権限テーブルをリロードさせるために FLUSH PRIVILEGES ステートメントまたは mysqladmin flush-privileges コマンドを実行する必要があることを覚えておいてください。そうしない場合、サーバーが次回再起動するまで変更の影響はありません。root パスワードを UPDATE ステートメントで変更したあと、権限をフラッシュするまで新規パスワードを指定する必要はありません。これは、パスワードが変更されたことがサーバーにまだ認識されないためです。

  • セッションの最中に権限が変更されたと思われる場合、MySQL 管理者によって権限が変更された可能性があります。付与テーブルのリロードは、新しいクライアント接続に影響しますが、セクション6.2.6「権限変更が有効化される時期」に示すように既存の接続にも影響します。

  • Perl、PHP、Python、または ODBC プログラムとのアクセスに問題がある場合、mysql -u user_namedb_name または mysql -u user_name -pyour_passdb_name を使用してサーバーに接続してみてください。mysql クライアントを使用して接続できる場合、問題はアクセス権限ではなくプログラムにあります。(-p とパスワードの間にスペースはありません。--password=your_pass 構文を使用してパスワードを指定することもできます。-p または --password オプションを使用してパスワード値を指定しない場合、MySQL はパスワードを要求します。)

  • テスト目的で、--skip-grant-tables オプションを指定して mysqld サーバーを起動します。これにより、MySQL 付与テーブルを変更でき、SHOW GRANTS ステートメントを使用して、変更による望ましい影響があるかどうかを確認することができます。変更に満足したら、mysqladmin flush-privileges を実行して、権限をリロードするよう mysqld サーバーに指示します。これにより、サーバーを停止して再起動することなく新しい付与テーブルの内容の使用を開始することができます。

  • すべてが失敗する場合、mysqld サーバーをデバッグオプション (--debug=d,general,query など) で起動します。これによって、発行された各コマンドに関する情報のほかに、試行された接続についてのホストおよびユーザー情報が出力されます。セクション24.4.3「DBUG パッケージ」を参照してください。

  • MySQL 付与テーブルに関して何かほかの問題があって、メーリングリストに問題を投稿する必要があると思われる場合、MySQL 付与テーブルのダンプを常に提供してください。mysqldump mysql コマンドでテーブルをダンプできます。バグレポートを提出するには、セクション1.7「質問またはバグをレポートする方法」の説明を参照してください。mysqldump を実行するには --skip-grant-tables を指定して mysqld を再起動することが必要な場合もあります。

6.3 MySQL ユーザーアカウントの管理

このセクションでは、MySQL サーバーのクライアント用にアカウントを設定する方法について説明します。次のトピックについて説明します。

  • MySQL で使用されるアカウント名とパスワードの意味、およびオペレーティングシステムで使用される名前とパスワードと比較する方法

  • 新しいアカウントを設定し、既存のアカウントを削除する方法

  • パスワードを変更する方法

  • パスワードをセキュアに使用するためのガイドライン

  • SSL によるセキュアな接続を使用する方法

すべてのユーザー管理 SQL ステートメントの構文および使用について説明されているセクション13.7.1「アカウント管理ステートメント」も参照してください。

6.3.1 ユーザー名とパスワード

MySQL では、mysql データベースの user テーブルにアカウントが格納されます。アカウントは、ユーザー名およびユーザーがサーバーに接続できるクライアントホスト (複数の場合あり) に関して定義されます。アカウントはパスワードを持っている場合もあります。user テーブルでのアカウントの表示については、セクション6.2.2「権限システム付与テーブル」を参照してください。MySQL 5.6 では、認証プラグインがサポートされているため、アカウントは一部の外部認証方式を使用して認証できます。セクション6.3.7「プラガブル認証」を参照してください。

ユーザー名とパスワードが MySQL で使用される方法と、オペレーティングシステムで使用される方法との間には、いくつかの違いがあります。

  • MySQL で認証目的に使用されるユーザー名と、Windows または Unix で使用されるユーザー名 (ログイン名) とには、まったく関係がありません。Unix では、ほとんどの MySQL クライアントがデフォルトで、現在の Unix ユーザー名を MySQL ユーザー名として使用してログインを試みますが、これは便宜上の目的に過ぎません。クライアントプログラムでは、-u または --user オプションを使用して任意のユーザー名を指定することが許可されているため、簡単にデフォルトをオーバーライドできます。これは、ユーザー名を使用すればだれでもサーバーへの接続を試みることができることを意味するため、すべての MySQL アカウントがパスワードを持っていなければ、どのような方法でもデータベースをセキュアにすることはできません。パスワードを持っていないアカウントにユーザー名を指定するユーザーはだれでも、正常にサーバーに接続できます。

  • MySQL ユーザー名は、最大で 16 文字の長さまで指定できます。オペレーティングシステムのユーザー名は、MySQL ユーザー名とは完全に無関係であるため、最大長が異なる可能性があります。たとえば、Unix ユーザー名は通常、8 文字までに制限されています。

    警告

    MySQL サーバーおよびクライアントでは、MySQL ユーザー名の長さの制限がハードコードされているため、mysql データベース内のテーブル定義を変更してこれを回避しようとしても、効果がありません

    セクション4.4.7「mysql_upgrade — MySQL テーブルのチェックとアップグレード」で説明する手順を使用する以外は、どのような方法でも mysql データベース内のテーブルは変更するべきではありません。その他の方法で MySQL のシステムテーブルを再定義しようとすると、未定義 (および未サポート) の動作が発生します。

  • サーバーは (mysql.user テーブルに格納されたパスワードと照合する) MySQL ネイティブ認証を使用してクライアント接続を認証する際に、user テーブルに格納された MySQL パスワードを使用します。これらのパスワードと、オペレーティングシステムにログインするためのパスワードとには、まったく関係がありません。Windows または Unix マシンにログインする際に使用される外部パスワードと、そのマシン上の MySQL サーバーにアクセスする際に使用されるパスワードとの間には、必要な関係はありません。

    サーバーがプラグインを使用してクライアントを認証する場合は、プラグインで実装されている認証方式で、user テーブル内のパスワードが使用される場合と、使用されない場合があります。この場合、MySQL サーバーへの認証を行う際に、外部パスワードも使用される可能性があります。

  • MySQL では独自アルゴリズムを使用して、user テーブルに格納されたパスワードが暗号化されます。この暗号化は、PASSWORD() SQL 関数で実装されたものと同じですが、Unix のログインプロセス時に使用されるものとは異なります。Unix のパスワード暗号化は、ENCRYPT() SQL 関数で実装されたものと同じです。PASSWORD() および ENCRYPT() 関数については、セクション12.13「暗号化関数と圧縮関数」を参照してください。

    MySQL バージョン 4.1 以降では、旧バージョンよりも強固な認証方式が採用され、接続プロセス時のパスワード保護が改善されています。TCP/IP パケットが盗聴されたり、mysql データベースが乗っ取られたりしてもセキュアです。(旧バージョンでは、パスワードが暗号化された形式で user テーブルに格納されますが、MySQL サーバーに接続する際に、暗号化されたパスワード値を知っていることが利用される可能性があります。)セクション6.1.2.4「MySQL でのパスワードハッシュ」では、パスワードの暗号化について詳細に説明します。

  • ユーザー名およびパスワードに ASCII 文字のみが含まれている場合は、文字セットの設定に関係なく、サーバーに接続できます。ユーザー名またはパスワードに ASCII 文字以外が含まれているときに接続するには、クライアントは MYSQL_SET_CHARSET_NAME オプションと引数として適切な文字セット名を指定して、mysql_options() C API 関数を呼び出すようにしてください。これにより、指定された文字セットを使用した認証が実行されます。それ以外の場合、サーバーのデフォルト文字セットが認証のデフォルトエンコーディングと同じでなければ、認証に失敗します。

    標準の MySQL クライアントプログラムでは、先ほど説明したように、mysql_options() が呼び出される --default-character-set オプションがサポートされています。さらに、セクション10.1.4「接続文字セットおよび照合順序」で説明したように、文字セットの自動検出もサポートされています。C API に基づいていないコネクタを使用するプログラムでは、mysql_options() と同等のものがコネクタで提供されている場合があり、それを代わりに使用できます。コネクタのドキュメントを確認してください。

    前述の注は、クライアントの文字セットとして許可されていない ucs2utf16、および utf32 には適用されません。

MySQL をインストールすると、付与テーブルにアカウントの初期セットが移入されます。これらのアカウントの名前およびアクセス権限については、セクション2.10.2「最初の MySQL アカウントのセキュリティー設定」で説明されています。ここでは、パスワードを割り当てる方法についても説明されています。そのあと、通常は CREATE USERGRANT、および REVOKE などのステートメントを使用して、MySQL アカウントを設定、変更、および削除します。セクション13.7.1「アカウント管理ステートメント」を参照してください。

コマンド行クライアントを使用して MySQL サーバーに接続する場合は、使用するアカウントでの必要に応じて、ユーザー名とパスワードを指定します。

shell> mysql --user=monty --password=passworddb_name

短いオプションを好む場合は、コマンドは次のようになります。

shell> mysql -u monty -ppassworddb_name

-p オプションとそれに続くパスワード値との間には、空白文字を入れないでください。

コマンド行で --password または -p オプションに続く password 値を省略した場合は、値を 1 つ指定するように求めるプロンプトがクライアントに表示されます。

コマンド行でパスワードを指定することは、セキュアでないと考えるべきです。セクション6.1.2.1「パスワードセキュリティーのためのエンドユーザーガイドライン」を参照してください。オプションファイルを使用すれば、コマンド行でパスワードを指定することを回避できます。

ユーザー名、パスワード、およびその他の接続パラメータの指定に関する追加情報については、セクション4.2.2「MySQL サーバーへの接続」を参照してください。

6.3.2 ユーザーアカウントの追加

MySQL アカウントは、次の 2 つの方法で作成できます。

  • アカウントを作成するためのステートメント (CREATE USERGRANT など) を使用する。これらのステートメントを発行すると、サーバーによって付与テーブルへの適切な変更が行われます。

  • INSERTUPDATEDELETE などのステートメントを使用して、MySQL 付与テーブルを直接操作する。

アカウント作成のステートメントを使用する方が、付与テーブルを直接操作するよりも簡潔で、エラーの発生率も低いため、推奨される方法です。CREATE USER および GRANT については、セクション13.7.1「アカウント管理ステートメント」で説明されています。

アカウントを作成するためのもう 1 つのオプションは、GUI ツール MySQL Workbench を使用する方法です。または、MySQL アカウント管理の機能を提供する使用可能な複数のサードパーティープログラムのいずれかを使用します。phpMyAdmin は、このようなプログラムの 1 つです。

次の例では、mysql クライアントプログラムを使用して、新しいアカウントを設定する方法を示します。これらの例は、セクション2.10.2「最初の MySQL アカウントのセキュリティー設定」で説明するデフォルトに従って、権限が設定されていることが前提となっています。つまり、変更を行うには、MySQL root ユーザーとして MySQL サーバーに接続する必要があり、root アカウントは mysql データベースに対する INSERT 権限および RELOAD 管理権限を持っている必要があります。

該当する例で注記したように、特定の制約が有効になるようにサーバーの SQL モードが設定されている場合は、一部のステートメントに失敗します。特に、厳密モード (STRICT_TRANS_TABLESSTRICT_ALL_TABLES、および NO_AUTO_CREATE_USER) では、サーバーが一部のステートメントを受け入れることが回避されます。このような場合のために、回避策を示します。SQL モードおよびそれによる付与テーブルの操作への影響についての詳細は、セクション5.1.7「サーバー SQL モード」およびセクション13.7.1.4「GRANT 構文」を参照してください。

まず、mysql プログラムを使用して、MySQL root ユーザーとしてサーバーに接続します。

shell> mysql --user=root mysql

root アカウントにパスワードを割り当てた場合は、この mysql コマンドと、このセクションで後述するコマンドの両方に、--password または -p オプションを指定する必要もあります。

root としてサーバーに接続したあとは、新しいアカウントを追加できます。次のステートメントは、GRANT を使用して 4 つの新しいアカウントを設定します。

mysql> CREATE USER 'monty'@'localhost' IDENTIFIED BY 'some_pass';mysql> GRANT ALL PRIVILEGES ON *.* TO 'monty'@'localhost' ->  WITH GRANT OPTION;mysql> CREATE USER 'monty'@'%' IDENTIFIED BY 'some_pass';mysql> GRANT ALL PRIVILEGES ON *.* TO 'monty'@'%' ->  WITH GRANT OPTION;mysql> CREATE USER 'admin'@'localhost';mysql> GRANT RELOAD,PROCESS ON *.* TO 'admin'@'localhost';mysql> CREATE USER 'dummy'@'localhost';

これらのステートメントで作成されたアカウントには、次のプロパティーがあります。

  • アカウントのうち 2 つは、ユーザー名が monty、パスワードが some_pass です。どちらのアカウントも、すべてを実行するための完全な権限を持っているスーパーユーザーアカウントです。'monty'@'localhost' アカウントは、ローカルホストから接続する際にのみ使用できます。'monty'@'%' アカウントでは、ホスト部分に '%' ワイルドカードが使用されているため、これを使用すれば任意のホストから接続できます。

    monty として任意の場所から接続できるようにするには、monty に両方のアカウントが必要です。localhost アカウントがない場合は、monty がローカルホストから接続する際に、mysql_install_db で作成された localhost の匿名ユーザーアカウントが優先されます。その結果、monty は匿名ユーザーとして処理されます。その理由は、匿名ユーザーアカウントが 'monty'@'%' アカウントよりも固有の Host カラム値を持っているため、user テーブルのソート順でより早く表示されるためです。(user テーブルのソートについては、セクション6.2.4「アクセス制御、ステージ 1: 接続の検証」で説明されています。)

  • 'admin'@'localhost' アカウントにはパスワードがありません。このアカウントは、admin がローカルホストから接続する際にのみ使用できます。これには、RELOAD および PROCESS の管理者権限が付与されます。これらの権限を持つ admin ユーザーは、mysqladmin reloadmysqladmin refreshmysqladmin flush-xxx コマンド、および mysqladmin processlist を実行できます。任意のデータベースにアクセスするための権限は付与されません。その他の GRANT ステートメントを発行すれば、あとでこのような権限を追加できることがあります。

  • 'dummy'@'localhost' アカウントにはパスワードがありません。このアカウントは、ローカルホストから接続する際にのみ使用できます。権限は付与されません。あとでアカウントに特定の権限を付与することを前提としています。

NO_AUTO_CREATE_USER SQL モードが有効になっている場合は、パスワードなしでアカウントを作成するステートメントに失敗します。これに対処するには、空でないパスワードを指定する IDENTIFIED BY 句を使用します。

アカウントに対する権限をチェックするには、SHOW GRANTS を使用します。

mysql> SHOW GRANTS FOR 'admin'@'localhost';+-----------------------------------------------------+
| Grants for admin@localhost |
+-----------------------------------------------------+
| GRANT RELOAD, PROCESS ON *.* TO 'admin'@'localhost' |
+-----------------------------------------------------+

CREATE USER および GRANT の代わりとして、直接 INSERT ステートメントを発行してから、FLUSH PRIVILEGES を使用して付与テーブルを再ロードするようにサーバーに指示することで、同じアカウントを作成できます。

shell> mysql --user=root mysqlmysql> INSERT INTO user -> VALUES('localhost','monty',PASSWORD('some_pass'), -> 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');mysql> INSERT INTO user -> VALUES('%','monty',PASSWORD('some_pass'), -> 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', -> 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', -> '','','','',0,0,0,0);mysql> INSERT INTO user SET Host='localhost',User='admin', -> Reload_priv='Y', Process_priv='Y';mysql> INSERT INTO user (Host,User,Password) -> VALUES('localhost','dummy','');mysql> FLUSH PRIVILEGES;

INSERT を使用してアカウントを作成する場合は、FLUSH PRIVILEGES を使用して、付与テーブルを再ロードするようにサーバーに指示する必要があります。そうしなければ、サーバーを再起動するまで変更が認識されません。CREATE USER では、FLUSH PRIVILEGES が必要ありません。

INSERT PASSWORD() 関数を使用する理由は、パスワードを暗号化するためです。CREATE USER ステートメントでは自動的にパスワードが暗号化されるため、PASSWORD() は必要ありません。

'Y' 値を指定すると、アカウントに対する権限が有効になります。MySQL のバージョンによっては、最初の 2 つの INSERT ステートメントに異なる数の 'Y' 値を使用する必要がある場合もあります。admin アカウントに対する INSERT ステートメントでは、SET を使用することで、さらに読み取り可能になるように拡張された INSERT 構文が採用されています。

dummy アカウントに対する INSERT ステートメントでは、user テーブル行内の HostUser、および Password カラムにのみ、値が割り当てられます。権限カラムは明示的に設定されないため、MySQL によってすべてのカラムに、デフォルト値の 'N' が割り当てられます。これは、CREATE USER の動作と同等です。

厳密な SQL モードが有効になっている場合は、デフォルト値を持たないすべてのカラムに値を指定する必要があります。この場合、INSERT ステートメントは、明示的に ssl_cipherx509_issuer、および x509_subject カラムに値を指定する必要があります。

スーパーユーザーアカウントを設定するために必要な操作は、すべての権限カラムが 'Y' に設定された user テーブル行を挿入することだけです。user テーブルの権限はグローバルであるため、その他の付与テーブルのいずれにもエントリは必要ありません。

次の例では、3 つのアカウントを作成し、それらに特定のデータベースへのアクセス権を付与します。それぞれのユーザー名は custom で、パスワードは obscure です。

CREATE USER および GRANT を使用してアカウントを作成するには、次のステートメントを使用します。

shell> mysql --user=root mysqlmysql> CREATE USER 'custom'@'localhost' IDENTIFIED BY 'obscure';mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ->  ON bankaccount.* ->  TO 'custom'@'localhost';mysql> CREATE USER 'custom'@'host47.example.com' IDENTIFIED BY 'obscure';mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ->  ON expenses.* ->  TO 'custom'@'host47.example.com';mysql> CREATE USER 'custom'@'server.domain' IDENTIFIED BY 'obscure';mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ->  ON customer.* ->  TO 'custom'@'server.domain';

3 つのアカウントは、次のように使用できます。

  • 1 番目のアカウントは、bankaccount データベースにアクセスできますが、ローカルホストからに限定されます。

  • 2 番目のアカウントは、expenses データベースにアクセスできますが、host47.example.com ホストからに限定されます。

  • 3 番目のアカウントは、customer データベースにアクセスできますが、server.domain ホストからに限定されます。

GRANT を使用せずに custom アカウントを設定するには、次のように INSERT ステートメントを使用して、付与テーブルを直接変更します。

shell> mysql --user=root mysqlmysql> INSERT INTO user (Host,User,Password) -> VALUES('localhost','custom',PASSWORD('obscure'));mysql> INSERT INTO user (Host,User,Password) -> VALUES('host47.example.com','custom',PASSWORD('obscure'));mysql> INSERT INTO user (Host,User,Password) -> VALUES('server.domain','custom',PASSWORD('obscure'));mysql> INSERT INTO db -> (Host,Db,User,Select_priv,Insert_priv, -> Update_priv,Delete_priv,Create_priv,Drop_priv) -> VALUES('localhost','bankaccount','custom', -> 'Y','Y','Y','Y','Y','Y');mysql> INSERT INTO db -> (Host,Db,User,Select_priv,Insert_priv, -> Update_priv,Delete_priv,Create_priv,Drop_priv) -> VALUES('host47.example.com','expenses','custom', -> 'Y','Y','Y','Y','Y','Y');mysql> INSERT INTO db -> (Host,Db,User,Select_priv,Insert_priv, -> Update_priv,Delete_priv,Create_priv,Drop_priv) -> VALUES('server.domain','customer','custom', -> 'Y','Y','Y','Y','Y','Y');mysql> FLUSH PRIVILEGES;

最初の 3 つの INSERT ステートメントは、付与されたパスワードを使用してさまざまなホストから接続することをユーザー custom に許可する user テーブルエントリを追加しますが、グローバルな権限は付与しません (すべての権限はデフォルト値の 'N' に設定されます)。次の 3 つの INSERT ステートメントは、bankaccountexpenses、および customer データベースに対する権限を custom に付与するが、適切なホストからのアクセス時に限定される db テーブルエントリを追加します。通常どおりに付与テーブルを直接変更する場合は、権限の変更が有効になるように、FLUSH PRIVILEGES を使用して再ロードするようにサーバーに指示する必要があります。

特定のドメイン (mydomain.com など) 内のすべてのマシンからのアクセス権を持つユーザーを作成する際には、アカウント名のホスト部分に % ワイルドカード文字を使用できます。

mysql> CREATE USER 'myname'@'%.mydomain.com' IDENTIFIED BY 'mypass';

付与テーブルを直接変更することで同じ処理を行うには、次のように実行します。

mysql> INSERT INTO user (Host,User,Password,...) -> VALUES('%.mydomain.com','myname',PASSWORD('mypass'),...);mysql> FLUSH PRIVILEGES;

6.3.3 ユーザーアカウントの削除

アカウントを削除するには、セクション13.7.1.3「DROP USER 構文」で説明されている DROP USER ステートメントを使用します。

6.3.4 アカウントリソース制限の設定

MySQL サーバーリソースの使用を制限する方法の 1 つは、グローバルな max_user_connections システム変数をゼロ以外の値に設定することです。これにより、任意の特定のアカウントで実行できる同時接続の数が制限されますが、一度クライアントが接続したら、実行内容には制限が課されません。さらに、max_user_connections を設定しても、各アカウントの管理は有効になりません。どちらのタイプの制御も、多くの MySQL 管理者 (特に、インターネットサービスプロバイダの従業員) にとって関心のあるものです。

MySQL 5.6 では、各アカウントに対して次のサーバーリソースの使用を制限できます。

  • アカウントが 1 時間ごとに発行できるクエリーの数

  • アカウントが 1 時間ごとに発行できる更新の数

  • アカウントが 1 時間ごとにサーバーに接続できる回数

  • アカウントによるサーバーへの同時接続の数

クエリー制限に対して、クライアントが発行できるステートメントがすべてカウントされます (その結果がクエリーキャッシュから提供される場合は除きます)。更新制限に対して、データベースまたはテーブルを変更するステートメントのみがカウントされます。

このコンテキストでは、アカウントmysql.user テーブル内の行に対応しています。つまり、接続に適用される user テーブル行内の User および Host 値に対して、接続が評価されます。たとえば、アカウント 'usera'@'%.example.com' は、example.com ドメイン内の任意のホストから接続することを usera に許可するために、usera および %.example.comUser および Host 値を持つ user テーブル内の行に対応しています。この場合、このような接続ではすべて同じアカウントが使用されるため、サーバーは、usera による example.com ドメイン内の任意のホストからのすべての接続に、この行のリソース制限をまとめて適用します。

MySQL 5.0.3 よりも前では、ユーザーの接続元である実際のホストに対して、アカウントが評価されていました。--old-style-user-limits オプションを付けてサーバーを起動すれば、この古いアカウント方式を選択できます。この場合、userahost1.example.comhost2.example.com から同時に接続すると、サーバーは各接続に個別にアカウントリソースの制限を適用します。userahost1.example.com から再度接続すると、サーバーはそのホストからの既存の接続とともに、その接続に対する制限を適用します。

アカウントに対してリソース制限を設定するには、GRANT ステートメントを使用します (セクション13.7.1.4「GRANT 構文」を参照してください)。制限される各リソースの名前を指定する WITH 句を指定します。各制限のデフォルト値は、ゼロ (制限なし) です。たとえば、制限された方法でのみ customer データベースにアクセスできる新しいアカウントを作成するには、次のようなステートメントを発行します。

mysql> CREATE USER 'francis'@'localhost' IDENTIFIED BY 'frank';mysql> GRANT ALL ON customer.* TO 'francis'@'localhost' ->  WITH MAX_QUERIES_PER_HOUR 20 ->  MAX_UPDATES_PER_HOUR 10 ->  MAX_CONNECTIONS_PER_HOUR 5 ->  MAX_USER_CONNECTIONS 2;

制限タイプの名前をすべて WITH 句に指定する必要はありませんが、名前を指定したものは任意の順序で表示できます。1 時間ごとの各制限の値は、1 時間当たりの回数を表す整数にするようにしてください。MAX_USER_CONNECTIONS では、制限はアカウントによる同時接続の最大数を表す整数です。この制限がゼロに設定されている場合は、グローバルな max_user_connections システム変数の値によって同時接続の数が決定されます。max_user_connections もゼロである場合は、アカウントに制限がありません。

アカウントに対する既存の制約を変更するには、グローバルレベル (ON *.*) で GRANT USAGE ステートメントを使用します。次のステートメントは、francis に対するクエリー制限を 100 に変更します。

mysql> GRANT USAGE ON *.* TO 'francis'@'localhost' -> WITH MAX_QUERIES_PER_HOUR 100;

このステートメントは、指定された制限値のみを変更し、それ以外のアカウントは未変更のままにします。

制限を削除するには、その値をゼロに設定します。たとえば、francis が接続できる 1 時間当たりの回数に対する制限を削除するには、次のステートメントを使用します。

mysql> GRANT USAGE ON *.* TO 'francis'@'localhost' -> WITH MAX_CONNECTIONS_PER_HOUR 0;

すでに説明したように、アカウントに対する同時接続の制限は、MAX_USER_CONNECTIONS 制限および max_user_connections システム変数によって決定されます。グローバルな max_user_connections 値が 10 であり、3 つのアカウントが GRANT を使用して指定されたリソース制限を持っていると仮定します。

GRANT ... TO 'user1'@'localhost' WITH MAX_USER_CONNECTIONS 0;
GRANT ... TO 'user2'@'localhost' WITH MAX_USER_CONNECTIONS 5;
GRANT ... TO 'user3'@'localhost' WITH MAX_USER_CONNECTIONS 20;

user1MAX_USER_CONNECTIONS はゼロであるため、接続の制限は 10 (グローバルな max_user_connections 値) です。user2user3MAX_USER_CONNECTIONS はゼロ以外であるため、接続の制限はそれぞれ 5 と 20 です。

サーバーはアカウントに対応する user テーブル行に、アカウントに対するリソース制限を格納します。max_questionsmax_updates、または max_connections カラムには、1 時間当たりの制限が格納され、max_user_connections カラムには、MAX_USER_CONNECTIONS の制限が格納されます。セクション6.2.2「権限システム付与テーブル」を参照してください。

任意のアカウントによるリソースのいずれかの使用に対してゼロ以外の制限が設定されている場合は、リソース使用のカウントが発生します。

サーバーが実行されると、各アカウントがリソースを使用する回数がカウントされます。過去 1 時間以内にアカウントが接続数に対する制限に達した場合は、その時間が経過するまで、そのアカウントによる以降の接続が拒否されます。同様に、アカウントがクエリーまたは更新の回数に対する制限に達した場合も、その時間が経過するまで、以降のクエリーまたは更新が拒否されます。このような場合はすべて、適切なエラーメッセージが発行されます。

リソースのカウントはクライアントごとではなく、アカウントごとに実行されます。たとえば、アカウントのクエリー制限が 50 である場合は、サーバーへの 2 つの同時クライアント接続を作成しても、制限を 100 に増加できません。両方の接続で発行されたクエリーは、まとめてカウントされます。

現在の 1 時間ごとのリソース使用のカウントは、すべてのアカウントに対してグローバルにリセットすることも、特定のアカウントごとに個別にリセットすることもできます。

  • すべてのアカウントに対して現在のカウントをゼロにリセットするには、FLUSH USER_RESOURCES ステートメント発行します。また、(たとえば、FLUSH PRIVILEGES ステートメントまたは mysqladmin reload コマンドを使用して) 付与テーブルを再ロードして、カウントをリセットすることもできます。

  • 各アカウントの制限のいずれかを再度付与すれば、そのカウントをゼロに設定できます。これを行うには、前述のように GRANT USAGE を使用して、アカウントが現在持っている値と等しい制限値を指定します。

カウンタをリセットしても、MAX_USER_CONNECTIONS の制限は影響を受けません。

サーバーが起動されると、すべてのカウントがゼロで始まります。再起動後は、カウントが繰り越されません。

MAX_USER_CONNECTIONS の制限では、アカウントが許可されている接続の最大数を現在開いている場合に、エッジケースが発生する可能性があります。接続が発生する時点までにサーバーで切断が完全に処理されていない場合に、切断後にすぐに接続すると、エラー (ER_TOO_MANY_USER_CONNECTIONS または ER_USER_LIMIT_REACHED) が発生する可能性があります。サーバーで切断処理が終了すると、別の接続がもう一度許可されます。

6.3.5 アカウントパスワードの割り当て

MySQL サーバーに接続するクライアントに必要な証明書には、パスワードを含めることができます。このセクションでは、MySQL アカウントにパスワードを割り当てる方法について説明します。クライアント認証は、プラグインを使用することで発生します。セクション6.3.7「プラガブル認証」を参照してください。

CREATE USER を使用して新しいアカウントを作成するときに、パスワードを割り当てるには、IDENTIFIED BY 句を含めます。

mysql> CREATE USER 'jeffrey'@'localhost' -> IDENTIFIED BY 'mypass';

既存のアカウントにパスワードを割り当てる方法またはそれを変更する方法の 1 つは、SET PASSWORD ステートメントを発行することです。

mysql> SET PASSWORD FOR -> 'jeffrey'@'localhost' = PASSWORD('mypass');

MySQL では、mysql データベースの user テーブルにパスワードが格納されます。mysql データベースに対する UPDATE 権限を持っている root などのユーザーのみが、ほかのユーザーのパスワードを変更できます。匿名ユーザーとして接続していない場合は、FOR 句を省略すれば自分自身のパスワードを変更できます。

mysql> SET PASSWORD = PASSWORD('mypass');

old_passwords システム変数の値によって、PASSWORD() で使用されるハッシュ化方式が決定されます。その関数を使用しているパスワードを指定しても、SET PASSWORD でそのパスワードの形式が正しくないとして拒否される場合は、old_passwords を設定してハッシュ化方式を変更する必要がある場合もあります。許可されている値については、セクション5.1.4「サーバーシステム変数」を参照してください。

read_only システム変数を有効にすると、SUPER 権限を持っていない任意のユーザーによる SET PASSWORD ステートメントの使用が回避されます。

また、グローバルレベル (ON *.*) で GRANT USAGE ステートメントを使用すると、アカウントの現在の権限に影響を与えずに、アカウントにパスワードを割り当てることができます。

mysql> GRANT USAGE ON *.* TO 'jeffrey'@'localhost' -> IDENTIFIED BY 'mypass';

コマンド行からパスワードを割り当てるには、mysqladmin コマンドを使用します。

shell> mysqladmin -u user_name -h host_name password "newpwd"

このコマンドでパスワードが設定されるアカウントは、User カラム内の user_name に一致する user テーブル行を持つアカウント、および Host カラム内の接続元のクライアントホストです。

認証中にクライアントがサーバーに接続すると、MySQL では user テーブル内のパスワードが暗号化されたハッシュ値 (PASSWORD() でパスワードに返される値) として処理されます。アカウントにパスワードを割り当てる際は、平文のパスワードではなく、暗号化された値を格納することが重要です。次のガイドラインを使用します。

  • CREATE USERIDENTIFIED BY 句を含む GRANT、または mysqladmin password コマンドを使用してパスワードを割り当てると、自動的にパスワードが暗号化されます。リテラルの平文パスワードを指定します。

    mysql> CREATE USER 'jeffrey'@'localhost' -> IDENTIFIED BY 'mypass';
  • CREATE USER または GRANT では、PASSWORD() でパスワードに返されるハッシュ値がわかっている場合に、平文パスワードの送信を回避できます。前にキーワード PASSWORD を付けたハッシュ値を指定します。

    mysql> CREATE USER 'jeffrey'@'localhost' -> IDENTIFIED BY PASSWORD '*90E462C37378CED12064BB3388827D2BA3A9B689';
  • SET PASSWORD を使用して、アカウントに空でないパスワードを割り当てる場合は、PASSWORD() 機能を使用してパスワードを暗号化する必要があります。それ以外の場合は、パスワードが平文として格納されます。次のようなパスワードを割り当てると仮定します。

    mysql> SET PASSWORD FOR -> 'jeffrey'@'localhost' = 'mypass';

    その結果、暗号化された値ではなく、リテラル値の 'mypass' がパスワードとして user テーブルに格納されます。jeffrey がこのパスワードを使用してサーバーへの接続を試みると、その値が暗号化され、user テーブルに格納された値と比較されます。ただし、格納されている値はリテラル文字列の 'mypass' であるため、比較に失敗し、サーバーは接続を拒否し、「アクセスが拒否されました」というエラーを返します。

注記

PASSWORD() の暗号化は、Unix のパスワード暗号化とは異なります。セクション6.3.1「ユーザー名とパスワード」を参照してください。

SET PASSWORDGRANT、または mysqladmin を使用してパスワードを割り当てることが望ましいですが、user テーブルを直接変更することもできます。この場合、FLUSH PRIVILEGES を使用して、サーバーで付与テーブルを再ロードさせる必要もあります。それ以外の場合は、サーバーを再起動するまで変更が認識されないままです。

6.3.6 パスワードの期限切れとサンドボックスモード

MySQL 5.6 では、データベース管理者がアカウントのパスワードを期限切れにして、ユーザーに自分のパスワードをリセットするように要求できるパスワード期限切れ機能が導入されています。直後の説明では、パスワードの期限切れの現在の動作について記述します。そのあと、どの機能がどのような状況で使用できるのかを理解する際に役立つ背景として、この機能の開発について、複数のバージョンにわたって詳細に説明します。ただし、すべての機能と修正を活用できるようにするには、可能なかぎり、MySQL 5.6 の最新バージョンを使用するようにしてください。

パスワードの期限切れの動作

アカウントのパスワードを期限切れにするには、ALTER USER ステートメントを使用します。例:

ALTER USER 'myuser'@'localhost' PASSWORD EXPIRE;

このステートメントは、password_expired カラムを 'Y' に設定することで、指定されたアカウントに関連付けられた mysql.user テーブルの行を変更します。これにより、アカウントが開いている現在の接続は影響を受けません。そのアカウントを使用する後続の各接続では、サーバーはクライアントを切断するか、サンドボックスモードでクライアントを処理します。このモードでは、期限切れのパスワードをリセットするために必要な操作のみが、サーバーからクライアントに許可されます。(サーバーで実行されるアクションは、クライアントとサーバー両方の設定に依存します。)

サーバーがクライアントを切断すると、ER_MUST_CHANGE_PASSWORD_LOGIN エラーが返されます。

shell> mysql -u myuser -pPassword: ******ERROR 1862 (HY000): Your password has expired. To log in you must
change it using a client that supports expired passwords.

サーバーがクライアントをサンドボックスモードに移行すると、これらの操作がクライアントセッション内で許可されます。

  • クライアントは SET PASSWORD を使用して、アカウントのパスワードをリセットできます。これは、password_expired カラムを 'N' に設定することで、現在のアカウントに関連付けられた mysql.user テーブルの行を変更します。パスワードがリセットされると、サーバーはそのセッション、およびアカウントを使用する後続の接続への通常のアクセスをリストアします。

    パスワードを現在の値に設定すれば、リセットできます。適切なポリシーとして、別のパスワードを選択することをお勧めします。

  • クライアントは SET ステートメントを使用できます。たとえば、old_passwords システム変数をデフォルトとは異なる値に設定する必要のあるハッシュ化形式がアカウントのパスワードで使用されている場合は、パスワードをリセットする前に、これが必要になることがあります。

セッション内で許可されていない操作の場合、サーバーは ER_MUST_CHANGE_PASSWORD エラーを返します。

mysql> USE test;ERROR 1820 (HY000): You must SET PASSWORD before executing this statement

すでに説明したように、サーバーがパスワードの期限が切れているクライアントを切断するのか、サンドボックスモードに移行するのかは、クライアント設定とサーバー設定の組み合わせによって異なります。次の説明では、関連する設定と、それらがどのように相互作用するのかについて記述します。

クライアント側では、特定のクライアントが期限切れパスワードに対してサンドボックスモードを処理できるかどうかを示します。C クライアントライブラリを使用するクライアントの場合、これを実行するための方法が 2 つあります。

  • 接続前に MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS フラグを mysql_options() に渡します。

    arg = 1;
    result = mysql_options(mysql, MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS, &arg);
  • 接続時に CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS フラグを mysql_real_connect() に渡します。

    mysql = mysql_real_connect(mysql, host, user, password, "test", port, unix_socket, CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS);

その他の MySQL コネクタには、サンドボックスモードを処理する準備ができていることを示す独自の規則が用意されています。関連するコネクタのドキュメントを参照してください。

サーバー側では、クライアントが期限切れパスワードを処理できることを示している場合、サーバーはサンドボックスモードに移行します。

クライアントが期限切れパスワードを処理できることを示していない場合 (または、そのように示すことができない古いバージョンのクライアントライブラリを使用している場合)、サーバーのアクションは disconnect_on_expired_password システム変数の値によって異なります。

  • disconnect_on_expired_password が有効になっている (デフォルト) 場合、サーバーはクライアントを切断し、ER_MUST_CHANGE_PASSWORD_LOGIN エラーを返します。

  • disconnect_on_expired_password が無効になっている場合、サーバーはクライアントをサンドボックスモードに移行します。

前述のクライアント設定とサーバー設定は、期限切れパスワードを持つアカウントにのみ適用されます。クライアントが期限切れでないパスワードを使用して接続すれば、サーバーはクライアントを通常どおりに処理します。

パスワードの期限切れ機能の開発

次のタイムラインには、さまざまなパスワードの期限切れ機能が追加されたバージョンを記載します。

MySQL 5.6.6: パスワードの期限切れの初期実装

DBA がアカウントのパスワードを期限切れにすることができるように、password_expired カラムが mysql.user テーブルに導入されました。このカラムのデフォルト値は、'N' (期限切れなし) です。

password_expired カラムを 'Y' に設定するための SQL インタフェースとして、ALTER USER ステートメントが導入されました。

期限切れパスワードを持つアカウントを使用して接続すると、SET PASSWORD ステートメントのみが許可されるサンドボックスモードに移行します。その他のステートメントの場合、サーバーは ER_MUST_CHANGE_PASSWORD エラーを返します。この目的は、サーバーでその他の操作が許可される前に、クライアントにパスワードのリセットを強制することです。SET PASSWORD はアカウントのパスワードをリセットし、password_expired'N' に設定します。

初期実装には、ALTER USER を使用すると mysql.user テーブル内の Password カラムが空の文字列に設定されるというバグがあります。つまり、このステートメントを使用するには、ユーザーは MySQL 5.6.7 まで待つべきです。

MySQL 5.6.7:

Password カラムが空の文字列に設定されないように、ALTER USER が固定されました。

MySQL 5.6.8:

ALTER USER は、準備されたステートメントとして使用できます。

mysqladmin password は、期限切れのネイティブまたは古いネイティブのパスワードを持つアカウントのパスワードを設定できるようになりました。

SET PASSWORD に加えて、クライアントが SET ステートメントを実行することが許可されるように、サンドボックスモードが変更されました。SET の禁止により、old_passwords を設定する必要があるクライアントがパスワードをリセットできませんでした。また、これにより、接続時に SET を広範囲に使用してセッション環境を初期化する一部のコネクタも使用できませんでした。

MySQL 5.6.9:

ステートメントで指定されたアカウントとクライアントが認証したアカウントが一致する場合にのみ、SET PASSWORD が許可されるように、サンドボックスモードが変更されました。

MySQL 5.6.10:

期限切れパスワードを持つアカウントのクライアント接続をサーバーが処理する方法をより適切に制御することが許可され、クライアントが期限切れパスワードを処理できるどうかを示すことが許可されるように、サンドボックスモードが変更されました。

  • サーバーが期限切れパスワードを持つアカウントを処理する方法を制御する disconnect_on_expired_password システム変数が追加されました。

  • C API クライアントライブラリに、mysql_options() 用の MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDSmysql_real_connect() 用の CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS の 2 つのフラグが追加されました。各フラグを使用すると、クライアントプログラムが期限切れパスワードを持つアカウントに対してサンドボックスモードを処理できるかどうかを示すことができます。

    MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDSmysqltest では無条件に、mysql ではインタラクティブモードで、mysqladmin では最初のコマンドが password の場合に有効になりました。

  • ER_MUST_CHANGE_PASSWORD_LOGIN エラーが追加されました。クライアントが切断されると、サーバーはこのエラーを返します。

MySQL サーバーと C API クライアントライブラリにおけるサンドボックスモードへのこれらの変更に合わせて、コネクタを変更に適合させるための修正の取り組みも始まっています。

6.3.7 プラガブル認証

クライアントが MySQL サーバーに接続すると、サーバーはクライアントおよびクライアントホストで提供されたユーザー名を使用して、mysql.user テーブルから適切なアカウント行を選択します。そのあと、サーバーは認証プラグインでクライアントに適用されるアカウント行から決定することで、クライアントを認証します。

  • アカウント行にプラグインが指定されている場合、サーバーはそれを呼び出すことで、ユーザーを認証します。サーバーがプラグインを検出できない場合は、エラーが発生します。

  • アカウント行にプラグイン名が指定されていない場合、Password カラム内のパスワードハッシュ値でネイティブのハッシュ化方式と、4.1 よりも前の古いハッシュ化方式のどちらが使用されているのかに応じて、サーバーは mysql_native_passwordmysql_old_password のいずれかのプラグインを使用してアカウントを認証します。クライアントは、アカウント行の Password カラム内のパスワードと一致する必要があります。

ユーザーが接続を許可されているかどうかを示すステータスがプラグインからサーバーに返されます。

プラガブル認証を使用すると、次の 2 つの重要な機能が有効になります。

  • 外部認証: プラガブル認証を使用すると、mysql.user テーブルに格納されているパスワードに基づいたネイティブ認証以外の認証方式に適した証明書を使用して、クライアントが MySQL サーバーに接続できます。たとえば、PAM、Windows のログイン ID、LDAP、Kerberos などの外部認証方式を使用するプラグインを作成できます。

  • プロキシユーザー: ユーザーが接続を許可されている場合、接続中のユーザーが別のユーザーのプロキシであることを示すために、認証プラグインは接続中のユーザーの名前と異なるユーザー名をサーバーに返すことができます。接続が存続している間は、アクセス制御のために、プロキシユーザーは別のユーザーの権限を持っているものとして処理されます。実際に、あるユーザーは別のユーザーを偽装します。詳細については、セクション6.3.9「プロキシユーザー」を参照してください。

MySQL では、複数の認証プラグインが使用可能です。

  • アカウント行の Password カラムと照合してパスワードを一致させるネイティブ認証を実行するプラグイン。mysql_native_password プラグインには、ネイティブのパスワードハッシュ化方式に基づいた認証が実装されています。mysql_old_password プラグインには、古い (4.1 よりも前の) パスワードハッシュ化方式 (現在は非推奨です) に基づいたネイティブ認証が実装されています。セクション6.3.8.1「ネイティブ認証プラグイン」およびセクション6.3.8.2「古いネイティブ認証プラグイン」を参照してください。サーバーの起動時に --default-authentication-plugin オプションが設定されている場合を除き、mysql_native_password を使用したネイティブ認証が新しいアカウントのデフォルトです。

  • SHA-256 のパスワードハッシュ化を使用して認証を実行するプラグイン。このプラグインは、アカウント行の authentication_string カラムと照合してパスワードを一致させます。これは、ネイティブ認証で実現できるよりも強力な暗号化です。セクション6.3.8.4「SHA-256 認証プラグイン」を参照してください。

  • PAM (Pluggable Authentication Module) と照合して外部認証を実行するプラグイン。これを使用すると、MySQL サーバーが PAM を使用して MySQL ユーザーを認証できます。このプラグインでは、プロキシユーザーもサポートされています。セクション6.3.8.5「PAM 認証プラグイン」を参照してください。

  • Windows で外部認証を実行するプラグイン。これを使用すると、MySQL サーバーがネイティブの Windows サービスを使用して、クライアント接続を認証できます。Windows にログインしたユーザーは、追加のパスワードを指定せずに、自分の環境内の情報に基づいて MySQL クライアントプログラムからサーバーに接続できます。このプラグインでは、プロキシユーザーもサポートされています。セクション6.3.8.6「Windows ネイティブ認証プラグイン」を参照してください。

  • ハッシュ化または暗号化を行わずに、サーバーにパスワードを送信するクライアント側のプラグイン。このプラグインは、クライアントユーザーから提供されたものとまったく同じパスワードにアクセスする必要があるサーバー側のプラグインで使用できます。セクション6.3.8.7「クライアント側のクリアテキスト認証プラグイン」を参照してください。

  • Unix ソケットファイルを使用してローカルホストから接続するクライアントを認証するプラグイン。セクション6.3.8.8「ソケットピア証明書認証プラグイン」を参照してください。

  • MySQL のネイティブ認証を使用して認証するテストプラグイン。このプラグインは、テストおよび開発のために、認証プラグインを作成する方法を示す例として使用されます。セクション6.3.8.9「テスト認証プラグイン」を参照してください。

注記

プラガブル認証の使用に対する現在の制約 (どのコネクタがどのプラグインをサポートしているのかなど) については、セクションD.9「プラガブルな認証の制約」を参照してください。

サードパーティー製コネクタの開発者は、コネクタがプラガブル認証機能を活用できる範囲と、より準拠させるために実行する手順を確認するために、そのセクションを読むべきです。

独自の認証プラグインを作成することに関心がある場合は、セクション24.2.4.9「認証プラグインの作成」を参照してください。

認証プラグインの使用手順

このセクションでは、認証プラグインをインストールおよび使用するための一般的な手順を示します。

通常、プラガブル認証では、サーバー側とクライアント側で対応するプラグインが使用されます。そのため、次のような特定の認証方式を使用します。

  • サーバーホストでは、必要に応じて、適切なサーバープラグインを含むライブラリをインストールします。これにより、サーバーはこれを使用して、クライアント接続を認証できます。同様に、各クライアントホストでは、クライアントプログラムで使用される適切なクライアントプラグインを含むライブラリをインストールします。

  • 認証用のプラグインの使用を指定する MySQL アカウントを作成します。

  • クライアントが接続すると、サーバープラグインからクライアントプログラムに、認証に使用されるクライアントプラグインが指示されます。

ここで示す指示では、MySQL 配布に含まれるサンプルの認証プラグインが使用されています (セクション6.3.8.9「テスト認証プラグイン」を参照してください)。この手順は、その他の認証プラグインに似ています。適切なプラグインとファイル名に置き換えてください。

サンプルの認証プラグインには、次のような特性があります。

  • サーバー側のプラグイン名は test_plugin_server です。

  • クライアント側のプラグイン名は auth_test_plugin です。

  • どちらのプラグインも、プラグインディレクトリ (plugin_dir システム変数で指定されたディレクトリ) 内の auth_test_plugin.so という名前の共有ライブラリオブジェクトファイルに配置されています。ファイル名のサフィクスは、システムによって異なる場合があります。

次のように、サンプルの認証プラグインをインストールして使用します。

  1. サーバーホストおよびクライアントホスト上に、プラグインライブラリがインストールされていることを確認します。

  2. サーバーの起動時または実行時に、サーバー側のテストプラグインをインストールします。

    • 起動時にプラグインをインストールするには、--plugin-load オプションを使用します。このプラグインのロード方式では、サーバーを起動するたびにオプションを指定する必要があります。たとえば、my.cnf オプションファイル内で次の行を使用します。

      [mysqld]
      plugin-load=test_plugin_server=auth_test_plugin.so
    • 実行時にプラグインをインストールするには、INSTALL PLUGIN ステートメントを使用します。

      mysql> INSTALL PLUGIN test_plugin_server SONAME 'auth_test_plugin.so';

      これにより、プラグインが永続的にインストールされるため、1 回しか実行する必要がありません。

  3. プラグインがインストールされていることを確認します。たとえば、SHOW PLUGINS を使用します。

    mysql> SHOW PLUGINS\G...
    *************************** 21. row *************************** Name: test_plugin_server Status: ACTIVE Type: AUTHENTICATION
    Library: auth_test_plugin.so
    License: GPL

    プラグインをチェックするためのその他の方法については、セクション5.1.8.2「サーバープラグイン情報の取得」を参照してください。

  4. 特定のサーバープラグインを使用して MySQL ユーザーを認証する必要があることを指定するには、ユーザーを作成する CREATE USER ステートメントの IDENTIFIED WITH 句にプラグインの名前を指定します。

    CREATE USER 'testuser'@'localhost' IDENTIFIED WITH test_plugin_server;
  5. クライアントプログラムを使用して、サーバーに接続します。テストプラグインは、ネイティブの MySQL 認証と同じ方法で認証を実行します。したがって、サーバーに接続する際に一般的に使用される通常の --user および --password オプションを指定します。例:

    shell> mysql --user=your_name --password=your_pass

    testuser による接続の場合、サーバーは test_plugin_server という名前のサーバー側のプラグインを使用してアカウントを認証する必要があることを認識し、クライアント側のプラグイン (この場合、auth_test_plugin) を使用する必要のあるクライアントプログラムと通信します。

    アカウントがサーバープログラムとクライアントプログラムの両方のデフォルトである認証方式を使用する場合、サーバーはプラグインを使用するクライアントと通信する必要がなく、クライアントとサーバーのネゴシエーションでラウンドトリップが発生することを回避できます。現在、これはネイティブの MySQL 認証 (mysql_native_password) を使用するアカウントに適用されます。

    mysql コマンド行で --default-auth=plugin_name オプションを指定すると、プログラムで使用するように要求できるクライアント側のプラグインを明示的に作成できます。ただし、ユーザーアカウントが別のプラグインを要求した場合、これはサーバーによってオーバーライドされます。

    クライアントプログラムでプラグインが見つからない場合は、プラグインが配置されている場所を示す --plugin-dir=dir_name オプションを指定します。

注記

--skip-grant-tables オプションを付けてサーバーを起動した場合、サーバーはクライアント認証を実行せず、任意のクライアントが接続することを許可するため、認証プラグインはロードされたとしても使用されません。これはセキュアではないため、リモートクライアントによる接続を回避するために、--skip-networking と組み合わせて --skip-grant-tables を使用する必要がある場合もあります。

6.3.8 MySQL で使用可能な認証プラグイン

次のセクションでは、MySQL で使用可能な認証プラグインについて説明します。

6.3.8.1 ネイティブ認証プラグイン

MySQL には、ネイティブ認証 (つまり、mysql.user テーブルの Password カラムに格納されたパスワードと照合する認証) を実装する 2 つのプラグインが含まれています。このセクションでは、ネイティブのパスワードハッシュ化方式を使用して、mysql.user テーブルと照合する認証が実装された mysql_native_password について説明します。古い (4.1 よりも前の) パスワードハッシュ化方式を使用した認証が実装された mysql_old_password については、セクション6.3.8.2「古いネイティブ認証プラグイン」を参照してください。これらのパスワードハッシュ化方式については、セクション6.1.2.4「MySQL でのパスワードハッシュ」を参照してください。

mysql_native_password ネイティブ認証プラグインには、下位互換性があります。MySQL 5.5.7 よりも古いクライアントでは、認証プラグインがサポートされていませんが、ネイティブ認証プロトコルは使用されます。そのため、MySQL 5.5.7 以上からサーバーに接続できます。

次の表に、サーバー側とクライアント側のプラグイン名を示します。

表 6.8 MySQL ネイティブパスワード認証プラグイン

サーバー側のプラグイン名mysql_native_password
クライアント側のプラグイン名mysql_native_password
ライブラリオブジェクトファイル名なし (プラグインは組み込み済み)

プラグインは、クライアントとサーバーの両方の形式で存在します。

  • サーバー側のプラグインはサーバーに組み込まれているため、明示的にロードする必要はなく、アンロードしても無効にすることができません。

  • クライアント側のプラグインは、MySQL 5.5.7 の時点で libmysqlclient クライアントライブラリに組み込まれ、そのバージョン以降では libmysqlclient に対してリンクされている任意のプログラムで使用可能です。

  • MySQL クライアントプログラムでは、デフォルトで mysql_native_password が使用されます。--default-auth オプションを使用すると、プラグインを明示的に指定できます。

    shell> mysql --default-auth=mysql_native_password ...

アカウント行にプラグイン名が指定されていない場合、Password カラム内のパスワードハッシュ値でネイティブのハッシュ化方式と、4.1 よりも前の古いハッシュ化方式のどちらが使用されるのかに応じて、サーバーは mysql_native_passwordmysql_old_password のいずれかのプラグインを使用してアカウントを認証します。クライアントは、アカウント行の Password カラム内のパスワードと一致する必要があります。

MySQL のプラガブル認証に関する一般的な情報については、セクション6.3.7「プラガブル認証」を参照してください。

6.3.8.2 古いネイティブ認証プラグイン

MySQL には、ネイティブ認証 (つまり、mysql.user テーブルの Password カラムに格納されたパスワードと照合する認証) を実装する 2 つのプラグインが含まれています。このセクションでは、古い (4.1 よりも前の) パスワードハッシュ化方式を使用して、mysql.user テーブルと照合する認証が実装された mysql_old_password について説明します。ネイティブのパスワードハッシュ化方式を使用した認証が実装された mysql_native_password については、セクション6.3.8.1「ネイティブ認証プラグイン」を参照してください。これらのパスワードハッシュ化方式については、セクション6.1.2.4「MySQL でのパスワードハッシュ」を参照してください。

注記

4.1 よりも前のハッシュ化方式を使用したパスワードは、ネイティブのパスワードハッシュ化方式を使用したパスワードよりもセキュアではありません。4.1 よりも前のパスワードは非推奨であり、これらのサポートは今後の MySQL リリースで削除される予定です。アカウントのアップグレード手順については、セクション6.3.8.3「4.1 よりも前のパスワードハッシュ方式と mysql_old_password プラグインからの移行」を参照してください。

mysql_old_password ネイティブ認証プラグインには、下位互換性があります。MySQL 5.5.7 よりも古いクライアントでは、認証プラグインがサポートされていませんが、ネイティブ認証プロトコルは使用されます。そのため、MySQL 5.5.7 以上からサーバーに接続できます。

次の表に、サーバー側とクライアント側のプラグイン名を示します。

表 6.9 MySQL の古いネイティブ認証プラグイン

サーバー側のプラグイン名mysql_old_password
クライアント側のプラグイン名mysql_old_password
ライブラリオブジェクトファイル名なし (プラグインは組み込み済み)

プラグインは、クライアントとサーバーの両方の形式で存在します。

  • サーバー側のプラグインはサーバーに組み込まれているため、明示的にロードする必要はなく、アンロードしても無効にすることができません。

  • クライアント側のプラグインは、MySQL 5.5.7 の時点で libmysqlclient クライアントライブラリに組み込まれ、そのバージョン以降では libmysqlclient に対してリンクされている任意のプログラムで使用可能です。

  • MySQL クライアントプログラムは、--default-auth オプションを使用して、mysql_old_password プラグインを明示的に指定できます。

    shell> mysql --default-auth=mysql_old_password ...

アカウント行にプラグイン名が指定されていない場合、Password カラム内のパスワードハッシュ値でネイティブのハッシュ化方式と、4.1 よりも前の古いハッシュ化方式のどちらが使用されるのかに応じて、サーバーは mysql_native_passwordmysql_old_password のいずれかのプラグインを使用してアカウントを認証します。クライアントは、アカウント行の Password カラム内のパスワードと一致する必要があります。

MySQL のプラガブル認証に関する一般的な情報については、セクション6.3.7「プラガブル認証」を参照してください。

6.3.8.3 4.1 よりも前のパスワードハッシュ方式と mysql_old_password プラグインからの移行

MySQL サーバーは、plugin カラムで名前が指定された認証プラグインを使用して、mysql.user テーブルに一覧表示されたアカウントごとに接続の試行を認証します。plugin カラムが空である場合、サーバーは次のように認証を実行します。

  • MySQL 5.7.2 よりも前では、Password カラム内のパスワードハッシュ形式に応じて、サーバーは暗黙的に mysql_native_password または mysql_old_password プラグインを使用します。Password 値が空または 4.1 のパスワードハッシュ (41 文字) である場合、サーバーは mysql_native_password を使用します。パスワード値が 4.1 より前のパスワードハッシュ (16 文字) の場合、サーバーは mysql_old_password を使用します。(これらのハッシュ形式に関する追加情報については、セクション6.1.2.4「MySQL でのパスワードハッシュ」を参照してください。)

  • MySQL 5.7.2 の時点では、plugin カラムを空以外にする必要があり、サーバーは空の plugin 値を持つアカウントを無効にします。5.7.5 の時点では、mysql_old_password のサポートが削除されています。

4.1 よりも前のパスワードハッシュおよび mysql_old_password プラグインは、MySQL 5.6.5 の時点で非推奨となり、4.1 のパスワードハッシュ化および mysql_native_password プラグインによって提供されるよりも低いセキュリティーレベルを提供します。plugin カラムを空以外にする必要のある MySQL 5.7.2 の要件と、5.7.5 で mysql_old_password のサポートが削除されたことを合わせて考えると、DBA は次のようにアカウントをアップグレードすることをお勧めします。

  • mysql_native_password を明示的に使用するために、それを暗黙的に使用しているアカウントをアップグレードします。

  • mysql_native_password を明示的に使用するために、(暗黙的または明示的に) mysql_old_password を使用しているアカウントをアップグレードします。

このセクションの手順では、これらのアップグレードを実行する方法について説明します。その結果、アカウントは空の plugin 値を持たず、4.1 よりも前のパスワードハッシュ化または mysql_old_password プラグインを使用しません。

これらの手順のバリエーションとして、DBA は、SHA-256 パスワードハッシュを使用して認証する sha256_password プラグインにアップグレードするという選択肢をユーザーに提示することがあります。このプラグインについては、セクション6.3.8.4「SHA-256 認証プラグイン」を参照してください。

次の表には、この説明で検討される mysql.user アカウントのタイプを一覧表示します。

plugin カラムPassword カラム認証結果アップグレードアクション
暗黙的に mysql_native_password を使用するプラグインの割り当て
4.1 のハッシュ暗黙的に mysql_native_password を使用するプラグインの割り当て
4.1 よりも前のハッシュ暗黙的に mysql_old_password を使用するプラグインを割り当て、パスワードを再ハッシュ化する
mysql_native_password明示的に mysql_native_password を使用するなし
mysql_native_password4.1 のハッシュ明示的に mysql_native_password を使用するなし
mysql_old_password明示的に mysql_old_password を使用するプラグインのアップグレード
mysql_old_password4.1 よりも前のハッシュ明示的に mysql_old_password を使用するプラグインをアップグレードし、パスワードを再ハッシュ化する

mysql_native_password プラグインの行に対応するアカウントでは、(プラグインやハッシュ形式を変更する必要がないため) アップグレードアクションは必要ありません。パスワードが空の行に対応するアカウントでは、DBA は、パスワードを選択するようにアカウントの所有者に要求することを検討するべきです (または、ALTER USER を使用して空のアカウントパスワードを期限切れにすることで、それを要求するべきです)。

mysql_native_password の暗黙的な使用から明示的な使用へのアップグレード

空のプラグインと 4.1 のパスワードハッシュを持つアカウントは、暗黙的に mysql_native_password を使用します。mysql_native_password を明示的に使用するようにアカウントをアップグレードするには、DBA は次のステートメントを実行するようにしてください。

UPDATE mysql.user SET plugin = 'mysql_native_password'
WHERE plugin = '' AND (Password = '' OR LENGTH(Password) = 41);
FLUSH PRIVILEGES;

MySQL 5.7.2 以降では、DBA は、そのアップグレードアクション間で同じ処理を行う mysql_upgrade を実行できます。5.7.2 よりも前では、DBA はこれらのステートメントを実行して、アカウントをプロアクティブにアップグレードできます。

注:

  • この手順は、すでに暗黙的に使用しているアカウントに対してのみ、mysql_native_password プラグインを明示的にするため、いつ実行しても安全です。

  • この手順ではパスワードを変更する必要がないため、DBA はユーザーに影響を与えたり、アップグレードプロセスに関与するようにユーザーに要求したりせずに、このアクションを実行できます。

mysql_old_password から mysql_native_password へのアカウントのアップグレード

mysql_native_password を明示的に使用するには、(暗黙的または明示的に) mysql_old_password を使用しているアカウントをアップグレードするようにしてください。これを行うには、プラグインを変更かつ4.1 よりも前から 4.1 のハッシュ形式にパスワードを変更する必要があります。

この手順で説明したアカウントをアップグレードする必要がある場合は、次の条件のいずれかに当てはまります。

  • plugin カラムが空であり、パスワードハッシュ形式が 4.1 よりも前 (16 文字) であるため、アカウントは暗黙的に mysql_old_password を使用します。

  • アカウントは明示的に mysql_old_password を使用します。

このようなアカウント識別するには、次のクエリーを使用します。

SELECT User, Host, Password FROM mysql.user
WHERE (plugin = '' AND LENGTH(Password) = 16)
OR plugin = 'mysql_old_password';

次の説明では、そのアカウントセットを更新するための 2 つの方法を示します。これらは異なる特性を持っているため、DBA は両方とも読み、特定の MySQL インストールに最適な方を決定するようにしてください。

方法 1.

この方法の特性:

  • すべてのユーザーが mysql_native_password にアップグレードされるまで、secure_auth=0 を指定してサーバーおよびクライアントを実行する必要があります。(それ以外の場合、ユーザーは新しい形式のハッシュにアップグレードするために、古い形式のパスワードハッシュを使用してサーバーに接続できません。)

  • MySQL 5.5 から 5.7.1 まででは、動作します。5.7.2 の時点では、サーバーは空でないプラグインを持つようにアカウントに要求し、そうでない場合はそれらのアカウントを無効にするため、動作しません。したがって、5.7.2 以降にアップグレードした場合は、方法 2 を選択してください。

DBA は、サーバーが secure_auth=0 を指定して実行されていることを確認するようにしてください。

明示的に mysql_old_password を使用するすべてのアカウントでは、DBA は空のプラグインに設定するようにしてください。

UPDATE mysql.user SET plugin = ''
WHERE plugin = 'mysql_old_password';
FLUSH PRIVILEGES;

また、影響を受けるアカウントのパスワードを期限切れにするには、次のステートメントを使用します。

UPDATE mysql.user SET plugin = '', password_expired = 'Y'
WHERE plugin = 'mysql_old_password';
FLUSH PRIVILEGES;

この時点で、影響を受けるユーザーはサーバーに接続し、4.1 のハッシュ化が使用されるようにパスワードをリセットできます。DBA は空のプラグインを現在持っている各ユーザーに、接続して次のステートメントを実行するように要求するようにしてください。

SET old_passwords = 0;
SET PASSWORD = PASSWORD('user-chosen-password');
注記

MySQL 5.6.5 以降では、クライアント側の --secure-auth がデフォルトで有効になっているため、DBA はこれを無効にするようにユーザーに思い出させるようにしてください。そうしなければ、ユーザーは接続できなくなります。

shell> mysql -u user_name -p --secure-auth=0

影響を受けるユーザーがこれらのステートメントを実行したあとに、DBA は対応するアカウントプラグインを mysql_native_password に設定すると、プラグインを明示的にすることができます。また、DBA は次のステートメントを定期的に実行すると、影響を受けるユーザーが自分のパスワードをリセットした任意のアカウントを検索および修正できます。

UPDATE mysql.user SET plugin = 'mysql_native_password'
WHERE plugin = '' AND (Password = '' OR LENGTH(Password) = 41);
FLUSH PRIVILEGES;

空のプラグインを持つアカウントがなくなると、このクエリーは空の結果を返します。

SELECT User, Host, Password FROM mysql.user
WHERE (plugin = '' AND LENGTH(Password) = 16);

この時点で、すべてのアカウントは 4.1 よりも前のパスワードハッシュ化から移行され、secure_auth=0 を指定してサーバーを実行する必要がなくなります。

方法 2.

この方法の特性:

  • DBA は、影響を受ける各アカウントに新しいパスワードを割り当てます。そのため、DBA はこのような各ユーザーに新しいパスワードを通知し、新しいパスワードを選択するようにユーザーに要求する必要があります。DBA からユーザーへのパスワードの通知は、MySQL のスコープ外です。DBA はパスワードを慎重に通知するようにしてください。

  • secure_auth=0 を指定してサーバーまたはクライアントを実行する必要はありません。

  • MySQL 5.5 以降のどのバージョンでも動作します。

この方法では、パスワードを個別に設定する必要があるため、DBA は各アカウントを別々に更新します。DBA は、アカウントごとに別々のパスワードを選択するようにしてください。

'user1'@'localhost' がアップグレードされるアカウントの 1 つであると仮定します。DBA は、次のように変更するようにしてください。

SET old_passwords = 0;
UPDATE mysql.user SET plugin = 'mysql_native_password',
Password = PASSWORD('DBA-chosen-password')
WHERE (User, Host) = ('user1', 'localhost');
FLUSH PRIVILEGES;

また、パスワードを期限切れにするには、代わりに次のステートメントを使用します。

SET old_passwords = 0;
UPDATE mysql.user SET plugin = 'mysql_native_password',
Password = PASSWORD('DBA-chosen-password'), password_expired = 'Y'
WHERE (User, Host) = ('user1', 'localhost');
FLUSH PRIVILEGES;

次に DBA は、ユーザーに新しいパスワードを通知して、そのパスワードを使用してサーバーに接続し、新しいパスワードを選択するために次のステートメントを実行するようにユーザーに要求するようにしてください。

SET old_passwords = 0;
SET PASSWORD = PASSWORD('user-chosen-password');

アップグレードするアカウントごとに繰り返します。

6.3.8.4 SHA-256 認証プラグイン

MySQL 5.6.6 の時点で、MySQL では、ユーザーアカウントのパスワード用に SHA-256 ハッシュ化が実装された認証プラグインが提供されています。

重要

sha256_password プラグインで認証するアカウントを使用してサーバーに接続するには、このセクションの後半で説明するように、SSL 接続または、RSA を使用してパスワードを暗号化する単純な接続を使用する必要があります。どちらの方法でも、sha256_password プラグインを使用するには、SSL の機能を使用して MySQL を構築する必要があります。セクション6.3.10「セキュアな接続のための SSL の使用」を参照してください。

次の表に、サーバー側とクライアント側のプラグイン名を示します。

表 6.10 MySQL SHA-256 認証プラグイン

サーバー側のプラグイン名sha256_password
クライアント側のプラグイン名sha256_password
ライブラリオブジェクトファイル名なし (プラグインは組み込み済み)

サーバー側の sha256_password プラグインはサーバーに組み込まれているため、明示的にロードする必要はなく、アンロードしても無効にすることはできません。同様に、クライアントはクライアント側のプラグインの場所を指定する必要がありません。

SHA-256 パスワードのハッシュ化を使用するアカウントを設定するには、次の手順を使用します。

  1. アカウントを作成し、sha256_password プラグインを使用して認証するように指定します。

    CREATE USER 'sha256user'@'localhost' IDENTIFIED WITH sha256_password;
  2. PASSWORD () 関数でパスワード文字列の SHA-256 ハッシュ化が使用されるように、old_passwords システム変数を 2 に設定してから、アカウントのパスワードを設定します。

    SET old_passwords = 2;
    SET PASSWORD FOR 'sha256user'@'localhost' = PASSWORD('Sh@256Pa33');

または、sha256_password に設定されたデフォルトの認証プラグインを使用して、サーバーを起動します。たとえば、サーバーのオプションファイルに次の行を挿入します。

[mysqld]
default-authentication-plugin=sha256_password

これにより、新しいアカウント用に sha256_password プラグインがデフォルトで使用され、old_passwords が 2 に設定されます。その結果、アカウント作成時に CREATE USER ステートメントで IDENTIFIED BY 句を使用して、パスワードを設定できます。

mysql> CREATE USER 'sha256user2'@'localhost' IDENTIFIED BY 'Sh@256Pa33';Query OK, 0 rows affected (0.06 sec)

この場合、サーバーは sha256_password プラグインをアカウントに割り当て、SHA-256 を使用してパスワードを暗号化します。(もう 1 つの結果として、sha256_password とは異なる認証プラグインを使用するアカウントを作成するには、CREATE USER ステートメントで IDENTIFIED BY 句を使用して、そのプラグインを指定し、プラグインに old_passwords を適切に設定してから、SET PASSWORD を使用してアカウントのパスワードを設定する必要があります。)

old_passwords および PASSWORD() についての詳細は、セクション5.1.4「サーバーシステム変数」およびセクション12.13「暗号化関数と圧縮関数」を参照してください。

sha256_password プラグインを使用して認証する任意のアカウントのパスワードを変更するには、SET PASSWORD を使用する前に、old_passwords の値が 2 になっていることを確認します。old_passwords の値が 2 以外になっている場合は、パスワードを設定しようとするとエラーが発生します。

mysql> SET old_passwords = 0;mysql> SET PASSWORD FOR 'sha256user'@'localhost' = PASSWORD('NewSh@256Pa33');ERROR 1827 (HY000): The password hash doesn't have the expected format.
Check if the correct password algorithm is being used with the
PASSWORD() function.

SHA-256 のパスワードを使用する mysql.user テーブル内のアカウントは、plugin カラム内の 'sha256_password' および authentication_string カラム内の SHA-256 パスワードハッシュを含む行として識別できます。

MySQL は yaSSL と OpenSSL のいずれかを使用して構築でき、sha256_password プラグインは、いずれかのパッケージを使用して構築された配布で動作します。デフォルトは、yaSSL を使用する方法です。代わりに OpenSSL を使用して MySQL が構築されている場合は、RSA 暗号化が使用可能であり、次のリストに示す追加の機能が sha256_password に実装されます。(これらの機能を有効にするには、このセクションの後半で示す RSA の構成手順に従う必要もあります。)

  • あとで説明するように、クライアント接続プロセス中に RSA 暗号化を使用すると、クライアントがサーバーにパスワードを送信できます。

  • サーバーは sha256_password_private_key_pathsha256_password_public_key_path の 2 つの追加のシステム変数を公開します。これは、サーバーの起動時にデータベース管理者が、これらを RSA 秘密鍵と公開鍵ファイルの名前に設定するために使用されます。

  • サーバーは、RSA 公開鍵の値を示すステータス変数 Rsa_public_key を公開します。

  • mysql および mysqltest クライアントプログラムでは、RSA 公開鍵ファイルを明示的に指定するための --server-public-key-path オプションがサポートされています。(このオプションは、--server-public-key という名前で MySQL 5.6.6 に追加されましたが、5.6.7 で --server-public-key-path という名前に変更されました。)

sha256_password プラグインを使用するクライアントでは、サーバーへの接続時にパスワードがクリアテキストとして公開されません。パスワードの送信がどのように発生するのかは、SSL 接続が使用されるのかどうか、および RSA 暗号化が使用可能であるかどうかによって異なります。

  • SSL 接続が使用される場合、パスワードはクリアテキストとして送信されますが、接続は SSL を使用して暗号化されるため、覗き見られる可能性はありません。

  • SSL 接続は使用されないが、RSA 暗号化が使用可能である場合、パスワードは暗号化されていない接続内に送信されます。ただし、パスワードは覗き見られないように RSA で暗号化されます。サーバーはパスワードを受信すると、それを復号化します。繰り返し攻撃を防ぐために、スクランブルが暗号化で使用されます。

  • SSL 接続が使用されず、RSA 暗号化が使用可能でない場合、パスワードはクリアテキストとして公開されずに送信できないため、sha256_password プラグインによる接続の試行に失敗します。

すでに説明したように、RSA のパスワード暗号化は、OpenSSL を使用して MySQL が構築された場合にのみ使用可能です。yaSSL を使用して MySQL 配布を構築したということは、クライアントが SSL 接続を使用してサーバーにアクセスする際にのみ、SHA-256 のパスワードを使用できることを意味します。SSL を使用したサーバーへの接続については、セクション6.3.10「セキュアな接続のための SSL の使用」を参照してください。

次の手順では、MySQL が OpenSSL を使用して構築されたと仮定して、クライアント接続プロセス中にパスワードの RSA 暗号化を有効にする方法について説明します。

  1. RSA の秘密鍵および公開鍵ファイルを作成します。MySQL サーバーを実行する際に使用されるシステムアカウントにログインしている間に、次のコマンドを実行します。これにより、ファイルはそのアカウントによって所有されます。

    openssl genrsa -out mykey.pem 1024
    openssl rsa -in mykey.pem -pubout -out mykey.pub

    これらのコマンドでは、1,024 ビットの鍵が作成されます。より強固な鍵を作成するには、2,048 のような大きな値を使用します。

  2. 鍵ファイルのアクセスモードを設定します。秘密鍵は、サーバーからのみ読み取り可能にするべきです。一方で、公開鍵は、クライアントユーザーに自由に配布できます。

    chmod 400 mykey.pem
    chmod 444 mykey.pub
  3. サーバーのオプションファイルで、鍵ファイルの名前を使用して適切なシステム変数を構成します。サーバーのデータディレクトリにファイルを配置する場合は、完全パス名を指定する必要がありません。

    [mysqld]
    sha256_password_private_key_path=mykey.pem
    sha256_password_public_key_path=mykey.pub

    ファイルがデータディレクトリ内にない場合や、システム変数の値でそれらの場所を明示的に指定する場合は、完全パス名を使用します。

    [mysqld]
    sha256_password_private_key_path=/usr/local/mysql/mykey.pem
    sha256_password_public_key_path=/usr/local/mysql/mykey.pub
  4. サーバーを再起動してから、それに接続し、Rsa_public_key ステータス変数の値をチェックします。値はここで示すものとは異なりますが、空以外を指定するようにしてください。

    mysql> SHOW STATUS LIKE 'Rsa_public_key'\G*************************** 1. row ***************************
    Variable_name: Rsa_public_key Value: -----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO9nRUDd+KvSZgY7cNBZMNpwX6
    MvE1PbJFXO7u18nJ9lwc99Du/E7lw6CVXw7VKrXPeHbVQUzGyUNkf45Nz/ckaaJa
    aLgJOBCIDmNVnyU54OT/1lcs2xiyfaDMe8fCJ64ZwTnKbY2gkt1IMjUAB5Ogd5kJ
    g8aV7EtKwyhHb0c30QIDAQAB
    -----END PUBLIC KEY-----

    値が空の場合は、鍵ファイルに関するいくつかの問題がサーバーで見つかっています。エラーログをチェックして、診断情報を確認してください。

サーバーに RSA 鍵ファイルが構成されると、クライアントはそれらのファイルを使用して、sha256_password プラグインで認証するアカウントを使用したサーバーに接続できます。すでに説明したように、このようなアカウントは SSL 接続 (この場合、RSA が使用されません)、または RSA を使用してパスワードを暗号化する単純な接続を使用できます。次の説明は、SSL が使用されないことが前提となっています。サーバーに接続するために、クライアント側で特別な準備をする必要はありません。例:

shell> mysql -u sha256user -pEnter password: Sh@256Pa33

sha256user によって接続を試みる場合、サーバーは sha256_password が適切な認証プラグインであると判断し、それを呼び出します。接続で SSL が使用されないために、RSA 暗号化を使用してパスワードを送信する必要があることがプラグインによって検出されます。RSA 公開鍵がクライアントに送信され、この鍵を使用してパスワードが暗号化され、結果がサーバーに返されます。このプラグインは、サーバー側の RSA 鍵を使用してパスワードを復号化し、パスワードが正しいかどうかに基づいて接続を承認または拒否します。

サーバーは必要に応じて公開鍵をクライアントに送信しますが、クライアントホスト上で RSA 公開鍵のコピーが使用可能である場合は、クライアントはその鍵を使用して、クライアント/サーバープロトコルにラウンドトリップを保存できます。

shell> mysql -u sha256user -p --server-public-key-path=file_name

--server-public-key-path オプションで指定されたファイル内の公開鍵値は、sha256_password_public_key_path システム変数で指定されたサーバー側のファイル内の鍵値と同じにするようにしてください。鍵ファイルに有効な公開鍵値が含まれているが、その値が正しくない場合は、アクセス拒否のエラーが発生します。鍵ファイルに有効な公開鍵が含まれていない場合は、その鍵をクライアントプログラムで使用できません。この場合、サーバーは --server-public-key-path オプションが指定された場合と同様に、クライアントに公開鍵を送信します。

クライアントユーザーは、次の 2 つの方法で RSA 公開鍵を取得できます。

  • データベース管理者は、公開鍵ファイルのコピーを提供できます。

  • その他の方法でサーバーに接続できるクライアントユーザーは、SHOW STATUS LIKE 'Rsa_public_key' ステートメントを使用し、返された鍵値をファイル内に保存できます。

6.3.8.5 PAM 認証プラグイン

注記

PAM 認証プラグインは、商用の拡張機能です。商用の製品 (MySQL Enterprise Edition) についてさらに学習するには、http://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「プロキシユーザー」を参照してください。

6.3.8.5.1 PAM 認証プラグインのインストール

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「サーバープラグイン情報の取得」を参照してください。

6.3.8.5.2 PAM 認証プラグインの使用

このセクションでは、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_namegroup_name、および sql_user_name の値には、等号、カンマ、または空白文字を除く、任意の文字を含めることができます。

  • pam_service_namegroup_name、または sql_user_name の値を二重引用符で囲むと、引用符間のすべての文字が値の一部となります。たとえば、値に空白文字が含まれている場合は、これが必要です。二重引用符およびバックスラッシュ ('\') を除く、すべての文字が有効です。どちらかの文字を含めるには、バックスラッシュを使用してエスケープします。

このプラグインは、各ログインチェック時に認証文字列を解析します。オーバーヘッドを最小限に抑えるには、できるだけ文字列を短く保ちます。

プラグインが正常にログイン名を認証すると、認証文字列でグループマッピングリストを検索し、そのリストを使用して外部ユーザーがメンバーになっているグループに基づいて MySQL サーバーに別のユーザー名を返します。

  • 認証文字列にグループマッピングリストが含まれていない場合は、プラグインはログイン名を返します。

  • 認証文字列にグループマッピングリストが含まれている場合は、プラグインはリスト内の各 group_name=sql_user_name ペアを左から右へと調査し、認証済みのユーザーに割り当てられたグループの MySQL 以外のディレクトリ内で、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 認証プラグインのデバッグ」を参照してください。

6.3.8.5.2.1 プロキシユーザーを使用しない Unix パスワード認証

この認証シナリオでは、Unix ユーザーのログイン名とパスワードをチェックする際にのみ PAM が使用されます。MySQL サーバーへの接続が許可されている外部ユーザーはすべて、外部 PAM 認証を使用するように定義されている一致する MySQL アカウントを持つべきです。

  1. PAM の Unix 認証で、パスワード verysecret を使用して antonio としてログインすることが許可されていることを確認します。

  2. mysql サービスを認証するように PAM を設定します。/etc/pam.d/mysql に次の行を挿入します。

    #%PAM-1.0
    auth include password-auth
    account include password-auth
  3. Unix ログイン名と同じユーザー名を持つ MySQL アカウントを作成し、PAM プラグインを使用して認証するように定義します。

    CREATE USER 'antonio'@'localhost' IDENTIFIED WITH authentication_pam AS 'mysql';
    GRANT ALL PRIVILEGES ON mydb.* TO 'antonio'@'localhost';
  4. 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 |
    +-------------------+-------------------+--------------+

    これは、antonioantonio MySQL アカウントに付与された権限を使用し、プロキシ処理が発生していないことを示します。

6.3.8.5.2.2 プロキシユーザーを使用しない LDAP 認証

この認証シナリオでは、LDAP ユーザーのログイン名とパスワードをチェックする際にのみ PAM が使用されます。MySQL サーバーへの接続が許可されている外部ユーザーはすべて、外部 PAM 認証を使用するように定義されている一致する MySQL アカウントを持つべきです。

  1. PAM の LDAP 認証で、パスワード verysecret を使用して antonio としてログインすることが許可されていることを確認します。

  2. LDAP を使用して mysql サービスを認証するように PAM を設定します。/etc/pam.d/mysql に次の行を挿入します。

    #%PAM-1.0
    auth required pam_ldap.so
    account required pam_ldap.so

    PAM オブジェクトファイルのサフィクスがシステム上の .so と異なる場合は、正しいサフィクスに置き換えてください。

  3. MySQL アカウントの作成およびサーバーへの接続は、セクション6.3.8.5.2.1「プロキシユーザーを使用しない Unix パスワード認証」ですでに説明したものと同じです。

6.3.8.5.2.3 プロキシユーザーとグループマッピングを使用した Unix パスワード認証

この認証スキームでは、さまざまな権限セットを定義する数個の MySQL アカウント上に、PAM を使用して MySQL サーバーに接続するユーザーをマップするグループマッピング、およびプロキシ処理が使用されます。ユーザーは、権限を定義するアカウントを使用して直接接続しません。代わりに、権限を保持している数個の MySQL アカウントに、すべての外部ログインをマップするマッピングスキームが使用される PAM を使用して、デフォルトのプロキシユーザー認証を使用して接続します。接続する任意のユーザーは、MySQL アカウントのいずれかにマップされ、その権限を使用します。

ここに示す手順では、Unix パスワード認証が使用されます。代わりに LDAP を使用するには、前半で示したセクション6.3.8.5.2.2「プロキシユーザーを使用しない LDAP 認証」の手順を参照してください。

  1. PAM の Unix 認証で、パスワード verysecret を使用して antonio としてログインすることが許可されること、および antonioroot または users のメンバーであることを確認します。

  2. mysql サービスを認証するように PAM を設定します。/etc/pam.d/mysql に次の行を挿入します。

    #%PAM-1.0
    auth include password-auth
    account include password-auth
  3. プロキシ対象アカウントに外部 PAM ユーザーをマップするデフォルトのプロキシユーザーを作成します。root PAM グループから developer MySQL アカウントに外部ユーザーをマップし、users PAM グループから data_entry MySQL アカウントに外部ユーザーをマップします。

    CREATE USER ''@'' IDENTIFIED WITH authentication_pam AS 'mysql, root=developer, users=data_entry';

    サービス名のあとのマッピングリストは、プロキシユーザーを設定する際に必要です。それ以外の場合、プラグインは適切なプロキシ対象ユーザー名に PAM グループの名前をマップする方法を指示できません。

  4. データベースにアクセスする際に使用されるプロキシ対象アカウントを作成します。

    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 アカウントを使用することが予想されます。

  5. プロキシ対象アカウント用のプロキシアカウントに、PROXY 権限を付与します。

    GRANT PROXY ON 'developer'@'localhost' TO ''@'';
    GRANT PROXY ON 'data_entry'@'localhost' TO ''@'';
  6. mysql コマンド行クライアントを使用して、MySQL サーバーへの接続を試みます。例:

    mysql --user=antonio --password=verysecret --enable-cleartext-plugin mydb

    サーバーは ''@'' アカウントを使用して、接続を認証します。権限 antonio は、メンバーとして属する PAM グループによって異なります。antonioroot PAM グループのメンバーである場合、PAM プラグインは、developer MySQL ユーザー名に root をマップし、その名前をサーバーに返します。サーバーは、''@''developer に対する PROXY 権限を持っていることを確認し、接続を許可します。以降のクエリーは、次に示すような出力を返すはずです。

    mysql> SELECT USER(), CURRENT_USER(), @@proxy_user;+-------------------+---------------------+--------------+
    | USER() | CURRENT_USER() | @@proxy_user |
    +-------------------+---------------------+--------------+
    | antonio@localhost | developer@localhost | ''@'' |
    +-------------------+---------------------+--------------+

    これは、antoniodeveloper MySQL アカウントに付与された権限を使用し、デフォルトのプロキシユーザーアカウントからプロキシ処理が発生していないことを示します。

    antonioroot PAM グループのメンバーではないが、users グループのメンバーである場合にも、同様のプロセスが発生しますが、プラグインは data_entry MySQL ユーザー名に user グループメンバーシップをマップし、その名前をサーバーに返します。この場合、antoniodata_entry MySQL アカウントの権限を使用します。

    mysql> SELECT USER(), CURRENT_USER(), @@proxy_user;+-------------------+----------------------+--------------+
    | USER() | CURRENT_USER() | @@proxy_user |
    +-------------------+----------------------+--------------+
    | antonio@localhost | data_entry@localhost | ''@'' |
    +-------------------+----------------------+--------------+
6.3.8.5.3 PAM 認証プラグインのデバッグ

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

6.3.8.6 Windows ネイティブ認証プラグイン

注記

Windows 認証プラグインは、商用の拡張機能です。商用の製品 (MySQL Enterprise Edition) についてさらに学習するには、http://www.mysql.com/products/ を参照してください。

MySQL 5.6.10 の時点で、Windows 向けの MySQL の商用配布には、Windows 上で外部認証を実行する認証プラグインが含まれています。これを使用すると、MySQL サーバーがネイティブの Windows サービスを使用して、クライアント接続を認証できます。Windows にログインしたユーザーは、追加のパスワードを指定せずに、自分の環境内の情報に基づいて MySQL クライアントプログラムからサーバーに接続できます。

クライアントとサーバーは、認証ハンドシェイクでデータパケットを交換します。この交換の結果として、サーバーは Windows OS 内のクライアントのアイデンティティーを表すセキュリティーコンテキストオブジェクトを作成します。このアイデンティティーには、クライアントアカウントの名前が含まれています。Windows 認証プラグインはクライアントのアイデンティティーを使用して、特定のアカウントまたはグループのメンバーであるのかどうかをチェックします。デフォルトでは、認証のネゴシエーションに Kerberos が使用されます。Kerberos が使用できない場合は、NTLM が使用されます。

Windows 認証プラグインには、次のような機能が備わっています。

  • 外部認証: このプラグインを使用すると、MySQL サーバーは、MySQL 付与テーブルの外部で定義されたユーザーからの接続を受け入れることができます。

  • プロキシユーザーのサポート: このプラグインは、クライアントユーザーとは異なるユーザー名を MySQL に返すことができます。つまり、このプラグインは、外部の Windows で認証されたユーザーが持つべき権限を定義する MySQL ユーザーを返すことができます。たとえば、joe という名前の Windows ユーザーは接続して、developer という名前の MySQL ユーザーの権限を持つことができます。

次の表には、プラグインおよびライブラリファイルの名前を示します。ファイルの場所は、plugin_dir システム変数で指定されたディレクトリである必要があります。インストールに関する情報については、セクション6.3.8.6.1「Windows 認証プラグインのインストール」を参照してください。

表 6.12 MySQL Windows 認証プラグイン

サーバー側のプラグイン名authentication_windows
クライアント側のプラグイン名authentication_windows_client
ライブラリオブジェクトファイル名authentication_windows.dll

ライブラリファイルには、サーバー側のプラグインのみが含まれています。クライアント側のプラグインは、libmysqlclient クライアントライブラリに組み込まれています。

サーバー側の Windows 認証プラグインは、商用配布にのみ含まれています。MySQL コミュニティー配布には含まれていません。クライアント側のプラグインは、コミュニティー配布を含むすべての配布に含まれています。これにより、任意の配布から、サーバー側のプラグインがロードされたサーバーに接続することがクライアントに許可されます。

Windows 認証プラグインは、MySQL 5.6 でサポートされている任意のバージョンの Windows でサポートされています (http://www.mysql.com/support/supportedplatforms/database.htmlを参照してください)。これには、MySQL Server 5.6.10 以降が必要です。

MySQL のプラガブル認証に関する一般的な情報については、セクション6.3.7「プラガブル認証」を参照してください。プロキシユーザーについては、セクション6.3.9「プロキシユーザー」を参照してください。

6.3.8.6.1 Windows 認証プラグインのインストール

Windows 認証プラグインは、MySQL プラグインディレクトリ (plugin_dir システム変数で指定されたディレクトリ) にインストールする必要があります。必要に応じて、サーバーの起動時に、プラグインディレクトリの場所をサーバーに指示する plugin_dir の値を設定します。

プラグインを有効にするには、--plugin-load オプションを付けてサーバーを起動します。たとえば、my.ini ファイルに次の行を挿入します。

[mysqld]
plugin-load=authentication_windows.dll

このプラグインを使用して認証される MySQL アカウントには、CREATE USER または GRANT ステートメントの IDENTIFIED WITH 句のプラグイン名 authentication_windows を使用します。

プラグインのインストールを確認するには、INFORMATION_SCHEMA.PLUGINS テーブルを調査するか、または SHOW PLUGINS ステートメントを使用します。セクション5.1.8.2「サーバープラグイン情報の取得」を参照してください。

6.3.8.6.2 Windows 認証プラグインの使用

Windows 認証プラグインでは、Windows にログインしたユーザーが追加のパスワードを指定しなくても、MySQL サーバーに接続できるように、MySQL アカウントの使用がサポートされています。サーバー側のプラグインが有効になっていて、クライアントプログラムが libmysqlclient に組み込まれたクライアント側のプラグインを追加するために十分新しいバージョンであることが前提となっています。DBA がサーバー側のプラグインを有効にして、それを使用するようにアカウントを設定すると、クライアントは自分の側でその他の設定を行う必要なしで、これらのアカウントを使用して接続できます。

CREATE USER または GRANT ステートメントの IDENTIFIED WITH 句で Windows 認証プラグインを参照するには、authentication_windows という名前を使用します。RafalTasha という Windows ユーザー、および Administrators または Power Users グループ内の任意のユーザーが MySQL への接続が許可されるべきであると仮定します。このように設定するには、Windows プラグインを使用して認証する sql_admin という名前の MySQL アカウントを作成します。

CREATE USER sql_admin IDENTIFIED WITH authentication_windows AS 'Rafal, Tasha, Administrators, "Power Users"';

プラグイン名は authentication_windows です。AS キーワードに続く文字列は、認証文字列です。Rafal または Tasha という名前の Windows ユーザー、および Administrators または Power Users グループ内の任意の Windows ユーザーが MySQL ユーザー sql_admin として、サーバーへの認証が許可されるように指定されます。後者のグループ名には空白文字が含まれているため、二重引用符で囲む必要があります。

sql_admin アカウントを作成したあとは、Windows にログインしたユーザーはそのアカウントを使用して、サーバーへの接続を試みることができます。

C:\> mysql --user=sql_admin

ここでは、パスワードは必要ありません。authentication_windows プラグインは Windows のセキュリティー API を使用して、接続中の Windows ユーザーをチェックします。そのユーザーが Rafal または Tasha という名前であるか、Administrators または Power Users グループに属する場合、サーバーはアクセス権を付与し、クライアントは sql_admin として認証され、sql_admin アカウントに付与される任意の権限を持ちます。それ以外の場合、サーバーはアクセスを拒否します。

Windows 認証プラグインでの認証文字列の構文は、次のようなルールに従っています。

  • 文字列は、カンマで区切られた 1 つ以上のユーザーマッピングで構成されます。

  • 各ユーザーマッピングによって、Windows ユーザー名またはグループ名が MySQL ユーザー名に関連付けられます。

    win_user_or_group_name=sql_user_namewin_user_or_group_name

    後者の構文に sql_user_name 値を指定しない場合、値は暗黙的に、CREATE USER ステートメントで作成された MySQL ユーザーとなります。したがって、次のステートメントは同等です。

    CREATE USER sql_admin IDENTIFIED WITH authentication_windows AS 'Rafal, Tasha, Administrators, "Power Users"';
    CREATE USER sql_admin IDENTIFIED WITH authentication_windows AS 'Rafal=sql_admin, Tasha=sql_admin, Administrators=sql_admin, "Power Users"=sql_admin';
  • MySQL の文字列ではバックスラッシュ ('\') はエスケープ文字であるため、値内の各バックスラッシュは二重に入力する必要があります。

  • 二重引用符で囲まれていない先頭および末尾の空白文字は、無視されます。

  • 引用符で囲まれていない win_user_or_group_name および sql_user_name の値には、等号、カンマ、または空白文字を除く、任意の文字を含めることができます。

  • win_user_or_group_name または sql_user_name の値を二重引用符で囲むと、引用符間のすべての文字が値の一部となります。たとえば、名前に空白文字が含まれている場合は、これが必要です。二重引用符およびバックスラッシュを除く、二重引用符内のすべての文字が有効です。どちらかの文字を含めるには、バックスラッシュを使用してエスケープします。

  • win_user_or_group_name 値では、Windows 主体 (ローカルまたはドメイン内) 用の従来の構文が使用されます。例 (バックスラッシュを二重にすることに注意してください):

    domain\\user
    .\\user
    domain\\group
    .\\group
    BUILTIN\\WellKnownGroup

クライアントを認証するためにサーバーから呼び出されると、プラグインは認証文字列を左から右へとスキャンして、Windows ユーザーとのユーザーまたはグループの一致があるかどうかを確認します。一致がある場合、このプラグインは対応する sql_user_name を MySQL サーバーに返します。一致がない場合は、認証に失敗します。

ユーザー名の一致は、グループ名の一致よりも優先されます。win_user という名前の Windows ユーザーが win_group のメンバーであり、認証文字列が次のとおりであると仮定します。

'win_group = sql_user1, win_user = sql_user2'

win_user が MySQL サーバーに接続すると、win_groupwin_user の両方への一致があります。グループが認証文字列の最初に一覧表示されますが、より具体的なユーザーの一致がグループの一致よりも優先されるため、プラグインは sql_user2 としてユーザーを認証します。

サーバーが実行されているものと同じコンピュータからの接続では、Windows 認証は常に機能します。コンピュータ間の接続では、両方のコンピュータを Windows Active Directory に登録する必要があります。同じ Windows ドメイン内にある場合は、ドメイン名を指定する必要はありません。次の例に示すように、別のドメインからの接続を許可することもできます。

CREATE USER sql_accounting IDENTIFIED WITH authentication_windows AS 'SomeDomain\\Accounting';

ここで、SomeDomain は別のドメインの名前です。バックスラッシュ文字は文字列内の MySQL エスケープ文字であるため、二重に入力されています。

MySQL では、クライアントは 1 つのアカウントを使用して MySQL サーバーに接続して認証できるが、接続されると別のアカウントの権限を持つというプロキシユーザーの概念がサポートされています (セクション6.3.9「プロキシユーザー」を参照してください)。次のように、Windows ユーザーは単一のユーザー名を使用して接続するが、Windows ユーザー名およびグループ名に基づいて特定の MySQL アカウント上にマップされると仮定します。

  • local_user および MyDomain\domain_user というローカルおよびドメインの Windows ユーザーは、local_wlad MySQL アカウントにマップするべきです。

  • MyDomain\Developers ドメイングループ内のユーザーは、local_dev MySQL アカウントにマップするべきです。

  • ローカルマシンの管理者は、local_admin MySQL アカウントにマップするべきです。

このように設定するには、接続先の Windows ユーザーのプロキシアカウントを作成し、ユーザーとグループが適切な MySQL アカウント (local_wladlocal_devlocal_admin) にマップされるように、このアカウントを構成します。さらに、実行する必要がある操作に適した権限を MySQL アカウントに付与します。次の手順では、プロキシアカウントとして win_proxy が使用され、プロキシ対象アカウントとして local_wladlocal_dev、および local_admin が使用されています。

  1. プロキシ MySQL アカウントを作成します。

    CREATE USER win_proxy IDENTIFIED WITH authentication_windows AS 'local_user = local_wlad, MyDomain\\domain_user = local_wlad, MyDomain\\Developers = local_dev, BUILTIN\\Administrators = local_admin';
  2. プロキシ処理が動作するには、プロキシ対象アカウントが存在する必要があるため、次のように作成します。

    CREATE USER local_wlad IDENTIFIED BY 'wlad_pass';
    CREATE USER local_dev IDENTIFIED BY 'dev_pass';
    CREATE USER local_admin IDENTIFIED BY 'admin_pass';

    これらのアカウント用のパスワードをだれにも通知できない場合、ほかのユーザーはこれらのパスワードを使用して、MySQL サーバーに直接接続できません。

    また、必要な権限を各プロキシ対象アカウントに付与する GRANT ステートメント (非表示) も発行するようにしてください。

  3. プロキシアカウントは、プロキシ対象アカウントごとに PROXY 権限を持つ必要があります。

    GRANT PROXY ON local_wlad TO win_proxy;
    GRANT PROXY ON local_dev TO win_proxy;
    GRANT PROXY ON local_admin TO win_proxy;

この時点で、local_user および MyDomain\domain_user という Windows ユーザーは、win_proxy として MySQL サーバーに接続でき、認証されると、認証文字列 (この場合は local_wlad) に指定されたアカウントの権限を持ちます。win_proxy として接続する MyDomain\Developers グループ内のユーザーは、local_dev アカウントの権限を持っています。BUILTIN\Administrators グループ内のユーザーは、local_admin アカウントの権限を持っています。

自分の MySQL アカウントを持っていないのすべての Windows ユーザーがプロキシアカウントを通過するように認証を構成するには、前述の手順で、win_proxy をデフォルトのプロキシユーザー (''@'') に置き換えてください。デフォルトのプロキシユーザーについては、セクション6.3.9「プロキシユーザー」を参照してください。

Connection/Net 6.4.4 以上で、Connector/Net 接続文字列とともに Windows 認証プラグインを使用する方法については、Using the Windows Native Authentication Pluginを参照してください。

authentication_windows_use_principal_name および authentication_windows_log_level システム変数では、Windows 認証プラグインへの追加の制御が提供されています。セクション5.1.4「サーバーシステム変数」を参照してください。

6.3.8.7 クライアント側のクリアテキスト認証プラグイン

MySQL 5.6.2 の時点では、ハッシュ化または暗号化なしでサーバーにパスワードを送信するクライアント側の認証プラグインが使用可能です。このプラグインは、MySQL クライアントライブラリに組み込まれています。

次の表に、プラグイン名を示します。

表 6.13 MySQL クリアテキスト認証プラグイン

サーバー側のプラグイン名なし (説明を参照してください)
クライアント側のプラグイン名mysql_clear_password
ライブラリオブジェクトファイル名なし (プラグインは組み込み済みです)

ネイティブの MySQL 認証では、クライアントはパスワードに一方向のハッシュ化を実行してから、それをサーバーに送信します。これにより、クライアントがパスワードをクリアテキストで送信することを回避できます。セクション6.1.2.4「MySQL でのパスワードハッシュ」を参照してください。ただし、ハッシュアルゴリズムは一方向であるため、サーバー側で元のパスワードをリカバリできません。

クライアント側で入力されたパスワードを受信するようにサーバーに要求する認証スキームの場合、一方向のハッシュ化を実行できません。このような場合、クライアント側のプラグイン mysql_clear_password を使用すると、パスワードをクリアテキストでサーバーに送信できます。対応するサーバー側のプラグインはありません。その上、クライアント側のプラグインは、クリアテキストのパスワードを必要とする任意のサーバー側のプラグインで使用できます。(PAM 認証プラグインは、このような例の 1 つです。セクション6.3.8.5「PAM 認証プラグイン」を参照してください。)

MySQL のプラガブル認証に関する一般的な情報については、セクション6.3.7「プラガブル認証」を参照してください。

注記

クリアテキストでパスワードを送信すると、一部の構成でセキュリティーの問題が発生する可能性があります。パスワードが傍受される可能性がある場合に問題を回避するには、クライアントはパスワードが保護される方式を使用して、MySQL サーバーに接続するようにしてください。SSL (セクション6.3.10「セキュアな接続のための SSL の使用」を参照)、IPsec、またはプライベートネットワークでも発生する可能性があります。

MySQL 5.6.7 の時点で、このプラグインが不注意に使用される可能性を低くするには、クライアントが明示的に有効にする必要があります。これは、複数の方法で実行できます。

  • LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN 環境変数を 1Y、または y で始まる値に設定します。これにより、すべてのクライアント接続でプラグインが有効になります。

  • mysqlmysqladmin、および mysqlslap クライアントプログラムでは、呼び出すたびにプラグインを有効にする --enable-cleartext-plugin オプションがサポートされています。

  • mysql_options() C API 関数では、接続するたびにプラグインを有効にする MYSQL_ENABLE_CLEARTEXT_PLUGIN オプションがサポートされています。また、クライアントライブラリによって読み取られるオプショングループ内に enable-cleartext-plugin を含めると、libmysqlclient を使用し、オプションファイルを読み取る任意のプログラムでプラグインを有効にすることができます。

6.3.8.8 ソケットピア証明書認証プラグイン

MySQL 5.6.2 の時点では、Unix ソケットファイル経由でローカルホストから接続するクライアントを認証するサーバー側の認証プラグインが使用可能です。

このプラグインのソースコードは、ロード可能な認証プラグインを記述する方法を示す比較的単純な例として調査できます。

次の表には、プラグインおよびライブラリファイルの名前を示します。ファイル名のサフィクスは、システムによって異なる場合があります。ファイルの場所は、plugin_dir システム変数で指定されたディレクトリです。インストールに関する情報については、セクション6.3.7「プラガブル認証」を参照してください。

表 6.14 MySQL ソケットピア証明書認証プラグイン

サーバー側のプラグイン名auth_socket
クライアント側のプラグイン名なし (説明を参照してください)
ライブラリオブジェクトファイル名auth_socket.so

auth_socket 認証プラグインは、Unix ソケットファイル経由でローカルホストから接続するクライアントを認証します。このプラグインは SO_PEERCRED ソケットオプションを使用して、クライアントプログラムを実行しているユーザーに関する情報を取得します。このプラグインは、ユーザー名がサーバーへのクライアントプログラムで指定された MySQL ユーザー名と一致するかどうかをチェックし、その名前が一致する場合にのみ接続を許可します。SO_PEERCRED オプションがサポートされているシステム (Linux など) 上でのみ、このプラグインを構築できます。

ソケットファイル経由でローカルホストから接続する際に、auth_socket プラグインで認証される valerie という名前のユーザー用に、MySQL アカウントが作成されると仮定します。

CREATE USER 'valerie'@'localhost' IDENTIFIED WITH auth_socket;

stefanie というログイン名を持つローカルホスト上のユーザーが --user=valerie オプションを付けて mysql を呼び出して、ソケットファイル経由で接続する場合、サーバーは auth_socket を使用してクライアントを認証します。このプラグインは、--user オプションの値 (valerie) がクライアントユーザー名 (stephanie) とは異なると判断し、接続を拒否します。valerie という名前のユーザーが同じことを試みた場合、プラグインはユーザー名と MySQL ユーザー名が両方とも valerie であると判断し、接続を許可します。ただし、TCP/IP などの別のプロトコルを使用して接続されると、valerie の場合でもプラグインは接続を拒否します。

MySQL のプラガブル認証に関する一般的な情報については、セクション6.3.7「プラガブル認証」を参照してください。

6.3.8.9 テスト認証プラグイン

MySQL には、MySQL ネイティブ認証を使用して認証するテストプラグインが含まれていますが、(組み込まれていない) ロード可能なプラグインであるため、使用する前にインストールする必要があります。標準または古い (短い) パスワードのハッシュ値と照合して認証できます。

このプラグインは、テストおよび開発のために使用され、本番環境では使用されません。テストプラグインのソースコードは組み込みのネイティブプラグインとは異なり、サーバーソースとは別々のものであるため、ロード可能な認証プラグインを記述する方法を示す比較的単純な例として調査できます。

次の表には、プラグインおよびライブラリファイルの名前を示します。ファイル名のサフィクスは、システムによって異なる場合があります。ファイルの場所は、plugin_dir システム変数で指定されたディレクトリです。インストールに関する情報については、セクション6.3.7「プラガブル認証」を参照してください。

表 6.15 MySQL テスト認証プラグイン

サーバー側のプラグイン名test_plugin_server
クライアント側のプラグイン名auth_test_plugin
ライブラリオブジェクトファイル名auth_test_plugin.so

テストプラグインでは、ネイティブの MySQL 認証と同じ方法で認証されるため、サーバーに接続する際に、ネイティブ認証を使用するアカウント用に一般的に使用される通常の --user および --password オプションを指定します。例:

shell> mysql --user=your_name --password=your_pass

MySQL のプラガブル認証に関する一般的な情報については、セクション6.3.7「プラガブル認証」を参照してください。

6.3.9 プロキシユーザー

認証プラグインを使用した MySQL サーバーへの認証が発生すると、接続中の (外部) ユーザーを権限チェックのために別のユーザーとして処理するようにプラグインから要求されることがあります。これにより、外部ユーザーを 2 番目のユーザーのプロキシにすることができます。つまり、2 番目のユーザーの権限を持つことができます。言い換えると、外部ユーザーはプロキシユーザー (偽装できるユーザーまたは別のユーザーと呼ばれるようになるユーザー) であり、2 番目のユーザーはプロキシ対象ユーザー (プロキシユーザーが実行できるアイデンティティーを持つユーザー) です。

このセクションでは、プロキシユーザー機能の動作について説明します。認証プラグインに関する一般的な情報については、セクション6.3.7「プラガブル認証」を参照してください。プロキシユーザーがサポートされている独自の認証プラグインを作成することに関心がある場合は、セクション24.2.4.9.4「認証プラグインでのプロキシユーザーサポートの実装」を参照してください。

プロキシ処理を発生させるには、次の条件を満たす必要があります。

  • 接続中のクライアントがプロキシユーザーとして処理されるときに、プラグインはプロキシ対象ユーザーの名前を示すために、別の名前を返す必要があります。

  • プロキシユーザーのアカウントがプラグインで認証されるように設定する必要があります。CREATE USER または GRANT ステートメントを使用して、アカウントをプラグインに関連付けます。

  • プロキシユーザーのアカウントは、プロキシ対象アカウントの PROXY 権限を持つ必要があります。これを行うには、GRANT ステートメントを使用します。

次のような定義について検討します。

CREATE USER 'empl_external'@'localhost' IDENTIFIED WITH auth_plugin AS 'auth_string';
CREATE USER 'employee'@'localhost' IDENTIFIED BY 'employee_pass';
GRANT PROXY ON 'employee'@'localhost' TO 'empl_external'@'localhost';

クライアントがローカルホストから empl_external として接続すると、MySQL は auth_plugin を使用して認証を実行します。auth_plugin が ('auth_string' の内容に基づいて、おそらく一部の外部認証システムを参照することで) サーバーに employee というユーザー名を返す場合は、このクライアントを権限チェックのために、employee ローカルユーザーとして処理するように求めるサーバーへのリクエストとして機能します。

この場合、empl_external はプロキシユーザー、employee はプロキシ対象ユーザーです。

サーバーは empl_externalemployee に対する PROXY 権限を持っているかどうかをチェックすることで、empl_external ユーザーに対して employee のプロキシ認証を実行できることを確認します。(この権限が付与されていない場合は、エラーが発生します。)

プロキシ処理が発生したときに、USER() および CURRENT_USER() 関数を使用すると、接続中のユーザーと現在のセッション中に権限が適用されるアカウントとの相違点を確認できます。先ほど説明した例では、これらの関数は次の値を返します。

mysql> SELECT USER(), CURRENT_USER();+-------------------------+--------------------+
| USER() | CURRENT_USER() |
+-------------------------+--------------------+
| empl_external@localhost | employee@localhost |
+-------------------------+--------------------+

認証プラグインの名前を指定する IDENTIFIED WITH 句のあとに、ユーザーの接続時にサーバーがプラグインに渡す文字列を指定する AS 句が続く場合があります。AS 句が必要であるかどうかは、各プラグインに依存します。必要な場合、認証文字列の形式は、プラグインを使用する目的によって異なります。許可される認証文字列の値については、特定のプラグインに関するドキュメントを参照してください。

プロキシ権限の付与

外部ユーザーが別のユーザーとして接続し、その権限を持つことができるようにするには、特別な PROXY 権限が必要です。この権限を付与するには、GRANT ステートメントを使用します。例:

GRANT PROXY ON 'proxied_user' TO 'proxy_user';

proxy_user は、接続時に外部で認証された有効な MySQL ユーザーを表している必要があります。そうでない場合は、接続の試行に失敗します。proxied_user は、接続時にローカルで認証された有効なユーザーを表している必要があります。そうでない場合は、接続の試行に失敗します。

対応する REVOKE 構文は次のとおりです。

REVOKE PROXY ON 'proxied_user' FROM 'proxy_user';

MySQL GRANT および REVOKE 構文の拡張機能は、通常どおりに動作します。例:

GRANT PROXY ON 'a' TO 'b', 'c', 'd';
GRANT PROXY ON 'a' TO 'd' IDENTIFIED BY ...;
GRANT PROXY ON 'a' TO 'd' WITH GRANT OPTION;
GRANT PROXY ON 'a' TO ''@'';
REVOKE PROXY ON 'a' FROM 'b', 'c', 'd';

前述の例では、''@'' はデフォルトのプロキシユーザーであり、任意のユーザーを意味します。デフォルトのプロキシユーザーについては、このセクションの後半で説明します。

次のような場合に、PROXY 権限を付与できます。

  • 自分で proxied_user による: アカウント名のユーザー名とホスト名の両方の部分で、USER() の値が CURRENT_USER() および proxied_user と完全に一致する必要があります。

  • proxied_user に対する GRANT PROXY ... WITH GRANT OPTION を持つユーザーによる。

MySQL のインストール時にデフォルトで作成された root アカウントは、''@'' (つまり、すべてのユーザー) に対する PROXY ... WITH GRANT OPTION 権限を持っています。これにより、root はプロキシユーザーを設定したり、プロキシユーザーを設定するための権限をほかのアカウントに委任したりできます。たとえば、root は次の操作を実行できます。

CREATE USER 'admin'@'localhost' IDENTIFIED BY 'test';
GRANT PROXY ON ''@'' TO 'admin'@'localhost' WITH GRANT OPTION;

この時点で、admin ユーザーは特定のすべての GRANT PROXY マッピングを管理できます。たとえば、admin は次の操作を実行できます。

GRANT PROXY ON sally TO joe;

デフォルトのプロキシユーザー

一部またはすべてのユーザーが特定の外部プラグインを使用して接続するように指定するには、空白の MySQL ユーザーを作成し、そのプラグインを使用して認証するように設定し、(空白のユーザーとは異なる場合に) プラグインが認証された実際のユーザー名を返すことができるようにします。たとえば、LDAP 認証を実装する ldap_auth という名前の仮のプラグインが存在すると仮定します。

CREATE USER ''@'' IDENTIFIED WITH ldap_auth AS 'O=Oracle, OU=MySQL';
CREATE USER 'developer'@'localhost' IDENTIFIED BY 'developer_pass';
CREATE USER 'manager'@'localhost' IDENTIFIED BY 'manager_pass';
GRANT PROXY ON 'manager'@'localhost' TO ''@'';
GRANT PROXY ON 'developer'@'localhost' TO ''@'';

ここで、クライアントが次のように接続を試みるとします。

mysql --user=myuser --password='myuser_pass' ...

サーバーでは、MySQL ユーザーとして定義された myuser が見つかりません。ただし、クライアントのユーザー名およびホスト名と一致する空白のユーザーアカウント (''@'') があるため、サーバーはそのアカウントと照合してクライアントを認証します。サーバーは ldap_auth を呼び出して、それをユーザー名とパスワードとして myuser および myuser_pass に渡します。

ldap_auth プラグインによって、myuser_passmyuser の正しいパスワードでないことが LDAP ディレクトリで検出された場合は、認証に失敗し、サーバーは接続を拒否します。

パスワードが正しく、ldap_auth によって myuser が開発者であることが検出された場合は、MySQL サーバーに myuser ではなく、developer というユーザー名が返されます。サーバーは、(実行するための PROXY 権限を持っているため) ''@''developer として認証できることを確認し、接続を受け入れます。セッションは、developer の権限を持っている myuser で続行されます。(これらの権限は、DBA が GRANT ステートメントを使用して設定するべきですが、表示されません。)USER() および CURRENT_USER() 関数は、次の値を返します。

mysql> SELECT USER(), CURRENT_USER();+------------------+---------------------+
| USER() | CURRENT_USER() |
+------------------+---------------------+
| myuser@localhost | developer@localhost |
+------------------+---------------------+

代わりに、プラグインによって myuser がマネージャーであることが LDAP ディレクトリで検出された場合は、ユーザー名として manager が返され、セッションは manager の権限を持つ myuser で続行されます。

mysql> SELECT USER(), CURRENT_USER();+------------------+-------------------+
| USER() | CURRENT_USER() |
+------------------+-------------------+
| myuser@localhost | manager@localhost |
+------------------+-------------------+

単純にするために、外部認証はマルチレベルで実行できません。前述の例では、developer の証明書も、manager の証明書も考慮されません。ただし、クライアントが developer または manager アカウントと照合して直接認証を試みる場合は、引き続き使用されます (そのため、これらのアカウントにはパスワードを割り当てられるはずです)。

デフォルトのプロキシアカウントは、任意のホストと一致する '' をホスト部分で使用します。デフォルトのプロキシユーザーを設定する場合は、ホスト部分で '%' を含むアカウントもチェックするように注意してください。その理由は、これらのアカウントは任意のホストにも一致しますが、サーバー内部でアカウント行をソートする際に使用されるルールによって、'' よりも優先されるためです (セクション6.2.4「アクセス制御、ステージ 1: 接続の検証」を参照してください)。

MySQL のインストールに、次の 2 つのアカウントが含まれていると仮定します。

CREATE USER ''@'' IDENTIFIED WITH some_plugin;
CREATE USER ''@'%' IDENTIFIED BY 'some_password';

1 番目のアカウントの目的は、それ以外の場合は、より具体的なアカウントと一致しないユーザーの接続を認証する際に使用されるデフォルトのプロキシユーザーとして機能することです。2 番目のアカウントは、たとえば、匿名ユーザーとして独自のアカウントを持っていないユーザーを有効にするために、作成されることがあります。

ただし、この構成では、一致のルールによって ''@'' よりも先に ''@'%' がソートされるため、1 番目のアカウントは使用されません。より具体的などのアカウントにも一致しないアカウントの場合、サーバーは ''@'' ではなく、''@'%' と照合して認証を試みます。

デフォルトのプロキシユーザーを作成する場合は、デフォルトのプロキシユーザーよりも優先されるために、そのユーザーが目的どおりに動作することを妨げるその他の既存の任意のユーザーに一致するアカウントがないかどうかチェックします。このようなアカウントをすべて削除する必要がある場合もあります。

プロキシユーザーのシステム変数

次の 2 つのシステム変数は、プロキシのログインプロセスをトレースする際に役立ちます。

  • proxy_user: プロキシ処理が使用されていない場合、この値は NULL です。それ以外の場合は、プロキシユーザーのアカウントを示します。たとえば、クライアントがデフォルトのプロキシアカウントを使用して認証する場合、この変数は次のように設定されます。

    mysql> SELECT @@proxy_user;+--------------+
    | @@proxy_user |
    +--------------+
    | ''@'' |
    +--------------+
  • external_user: 認証プラグインは外部ユーザーを使用して、MySQL サーバーへの認証を行うことがあります。たとえば、Windows のネイティブ認証を使用するときは、Windows の API を使用して認証するプラグインに、ログイン ID を渡す必要がありません。ただし、認証には引き続き Windows ユーザー ID が使用されます。このプラグインは、読み取り専用のセッション変数 external_user を使用して、この外部ユーザー ID (または最初の 512 UTF-8 バイト) をサーバーに返すことがあります。プラグインがこの変数を設定しない場合、その値は NULL です。

6.3.10 セキュアな接続のための SSL の使用

MySQL では、Secure Sockets Layer (SSL) プロトコルを使用した、MySQL クライアントとサーバー間のセキュアな (暗号化された) 接続がサポートされています。このセクションでは、SSL 接続を使用する方法について説明します。SSL 接続を使用するようにユーザーに要求する方法については、セクション13.7.1.4「GRANT 構文」で、GRANT ステートメントの REQUIRE 句の説明を参照してください。

MySQL の標準構成の目的は、できるかぎり高速にすることであるため、デフォルトでは暗号化された接続が使用されません。暗号化された接続で提供されるセキュリティーがアプリケーションで必要である場合は、データを暗号化する際に追加の計算を行なってみる価値があります。

MySQL では、接続ごとに暗号化できます。各アプリケーションの要件に従って、暗号化されていない接続または暗号化されたセキュアな SSL 接続を選択できます。

セキュアな接続は OpenSSL API に基づいており、MySQL C API を介して使用できます。レプリケーションでは C API が使用されるため、マスターサーバーとスレーブサーバー間でセキュアな接続を使用できます。セクション17.3.7「SSL を使用してレプリケーションをセットアップする」を参照してください。

セキュアに接続するためのもう 1 つの方法は、SSH 接続内から MySQL サーバーホストに接続することです。例については、セクション6.3.11「SSH を使用した Windows から MySQL へのリモート接続」を参照してください。

6.3.10.1 基本的な SSL の概念

どのように MySQL で SSL が使用されるのかを理解するには、SSL と X509 の基本概念についていくつか説明する必要があります。これらの概念に精通しているユーザーは、説明のこの部分をスキップできます。

MySQL のデフォルトでは、クライアントとサーバー間で暗号化されていない接続が使用されます。つまり、ネットワークへのアクセス権を持っているユーザーは、すべてのトラフィックを監視し、送受信されるデータを調査できます。クライアントとサーバー間で送受信中のデータでも変更できます。

セキュアな方法でネットワーク経由で情報を移動する必要がある場合は、暗号化されていない接続が許可されません。暗号化は、すべての種類のデータを読み取り不可にする方法です。暗号化されたメッセージの順序を変更したり、データを 2 回再生したりするなどの、多くの種類の既知の攻撃に対抗するために、暗号化アルゴリズムには、セキュリティー要素を含める必要があります。

SSL は、パブリックネットワーク経由で受信したデータを信頼できるようにするために、さまざまな暗号化アルゴリズムが使用されたプロトコルです。すべてのデータの変更、損失、または再生を検出するためのメカニズムが備わっています。SSL には、X509 標準を使用してアイデンティティーを検証するアルゴリズムも組み込まれています。

X509 を使用すると、インターネット上の人物を識別できます。電子商取引アプリケーションで、もっとも一般的に使用されます。基本的な用語には、必要とするすべてのユーザーに電子証明書を割り当てる認証局 (CA) と呼ばれるエンティティーがいくつか存在するはずです。証明書は、2 つの暗号化鍵 (公開鍵と秘密鍵) を持つ非対称の暗号化アルゴリズムに依存しています。証明書の所有者は、アイデンティティーの証明として別のパーティーに証明書を表示できます。証明書は、所有者の公開鍵で構成されます。この公開鍵を使用して暗号化されたデータはすべて、対応する秘密鍵 (証明書の所有者が保持しています) を使用しなければ復号化できません。

SSL、X509、暗号化、または公開鍵暗号についての詳細は、インターネット検索を実行して関心のあるキーワードを調べてください。

6.3.10.2 SSL を使用するための MySQL の構成

MySQL サーバーとクライアントプログラム間で SSL 接続を使用するには、システムで OpenSSL または yaSSL がサポートされている必要があります。MySQL 5.6.6 の時点では、SSL サポートがデフォルトで含まれています。

重要

MySQL Community Edition は yaSSL にバンドルされていますが、ソース配布から構築する際に、OpenSSL を使用するように構成できます。MySQL Enterprise Edition は OpenSSL にバンドルされています。MySQL Enterprise Edition では yaSSL を使用できません。

OpenSSL サポートを使用して MySQL サーバーを構築するには、次を実行する必要があります。

  1. システムに openSSL 1.0.1 以上がインストールされていることを確認します。OpenSSL を入手するには、http://www.openssl.org にアクセスします。

  2. 次の方法で CMake を呼び出して、openSSL が使用されるように MySQL ソース配布を構成します。

    shell> cmake . -DWITH_SSL=system

    このコマンドは、インストールされた OpenSSL ライブラリが使用されるように配布を構成します。セクション2.9.4「MySQL ソース構成オプション」を参照してください。-DWITH_SSL を指定しない場合は、yaSSL がデフォルトで使用されます。

    重要

    インストールされた OpenSSL のバージョンが 1.0.1 よりも小さい場合は、CMake でエラーが生成されます。

  3. 配布をコンパイルし、インストールします。

mysqld サーバーで SSL がサポートされているかどうかチェックするには、have_ssl システム変数の値を調査します。

mysql> SHOW VARIABLES LIKE 'have_ssl';+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| have_ssl | YES |
+---------------+-------+

値が YES の場合は、サーバーで SSL 接続がサポートされています。値が DISABLED の場合、サーバーは SSL 接続をサポートできますが、SSL 接続の使用が有効になるように、適切な --ssl-xxx オプションを付けて起動されませんでした。セクション6.3.10.3「SSL 接続の使用」を参照してください。

6.3.10.3 SSL 接続の使用

SSL 接続を有効にするには、セクション6.3.10.2「SSL を使用するための MySQL の構成」で説明するように、SSL サポートを使用して MySQL 配布を構築します。さらに、適切な証明書および鍵ファイルを指定するには、適切な SSL 関連のオプションを使用する必要があります。SSL オプションの完全なリストについては、セクション6.3.10.4「SSL コマンドのオプション」を参照してください。

SSL を使用した接続がクライアントに許可されるように MySQL サーバーを起動するには、セキュアな接続を確立する際に、サーバーで使用される証明書および鍵ファイルを識別するオプションを使用します。

  • --ssl-ca は、認証局 (CA) 証明書を識別します。

  • --ssl-cert は、サーバーの公開鍵証明書を識別します。これをクライアントに送信し、それに含まれる CA 証明書と照合して認証できます。

  • --ssl-key は、サーバーの秘密鍵を識別します。

たとえば、次のようにサーバーを起動します。

shell> mysqld --ssl-ca=ca-cert.pem \--ssl-cert=server-cert.pem \--ssl-key=server-key.pem

各オプションには、PEM 形式のファイル名が指定されます。必要な SSL 証明書および鍵ファイルを生成する手順については、セクション6.3.10.5「MySQL での SSL 証明書および鍵の設定」を参照してください。MySQL ソース配布を持っている場合は、配布の mysql-test/std_data ディレクトリで、デモ用の証明書および鍵ファイルを使用して設定をテストすることもできます。

クライアント側でも同様オプションが使用されますが、--ssl-cert および --ssl-key は、クライアントの公開鍵と秘密鍵を識別します。認証局の証明書を指定する場合は、サーバーで使用されるときと同じ形式で指定する必要があります。

SSL サポートを使用して MySQL サーバーへのセキュアな接続を確立するために、クライアントが指定する必要があるオプションは、クライアントで使用される MySQL アカウントの SSL 要件によって異なります。(セクション13.7.1.4「GRANT 構文」で、REQUIRE 句の説明を参照してください。)

特別な SSL 要件を持っていないアカウント、または REQUIRE SSL オプションを含む GRANT ステートメントを使用して作成されたアカウントを使用して接続すると仮定します。推奨される SSL オプションセットとして、少なくとも --ssl-cert--ssl-key を付けてサーバーを起動し、--ssl-ca を使用してクライアントを呼び出します。次のように、クライアントはセキュアに接続できます。

shell> mysql --ssl-ca=ca-cert.pem

クライアント証明書も指定されるように要求するには、REQUIRE X509 オプションを使用してアカウントを作成します。そのあと、クライアントは適切なクライアント鍵および証明書ファイルを指定する必要があります。そうしない場合、サーバーは接続を拒否します。

shell> mysql --ssl-ca=ca-cert.pem \--ssl-cert=client-cert.pem \--ssl-key=client-key.pem

SSL の使用を回避し、その他の SSL オプションをオーバーライドするには、--ssl=0 またはシノニム (--skip-ssl--disable-ssl) を使用してクライアントプログラムを呼び出します。

shell> mysql --ssl=0

クライアントは Ssl_cipher ステータス変数の値をチェックすることで、サーバーとの現在の接続で SSL が使用されているかどうかを確認できます。SSL が使用されている場合は、値が空以外になります。それ以外の場合は、空になります。例:

mysql> SHOW STATUS LIKE 'Ssl_cipher';+---------------+--------------------+
| Variable_name | Value |
+---------------+--------------------+
| Ssl_cipher | DHE-RSA-AES256-SHA |
+---------------+--------------------+

mysql クライアントの場合は、代わりに STATUS または \s コマンドを使用して、SSL 行をチェックすることもできます。

mysql> \s...
SSL: Cipher in use is DHE-RSA-AES256-SHA
...

または、

mysql> \s...
SSL: Not in use
...

C API を使用すると、アプリケーションプログラムで SSL を使用できます。

  • セキュアな接続を確立するには、mysql_real_connect() を呼び出す前に、mysql_ssl_set() C API 関数を使用して、適切な証明書オプションを設定します。セクション23.8.7.68「mysql_ssl_set()」を参照してください。

  • 接続が確立されたあとに、SSL が使用中であるかどうかを判断するには、mysql_get_ssl_cipher() を使用します。NULL 以外の戻り値は、セキュアな接続であることを示し、暗号化に使用される SSL 暗号の名前を示します。NULL の戻り値は、SSL が使用されていないことを示します。セクション23.8.7.33「mysql_get_ssl_cipher()」を参照してください。

レプリケーションでは C API が使用されるため、マスターサーバーとスレーブサーバー間でセキュアな接続を使用できます。セクション17.3.7「SSL を使用してレプリケーションをセットアップする」を参照してください。

6.3.10.4 SSL コマンドのオプション

このセクションでは、SSL を使用するかどうかを指定するオプションと、SSL 証明書および鍵ファイルの名前を指定するオプションについて説明します。これらのオプションは、コマンド行またはオプションファイルで指定できます。MySQL が SSL サポートを使用して構築されていない場合は、これらを使用できません。セクション6.3.10.2「SSL を使用するための MySQL の構成」を参照してください。推奨される使用例および接続がセキュアであるかどうかをチェックする方法については、セクション6.3.10.3「SSL 接続の使用」を参照してください。

表 6.16 SSL オプション/変数のサマリー

名前コマンド行オプションファイルシステム変数ステータス変数変数スコープ動的
have_openssl  はい グローバルいいえ
have_ssl  はい グローバルいいえ
skip-sslはいはい    
sslはいはい    
ssl-caはいはい  グローバルいいえ
- 変数: ssl_ca  はい グローバルいいえ
ssl-capathはいはい  グローバルいいえ
- 変数: ssl_capath  はい グローバルいいえ
ssl-certはいはい  グローバルいいえ
- 変数: ssl_cert  はい グローバルいいえ
ssl-cipherはいはい  グローバルいいえ
- 変数: ssl_cipher  はい グローバルいいえ
ssl-crlはいはい  グローバルいいえ
- 変数: ssl_crl  はい グローバルいいえ
ssl-crlpathはいはい  グローバルいいえ
- 変数: ssl_crlpath  はい グローバルいいえ
ssl-keyはいはい  グローバルいいえ
- 変数: ssl_key  はい グローバルいいえ

  • --ssl

    サーバーに対して、このオプションを指定すると、サーバーで SSL 接続が許可されますが、必須にはなりません。

    クライアントプログラムに対して、このオプションを指定すると、SSL を使用してサーバーに接続することがクライアントに許可されますが、必須にはなりません。したがって、このオプションだけでは、SSL 接続を使用させるのに十分ではありません。たとえば、このオプションをクライアントプログラムに対して指定するが、サーバーは SSL 接続が許可されるよう構成されていない場合は、暗号化されていない接続が使用されます。

    SSL 接続を有効にするための推奨される SSL オプションセットとして、サーバー側で少なくとも --ssl-cert--ssl-key を使用し、クライアント側で --ssl-ca を使用します。セクション6.3.10.3「SSL 接続の使用」を参照してください。

    その他の --ssl-xxx オプションに関する説明で示したように、これらのオプションによって、--ssl が暗黙的に指定されている可能性があります。

    --ssl オプションをネストされた形式で指定すると、その他の SSL をオーバーライドし、SSL が使用されないように指定できます。これを行うには、--ssl=0 またはシノニム (--skip-ssl--disable-ssl) としてオプションを指定します。たとえば、MySQL クライアントプログラムを呼び出し時にデフォルトで SSL 接続が使用されるように、SSL オプションをオプションファイルの [client] グループに指定することがあります。代わりに、暗号化されていない接続を使用するには、コマンド行で --skip-ssl を指定してクライアントプログラムを呼び出して、オプションファイルのオプションをオーバーライドします。

    MySQL アカウントに対して SSL 接続の使用を要求にするには、そのアカウントに対して、少なくとも REQUIRE SSL 句を含む GRANT ステートメントを発行します。MySQL で SSL 接続がサポートされ、サーバーとクライアントが適切な SSL オプションを付けて起動されていない場合は、アカウントの接続が拒否されます。

    REQUIRE 句は、その他の SSL 関連のオプションを許可します。これを使用すれば、REQUIRE SSL よりも厳密な要件を強制的に適用できます。さまざまな REQUIRE オプションを使用して構成されているアカウントを使用して接続するクライアントが、どの SSL コマンドオプションを指定する可能性があるのか、またはどのオプションを指定する必要があるのかについての詳細は、セクション13.7.1.4「GRANT 構文」REQUIRE の説明を参照してください。

  • --ssl-ca=file_name

    信頼できる SSL 証明書認証局のリストを含む PEM 形式のファイルへのパス。このオプションは、暗黙的に --ssl を示します。

    クライアント接続を確立する際に SSL を使用して、サーバー証明書を認証しないようにクライアントに指示する場合は、--ssl-ca--ssl-capath も指定しません。サーバーは引き続き、クライアントアカウントに対して GRANT ステートメントを使用して確立された適用可能な要件に応じてクライアントを検証し、サーバーの起動時に指定された --ssl-ca または --ssl-capath オプションの値を使用します。

  • --ssl-capath=dir_name

    PEM 形式の信頼できる SSL 認証機関証明書を含むディレクトリへのパス。このオプションは、暗黙的に --ssl を示します。

    クライアント接続を確立する際に SSL を使用して、サーバー証明書を認証しないようにクライアントに指示する場合は、--ssl-ca--ssl-capath も指定しません。サーバーは引き続き、クライアントアカウントに対して GRANT ステートメントを使用して確立された適用可能な要件に応じてクライアントを検証し、サーバーの起動時に指定された --ssl-ca または --ssl-capath オプションの値を使用します。

    OpenSSL サポートを使用して構築された MySQL 配布では、--ssl-capath オプションがサポートされています。yaSSL は、どのディレクトリにも表示されず、チェーン証明書ツリーをたどらないため、yaSSL を使用して構築された配布ではサポートされません。yaSSL では、CA 証明書ツリーのコンポーネントをすべて単一の CA 証明書ツリー内に含め、そのファイル内の各証明書は一意の SubjectName 値を持つ必要があります。このような yaSSL の制限を回避するには、証明書ツリーを構成する個々の証明書ファイルを新しいファイルに連結し、そのファイルを --ssl-ca オプションの値として指定します。

  • --ssl-cert=file_name

    セキュアな接続を確立する際に使用される PEM 形式の SSL 証明書ファイルの名前。このオプションは、暗黙的に --ssl を示します。

  • --ssl-cipher=cipher_list

    SSL 暗号化に使用する許可されている暗号のリスト。リスト内の暗号がサポートされていない場合は、SSL 接続が機能しません。このオプションは、暗黙的に --ssl を示します。

    移植性を最大にするには、cipher_list をコロンで区切った 1 つ以上の暗号名のリストで指定するようにしてください。この形式は、OpenSSL と yaSSL の両方で認識されます。例:

    --ssl-cipher=AES128-SHA
    --ssl-cipher=DHE-RSA-AES256-SHA:AES128-SHA

    http://www.openssl.org/docs/apps/ciphers.html にある OpenSSL のドキュメントで説明されているように、OpenSSL では、暗号を指定するためのより柔軟な構文がサポートされています。ただし、yaSSL ではサポートされてないため、yaSSL を使用して構築された MySQL 配布で拡張構文の使用を試みると失敗します。

    OpenSSL では、サーバーがリンクされているバージョンによって、サポートされている暗号が異なる場合があります。たとえば、リストには次の暗号が含まれている可能性があります。

    AES256-GCM-SHA384
    AES256-SHA
    AES256-SHA256
    CAMELLIA256-SHA
    DES-CBC3-SHA
    DHE-DSS-AES256-GCM-SHA384
    DHE-DSS-AES256-SHA
    DHE-DSS-AES256-SHA256
    DHE-DSS-CAMELLIA256-SHA
    DHE-RSA-AES256-GCM-SHA384
    DHE-RSA-AES256-SHA
    DHE-RSA-AES256-SHA256
    DHE-RSA-CAMELLIA256-SHA
    ECDH-ECDSA-AES256-GCM-SHA384
    ECDH-ECDSA-AES256-SHA
    ECDH-ECDSA-AES256-SHA384
    ECDH-ECDSA-DES-CBC3-SHA
    ECDH-RSA-AES256-GCM-SHA384
    ECDH-RSA-AES256-SHA
    ECDH-RSA-AES256-SHA384
    ECDH-RSA-DES-CBC3-SHA
    ECDHE-ECDSA-AES128-GCM-SHA256
    ECDHE-ECDSA-AES128-SHA
    ECDHE-ECDSA-AES128-SHA256
    ECDHE-ECDSA-AES256-GCM-SHA384
    ECDHE-ECDSA-AES256-SHA
    ECDHE-ECDSA-AES256-SHA384
    ECDHE-ECDSA-DES-CBC3-SHA
    ECDHE-RSA-AES128-GCM-SHA256
    ECDHE-RSA-AES128-SHA
    ECDHE-RSA-AES128-SHA256
    ECDHE-RSA-AES256-GCM-SHA384
    ECDHE-RSA-AES256-SHA
    ECDHE-RSA-AES256-SHA384
    ECDHE-RSA-DES-CBC3-SHA
    EDH-DSS-DES-CBC3-SHA
    EDH-RSA-DES-CBC3-SHA
    PSK-3DES-EDE-CBC-SHA
    PSK-AES256-CBC-SHA
    SRP-DSS-3DES-EDE-CBC-SHA
    SRP-DSS-AES-128-CBC-SHA
    SRP-DSS-AES-256-CBC-SHA
    SRP-RSA-3DES-EDE-CBC-SHA
    SRP-RSA-AES-128-CBC-S
    SRP-RSA-AES-256-CBC-SHA

    yaSSL では、次の暗号がサポートされています。

    AES128-RMD
    AES128-SHA
    AES256-RMD
    AES256-SHA
    DES-CBC-SHA
    DES-CBC3-RMD
    DES-CBC3-SHA
    DHE-RSA-AES128-RMD
    DHE-RSA-AES128-SHA
    DHE-RSA-AES256-RMD
    DHE-RSA-AES256-SHA
    DHE-RSA-DES-CBC3-RMD
    EDH-RSA-DES-CBC-SHA
    EDH-RSA-DES-CBC3-SHA
    RC4-MD5
    RC4-SHA

    特定のサーバーでサポートされている暗号を正確に確認するには、次のクエリーを使用して Ssl_cipher_list ステータス変数の値をチェックします。

    SHOW STATUS LIKE 'Ssl_cipher_list';
  • --ssl-crl=file_name

    証明書失効リストを含む PEM 形式のファイルへのパス。このオプションは、暗黙的に --ssl を示します。

    --ssl-crl--ssl-crlpath も指定されていない場合は、CA パスに証明書失効リストが含まれていても、CRL チェックが実行されません。

    OpenSSL を使用して構築された MySQL 配布では、--ssl-crl オプションがサポートされています。yaSSL では証明書失効リストが機能しないため、yaSSL を使用して構築された配布ではサポートされません。

    このオプションは MySQL 5.6.3 で追加されました。

  • --ssl-crlpath=dir_name

    証明書失効リストを含む PEM 形式のファイルが含まれるディレクトリへのパス。このオプションは、暗黙的に --ssl を示します。

    --ssl-crl--ssl-crlpath も指定されていない場合は、CA パスに証明書失効リストが含まれていても、CRL チェックが実行されません。

    OpenSSL を使用して構築された MySQL 配布では、--ssl-crlpath オプションがサポートされています。yaSSL では証明書失効リストが機能しないため、yaSSL を使用して構築された配布ではサポートされません。

    このオプションは MySQL 5.6.3 で追加されました。

  • --ssl-key=file_name

    セキュアな接続を確立する際に使用される PEM 形式の SSL 鍵ファイルの名前。このオプションは、暗黙的に --ssl を示します。

    MySQL 配布が OpenSSL または (MySQL 5.6.3 時点の) yaSSL を使用して構築され、鍵ファイルがパスフレーズで保護されている場合は、プログラムからパスフレーズを求めるプロンプトがユーザーに表示されます。パスワードは対話形式で指定する必要があり、ファイルには格納できません。パスフレーズが正しくない場合は、鍵を読み取ることができない場合と同様に、プログラムが続行されます。MySQL 5.6.3 よりも前では、MySQL 配布が yaSSL を使用して構築され、鍵ファイルがパスフレーズで保護されている場合は、エラーが発生します。

  • --ssl-verify-server-cert

    このオプションはクライアントプログラムでのみ使用でき、サーバーでは使用できません。これにより、サーバーがクライアントに送信する証明書内のサーバーの Common Name 値がクライアントによってチェックされます。クライアントは、サーバーへの接続時にクライアントで使用されるホスト名と照合してその名前を検証し、一致が見つからない場合は接続に失敗します。この機能は、中間者攻撃を防ぐために使用できます。検証はデフォルトで無効になっています。

6.3.10.5 MySQL での SSL 証明書および鍵の設定

このセクションでは、MySQL サーバーおよびクライアントで使用される SSL 証明書および鍵ファイルを設定する方法を示します。1 番目の例は、コマンド行から使用する場合などの単純化された手順を示しています。2 番目では、より詳細なものを含むスクリプトを示します。最初の 2 つの例は、Unix で使用するためのものであり、どちらの例でも OpenSSL の一部である openssl コマンドが使用されます。3 番目の例では、Windows 上で SSL ファイルを設定する方法について説明します。

重要

証明書および鍵ファイルを生成する際にどの方法を使用するのかには関係なく、サーバーおよびクライアントの証明書と鍵で使用される Common Name の値はそれぞれ、CA 証明書で使用されている Common Name の値と異なる必要があります。それ以外の場合は、OpenSSL を使用してコンパイルされたサーバーで証明書および鍵ファイルが機能しません。この場合の一般的なエラーは、次のとおりです。

ERROR 2026 (HY000): SSL connection error:
error:00000001:lib(0):func(0):reason(1)
例 1: Unix でコマンド行から SSL ファイルを作成する

次の例には、MySQL サーバーおよびクライアントの証明書および鍵ファイルを作成するためのコマンドセットを示します。openssl コマンドで複数のプロンプトに回答する必要があります。すべてのプロンプトに対して Enter キーを押せば、テストファイルを生成できます。本番環境用のファイルを生成するには、空でない回答を提供するようにしてください。

# Create clean environment
shell> rm -rf newcertsshell> mkdir newcerts && cd newcerts# Create CA certificate
shell> openssl genrsa 2048 > ca-key.pemshell> openssl req -new -x509 -nodes -days 3600 \-key ca-key.pem -out ca-cert.pem# Create server certificate, remove passphrase, and sign it
# server-cert.pem = public key, server-key.pem = private key
shell> openssl req -newkey rsa:2048 -days 3600 \-nodes -keyout server-key.pem -out server-req.pemshell> openssl rsa -in server-key.pem -out server-key.pemshell> openssl x509 -req -in server-req.pem -days 3600 \-CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem# Create client certificate, remove passphrase, and sign it
# client-cert.pem = public key, client-key.pem = private key
shell> openssl req -newkey rsa:2048 -days 3600 \-nodes -keyout client-key.pem -out client-req.pemshell> openssl rsa -in client-key.pem -out client-key.pemshell> openssl x509 -req -in client-req.pem -days 3600 \-CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem

証明書が生成されたら、それらを確認します。

shell> openssl verify -CAfile ca-cert.pem server-cert.pem client-cert.pemserver-cert.pem: OK
client-cert.pem: OK

この時点で、次のようなファイルセットを使用できます。

  • ca-cert.pem: これは、サーバー側とクライアント側で --ssl-ca への引数として使用します。(CA 証明書を使用する場合は、両側で同じものを指定する必要があります。)

  • server-cert.pemserver-key.pem: これらは、サーバー側で --ssl-cert および --ssl-key への引数として使用します。

  • client-cert.pemclient-key.pem: これらは、クライアント側で --ssl-cert および --ssl-key への引数として使用します。

ファイルを使用して SSL 接続をテストする方法については、セクション6.3.10.3「SSL 接続の使用」を参照してください。

例 2: Unix でスクリプトを使用して SSL ファイルを作成する

次に、MySQL に SSL 証明書および鍵ファイルを設定する方法を示したサンプルスクリプトを示します。スクリプトを実行したあとに、セクション6.3.10.3「SSL 接続の使用」で説明するように、ファイルを使用して SSL 接続をテストします。

DIR=`pwd`/openssl
PRIV=$DIR/private
mkdir $DIR $PRIV $DIR/newcerts
cp /usr/share/ssl/openssl.cnf $DIR
replace ./demoCA $DIR -- $DIR/openssl.cnf
# Create necessary files: $database, $serial and $new_certs_dir
# directory (optional)
touch $DIR/index.txt
echo "01" > $DIR/serial
#
# Generation of Certificate Authority(CA)
#
openssl req -new -x509 -keyout $PRIV/cakey.pem -out $DIR/ca-cert.pem \ -days 3600 -config $DIR/openssl.cnf
# Sample output:
# Using configuration from /home/monty/openssl/openssl.cnf
# Generating a 1024 bit RSA private key
# ................++++++
# .........++++++
# writing new private key to '/home/monty/openssl/private/cakey.pem'
# Enter PEM pass phrase:
# Verifying password - Enter PEM pass phrase:
# -----
# You are about to be asked to enter information that will be
# incorporated into your certificate request.
# What you are about to enter is what is called a Distinguished Name
# or a DN.
# There are quite a few fields but you can leave some blank
# For some fields there will be a default value,
# If you enter '.', the field will be left blank.
# -----
# Country Name (2 letter code) [AU]:FI
# State or Province Name (full name) [Some-State]:.
# Locality Name (eg, city) []:
# Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB
# Organizational Unit Name (eg, section) []:
# Common Name (eg, YOUR name) []:MySQL admin
# Email Address []:
#
# Create server request and key
#
openssl req -new -keyout $DIR/server-key.pem -out \ $DIR/server-req.pem -days 3600 -config $DIR/openssl.cnf
# Sample output:
# Using configuration from /home/monty/openssl/openssl.cnf
# Generating a 1024 bit RSA private key
# ..++++++
# ..........++++++
# writing new private key to '/home/monty/openssl/server-key.pem'
# Enter PEM pass phrase:
# Verifying password - Enter PEM pass phrase:
# -----
# You are about to be asked to enter information that will be
# incorporated into your certificate request.
# What you are about to enter is what is called a Distinguished Name
# or a DN.
# There are quite a few fields but you can leave some blank
# For some fields there will be a default value,
# If you enter '.', the field will be left blank.
# -----
# Country Name (2 letter code) [AU]:FI
# State or Province Name (full name) [Some-State]:.
# Locality Name (eg, city) []:
# Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB
# Organizational Unit Name (eg, section) []:
# Common Name (eg, YOUR name) []:MySQL server
# Email Address []:
#
# Please enter the following 'extra' attributes
# to be sent with your certificate request
# A challenge password []:
# An optional company name []:
#
# Remove the passphrase from the key
#
openssl rsa -in $DIR/server-key.pem -out $DIR/server-key.pem
#
# Sign server cert
#
openssl ca -cert $DIR/ca-cert.pem -policy policy_anything \ -out $DIR/server-cert.pem -config $DIR/openssl.cnf \ -infiles $DIR/server-req.pem
# Sample output:
# Using configuration from /home/monty/openssl/openssl.cnf
# Enter PEM pass phrase:
# Check that the request matches the signature
# Signature ok
# The Subjects Distinguished Name is as follows
# countryName :PRINTABLE:'FI'
# organizationName :PRINTABLE:'MySQL AB'
# commonName :PRINTABLE:'MySQL admin'
# Certificate is to be certified until Sep 13 14:22:46 2003 GMT
# (365 days)
# Sign the certificate? [y/n]:y
#
#
# 1 out of 1 certificate requests certified, commit? [y/n]y
# Write out database with 1 new entries
# Data Base Updated
#
# Create client request and key
#
openssl req -new -keyout $DIR/client-key.pem -out \ $DIR/client-req.pem -days 3600 -config $DIR/openssl.cnf
# Sample output:
# Using configuration from /home/monty/openssl/openssl.cnf
# Generating a 1024 bit RSA private key
# .....................................++++++
# .............................................++++++
# writing new private key to '/home/monty/openssl/client-key.pem'
# Enter PEM pass phrase:
# Verifying password - Enter PEM pass phrase:
# -----
# You are about to be asked to enter information that will be
# incorporated into your certificate request.
# What you are about to enter is what is called a Distinguished Name
# or a DN.
# There are quite a few fields but you can leave some blank
# For some fields there will be a default value,
# If you enter '.', the field will be left blank.
# -----
# Country Name (2 letter code) [AU]:FI
# State or Province Name (full name) [Some-State]:.
# Locality Name (eg, city) []:
# Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB
# Organizational Unit Name (eg, section) []:
# Common Name (eg, YOUR name) []:MySQL user
# Email Address []:
#
# Please enter the following 'extra' attributes
# to be sent with your certificate request
# A challenge password []:
# An optional company name []:
#
# Remove the passphrase from the key
#
openssl rsa -in $DIR/client-key.pem -out $DIR/client-key.pem
#
# Sign client cert
#
openssl ca -cert $DIR/ca-cert.pem -policy policy_anything \ -out $DIR/client-cert.pem -config $DIR/openssl.cnf \ -infiles $DIR/client-req.pem
# Sample output:
# Using configuration from /home/monty/openssl/openssl.cnf
# Enter PEM pass phrase:
# Check that the request matches the signature
# Signature ok
# The Subjects Distinguished Name is as follows
# countryName :PRINTABLE:'FI'
# organizationName :PRINTABLE:'MySQL AB'
# commonName :PRINTABLE:'MySQL user'
# Certificate is to be certified until Sep 13 16:45:17 2003 GMT
# (365 days)
# Sign the certificate? [y/n]:y
#
#
# 1 out of 1 certificate requests certified, commit? [y/n]y
# Write out database with 1 new entries
# Data Base Updated
#
# Create a my.cnf file that you can use to test the certificates
#
cat <<EOF > $DIR/my.cnf
[client]
ssl-ca=$DIR/ca-cert.pem
ssl-cert=$DIR/client-cert.pem
ssl-key=$DIR/client-key.pem
[mysqld]
ssl-ca=$DIR/ca-cert.pem
ssl-cert=$DIR/server-cert.pem
ssl-key=$DIR/server-key.pem
EOF
例 3: Windows で SSL ファイルを作成する

Windows 用の OpenSSL がシステムにインストールされていない場合は、それをダウンロードします。次に、使用可能なパッケージの概要を示します。

http://www.slproweb.com/products/Win32OpenSSL.html

アーキテクチャー (32 ビットまたは 64 ビット) に応じて、Win32 OpenSSL Light または Win64 OpenSSL Light パッケージを選択します。デフォルトのインストール場所は、ダウンロードしたパッケージに応じて、C:\OpenSSL-Win32 または C:\OpenSSL-Win64 です。次の手順では、デフォルトの場所が C:\OpenSSL-Win32 であることが前提となっています。64 ビットのパッケージを使用している場合は、必要に応じて、これを変更します。

設定中に「...critical component is missing: Microsoft Visual C++ 2008 Redistributables」というメッセージが発生した場合は、設定を取り消し、アーキテクチャー (32 ビットまたは 64 ビット) に応じて、次のパッケージのいずれかをダウンロードします。

追加のパッケージをインストールしたら、OpenSSL の設定手順を再開します。

インストール時に、インストールパスとしてデフォルトの C:\OpenSSL-Win32 のままにして、デフォルトの「Copy OpenSSL DLL files to the Windows system directory」オプションも選択されたままにします。

インストールが完了したら、サーバーの Windows システムパス変数に C:\OpenSSL-Win32\bin を追加します。

  1. Windows デスクトップ上で「マイ コンピューター」アイコンを右クリックして、「プロパティ」を選択します。

  2. 表示された「システムのプロパティ」メニューから「詳細設定」タブを選択し、「環境変数」ボタンをクリックします。

  3. 「システム変数」「パス」を選択してから、「編集」ボタンをクリックします。「システム変数の編集」ダイアログが表示されるはずです。

  4. 末尾に「;C:\OpenSSL-Win32\bin」を追加します (セミコロンに注意してください)。

  5. 「OK」を 3 回押します。

  6. 新しいコマンドコンソール (Start>Run>cmd.exe) を開いて、OpenSSL が使用可能であることを確認することで、OpenSSL が Path 変数に正しく統合されたことをチェックします。

    Microsoft Windows [Version ...]
    Copyright (c) 2006 Microsoft Corporation. All rights reserved.
    C:\Windows\system32>cd \C:\>opensslOpenSSL> exit <<< If you see the OpenSSL prompt, installation was successful.
    C:\>

Windows のバージョンに応じて、前述のパス設定手順が多少異なる場合があります。

OpenSSL がインストールされたら、(このセクションの前半で示した) 例 1 と同様の手順を次のように変更して使用します。

  • 次のように Unix コマンドを変更します。

    # Create clean environment
    shell> rm -rf newcertsshell> mkdir newcerts && cd newcerts

    Windows では、代わりに次のコマンドを使用します。

    # Create clean environment
    shell> md c:\newcertsshell> cd c:\newcerts
  • コマンド行の末尾に「\」文字が表示されたら、この「\」文字を削除し、コマンド行をすべて 1 行で入力する必要があります。

証明書および鍵ファイルが生成されたあとに、それらを使用して SSL 接続をテストする方法については、セクション6.3.10.3「SSL 接続の使用」を参照してください。

6.3.11 SSH を使用した Windows から MySQL へのリモート接続

このセクションでは、SSH を使用してリモートの MySQL サーバーへのセキュアな接続を確立する方法について説明します。元の情報は、David Carlson によって提供されました。

  1. Windows マシン上に SSH クライアントをインストールします。SSH クライアントの比較については、http://en.wikipedia.org/wiki/Comparison_of_SSH_clientsを参照してください。

  2. Windows SSH クライアントを起動します。Host_Name = yourmysqlserver_URL_or_IP を設定します。サーバーにログインする userid=your_userid を設定します。この userid 値は、MySQL アカウントのユーザー名と同じでない可能性があります。

  3. ポートフォワーディングを設定します。リモート転送 (local_port: 3306remote_host: yourmysqlservername_or_ipremote_port: 3306 を設定します) とローカル転送 (port: 3306host: localhostremote port: 3306 を設定します) のいずれかを実行します。

  4. すべてを保存します。そうしない場合は、次回やり直す必要があります。

  5. 作成した SSH セッションを使用して、サーバーにログインします。

  6. Windows マシン上で、いくつかの ODBC アプリケーション (Access など) を起動します。

  7. 通常と同じ方法で、Windows で新しいファイルを作成し、ODBC ドライバを使用して MySQL へのリンクを作成します。ただし、MySQL ホストサーバーでは、yourmysqlservername ではなく、localhost に入力します。

この時点で、MySQL への ODBC 接続が SSH を使用して暗号化されているはずです。

6.3.12 MySQL Enterprise Audit ログプラグイン

注記

MySQL Enterprise Audit は、商用の拡張機能です。商用の製品 (MySQL Enterprise Edition) についてさらに学習するには、http://www.mysql.com/products/ を参照してください。

MySQL 5.6.10 の時点で、MySQL Enterprise Edition には、audit_log という名前のサーバープラグインを使用して実装された MySQL Enterprise Audit が含まれています。MySQL Enterprise Audit では、特定の MySQL サーバーで実行される接続およびクエリーアクティビティーのポリシーベースの標準モニタリングおよびロギングを有効にする際に、MySQL Audit API が使用されます。MySQL Enterprise Audit は、オラクルの監査仕様を満たすように設計されており、内部および外部の規制ガイドラインの両方に管理されているアプリケーションに対して、そのままで簡単に使用できる監査およびコンプライアンスのソリューションを提供しています。

インストール時に監査プラグインを使用すると、MySQL サーバーはサーバーアクティビティーの監査レコードを含むログファイルを生成できます。ログの内容には、クライアントが接続および切断したとき、および接続中に実行されたアクション (アクセスされたデータベースやテーブルなど) が含まれます。

プラグインをインストールすると (セクション6.3.12.1「監査ログプラグインのインストール」を参照してください)、監査ログファイルが書き込まれます。デフォルトでは、そのファイルはサーバーのデータディレクトリ内の audit.log という名前です。ファイルの名前を変更するには、サーバーの起動時に audit_log_file システム変数を設定します。

監査ログファイルの内容は暗号化されません。セクション6.3.12.2「監査ログプラグインのセキュリティーに関する考慮事項」を参照してください。

監査ログファイルは、<AUDIT_RECORD> 要素としてエンコードされた監査可能なイベントとともに、XML 形式で書き込まれます。ファイル形式を選択するには、サーバーの起動時に audit_log_format システム変数を設定します。ファイルの形式および内容についての詳細は、セクション6.3.12.3「監査ログファイル」を参照してください。

audit_log によってログファイルに書き込まれる情報の内容を制御するには、audit_log_policy システム変数を設定します。この変数はデフォルトで、ALL (監査可能なイベントをすべて書き込む) に設定されていますが、ログインまたはクエリーイベントのログのみを記録する LOGINS または QUERIES や、ロギングを無効にする NONE の値も許可されています。

ロギングが発生する方法の制御についての詳細は、セクション6.3.12.4「監査ログプラグインのロギング制御」を参照してください。監査ログプラグインを構成する際に使用されるパラメータについては、セクション6.3.12.6「監査ログプラグインのオプションおよびシステム変数」を参照してください。

audit_log プラグインが有効になっている場合は、パフォーマンススキーマ (第22章「MySQL パフォーマンススキーマを参照してください) に監査ログプラグイン用のインストゥルメンテーションが追加されます。関連するインストゥルメントを識別するには、次のクエリーを使用します。

SELECT NAME FROM performance_schema.setup_instruments
WHERE NAME LIKE '%/alog/%';

古い監査ログプラグインのバージョンからの変更

MySQL 5.6.14 では、Oracle Audit Vault との互換性を高くするために、監査ログプラグインにいくつかの変更が行われました。

新しい監査ログファイルの形式が実装されました。audit_log_format システム変数を使用すれば、古い形式または新しい形式を選択できます。この変数では、OLD および NEW (デフォルトは OLD) の値が許可されています。2 つの形式の相違点は次のとおりです。

  • 属性を使用した古い形式で書き込まれた <AUDIT_RECORD> 要素内の情報は、サブ要素を使用した新しい形式で書き込まれます。

  • 新しい形式には、<AUDIT_RECORD> 要素の詳細な情報が含まれています。各要素には、一意の識別子を提供する RECORD_ID 値が含まれています。TIMESTAMP 値には、タイムゾーンの情報が含まれています。クエリーレコードには、HOSTIPOS_LOGINUSER の情報、および COMMAND_CLASSSTATUS_CODE の値が含まれています。

古い <AUDIT_RECORD> 形式の例:

<AUDIT_RECORD TIMESTAMP="2013-09-15T15:27:27" NAME="Query" CONNECTION_ID="3" STATUS="0" SQLTEXT="SELECT 1"
/>

新しい <AUDIT_RECORD> 形式の例:

<AUDIT_RECORD> <TIMESTAMP>2013-09-15T15:27:27 UTC</TIMESTAMP> <RECORD_ID>3998_2013-09-15T15:27:27</RECORD_ID> <NAME>Query</NAME> <CONNECTION_ID>3</CONNECTION_ID> <STATUS>0</STATUS> <STATUS_CODE>0</STATUS_CODE> <USER>root[root] @ localhost [127.0.0.1]</USER> <OS_LOGIN></OS_LOGIN> <HOST>localhost</HOST> <IP>127.0.0.1</IP> <COMMAND_CLASS>select</COMMAND_CLASS> <SQLTEXT>SELECT 1</SQLTEXT>
</AUDIT_RECORD>

監査ログプラグインによって監査ログファイルがローテーションされると、別のファイル名形式が使用されます。audit.log という名前のログファイルの場合、以前はプラグインによってファイル名が audit.log.TIMESTAMP に変更されました。現在は、プラグインによってファイル名は XML ファイルであることを示す audit.log.TIMESTAMP.xml に変更されます。

audit_log_format の値を変更する場合は、次の手順を使用して、ある形式のログエントリが別の形式のエントリを含む既存のログファイルに書き込まれることを回避します。

  1. サーバーを停止します。

  2. 現在の監査ログファイルの名前を手動で変更します。

  3. 新しい audit_log_format の値でサーバーを再起動します。監査ログプラグインによって、選択した形式のログエントリを含む新しいログファイルが作成されます。

監査プラグインを記述するための API も変更されました。mysql_event_general の構造には、クライアントのホスト名と IP アドレス、コマンドのクラス、および外部ユーザーを表す新しいメンバーが含まれています。詳細については、セクション24.2.4.8「監査プラグインの作成」を参照してください。

6.3.12.1 監査ログプラグインのインストール

監査ログプラグインは、audit_log という名前です。サーバーで使用可能にするには、プラグインライブラリオブジェクトファイルを MySQL プラグインディレクトリ (plugin_dir システム変数で指定されたディレクトリ) に配置する必要があります。必要に応じて、サーバーの起動時に、プラグインディレクトリの場所をサーバーに指示する plugin_dir の値を設定します。

サーバーの起動時にプラグインをロードするには、--plugin-load オプションを使用して、プラグインを含むオブジェクトファイルの名前を指定します。このプラグインのロード方式では、サーバーを起動するたびにオプションを指定する必要があります。たとえば、my.cnf ファイルに次の行を挿入します。

[mysqld]
plugin-load=audit_log.so

システム上のオブジェクトファイルのサフィクスが .so とは異なる場合、正しいサフィクスに置き換えてください (たとえば Windows の場合は .dll)。

また、実行時にプラグインを登録するには、次のステートメントを使用します (必要に応じて、サフィクスを変更します)。

mysql> INSTALL PLUGIN audit_log SONAME 'audit_log.so';

INSTALL PLUGIN は、プラグインをロードします。また、後続の通常のサーバー起動のたびにプラグインがロードされるように、そのプラグインを mysql.plugins テーブルに登録します。

プラグインが --plugin-load を使用してロードされている場合、または INSTALL PLUGIN を使用して事前に登録されている場合は、サーバーの起動時に --audit-log オプションを使用すると、プラグインのアクティブ化を制御できます。たとえば、プラグインをロードして、実行時に削除されないようにするには、次のオプションを使用します。

[mysqld]
plugin-load=audit_log.so
audit-log=FORCE_PLUS_PERMANENT

監査プラグインを使用せずにサーバーが実行されることを回避する必要がある場合は、FORCE または FORCE_PLUS_PERMANENT の値とともに --audit-log を使用して、プラグインが正常に初期化されない場合にサーバーの起動を強制的に失敗させます。

プラグインのインストールについての一般的な情報は、セクション5.1.8「サーバープラグイン」を参照してください。プラグインのインストールを確認するには、INFORMATION_SCHEMA.PLUGINS テーブルを調査するか、または SHOW PLUGINS ステートメントを使用します。セクション5.1.8.2「サーバープラグイン情報の取得」を参照してください。

監査ログファイルの内容は暗号化されません。セクション6.3.12.2「監査ログプラグインのセキュリティーに関する考慮事項」を参照してください。

audit_log プラグインの操作を構成する際に使用されるパラメータに関する追加情報については、セクション6.3.12.6「監査ログプラグインのオプションおよびシステム変数」を参照してください。

6.3.12.2 監査ログプラグインのセキュリティーに関する考慮事項

audit_log 監査ログプラグインによって生成された監査ログファイルの内容は、暗号化されません。この内容には、SQL ステートメントのテキストなどの機密情報が含まれている可能性があります。セキュリティー上の理由から、このファイルは MySQL サーバーおよびログを表示する正当な理由を持つユーザーからのみアクセス可能なディレクトリに書き込むようにしてください。デフォルトのファイルは、データディレクトリ内の audit.log です。これは、サーバーの起動時に audit_log_file システム変数を設定することで変更できます。

6.3.12.3 監査ログファイル

監査ログファイルの内容は暗号化されません。セクション6.3.12.2「監査ログプラグインのセキュリティーに関する考慮事項」を参照してください。

監査ログファイルは、UTF-8 (1 文字当たり最大 4 バイト) を使用した XML として記述されています。ルート要素は、<AUDIT> です。監査プラグインログの終了時に、ルート要素の終了タグ </AUDIT> が書き込まれます。そのため、このタグは、プラグインがアクティブになっている間はファイル内に存在しません。

ルート要素には、<AUDIT_RECORD> 要素が含まれています。この要素のそれぞれは、監査対象のイベントに関する情報を提供します。

MySQL 5.6.14 では、Oracle Audit Vault との互換性を高くするために、新しい監査ログファイルの形式が導入されました。audit_log_format システム変数を使用すれば、古い形式または新しい形式を選択できます。この変数では、OLD および NEW (デフォルトは OLD) の値が許可されています。

audit_log_format の値を変更する場合は、次の手順を使用して、ある形式のログエントリが別の形式のエントリを含む既存のログファイルに書き込まれることを回避します。

  1. サーバーを停止します。

  2. 現在の監査ログファイルの名前を手動で変更します。

  3. 新しい audit_log_format の値でサーバーを再起動します。監査ログプラグインによって、選択した形式のログエントリを含む新しいログファイルが作成されます。

次に、デフォルトの (古い) 形式のサンプルログファイルを示します。ただし、読みやすくするために形式が若干変更されています。

<?xml version="1.0" encoding="UTF-8"?>
<AUDIT> <AUDIT_RECORD TIMESTAMP="2012-08-02T14:52:12" NAME="Audit" SERVER_ID="1" VERSION="1" STARTUP_OPTIONS="--port=3306" OS_VERSION="i686-Linux" MYSQL_VERSION="5.6.10-log"/> <AUDIT_RECORD TIMESTAMP="2012-08-02T14:52:41" NAME="Connect" CONNECTION_ID="1" STATUS="0" USER="root" PRIV_USER="root" OS_LOGIN="" PROXY_USER="" HOST="localhost" IP="127.0.0.1" DB=""/> <AUDIT_RECORD TIMESTAMP="2012-08-02T14:53:45" NAME="Query" CONNECTION_ID="1" STATUS="0" SQLTEXT="INSERT INTO t1 () VALUES()"/> <AUDIT_RECORD TIMESTAMP="2012-08-02T14:53:51" NAME="Quit" CONNECTION_ID="1" STATUS="0"/> <AUDIT_RECORD TIMESTAMP="2012-08-06T14:21:03" NAME="NoAudit" SERVER_ID="1"/>
</AUDIT>

次に、新しい形式のサンプルログファイルを示します。ただし、読みやすくするために形式が若干変更されています。

<?xml version="1.0" encoding="UTF-8"?>
<AUDIT> <AUDIT_RECORD> <TIMESTAMP>2013-09-17T15:03:24 UTC</TIMESTAMP> <RECORD_ID>1_2013-09-17T15:03:24</RECORD_ID> <NAME>Audit</NAME> <SERVER_ID>1</SERVER_ID> <VERSION>1</VERSION> <STARTUP_OPTIONS>/usr/local/mysql/bin/mysqld --socket=/usr/local/mysql/mysql.sock --port=3306</STARTUP_OPTIONS> <OS_VERSION>x86_64-osx10.6</OS_VERSION> <MYSQL_VERSION>5.7.2-m12-log</MYSQL_VERSION> </AUDIT_RECORD> <AUDIT_RECORD> <TIMESTAMP>2013-09-17T15:03:40 UTC</TIMESTAMP> <RECORD_ID>2_2013-09-17T15:03:24</RECORD_ID> <NAME>Connect</NAME> <CONNECTION_ID>2</CONNECTION_ID> <STATUS>0</STATUS> <STATUS_CODE>0</STATUS_CODE> <USER>root</USER> <OS_LOGIN></OS_LOGIN> <HOST>localhost</HOST> <IP>127.0.0.1</IP> <COMMAND_CLASS>connect</COMMAND_CLASS> <PRIV_USER>root</PRIV_USER> <PROXY_USER></PROXY_USER> <DB>test</DB> </AUDIT_RECORD>
... <AUDIT_RECORD> <TIMESTAMP>2013-09-17T15:03:41 UTC</TIMESTAMP> <RECORD_ID>4_2013-09-17T15:03:24</RECORD_ID> <NAME>Query</NAME> <CONNECTION_ID>2</CONNECTION_ID> <STATUS>0</STATUS> <STATUS_CODE>0</STATUS_CODE> <USER>root[root] @ localhost [127.0.0.1]</USER> <OS_LOGIN></OS_LOGIN> <HOST>localhost</HOST> <IP>127.0.0.1</IP> <COMMAND_CLASS>drop_table</COMMAND_CLASS> <SQLTEXT>DROP TABLE IF EXISTS t</SQLTEXT> </AUDIT_RECORD> <AUDIT_RECORD> <TIMESTAMP>2013-09-17T15:03:41 UTC</TIMESTAMP> <RECORD_ID>5_2013-09-17T15:03:24</RECORD_ID> <NAME>Query</NAME> <CONNECTION_ID>2</CONNECTION_ID> <STATUS>0</STATUS> <STATUS_CODE>0</STATUS_CODE> <USER>root[root] @ localhost [127.0.0.1]</USER> <OS_LOGIN></OS_LOGIN> <HOST>localhost</HOST> <IP>127.0.0.1</IP> <COMMAND_CLASS>create_table</COMMAND_CLASS> <SQLTEXT>CREATE TABLE t (i INT)</SQLTEXT> </AUDIT_RECORD>
... <AUDIT_RECORD> <TIMESTAMP>2013-09-17T15:03:41 UTC</TIMESTAMP> <RECORD_ID>7_2013-09-17T15:03:24</RECORD_ID> <NAME>Quit</NAME> <CONNECTION_ID>2</CONNECTION_ID> <STATUS>0</STATUS> <STATUS_CODE>0</STATUS_CODE> <USER></USER> <OS_LOGIN></OS_LOGIN> <HOST></HOST> <IP></IP> <COMMAND_CLASS>connect</COMMAND_CLASS> </AUDIT_RECORD>
... <AUDIT_RECORD> <TIMESTAMP>2013-09-17T15:03:47 UTC</TIMESTAMP> <RECORD_ID>9_2013-09-17T15:03:24</RECORD_ID> <NAME>Shutdown</NAME> <CONNECTION_ID>3</CONNECTION_ID> <STATUS>0</STATUS> <STATUS_CODE>0</STATUS_CODE> <USER>root[root] @ localhost [127.0.0.1]</USER> <OS_LOGIN></OS_LOGIN> <HOST>localhost</HOST> <IP>127.0.0.1</IP> <COMMAND_CLASS></COMMAND_CLASS> </AUDIT_RECORD> <AUDIT_RECORD> <TIMESTAMP>2013-09-17T15:03:47 UTC</TIMESTAMP> <RECORD_ID>10_2013-09-17T15:03:24</RECORD_ID> <NAME>Quit</NAME> <CONNECTION_ID>3</CONNECTION_ID> <STATUS>0</STATUS> <STATUS_CODE>0</STATUS_CODE> <USER></USER> <OS_LOGIN></OS_LOGIN> <HOST></HOST> <IP></IP> <COMMAND_CLASS>connect</COMMAND_CLASS> </AUDIT_RECORD> <AUDIT_RECORD> <TIMESTAMP>2013-09-17T15:03:49 UTC</TIMESTAMP> <RECORD_ID>11_2013-09-17T15:03:24</RECORD_ID> <NAME>NoAudit</NAME> <SERVER_ID>1</SERVER_ID> </AUDIT_RECORD>
</AUDIT>

<AUDIT_RECORD> 要素の属性には、次のような特性があります。

  • 一部の属性はすべての要素に表示されますが、大部分はオプションであり、必ずしもすべての要素に表示されるとはかぎりません。

  • 要素内の属性の順序は保証されません。

  • 属性値は固定長ではありません。あとで属性の説明で示すように、長い値は切り捨てられる可能性があります。

  • <>"、および & 文字は、それぞれ &lt;&gt;&quot;、および &amp; としてエンコードされます。NUL バイト (U+00) は、? 文字としてエンコードされます。

  • XML 文字として有効でない文字は、数値の文字参照を使用してエンコードされます。有効な XML 文字は次のとおりです。

    #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
新しい監査ログファイル形式

すべての <AUDIT_RECORD> 要素には、必須の要素セットが含まれています。監査レコードのタイプに応じて、その他のオプションの要素が表示される場合もあります。

次の要素は、すべての <AUDIT_RECORD> 要素で必須です。

  • <NAME>

    監査イベントを生成した命令 (サーバーがクライアントから受信したコマンドなど) のタイプを表す文字列。

    例:

    <NAME>Query</NAME>

    一部の一般的な <NAME> 値:

    Audit When auditing starts, which may be server startup time
    Connect When a client connects, also known as logging in
    Query An SQL statement (executed directly)
    Prepare Preparation of an SQL statement; usually followed by Execute
    Execute Execution of an SQL statement; usually follows Prepare
    Shutdown Server shutdown
    Quit When a client disconnects
    NoAudit Auditing has been turned off

    指定可能な値は AuditBinlog DumpChange userClose stmtConnect OutConnectCreate DBDaemonDebugDelayed insertDrop DBExecuteFetchField ListInit DBKillLong DataNoAuditPingPrepareProcesslistQueryQuitRefreshRegister SlaveReset stmtSet optionShutdownSleepStatisticsTable DumpTime です。

    AuditNoAudit を除いて、これらの値は mysql_com.h ヘッダーファイルに一覧表示された COM_xxx コマンドの値に対応します。たとえば、Create DBShutdown は、それぞれ COM_CREATE_DBCOM_SHUTDOWN に対応します。

  • <RECORD_ID>

    監査レコードを表す一意の識別子。この値はシーケンス番号とタイムスタンプで構成され、形式は SEQ_TIMESTAMP です。シーケンス番号は、監査ログプラグインによって開かれ、レコードのログが記録されるたびに 1 ずつ増分されると、監査ログファイルのサイズに初期化されます。タイムスタンプは、監査ログプラグインによってファイルが開かれた時間を示す yyyy-mm-ddThh:mm:ss 形式の UTC 値です。

    例:

    <RECORD_ID>28743_2013-09-18T21:03:24</RECORD_ID>
  • <TIMESTAMP>

    監査イベントが生成された日付と時間。たとえば、クライアントから受信された SQL ステートメントの実行に対応するイベントでは、<TIMESTAMP> 値はステートメントが受信されたときではなく、終了したあとに生成されます。この値の形式は、yyyy-mm-ddThh:mm:ss UTC (T の場合は小数点不可) です。この形式の末尾には、タイムゾーン指定子が含まれています。現在、タイムゾーンは常に UTC です。

    例:

    <TIMESTAMP>2013-09-17T15:03:49 UTC</TIMESTAMP>

次の要素は、<AUDIT_RECORD> 要素ではオプションです。これらの多くは、特定の <NAME> 値でのみ発生します。

  • <COMMAND_CLASS>

    実行されたアクションのタイプを示す文字列。

    例:

    <COMMAND_CLASS>drop_table</COMMAND_CLASS>

    この値は、MySQL ソース配布の sql/mysqld.cc ファイル内の com_status_vars 配列から取得されます。これらは、このステートメントで表示されるステータス変数に対応します。

    SHOW STATUS LIKE 'Com%';
  • <CONNECTION_ID>

    クライアント接続識別子を表す符号なし整数。これは、セッション内の CONNECTION_ID() 関数の値と同じです。

    例:

    <CONNECTION_ID>127</CONNECTION_ID>
  • <DB>

    デフォルトのデータベース名を表す文字列。この要素は、<NAME> 値が Connect または Change user である場合にのみ表示されます。

  • <HOST>

    クライアントのホスト名を表す文字列。この要素は、<NAME> 値が ConnectChange user、または Query である場合にのみ表示されます。

    例:

    <HOST>localhost</HOST>
  • <IP>

    クライアントの IP アドレスを表す文字列。この要素は、<NAME> 値が ConnectChange user、または Query である場合にのみ表示されます。

    例:

    <IP>127.0.0.1</IP>
  • <MYSQL_VERSION>

    MySQL サーバーのバージョンを表す文字列。これは、セッション内の VERSION() 関数または version システム変数の値と同じです。この要素は、<NAME> 値が Audit である場合にのみ表示されます。

    例:

    <MYSQL_VERSION>5.7.1-m11-log</MYSQL_VERSION>
  • <OS_LOGIN>

    外部ユーザーを表す文字列 (none の場合は空です)。たとえば、サーバーが外部の認証方式を使用してクライアントを認証する場合は、この値が <USER> の値と異なる可能性があります。この要素は、<NAME> 値が ConnectChange user、または Query である場合にのみ表示されます。

  • <OS_VERSION>

    サーバーが構築された、または実行されているオペレーティングシステムを表す文字列。この要素は、<NAME> 値が Audit である場合にのみ表示されます。

    例:

    <OS_VERSION>x86_64-Linux</OS_VERSION>
  • <PRIV_USER>

    サーバーがクライアントを認証する際に使用したユーザーを表す文字列。これは、サーバーが権限チェックを行う際に使用するユーザー名であり、<USER> の値とは異なる可能性があります。この要素は、<NAME> 値が Connect または Change user である場合にのみ表示されます。

  • <PROXY_USER>

    プロキシユーザーを表す文字列。ユーザーのプロキシ処理が有効になっていない場合は、値が空です。この要素は、<NAME> 値が Connect または Change user である場合にのみ表示されます。

  • <SERVER_ID>

    サーバー ID を表す符号なし整数。これは、server_id システム変数の値と同じです。この要素は、<NAME> 値が Audit または NoAudit である場合にのみ表示されます。

    例:

    <SERVER_ID>1</SERVER_ID>
  • <SQLTEXT>

    SQL ステートメントのテキストを表す文字列。この値は、空にすることができます。長い値は、切り捨てられる可能性があります。この要素は、<NAME> 値が Query または Execute である場合にのみ表示されます。

    監査ログファイル自体などの文字列は、UTF-8 (1 文字当たり最大 4 バイト) を使用して記述されるため、この値が変換の結果となる場合があります。たとえば、元のステートメントは、SJIS 文字列としてクライアントから受信された可能性があります。

    例:

    <SQLTEXT>DELETE FROM t1</SQLTEXT>
  • <STARTUP_OPTIONS>

    MySQL サーバーの起動時に、コマンド行またはオプションファイルで指定されたオプションを表す文字列。この要素は、<NAME> 値が Audit である場合にのみ表示されます。

    例:

    <STARTUP_OPTIONS>/usr/local/mysql/bin/mysqld --port=3306 --log-output=FILE</STARTUP_OPTIONS>
  • <STATUS>

    コマンドのステータスを表す符号なし整数 (成功した場合は 0、エラーが発生した場合はゼロ以外)。これは、mysql_errno() C API 関数の値と同じです。

    監査ログには、SQLSTATE 値またはエラーメッセージが含まれていません。エラーコード、SQLSTATE 値、およびメッセージ間の関連性を確認する方法については、セクションB.3「サーバーのエラーコードおよびメッセージ」を参照してください。

    警告のログは記録されません。

    <STATUS> と異なる点については、<STATUS_CODE> の説明を参照してください。

    例:

    <STATUS>1051</STATUS>
  • <STATUS_CODE>

    コマンドのステータスを表す符号なし整数 (成功した場合は 0、エラーが発生した場合は 1)。

    STATUS_CODE の値は、STATUS の値とは異なります。STATUS_CODE は、成功した場合は 0、エラーが発生した場合は 1 であり、Audit Vault の EZ_collector コンシューマとの互換性があります。STATUS は、mysql_errno() C API 関数の値です。これは、成功した場合は 0、エラーが発生した場合はゼロ以外です。そのため、エラーが発生した場合、必ずしも 1 であるとはかぎりません。

    例:

    <STATUS_CODE>0</STATUS_CODE>
  • <USER>

    クライアントによって送信されたユーザー名を表す文字列。これは、<PRIV_USER> の値とは異なる可能性があります。この要素は、<NAME> 値が ConnectChange user、または Query である場合にのみ表示されます。

    例:

    <USER>root[root] @ localhost [127.0.0.1]</USER>
  • <VERSION>

    監査ログファイル形式のバージョンを表す符号なし整数。この要素は、<NAME> 値が Audit である場合にのみ表示されます。

    例:

    <VERSION>1</VERSION>
古い監査ログファイル形式

すべての <AUDIT_RECORD> 要素には、必須の属性セットが含まれています。監査レコードのタイプに応じて、その他のオプションの属性が表示される場合もあります。

次の属性は、すべての <AUDIT_RECORD> 要素で必須です。

  • NAME

    監査イベントを生成した命令 (サーバーがクライアントから受信したコマンドなど) のタイプを表す文字列。

    例: NAME="Query"

    一部の一般的な NAME 値:

    "Audit" When auditing starts, which may be server startup time
    "Connect" When a client connects, also known as logging in
    "Query" An SQL statement (executed directly)
    "Prepare" Preparation of an SQL statement; usually followed by Execute
    "Execute" Execution of an SQL statement; usually follows Prepare
    "Shutdown" Server shutdown
    "Quit" When a client disconnects
    "NoAudit" Auditing has been turned off

    指定可能な値は "Audit""Binlog Dump""Change user""Close stmt""Connect Out""Connect""Create DB""Daemon""Debug""Delayed insert""Drop DB""Execute""Fetch""Field List""Init DB""Kill""Long Data""NoAudit""Ping""Prepare""Processlist""Query""Quit""Refresh""Register Slave""Reset stmt""Set option""Shutdown""Sleep""Statistics""Table Dump""Time" です。

    "Audit""NoAudit" を除いて、これらの値は mysql_com.h ヘッダーファイルに一覧表示された COM_xxx コマンドの値に対応します。たとえば、"Create DB""Shutdown" は、それぞれ COM_CREATE_DBCOM_SHUTDOWN に対応します。

  • TIMESTAMP

    監査イベントが生成された日付と時間。たとえば、クライアントから受信された SQL ステートメントの実行に対応するイベントでは、TIMESTAMP 値はステートメントが受信されたときではなく、終了したあとに生成されます。この値は、yyyy-mm-ddThh:mm:ss 形式 (T の場合は小数点不可) の UTC です。

    例: TIMESTAMP="2012-08-09T12:55:16"

次の属性は、<AUDIT_RECORD> 要素ではオプションです。これらの多くは、NAME 属性の特定の値を含む要素でのみ発生します。

  • CONNECTION_ID

    クライアント接続識別子を表す符号なし整数。これは、セッション内の CONNECTION_ID() 関数の値と同じです。

    例: CONNECTION_ID="127"

  • DB

    デフォルトのデータベース名を表す文字列。この属性は、NAME 値が "Connect" または "Change user" である場合にのみ表示されます。

  • HOST

    クライアントのホスト名を表す文字列。この属性は、NAME 値が "Connect" または "Change user" である場合にのみ表示されます。

    例: HOST="localhost"

  • IP

    クライアントの IP アドレスを表す文字列。この属性は、NAME 値が "Connect" または "Change user" である場合にのみ表示されます。

    例: IP="127.0.0.1"

  • MYSQL_VERSION

    MySQL サーバーのバージョンを表す文字列。これは、セッション内の VERSION() 関数または version システム変数の値と同じです。この属性は、NAME 値が "Audit" である場合にのみ表示されます。

    例: MYSQL_VERSION="5.6.11-log"

  • OS_LOGIN

    外部ユーザーを表す文字列 (none の場合は空です)。たとえば、サーバーが外部の認証方式を使用してクライアントを認証する場合は、この値が USER と異なる可能性があります。この属性は、NAME 値が "Connect" または "Change user" である場合にのみ表示されます。

  • OS_VERSION

    サーバーが構築された、または実行されているオペレーティングシステムを表す文字列。この属性は、NAME 値が "Audit" である場合にのみ表示されます。

    例: OS_VERSION="x86_64-Linux"

  • PRIV_USER

    サーバーがクライアントを認証する際に使用したユーザーを表す文字列。これは、サーバーが権限チェックを行う際に使用するユーザー名であり、USER の値とは異なる可能性があります。この属性は、NAME 値が "Connect" または "Change user" である場合にのみ表示されます。

  • PROXY_USER

    プロキシユーザーを表す文字列。ユーザーのプロキシ処理が有効になっていない場合は、値が空です。この属性は、NAME 値が "Connect" または "Change user" である場合にのみ表示されます。

  • SERVER_ID

    サーバー ID を表す符号なし整数。これは、server_id システム変数の値と同じです。この属性は、NAME 値が "Audit" または "NoAudit" である場合にのみ表示されます。

    例: SERVER_ID="1"

  • SQLTEXT

    SQL ステートメントのテキストを表す文字列。この値は、空にすることができます。長い値は、切り捨てられる可能性があります。この属性は、NAME 値が "Query" または "Execute" である場合にのみ表示されます。

    監査ログファイル自体などの文字列は、UTF-8 (1 文字当たり最大 4 バイト) を使用して記述されるため、この値が変換の結果となる場合があります。たとえば、元のステートメントは、SJIS 文字列としてクライアントから受信された可能性があります。

    例: SQLTEXT="DELETE FROM t1"

  • STARTUP_OPTIONS

    MySQL サーバーの起動時に、コマンド行またはオプションファイルで指定されたオプションを表す文字列。この属性は、NAME 値が "Audit" である場合にのみ表示されます。

    例: STARTUP_OPTIONS="--port=3306 --log-output=FILE"

  • STATUS

    コマンドのステータスを表す符号なし整数 (成功した場合は 0、エラーが発生した場合はゼロ以外)。これは、mysql_errno() C API 関数の値と同じです。

    監査ログには、SQLSTATE 値またはエラーメッセージが含まれていません。エラーコード、SQLSTATE 値、およびメッセージ間の関連性を確認する方法については、セクションB.3「サーバーのエラーコードおよびメッセージ」を参照してください。

    警告のログは記録されません。

    例: STATUS="1051"

  • USER

    クライアントによって送信されたユーザー名を表す文字列。これは、PRIV_USER の値とは異なる可能性があります。この属性は、NAME 値が "Connect" または "Change user" である場合にのみ表示されます。

  • VERSION

    監査ログファイル形式のバージョンを表す符号なし整数。この属性は、NAME 値が "Audit" である場合にのみ表示されます。

    例: VERSION="1"

6.3.12.4 監査ログプラグインのロギング制御

このセクションでは、audit_log プラグインでロギングを実行する方法、およびロギングの発生方法を制御するシステム変数について説明します。セクション6.3.12.3「監査ログファイル」で説明したログファイル形式に精通していることが前提となっています。

監査ログプラグインはそのログファイルを開くと、XML 宣言および開始ルート要素タグ <AUDIT> を書き込む必要があるかどうかをチェックし、その場合はそれらのタグを書き込みます。監査ログプラグインが終了すると、終了タグ </AUDIT> をファイルに書き込みます。

ログファイルを開くときに存在すれば、プラグインはファイルが </AUDIT> タグで終了しているかどうかをチェックし、その場合はそれを切り捨ててから、任意の <AUDIT_RECORD> 要素を書き込みます。ログファイルが存在するが、</AUDIT> タグで終了していない場合や、</AUDIT> タグを切り捨てることができない場合、プラグインではファイル形式が不正であり、初期化に失敗したとみなされます。これは、サーバーがクラッシュした場合や、監査ログプラグインの実行中に強制終了された場合に発生する可能性があります。ロギングは、問題が修正されるまで発生しません。エラーログをチェックして、診断情報を確認してください。

[ERROR] Plugin 'audit_log' init function returned error.

この問題に対処するには、不正な形式のログファイルを削除するか、ファイル名を変更してから、サーバーを再起動する必要があります。

MySQL サーバーは、クライアントから受信された SQL ステートメントの実行が完了するときなど、監査可能なイベントが発生するたびに監査ログプラグインを呼び出して、<AUDIT_RECORD> 要素を書き込みます。一般に、サーバーの起動後に最初に書き込まれた <AUDIT_RECORD> 要素には、サーバーの説明および起動オプションが含まれています。そのあとの要素は、クライアントの接続および切断イベント、SQL ステートメントの実行などのイベントを表します。最上位のステートメントのみのログが記録され、トリガーやストアドプロシージャーなどのストアドプログラム内のステートメントのログは記録されません。LOAD DATA INFILE などのステートメントから参照されるファイルの内容は、記録されません。

ロギングの発生方法に対する制御を許可するために、audit_log プラグインには、次に説明するような複数のシステム変数が用意されています。詳細については、セクション6.3.12.6「監査ログプラグインのオプションおよびシステム変数」を参照してください。

監査ログファイル名の指定

監査ログファイル名を制御するには、サーバーの起動時に audit_log_file システム変数を設定します。デフォルトでは、サーバーのデータディレクトリ内の audit.log という名前です。セキュリティー上の理由から、監査ログファイルは、MySQL サーバーおよびログを表示する正当な理由を持つユーザーにのみアクセス可能なディレクトリに書き込まれるべきです。

監査ロギングの戦略

監査プラグインは、ログの書き込みに関する複数の戦略のいずれかを使用できます。戦略を指定するには、サーバーの起動時に audit_log_strategy システム変数を設定します。デフォルトでは、戦略の値は ASYNCHRONOUS であり、プラグインは非同期的にログをバッファーに記録し、バッファーがいっぱいの場合は待機します。ファイルシステムのキャッシュ処理を使用するか (SEMISYNCHRONOUS)、各書き込みリクエストのあとに sync() を呼び出して出力を強制すれば (SYNCHRONOUS)、待機しないように (PERFORMANCE)、または同期的にログを記録するようにプラグインに指示できます。

非同期ロギングの戦略には、次のような特性があります。

  • サーバーのパフォーマンスと拡張性への影響が最小限です。

  • できるかぎり最短の時間 (つまり、バッファーを割り当てる時間とそのバッファーにイベントをコピーする時間を足した時間) で、監査イベントを生成するスレッドをブロックします。

  • 出力はバッファーに書き込まれます。個別のスレッドがバッファーからログファイルへの書き込みに対処します。

PERFORMANCE 戦略のデメリットは、バッファーがいっぱいの場合にイベントが破棄される点です。負荷の高いサーバーでは、監査ログでイベントが欠落する可能性が高くなります。

非同期ロギングを使用すると、ファイルへの書き込み中に問題が発生した場合や、プラグインが正常にシャットダウンされない場合 (たとえば、サーバーホストがクラッシュした場合) に、ログファイルの完全性が危険にさらされる可能性があります。このリスクを減らすには、同期ロギングが使用されるように audit_log_strategy を設定します。戦略に関係なく、ロギングはベストエフォートベーシスで発生するため、一貫性は保証されません。

監査ログ領域の管理

監査ログプラグインには、そのログファイルで使用される領域を管理できる複数のシステム変数が用意されています。

  • audit_log_buffer_size: 非同期ロギング用のバッファーサイズを設定するには、この変数をサーバーの起動時に設定します。このプラグインでは、初期化時に割り当てられ、終了時に削除される単一のバッファーが使用されます。このプラグインは、ロギングが非同期の場合にのみ、このバッファーを割り当てます。

  • audit_log_rotate_on_sizeaudit_log_flush: これらの変数を使用すると、監査ログファイルのローテーションおよびフラッシュが許可されます。監査ログファイルが非常に大きくなり、大量のディスク領域が消費される可能性があります。使用される領域を管理するには、自動的なログのローテーションを有効にするか、手動で監査ファイルの名前を変更し、ログをフラッシュして新しいファイルを開きます。必要に応じて、名前が変更されたファイルを削除したり、バックアップしたりできます。

    デフォルトでは、audit_log_rotate_on_size=0 であり、ログのローテーションは発生しません。この場合、audit_log_flush の値が無効から有効に変更されると、監査ログプラグインはログファイルを閉じてから再度開きます。ログファイル名の変更は、サーバーの外部で実行される必要があります。名前を audit.log.1 から audit.log.3 で循環させる 3 つの最近のログファイルを保持すると仮定します。Unix 上で、次のように手動でローテーションを実行します。

    1. コマンド行から、現在のログファイル名を変更します。

      shell> mv audit.log.2 audit.log.3shell> mv audit.log.1 audit.log.2shell> mv audit.log audit.log.1

      この時点で、プラグインは引き続き、audit.log.1 に名前が変更された現在のログファイルに書き込みます。

    2. サーバーに接続し、ログファイルをフラッシュします。これにより、プラグインはログファイルを閉じて、新しい audit.log ファイルログを再度開きます。

      mysql> SET GLOBAL audit_log_flush = ON;

    audit_log_rotate_on_size が 0 よりも大きい場合は、audit_log_flush を設定しても効果がありません。この場合、ファイルへの書き込みによってそのサイズが audit_log_rotate_on_size の値を超えるたびに、監査ログプラグインはそのログファイルを閉じてから再度開きます。このプラグインは、タイムスタンプ拡張子が追加されるように元のファイル名を変更します。たとえば、audit.logaudit.log.13440033615657730 という名前に変更される可能性があります。最後の 7 桁は小数部です。最初の 10 桁は、FROM_UNIXTIME() 関数を使用して解釈できる Unix タイムスタンプ値です。

    mysql> SELECT FROM_UNIXTIME(1344003361);+---------------------------+
    | FROM_UNIXTIME(1344003361) |
    +---------------------------+
    | 2012-08-03 09:16:01 |
    +---------------------------+
監査ログのフィルタリング

監査ログプラグインは、監査対象イベントをフィルタリングできます。これにより、イベントの発生元のアカウントやイベントのステータスに基づいて、監査ログファイルにイベントを書き込むかどうかを制御できます。ステータスのフィルタリングは、接続イベントおよびステートメントイベントごとに個別に発生します。

アカウント別のイベントフィルタリング

MySQL 5.6.20 の時点で、発生元のアカウントに基づいて監査対象イベントをフィルタリングするには、サーバーの起動時または実行時に、次のシステム変数のいずれかを設定します。

  • audit_log_include_accounts: 監査ロギングに含めるアカウント。この変数が設定されている場合は、これらのアカウントのみが監査されます。

  • audit_log_exclude_accounts: 監査ロギングから除外するアカウント。この変数が設定されている場合は、これらのアカウント以外がすべて監査されます。

いずれかの変数の値には、NULL またはカンマで区切った 1 つ以上のアカウント名を含む文字列を指定できます。それぞれの形式は user_name@host_name です。デフォルトでは、両方の変数が NULL になっています。この場合、アカウントのフィルタリングは実行されず、すべてのアカウントで監査が発生します。

例: user1 および user2 ローカルホストのアカウントでのみ監査ロギングを有効にするには、次のように audit_log_include_accounts システム変数を設定します。

SET GLOBAL audit_log_include_accounts = 'user1@localhost,user2@localhost';

同時に NULL 以外に設定できるのは、audit_log_include_accountsaudit_log_exclude_accounts のいずれかのみです。

  • audit_log_include_accounts を設定すると、サーバーは audit_log_exclude_accountsNULL に設定します。

  • audit_log_include_accountsNULL でない場合を除いて、audit_log_exclude_accounts を設定しようとするとエラーが発生します。この場合は、まず audit_log_include_accountsNULL に設定することでクリアする必要があります。

-- This sets audit_log_exclude_accounts to NULL
SET GLOBAL audit_log_include_accounts = value;
-- This fails because audit_log_include_accounts is not NULL
SET GLOBAL audit_log_exclude_accounts = value;
-- To set audit_log_exclude_accounts, first set
-- audit_log_include_accounts to NULL
SET GLOBAL audit_log_include_accounts = NULL;
SET GLOBAL audit_log_exclude_accounts = value;

いずれかの変数の値を調査する場合は、SHOW VARIABLESNULL が空の文字列として表示されることに注意してください。これを回避するには、代わりに SELECT を使用してください。

mysql> SHOW VARIABLES LIKE 'audit_log_include_accounts';+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| audit_log_include_accounts | |
+----------------------------+-------+
mysql> SELECT @@audit_log_include_accounts;+------------------------------+
| @@audit_log_include_accounts |
+------------------------------+
| NULL |
+------------------------------+

カンマ、スペース、またはその他の特殊文字が含まれているために、ユーザー名やホスト名を引用符で囲む必要がある場合は、一重引用符を使用して囲みます。変数の値自体が一重引用符で囲まれている場合は、内側の各一重引用符を二重に入力するか、バックスラッシュを使用してエスケープします。次のステートメントはそれぞれ、ローカルの root アカウントの監査ロギングを有効にします。引用符のスタイルが異なりますが、いずれも同等です。

SET GLOBAL audit_log_include_accounts = 'root@localhost';
SET GLOBAL audit_log_include_accounts = '''root''@''localhost''';
SET GLOBAL audit_log_include_accounts = '\'root\'@\'localhost\'';
SET GLOBAL audit_log_include_accounts = "'root'@'localhost'";

ANSI_QUOTES SQL モードでは、二重引用符は文字列の引用ではなく、識別子の引用を示すため、このモードが有効になっている場合は、最後のステートメントが機能しません。

ステータス別のイベントフィルタリング

MySQL 5.6.20 の時点で、ステータスに基づいて監査対象イベントをフィルタリングするには、サーバーの起動時または実行時に、次のシステム変数を設定します。

  • audit_log_connection_policy: 接続イベントのロギングポリシーです

  • audit_log_statement_policy: ステートメントイベントのロギングポリシーです

各変数には、ALL (関連付けられたすべてのイベントのログを記録します。これがデフォルトです)、ERRORS (失敗したイベントのログのみを記録します)、または NONE (イベントのログを記録しません) の値が指定されます。たとえば、ステートメントイベントのログはすべて記録するが、接続イベントのログは失敗したもののみを記録する場合は、次の設定を使用します。

SET GLOBAL audit_log_statement_policy = ALL;
SET GLOBAL audit_log_connection_policy = ERRORS;

MySQL 5.6.20 よりも前では、audit_log_connection_policy および audit_log_statement_policy を使用できません。代わりに、サーバーの起動時または実行時に audit_log_policy を使用します。これには、ALL (すべてのイベントのログを記録します。これがデフォルトです)、LOGINS (接続イベントのログを記録します)、QUERIES (ステートメントイベントのログを記録します)、または NONE (イベントのログを記録しません) の値が指定されます。これらの値のいずれを指定しても、監査ログプラグインは成功と失敗を区別せずに、選択したイベントのログをすべて記録します。

MySQL 5.6.20 の時点で、audit_log_policy は引き続き使用可能ですが、サーバーの起動時にしか設定できません。実行時は、読み取り専用の変数です。起動時に使用すると、次のように動作します。

  • audit_log_policy を設定しない場合や、デフォルト値の ALL に設定した場合でも、audit_log_connection_policy または audit_log_statement_policy を明示的に設定すれば、指定どおりに適用されます。指定しない場合は、デフォルトが ALL に設定されます。

  • audit_log_policyALL 以外の値に設定した場合は、次の表に示すように、その値が優先され、audit_log_connection_policy および audit_log_statement_policy を設定する際に使用されます。また、これらの変数のいずれかをデフォルトの ALL 以外の値に設定する場合、サーバーはそれらの値がオーバーライドされることを示すメッセージをエラーログに書き込みます。

    起動時の audit_log_policy 値結果として返される audit_log_connection_policy 値結果として返される audit_log_statement_policy 値
    LOGINSALLNONE
    QUERIESNONEALL
    NONENONENONE
イベントフィルタリングのレポート

次のステータス変数の値を調査すると、フィルタリングの結果を確認できます。

  • Audit_log_events: フィルタリングのポリシーに基づいてログに書き込まれたかどうかに関係なく、監査ログプラグインによって処理されたイベントの数。

  • Audit_log_events_filtered: フィルタリングのポリシーに基づいて、監査ログプラグインによってフィルタリングされた (ログに書き込まれなかった) イベントの数。

  • Audit_log_events_written: 監査ログに書き込まれたイベントの数。

MySQL 5.6.20 の時点では、これらの変数を使用できます。

6.3.12.5 監査ログプラグインのオプションおよび変数のリファレンス

表 6.17 監査ログプラグインのオプション/変数のリファレンス

名前コマンド行オプションファイルシステム変数ステータス変数変数スコープ動的
audit-logはいはい    
audit_log_buffer_sizeはいはいはい グローバルいいえ
audit_log_connection_policyはいはいはい グローバルはい
audit_log_current_session  はい 両方いいえ
Audit_log_current_size   はいグローバルいいえ
Audit_log_event_max_drop_size   はいグローバルいいえ
Audit_log_events   はいグローバルいいえ
Audit_log_events_filtered   はいグローバルいいえ
Audit_log_events_lost   はいグローバルいいえ
Audit_log_events_written   はいグローバルいいえ
audit_log_exclude_accountsはいはいはい グローバルはい
audit_log_fileはいはいはい グローバルいいえ
audit_log_flush  はい グローバルはい
audit_log_formatはいはいはい グローバルいいえ
audit_log_include_accountsはいはいはい グローバルはい
audit_log_policyはいはいはい グローバル異なる
audit_log_rotate_on_sizeはいはいはい グローバルはい
audit_log_statement_policyはいはいはい グローバルはい
audit_log_strategyはいはいはい グローバルいいえ
Audit_log_total_size   はいグローバルいいえ
Audit_log_write_waits   はいグローバルいいえ

6.3.12.6 監査ログプラグインのオプションおよびシステム変数

このセクションでは、監査ログプラグインの操作を制御するコマンドオプションおよびシステム変数について説明します。起動時に指定された値が正しくない場合は、プラグインが正常に初期化できない可能性があり、サーバーでロードされません。この場合、サーバーでその他の監査ログ設定が認識されないため、それに関するエラーメッセージが生成される可能性もあります。

audit_log プラグインのアクティブ化を制御するには、次のオプションを使用します。

  • --audit-log[=value]

    導入5.6.10
    コマンド行形式--audit-log[=value]
    許可されている値列挙
    デフォルトON
    有効な値ON
    OFF
    FORCE
    FORCE_PLUS_PERMANENT

    このオプションは、サーバーの起動時に audit_log プラグインをロードする方法を制御します。これは、監査ログプラグインが事前に INSTALL PLUGIN に登録されている場合や、--plugin-load を使用してロードされている場合にのみ指定可能です。セクション6.3.12.1「監査ログプラグインのインストール」を参照してください。

    セクション5.1.8.1「プラグインのインストールおよびアンインストール」で説明したように、オプションの値は、プラグインのロードオプションに指定可能な値のいずれかである必要があります。たとえば、--audit-log=FORCE_PLUS_PERMANENT は、プラグインをロードし、それがサーバーの実行時に削除されることを回避するようにサーバーに指示します。

    このオプションは MySQL 5.6.10 で追加されました。

audit_log プラグインがインストールされている場合は、ロギングに対する制御を許可する複数のシステム変数が表示されます。これらの変数は、audit_log プラグインが有効になっている場合にのみ指定可能です。

mysql> SHOW VARIABLES LIKE 'audit_log%';+-----------------------------+--------------+
| Variable_name | Value |
+-----------------------------+--------------+
| audit_log_buffer_size | 1048576 |
| audit_log_connection_policy | ALL |
| audit_log_current_session | ON |
| audit_log_exclude_accounts | |
| audit_log_file | audit.log |
| audit_log_flush | OFF |
| audit_log_format | OLD |
| audit_log_include_accounts | |
| audit_log_policy | ALL |
| audit_log_rotate_on_size | 0 |
| audit_log_statement_policy | ALL |
| audit_log_strategy | ASYNCHRONOUS |
+-----------------------------+--------------+

これらの変数のいずれも、サーバーの起動時 (一部は実行時) に設定できます。

  • audit_log_buffer_size

    導入5.6.10
    コマンド行形式--audit-log-buffer-size=value
    システム変数名前audit_log_buffer_size
    変数スコープグローバル
    動的変数いいえ
    許可されている値 (32 ビットプラットフォーム)数値
    デフォルト1048576
    最小値4096
    最大値4294967295
    許可されている値 (64 ビットプラットフォーム)数値
    デフォルト1048576
    最小値4096
    最大値18446744073709547520

    監査ログプラグインが非同期的にイベントをログに書き込むと、イベントの内容を書き込む前に、バッファーを使用してそれらを格納します。この変数は、そのバッファーのサイズ (バイト単位) を制御します。サーバーは、この値を 4096 の倍数に調整します。このプラグインでは、初期化時に割り当てられ、終了時に削除される単一のバッファーが使用されます。このプラグインは、ロギングが非同期の場合にのみ、このバッファーを割り当てます。

    この変数は MySQL 5.6.10 で追加されました。

  • audit_log_connection_policy

    導入5.6.20
    コマンド行形式--audit-log-connection-policy=value
    システム変数名前audit_log_connection_policy
    変数スコープグローバル
    動的変数はい
    許可されている値列挙
    デフォルトALL
    有効な値ALL
    ERRORS
    NONE

    監査ログプラグインが接続イベントをそのログファイルに書き込む方法を制御するポリシーです。次の表は、許可される値を示しています。

    説明
    ALL接続イベントのログをすべて記録します
    ERRORS失敗した接続イベントのログのみを記録します
    NONE接続イベントのログを記録しません
    注記

    セクション6.3.12.4「監査ログプラグインのロギング制御」で説明したように、audit_log_policy も指定されている場合は、サーバーの起動時に、audit_log_connection_policy に明示的に指定された値がオーバーライドされる可能性があります。

    この変数は、MySQL 5.6.20 で追加されました。

  • audit_log_current_session

    導入5.6.20
    システム変数名前audit_log_current_session
    変数スコープグローバル、セッション
    動的変数いいえ
    許可されている値ブール
    デフォルトdepends on filtering policy

    現在のセッションで監査ロギングが有効になっているかどうかを示します。この変数のセッションの値は、読み取り専用です。セッションの開始時に、audit_log_include_accounts および audit_log_exclude_accounts システム変数の値に基づいて設定されます。監査ログプラグインはこのセッション値を使用して、そのセッションでイベントを監査するかどうかを決定します。(グローバル値もありますが、このプラグインでは使用されません。)

    この変数は、MySQL 5.6.20 で追加されました。

  • audit_log_exclude_accounts

    導入5.6.20
    コマンド行形式--audit-log-exclude-accounts=value
    システム変数名前audit_log_exclude_accounts
    変数スコープグローバル
    動的変数はい
    許可されている値文字列
    デフォルトNULL

    イベントのログが記録されないアカウント。この値には、NULL またはカンマで区切った 1 つ以上のアカウント名のリストを含む文字列を指定するようにしてください。詳細については、セクション6.3.12.4「監査ログプラグインのロギング制御」を参照してください。

    この変数は、MySQL 5.6.20 で追加されました。

  • audit_log_file

    導入5.6.10
    コマンド行形式--audit-log-file=file_name
    システム変数名前audit_log_file
    変数スコープグローバル
    動的変数いいえ
    許可されている値ファイル名
    デフォルトaudit.log

    監査ログプラグインがイベントを書き込むファイルの名前。デフォルト値は audit.log です。ファイル名が相対パスの場合、サーバーはデータディレクトリに相対的なパスであると解釈します。セキュリティー上の理由から、監査ログファイルは、MySQL サーバーおよびログを表示する正当な理由を持つユーザーにのみアクセス可能なディレクトリに書き込まれるべきです。

    この変数は MySQL 5.6.10 で追加されました。

  • audit_log_flush

    導入5.6.10
    システム変数名前audit_log_flush
    変数スコープグローバル
    動的変数はい
    許可されている値ブール
    デフォルトOFF

    この変数が有効になるよう (1 または ON) に設定されている場合、監査ログプラグインはそのログファイルを閉じてから再度開いて、フラッシュします。(この値は、別のフラッシュを実行するために再度有効にする前に、明示的に無効にする必要がないように、OFF のままになっています。)audit_log_rotate_on_size が 0 である場合を除いて、この変数を有効にしても効果はありません。

    この変数は MySQL 5.6.10 で追加されました。

  • audit_log_format

    導入5.6.14
    コマンド行形式--audit-log-format=value
    システム変数名前audit_log_format
    変数スコープグローバル
    動的変数いいえ
    許可されている値 (>= 5.6.14)列挙
    デフォルトOLD
    有効な値OLD
    NEW

    監査ログファイルの形式。許可されている値は、OLD および NEW (デフォルトは OLD) です。各形式についての詳細は、セクション6.3.12.3「監査ログファイル」を参照してください。

    audit_log_format の値を変更する場合は、次の手順を使用して、ある形式のログエントリが別の形式のエントリを含む既存のログファイルに書き込まれることを回避します。

    1. サーバーを停止します。

    2. 現在の監査ログファイルの名前を手動で変更します。

    3. 新しい audit_log_format の値でサーバーを再起動します。監査ログプラグインによって、選択した形式のログエントリを含む新しいログファイルが作成されます。

    この変数は、MySQL 5.6.14 で追加されました。

  • audit_log_include_accounts

    導入5.6.20
    コマンド行形式--audit-log-include-accounts=value
    システム変数名前audit_log_include_accounts
    変数スコープグローバル
    動的変数はい
    許可されている値文字列
    デフォルトNULL

    イベントのログが記録されるアカウント。この値には、NULL またはカンマで区切った 1 つ以上のアカウント名のリストを含む文字列を指定するようにしてください。詳細については、セクション6.3.12.4「監査ログプラグインのロギング制御」を参照してください。

    この変数は、MySQL 5.6.20 で追加されました。

  • audit_log_policy

    導入5.6.10
    コマンド行形式--audit-log-policy=value
    システム変数 (<= 5.6.19)名前audit_log_policy
    変数スコープグローバル
    動的変数はい
    システム変数 (>= 5.6.20)名前audit_log_policy
    変数スコープグローバル
    動的変数いいえ
    許可されている値列挙
    デフォルトALL
    有効な値ALL
    LOGINS
    QUERIES
    NONE

    監査ログプラグインがイベントをそのログファイルに書き込む方法を制御するポリシーです。次の表は、許可される値を示しています。

    説明
    ALLイベントのログをすべて記録します
    LOGINSログインイベントのログのみを記録します
    QUERIESクエリーイベントのログのみを記録します
    NONEログを何も記録しません (監査ストリームを無効にします)

    MySQL 5.6.20 の時点で、audit_log_policy はサーバーの起動時にしか設定できません。実行時は、読み取り専用の変数です。これは、より詳細にロギングポリシーを制御し、起動時または実行時に設定できるその他の 2 つのシステム変数 (audit_log_connection_policyaudit_log_statement_policy) が導入されたためです。その他の 2 つの変数の代わりに、起動時に audit_log_policy を使用し続けると、サーバーはその値を使用して、これらの変数を設定します。ポリシーの変数とそれらの相互作用についての詳細は、セクション6.3.12.4「監査ログプラグインのロギング制御」を参照してください。

    MySQL 5.6.20 よりも前では、audit_log_connection_policy および audit_log_statement_policy システム変数が存在しません。audit_log_policy は、唯一のポリシー制御の変数であり、サーバーの起動時または実行時に設定できます。

    この変数は MySQL 5.6.10 で追加されました。

  • audit_log_rotate_on_size

    導入5.6.10
    コマンド行形式--audit-log-rotate-on-size=N
    システム変数名前audit_log_rotate_on_size
    変数スコープグローバル
    動的変数はい
    許可されている値数値
    デフォルト0

    audit_log_rotate_on_size 値を 0 よりも大きくした場合は、ファイルへの書き込みによってそのサイズがこの値を超えると、監査ログプラグインはそのログファイルを閉じてから再度開きます。元のファイル名は、タイムスタンプ拡張子が含まれるように変更されます。

    audit_log_rotate_on_size 値が 0 の場合、プラグインはサイズに基づいて、そのログを閉じてから再度開きません。代わりに、audit_log_flush 使用して、要求に応じてログを閉じてから再度開きます。この場合、ファイルをフラッシュする前に、サーバーの外部でファイル名を変更します。

    監査ログファイルのローテーションおよびタイムスタンプの解釈についての詳細は、セクション6.3.12.4「監査ログプラグインのロギング制御」を参照してください。

    この変数を 4096 の倍数でない値に設定すると、もっとも近い倍数に切り捨てられます。(したがって、4096 未満の値に設定すると、0 (ゼロ) に設定した結果となり、ローテーションは発生しません。)

    この変数は MySQL 5.6.10 で追加されました。

  • audit_log_statement_policy

    導入5.6.20
    コマンド行形式--audit-log-statement-policy=value
    システム変数名前audit_log_statement_policy
    変数スコープグローバル
    動的変数はい
    許可されている値列挙
    デフォルトALL
    有効な値ALL
    ERRORS
    NONE

    監査ログプラグインがステートメントイベントをそのログファイルに書き込む方法を制御するポリシーです。次の表は、許可される値を示しています。

    説明
    ALLステートメントイベントのログをすべて記録します
    ERRORS失敗したステートメントイベントのログのみを記録します
    NONEステートメントイベントのログを記録しません
    注記

    セクション6.3.12.4「監査ログプラグインのロギング制御」で説明したように、audit_log_policy も指定されている場合は、サーバーの起動時に、audit_log_statement_policy に明示的に指定された値がオーバーライドされる可能性があります。

    この変数は、MySQL 5.6.20 で追加されました。

  • audit_log_strategy

    導入5.6.10
    コマンド行形式--audit-log-strategy=value
    システム変数名前audit_log_strategy
    変数スコープグローバル
    動的変数いいえ
    許可されている値列挙
    デフォルトASYNCHRONOUS
    有効な値ASYNCHRONOUS
    PERFORMANCE
    SEMISYNCHRONOUS
    SYNCHRONOUS

    監査ログプラグインで使用されるロギング方法。次の表では、許可されている値について説明します。

    表 6.18 監査ログの戦略

    意味
    ASYNCHRONOUS非同期的にログを記録し、出力バッファー内の領域を待機します
    PERFORMANCE非同期的にログを記録し、出力バッファー内の領域が十分でない場合はリクエストを破棄します
    SEMISYNCHRONOUS同期的にログを記録し、オペレーティングシステムによるキャッシュ処理を許可します
    SYNCHRONOUS同期的にログを記録し、各リクエスト後に sync() を呼び出します

    この変数は MySQL 5.6.10 で追加されました。

6.3.12.7 監査ログプラグインのステータス変数

監査ログプラグインでは、次のステータス変数がサポートされています。これらは、audit_log プラグインが有効になっている場合にのみ指定可能です。

  • Audit_log_current_size

    現在の監査ログファイルのサイズ。この値は、イベントがログに書き込まれると増加し、ログがローテーションされると 0 にリセットされます。

    この変数は、MySQL 5.6.20 で追加されました。

  • Audit_log_event_max_drop_size

    パフォーマンスロギングモードで破棄された最大イベントのサイズ。ロギングモードについては、セクション6.3.12.4「監査ログプラグインのロギング制御」を参照してください。

    この変数は、MySQL 5.6.20 で追加されました。

  • Audit_log_events

    フィルタリングのポリシーに基づいてログに書き込まれたかどうかに関係なく、監査ログプラグインによって処理されたイベントの数 (セクション6.3.12.4「監査ログプラグインのロギング制御」を参照してください)。

    この変数は、MySQL 5.6.20 で追加されました。

  • Audit_log_events_filtered

    フィルタリングのポリシーに基づいて、監査ログプラグインによってフィルタリングされた (ログに書き込まれなかった) イベントの数 (セクション6.3.12.4「監査ログプラグインのロギング制御」を参照してください)。

    この変数は、MySQL 5.6.20 で追加されました。

  • Audit_log_events_lost

    イベントが使用可能な監査ログバッファー領域よりも大きかったために、パフォーマンスロギングモードで失われたイベントの数。この値は、audit_log_buffer_size を設定して、パフォーマンスモード用にバッファーのサイズを調整する方法を評価する際に役立つことがあります。ロギングモードについては、セクション6.3.12.4「監査ログプラグインのロギング制御」を参照してください。

    この変数は、MySQL 5.6.20 で追加されました。

  • Audit_log_events_written

    監査ログに書き込まれたイベントの数。

    この変数は、MySQL 5.6.20 で追加されました。

  • Audit_log_total_size

    すべての監査ログファイルに書き込まれたイベントの合計サイズ。Audit_log_current_size とは異なり、Audit_log_total_size の値は、ログがローテーションされたときにも増加します。

    この変数は、MySQL 5.6.20 で追加されました。

  • Audit_log_write_waits

    非同期ロギングモードでイベントが監査ログバッファー内の領域を待機する必要があった回数。ロギングモードについては、セクション6.3.12.4「監査ログプラグインのロギング制御」を参照してください。

    この変数は、MySQL 5.6.20 で追加されました。

6.3.12.8 監査ログプラグインの制限事項

監査ログプラグインは、次の制限事項の対象になっています。

  • 最上位のステートメントのみのログが記録され、トリガーやストアドプロシージャーなどのストアドプログラム内のステートメントのログは記録されません。

  • LOAD DATA INFILE などのステートメントから参照されるファイルの内容は、記録されません。

6.3.13 SQL ベースの MySQL アカウントアクティビティーの監査

アプリケーションは次のガイドラインを使用することで、データベースアクティビティーを 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' を使用すると、user2example.com ドメイン内の任意のホストから接続できます。user2remote.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';

user2example.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 |
+----------------------------------------+
関連キーワード:  サーバー,パスワード,アカウント,ユーザー,テーブル,user,セクション,ステートメント,audit,ハッシュ