MySQL は先進的な非標準のセキュリティ/特権システムを持っています。 本章ではどのようにそれが動くかを述べます。
よくあるセキュリティの間違いを避けるために、インターネットに接続されたコン ピュータ上で MySQL を使用する誰もが、このセクションを読むべきです。
``セキュリティ'' の議論において、我々は、すべての該当するアタックタイプ (eavesdropping, altering, playback, Denial of Service) に対して、すべてのサー バホスト(MySQL サーバだけではなく)の完全な保護の必要性を強調しま す。We do not cover all aspects of availability and fault tolerance here.
MySQL は、ユーザが実行しようとするすべての接続、クエリ、その他の オペレーションに対して、アクセス制御リスト(ACLs: Access Control Lists)セキュ リティを使用します。MySQL クライアントとサーバの間で SSL 暗号化接 続のサポートもいくつかあります。ここで議論されるコンセプトの多くは、 MySQL に特有のものではありません; 同じ一般的なアイデアはほとんど すべてのアプリケーションに適用します。
MySQL 実行時、可能な限りいつでもこれらのガイドラインに従ってくだ さい:
GRANT
と REVOKE
コマンドは MySQL へのアクセスを制限するための物です。
必要以上の権限を誰にも与えないでください。
全てのホストに対して、何か出来るような許可を与えてはいけません。
Checklist:
mysql -u root
を行ってみます。
パスワードを尋ねられること無しにサーバへの接続ができる場合、問題があります。
どのユーザでも(root でなくても)、MySQL サーバに完全な権限で接続で
きます! root
パスワードの設定についての項目に特別な注意を払って
MySQL インストール説明を見直してください。
SHOW GRANTS
を使用し、だれがなんのアクセスを持つかチェックします。
必要ない権限を、REVOKE
コマンドを使用して削除してください。
MD5()
や他の one-way hashing 関数を
使用してください。
nmap
のようなツールを使用して、
あなたのマシンのポートをスキャンしてみます。
MySQL はデフォルトで 3306 番を使用しています。
このポートには、ほとんどの場合、アクセスできないようにすべきです。
MySQL ポートがオープンしているかどうかをチェックする他の簡単な方
法は、いくつかのリモートマシンから telnet server_host 3306
を実行す
ることです。ここで server_host
はあなたの MySQL サーバのホ
スト名です。接続し、いくつかのゴミ文字が得られた場合、ポートはオープンして
います。それをオープンしておく正当な理由が本当にない限り、ファイアーウォー
ルやルータでクローズすべきです。telnet
がハングしたり拒否されたり
する場合、すべて OK です。ポートはブロックされています。
; DROP ALL DATABASES ;
のような文字を入力しても、
あなたのアプリケーションは安全ですか?
これは極端な例ですが、それらに対して準備しない場合、似たようなテクニックを
使用するハッカーの結果として、大きなセキュリティリークとデータ喪失が発生し
得ます。
数値データのチェックも忘れないでください。よくある間違いは文字列しか保護し
ないことです。時々、人はデータベースが保護される必要のない公に有効なデータ
だけを含んでいるかどうかを考えます。これは間違いです。少なくとも、
denial-of-service タイプのアタックはそのようなデータベースでも実行されます。
このタイプのアタックから保護するもっとも簡単な方法は、数値定数の回りにアポ
ストロフィを使用することです: SELECT * FROM table WHERE ID=234
の代
わりに SELECT * FROM table WHERE ID='234'
。MySQL は自動的
にこの文字列を数値に変換し、そこからすべての非数値シンボルを取り除きます。
チェックリスト:
%22
(`"'), %23
(`#') , %27
(`'') をつけてみて、動的URLを
いろいろ変更して試してみてください。
addslashes()
関数を調べてください。
mysql_escape()
API コールがあるか調べてください。
escape
と quote
モディファイヤを調べてください。
quote()
メソッドを調べてください。 or use placeholders.
shell> tcpdump -l -i eth0 -w - src or dst port 3306 | strings(この例は Linux のものです。他のシステムでは少し違うでしょう). 警告: データが見えなくても、実際に常に暗号化されているわけではありません。 高いセキュリティが必要なら、セキュリティエキスパートに相談すべきです。
MySQL サーバーに接続するときは、パスワードを使用すべきです。 パスワードはコネクション間で、べたテキストでは流れません。 しかし、暗号化アルゴリズムはそんなに強力なわけではありません。クライアント とサーバ間のトラフィックを sniff できれば、いくつかの試みで、賢いアタッカー はパスワードをクラックできます。クライアントとサーバ間の接続が信頼できない ネットワークを通るなら、通信を暗号化するために SSH トンネルを使用 すべきです。
その他の全ての情報はテキストで転送され、
これは接続を覗くことが出来る人に読まれます。
もしこれを心配するなら、圧縮プロトコル(MySQL バージョン 3.22 以上)を
使用することが出来ます。より安全にしたい場合、
ssh
をインストールすべきです。
オープンソースの ssh クライアントは http://www.openssh.org に、
商用の ssh クライアントは http://www.ssh.com に見ることができます。
これを使用すれば、MySQL サーバーと MySQL クライアント
間の TCP/IP コネクションは全て暗号化されます。
MySQL システムを安全にするためには、次のことを考えるべきです:
other_user
にパスワードが設定されていない場合、
誰でも mysql -u other_user db_name
として簡単に他の人としてログインでき
ることを覚えてください。これは全てのクライアント/サーバアプリケーション
で一般的な振る舞いです。全てのユーザのパスワードは、
mysql_install_db
スクリプトを実行前に編集することで、または
MySQL root
ユーザだけは次のようにして変更することができます。
shell> mysql -u root mysql mysql> UPDATE user SET Password=PASSWORD('new_password') WHERE user='root';
root
ユーザーで実行しないでください。
FILE
権限を持つ任意のユーザが root
としてファイル(例えば、
~root/.bashrc
)を生成できるためとても危険です。これを防ぐために、
mysqld
は、--user=root
オプションで直接指定されない限り、
root
としての実行を拒否します。
mysqld
は任意のユーザで実行できます。
より安全にするため、新しく UNIX ユーザ mysql
を追加することもできます。
mysqld
を 他の Unix ユーザーで起動したとしても、
MySQL の user
テーブルの root
ユーザーの名前を変更する必要はありません。
なぜなら、 MySQL ユーザーの名前は Unix のユーザー名とはなんの関係もないからです。
root ユーザ名を変更する必要はありません。
mysqld
を他の UNIX ユーザで起動するために、mysql.server
編集してもよいでしょう。
通常、これは su
コマンドで行われます。
より詳しい情報は → 「21.8 一般ユーザで MySQL を動かす方法」節.
mysql.server
スクリプト内に UNIX root
ユーザーのためにパスワードを
書いた場合、このスクリプトは root
だけが読めるようにしなくては
なりません。
mysqld
を実行している UNIX ユーザだけが
読み込み/書き込み可能なことをチェックしてください。
mysqld
を root で
は実行しないでください。その目的用にユーザ名 mysql
を生成することを
考慮してください。
mysqladmin processlist
コマンドで実行されているクエリーの中身を見ることができます。
もし誰かが、UPDATE user SET password=PASSWORD('not_secure')
クエリーを
実行していたとして、それが見えてしまいます。
mysqld
は process 権限を持つユーザに対する特別な接続をリザーブします。
そのため、たとえ全ての通常接続が使われたとしても、MySQL root
ユーザだけは、
ログインでき、いろいろチェックできます。
mysqld
デーモンを実行している Unix ユーザーの権限で
ファイルシステム内のどこにでもファイルを書き込むことができます!
これを少し安全にするために、SELECT ... INTO OUTFILE
で作成される全てのファイルは
全員に読み込み可能で生成され、既存のファイルには上書きできません。
file 権限はサーバーを走らせている UNIX ユーザーがアクセスできる
全てのファイルを読むために使用されかもしれません。
例えば、 `/etc/passwd' をテーブルに取り込むために LOAD DATA
が
使用されると、 SELECT
でその内容が読めることになります。
mysqld
への --secure
オプションは原理上はホスト名を安
全にします。どんな場合でも、ワイルドカードを含んだホスト名を、許可テーブルに登録する
事は本当に注意深くすべきです!
mysqld
の
max_user_connections
変数を設定することで、これを行なうことができま
す。
mysqld
の起動オプション
mysqld
への次のオプションはネットワークのセキュリティに影響します:
--secure
gethostbyname()
から返される ip がオリジナルのホスト名に戻せるかど
うかをチェックします。これは、外の誰かが他のホストを真似てアクセスを得る
ことを難しくします。このオプションはいくつかの正しいホスト名チェックも追
加します。これは、時にチェックに長い時間がかかるため、MySQL バージョン 3.21
ではデフォルトではオフにされています。MySQL 3.22 ではこのオプションは
デフォルトで有効になっていますが、ホスト名をキャッシュするようになっています。
--skip-grant-tables
mysqladmin flush-privileges
か mysqladmin reload
を実行することで、
起動しているサーバーは特権システムを使用するようになります。)
--skip-name-resolve
Host
フィールドは IP アドレスか
localhost
でなければなりません。
--skip-networking
mysqld
への全ての接続は、
UNIX ソケットで行われます。MIT-pthreads は UNIX ソケットをサポートしない
ため、このオプションは MIT-pthreads を使用するシステム上では、うまく動きません。
--skip-show-database
SHOW DATABASE
コマンドは何も返しません。
--safe-show-database
SHOW DATABASE
はユーザがいくつかの権限を持つデータベースだけを返し
ます。
MySQL 特権システムの基本機能は、与えられたホストから接続する ユーザを認証すること、そしてデータベースに対する select, insert, update, delete 等の権限を与えることです。
拡張機能は匿名ユーザをもつ能力を含み、LOAD DATA INFILE
のような
MySQL 固有の機能を使用する許可を与えます。
MySQL によって使用されるユーザー名とパスワードの使用のされ方と、 UNIX, Windows で使用される方法とは、いくつか異なる点があります。
-u
か --user
スイッチで変更できます。
これは、全てのユーザに対しパスワードを設定しておかないと、
全くデータベースを安全にできないことを意味します。
もしパスワードを全ユーザーに設定しておかないと、そのユーザー名で認証なしにサーバーに接続できます。
PASSWORD()
と ENCRYPT()
関数の説明を参照 → 「7.4.12 その他の関数」節.
注意: パスワードが '暗号化' されて格納されていても、あなたの '暗号化' され
たパスワードを知ることで、MySQL サーバに接続するのには十分です!
MySQL クライアントプログラムは、共通の決まった引数を持ちます:
接続したいホスト名、接続ユーザー名、そしてパスワードです。
例えば、mysql
コマンドは以下のような引数を持ちます
(オプションの引数は `[' と `]' で囲まれている部分です)
shell> mysql [-h host_name] [-u user_name] [-pyour_pass]
-h
, -u
, -p
オプションは以下と等価です。
--host=host_name
, --user=user_name
, --password=your_pass
-p
とパスワードの間にはスペースがないことに注意
注意: コマンドラインにパスワードを与えるのは安全ではありません!
システムに入っている如何なるユーザーも ps auxww
のようなコマンドを
使用する事でパスワードを見付ける事ができます
「4.16.5 オプションファイル ( my.cnf
)」節参照.
mysql
コマンドはコマンドラインに引数がなければ接続にデフォルト値を用います。
localhost
, ユーザー名は UNIX のログイン名です。
-p
が指定されていなければパスワードは与えられません)
UNIX のログインユーザーが joe
の場合、以下のコマンドは等価です:
shell> mysql -h localhost -u joe shell> mysql -h localhost shell> mysql -u joe shell> mysql
他の MySQL クライアントも同じように動作します。
UNIX システムでは、ある値をデフォルト値にして接続に使用することができます。 そうすることにそり、毎回毎回コマンドラインに引数を与えなくてすむようになります:
[client]
セクションに接続用のパラメターを記述できます。
その記述は以下のようです:
[client] host=host_name user=user_name password=your_pass「4.16.5 オプションファイル (
my.cnf
)」節参照.
MYSQL_HOST
環境変数を使用します。
MySQL のユーザー名は USER
(これは Windows のみ) に設定された値を使用します。
パスワードは MYSQL_PWD
環境変数を見ますが、これは危険です。(次の節参照)
「A Environment Variables」節参照.
自分のパスワードを他人にさらけ出すのは勧められることではありません。 それぞれの方法に於ける危険度に応じ、以下に示す方法でクライアントプログラムに あなたのパスワードをあたえて走らせることができます:
mysql.user
テーブルへのアクセスを与えてはいけません。
ユーザの暗号化されたパスワード知ることで、そのユーザとしてログインが可能に
なります。パスワードは、使用される本当のパスワードを見ることができないよう
に、スクランブルされているだけです(同じようなパスワードを他のアプリケーショ
ンでたまたま使用する場合のため)。
-pyour_pass
か --password=your_pass
オプションをコマンドラインで使用します。
これは便利ですが安全ではありません。あなたのパスワードは (ps
コマンドのような)
システムの状態を見るコマンドにて見ることができます。
(MySQL クライアントは初期化過程においてコマンドラインの引数をゼロで上書きして
見せないようにしているのですが、瞬間ですが値が見えてしまうのです)
-p
あるいは --password
オプションを your_pass
を与えないで使用します。
この場合、クライアントプログラムはターミナルを通じてパスワードの入力を促してきます:
shell> mysql -u user_name -p Enter password: ********`*' 文字はパスワードを表しています。 クライアントはあなたの入力したパスワードを `*' 文字で端末に返していますので、 画面をのぞき込まれたとしてもパスワードはわかりません。 これはコマンドラインにパスワードを指定するより安全です。他のユーザーには見えませんから。 しかしこのパスワードを毎回入れる方法は対話式のプログラムを実行する場合だけに使用できる手です。 もし非対話式のスクリプトからクライアントプログラムを起動したい場合、 パスワードを端末から入れる機会がありません。 On some systems, you may even find that the first line of your script is read and interpreted (incorrectly) as your password!
[client]
セクションに、以下のような形で書きます:
[client] password=your_passもし `.my.cnf' ファイルにパスワードを書いているなら、ファイルはグループや その他のユーザーが読み書きできないようにすべきです。ファイルのモードは
400
か 600
にします。
「4.16.5 オプションファイル ( my.cnf
)」節参照.
MYSQL_PWD
環境変数にパスワードを設定することもできます。しかしこの方法は
きわめて危険であるので、使用すべきではありません。
ps
のあるバージョンでは、実行中のプロセスの環境変数を表示するオプションがあります;
もし MYSQL_PWD
環境変数にパスワードを設定していると全てべたで見れます。
このバージョンの ps
を持っていないシステムだとしても、プロセスの環境変数を調べる
方法がないとはいえないので、この方法はあまりいい方法ではありません。
「A Environment Variables」節参照.
まとめると、より安全な方法は、 パスワードプロンプトを返すクライアントプログラムを実行するか、 適切なパーミッションをかけた `.my.cnf' ファイルにパスワードを書くか です。
権限の設定は mysql
データベースの user
, db
, host
,
tables_priv
, columns_priv
で行います。
(mysql
はデータベースの名前です)
MySQL サーバーは、サーバーの起動時か
「6.11 いつ権限の変更が反映されるか」節 で説明されている方法により、
これらのテーブルから権限の設定を読み込みます。
MySQL が提供する権限の名称は, 本マニュアルでは以下の表の名称を用います。 この表の項目名がそれぞれの許可される権限とその説明に対応しています:
Privilege | Column | Context |
select | Select_priv | tables |
insert | Insert_priv | tables |
update | Update_priv | tables |
delete | Delete_priv | tables |
index | Index_priv | tables |
alter | Alter_priv | tables |
create | Create_priv | databases, tables or indexes |
drop | Drop_priv | databases or tables |
grant | Grant_priv | databases or tables |
references | References_priv | databases or tables |
reload | Reload_priv | server administration |
shutdown | Shutdown_priv | server administration |
process | Process_priv | server administration |
file | File_priv | file access on server |
select, insert, update, delete の権限は、 存在しているデータベースのテーブルに対して許可されます。
もしテーブルから行を取り出すだけなら、SELECT
構文を実行するためには
select 権限だけあればかまいません。
だけでなく、サーバーのどのデータベースにアクセスを許可されていない場合でも、
ある種の SELECT
は実行することができます。
例えば、簡単な計算を mysql
クライアントで行う場合です:
mysql> SELECT 1+1; mysql> SELECT PI()*2;
index 権限はインデックスの作成と破棄(削除)を許可します。
alter 権限は ALTER TABLE
の実行を許可します。
create と drop 権限は、新しいデータベースやテーブルの作成、 あるいは既に存在するデータベース、テーブルの破棄(削除)を許可します。
注意: mysql
データベースに登録されているユーザーに drop 権限を与えると、
そのユーザーは MySQL のアクセス権限が格納されているデータベースを破棄できます!
grant 権限は、あなたが他のユーザーに対して自分の権限を持たせる事を許可します。
file の権限を与えると、LOAD DATA INFILE
と SELECT ... INTO OUTFILE
構文を使用して、サーバーのファイルを読み書きする事ができます。
MySQL サーバーがが読み書きできるファイルに対して、この権限が与えられたユーザーはファイルを読み書きできます。
残りの権限はアドミン操作に関する許可で、mysqladmin
コマンドを使用して実行します。
次の表に mysqladmin
コマンドのどれが、どの権限に対応しているかを示します:
Privilege | Commands permitted to privilege holders |
reload | reload , refresh ,
flush-privileges , flush-hosts , flush-logs , flush-tables
|
shutdown | shutdown
|
process | processlist , kill
|
reload
コマンドはサーバーに権限の設定を再読込させるように伝えます。
refresh
コマンドは全てのテーブルをフラッシュし、ログファイルを開き直します。
flush-privileges
は reload
と同義です。
その他の flush-*
コマンドは refresh
の動作とよく似ていますが、
適用範囲を絞っており、ちょっとした場合に有効です。
例えば、ログファイルだけをフラッシュしたい場合、
refresh
を行うよりも flush-logs
がいいです。
shutdown
コマンドは、サーバーをシャットダウンします。
processlist
コマンドはサーバーが実行しているスレッドの情報を表示します。
kill
コマンドはサーバーのスレッドをkillします。
自分のスレッドは常に表示、killできますが、他人のスレッドをそうするには process 権限が必要です。 「7.27 KILL
構文」節参照.
ある権限を欲しがるユーザーだけにその権限を許可するのはよい考えですが、 権限を与えるときには、特定の事項を熟知していなければなりません:
grant
権限を入れ換えることができます。
SELECT
文でアクセスできます。
これはサーバに置かれているすべてのデータベースの内容を含みます!
mysql
データベースに対しての権限は、パスワードの変更と他の権限の設定を変更時に使用されます。
(パスワードは暗号化されて登録されており、悪意のあるユーザーでも
単純に読むことはできません).
mysql.user
のパスワードフィールドにアクセスできれば、それを使用して
MySQL サーバに与えられたユーザでログインすることができます。(十分
な権限があれば、同じユーザが別のものにパスワードを置き換えることもできます。
)
以下は MySQL の特権システムで行うものではありません:
MySQL の特権システムは、全てのユーザーが与えられた許可の範囲内で動く事を保証します。 MySQL サーバーに接続するとき、本人の身元は、接続元のホスト と 接続に使用するユーザー名 によって確認されます。 このシステムは、あなたの身元とあなたが要求することが何か によって、権限を与えます。
MySQL はあなたのホスト名とユーザー名の両方をあわせてチェックします。
これはインターネット上に同じ名前のユーザーがどこかにいるかもしれないということからそうしています。
例えば、whitehouse.gov
から接続してきた bill
と、
microsoft.com
から接続してきた bill
は同一人物である必要はありません。
MySQL はこの違うホストから接続してきた同名のユーザーを以下のようにして扱います:
whitehouse.gov
から接続した bill
にある許可をあたえ、
それとは違う許可を microsoft.com
から接続してきた bill
に与えます。
MySQL のアクセスコントロールは以下の二つからなります:
サーバーは mysql
データベースの user
, db
, host
3つのテーブルから、
この2つのアクセス制限を決定します。
このテーブルのフィールドは以下のようになっています:
Table name | user | db | host
|
Scope fields | Host | Host | Host
|
User | Db | Db
| |
Password | User | ||
Privilege fields | Select_priv | Select_priv | Select_priv
|
Insert_priv | Insert_priv | Insert_priv
| |
Update_priv | Update_priv | Update_priv
| |
Delete_priv | Delete_priv | Delete_priv
| |
Index_priv | Index_priv | Index_priv
| |
Alter_priv | Alter_priv | Alter_priv
| |
Create_priv | Create_priv | Create_priv
| |
Drop_priv | Drop_priv | Drop_priv
| |
Grant_priv | Grant_priv | Grant_priv
| |
References_priv | |||
Reload_priv | |||
Shutdown_priv | |||
Process_priv | |||
File_priv |
アクセスコントロールの第2段階(要求承認)のために、サーバーはこれら 3 つの
テーブルによって決められた許可を基本としますが、もしテーブルに対する要求で
あるならば、tables_priv
と columns_priv
テーブルを
さらに調べます。これらのテーブルのフィールドは以下のようになっています:
Table name | tables_priv | columns_priv
|
Scope fields | Host | Host
|
Db | Db
| |
User | User
| |
Table_name | Table_name
| |
Column_name
| ||
Privilege fields | Table_priv | Type
|
Column_priv | ||
Other fields | Timestamp | Timestamp
|
Grantor |
テーブルの各フィールドを分類すると、2種類にわかれます: 適用範囲を指定するフィールド(以下 スコープフィールド)と許可を定義するフィールド(以下 権限フィールド)です。
スコープフィールドは、権限テーブルの登録ごとに、その適用範囲を決めます。
例えば、 user
テーブルの Host
と User
に
'thomas.loc.gov'
と 'bob'
が登録されている場合、
サーバーへの接続は ホスト thomas.loc.gov
から来た 'bob'
に許可されます。
同様に、db
テーブルの Host
, User
, Db
に
'thomas.loc.gov'
, 'bob'
, 'reports'
が登録されていると、
ホスト thomas.loc.gov
から来た bob
に対し reports
データベースへの接続が許されます。
tables_priv
と columns_priv
テーブルは、
テーブルか、テーブルとフィールドを対にしたスコープフィールドを含みます。
アクセスのチェックは、Host
の値はケース非依存で比較されます。
User
, Password
, Db
, Table_name
の値はケース依存で比較されます。
Column_name
の値は MySQL バージョン 3.22.12 以上ではケース非依存で比較されます。
(バージョン 3.22.11 までは ケース依存です)
権限フィールドは、テーブルに登録されることにより有効になった許可をしめし、 これはどの操作が実行できるかを示します。 サーバーは許可テーブルの情報をユーザーの権限を得るためにまとめます。 このユーザーの権限許可を割り出す方法は 「6.10 Access control, Stage 2: 要求の承認」節 に述べておきます。
スコープフィールドは文字で定義され、デフォルト値は空文字になっています:
Field name | Type | |
Host | CHAR(60)
| |
User | CHAR(16)
| |
Password | CHAR(16)
| |
Db | CHAR(64) | (CHAR(60) for the
tables_priv and columns_priv tables)
|
Table_name | CHAR(60)
| |
Column_name | CHAR(60)
|
user
, db
, host
テーブルでは、
全ての権限フィールドは ENUM('N','Y')
で定義されます。
この値は 'N'
か 'Y'
のどちらかで、デフォルト値は 'N'
です。
tables_priv
と columns_priv
テーブルでは、
権限フィールドは SET
フィールドとして定義されます:
Table name | Field name | Possible set elements |
tables_priv | Table_priv | 'Select', 'Insert',
'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter'
|
tables_priv | Column_priv | 'Select', 'Insert',
'Update', 'References'
|
columns_priv | column_priv | 'Select', 'Insert',
'Update', 'References'
|
サーバーは以下のように許可テーブルを使用します:
user
テーブルのスコープフィールドは、接続要求を受け入れるか拒否するかを決定します。
許可された接続について、user
テーブルで与えられたすべての権限は、ユー
ザのグローバル(スーパーユーザ)権限を示します。この権限はサーバ上の
すべての データベースに適用されます。
(訳注:
例えば、user
テーブル の権限を 'Y'
にした場合、
どんなに db
テーブルや host
テーブルで権限を 'N'
にしたとしても
権限は 'Y'
のままである。
ようは user
テーブルの権限許可 'Y'
が全てに反映されてしまうという事。
user
テーブルには最低限の許可を与えるようにし、
db
テーブルや host
テーブルで、それぞれの権限許可を定義する方が無難。
)
db
と host
テーブルは一緒に使用されます:
db
テーブルのスコープフィールドはどのホストからどのデータベースのアクセスできるかを決定します。
権限フィールドは、どういった操作ができるか定義します。
host
テーブルは、db
テーブルの登録をいくつかのホストに与えたい時に、
db
テーブルの拡張として使用されます。
例えば、ネットワーク上の限定したマシンからデータベースを使用したい場合、
db
テーブルの Host
の値は空にしておきます。
そして host
テーブルにそれぞれのホストについての登録を行います。
この機構は、 「6.10 Access control, Stage 2: 要求の承認」節 で詳細に述べられています。
tables_priv
と columns_priv
テーブルは db
テーブルに似ていますが、
それらはより細かく定義できます;
データベースレベルではなく、テーブルとフィールドのレベルで与えます。
管理者権限 (reload, shutdown,など) は user
テーブルにだけ定義するように。
これは、管理者操作はデータベースではなくサーバーへの操作であり、
他の許可テーブルにある必要がないからです。
またこうしておくと、管理者操作の許可は、user
テーブルの定義だけを
見ればわかるようになります。
file 操作の権限は user
テーブルにだけ定義するように。
これは管理者操作ではありませんが、アクセスしているデータベースにかかわらず、
サーバー内のファイルを読み書きできるのです。
mysqld
サーバーは起動時にこれらのテーブルを読み込みます。
許可テーブルの変更を反映させる方法はこちらを参照のこと → 「6.11 いつ権限の変更が反映されるか」節
これらのテーブルの登録を変更した場合、思ったとおりの権限状態になっている事を確認することはいいことです。
問題の解決には, 「6.15 何故 Access denied
エラーになるのか」節. セキュリティに関するアドバイスは
「6.2 MySQL をクラッカーに対して安全にする方法」節.
便利なツールとして mysqlaccess
スクリプト( Yves Carlier 作)が MySQL の配布に含まれています。
mysqlaccess
を --help
オプションで起動するとヘルプが表示されます。
mysqlaccess
は user
,db
and host
テーブルだけしか
検査しません。テーブルレベルの権限、フィールドレベルの権限は調べません。
MySQL サーバーに接続すると、あなたがパスワード認証して接続していようがいまいが、 サーバーはあなたの身元により接続の許可拒否を行います。 もし身元が一致しない場合接続を拒否し、接続許可した場合、サーバーは stage 2 へと進み、要求を待ちます。
身元は二つのものに基づいて確認されます:
身元の確認は user
テーブルのスコープフィールド(Host
, User
, Password
) を使用して行います。
サーバーは user
テーブルの登録に一致しているホスト名とユーザー名に限り接続を許可し、その後、パスワードを要求します。
user
テーブルのスコープフィールドの登録は以下のようになります:
Host
の値はホスト名か IP アドレスか 'localhost'
(ローカルホスト) です。
Host
にはワイルドカード文字 `%' と `_' を使用できます。
Host
に '%'
を設定すると、全てのホストにマッチします。
Host
値は、権限が host
テーブル内の与えられたホスト名に
適合するエントリと AND されることを意味します。次の章にこれについての詳し
い情報を見つけられます。
Host
値には、何
ビットがネットワークアドレスに使用されるかを示すネットマスクを記述すること
ができます。例えば:
GRANT ALL PRIVILEGES on db.* to david@'192.58.197.0/255.255.255.0';これは、次が真になる IP からの接続をすべて許可します:
user_ip & netmask = host_ip.上記の例では、192.58.197.0~192.58.197.255 のすべての IP が MySQL サーバに接続できます。
User
フィールドには設定できませんが、
User
フィールドをブランク(空)にすることはできます。ブランクは全ての名前にマッチします。
これはユーザー名がない状態で接続してきたものに適用され、
クライアントがユーザー名を明記しない限り、匿名ユーザー(名前がブランク)として扱われます。
全てのアクセスのチェックにブランクのユーザー名が使用される事を意味します。(that is, during Stage 2)
Password
フィールドは空にできます。その場合、パスワードなして接続できることになります。
非ブランクの Password
値はパスワードを暗号化したものです。
MySQL はだれもが見れるようにパスワードを平文では保存しません。
接続を試みようとしているユーザーのパスワードも、(PASSWORD()
関数で)
暗号化されます。
それから、暗号化パスワードは、クライアント/サーバがパスワードが正しいかチェッ
クする時に使用されます(This is done without the encrypted password ever
traveling over the connection)。注意: MySQL では、暗号化パスワー
ドが本当のパスワードです。そのため、それへのアクセスを誰にも与えるべきでは
ありません! 特に、一般ユーザにはmysql
データベース内のテーブルの読
み取り権を与えないでください!
以下の表は、接続要求に対して与える、
user
テーブルの Host
と User
の設定例です:
Host value | User value | Connections matched by entry |
'thomas.loc.gov' | 'fred' | fred , thomas.loc.gov から接続
|
'thomas.loc.gov' | '' | thomas.loc.gov から接続してくる全てのユーザー
|
'%' | 'fred' | fred , 全てのホストから接続
|
'%' | '' | 全てのホストから接続してくる全ユーザー |
'%.loc.gov' | 'fred' | fred , loc.gov ドメイン内の全てのホストからの接続
|
'x.y.%' | 'fred' | fred , x.y.net , x.y.com ,x.y.edu , などからの接続. (あまり有効な使い方ではないです)
|
'144.155.166.177' | 'fred' | fred , IP address が 144.155.166.177 のホストからの接続
|
'144.155.166.%' | 'fred' | fred , 144.155.166 class C subnet 内の全てのホストからの接続
|
'144.155.166.0/255.255.255.0' | 'fred' | 上の例と同じ |
Host
に IP のワイルドカード(例えば '144.155.166.%'
は
サブネットの全てのホストにマッチ) を使用することができます。
が、この場合、 144.155.166.somewhere.com
というホスト名で
だれかが接続しようとしてくるかもしれません。
このような攻撃に対し、MySQL は数字やドットで始まるホスト名を拒否しています。
もし 1.2.foo.com
のような名前のホストを持っている場合、
許可テーブルの Host
には絶対にマッチしません。
IPアドレスのみ、IP のワイルドカードにマッチする事になります。
サーバーに来る接続は、user
テーブル内の登録に1つ以上
マッチするかもしれません。
例えば, thomas.loc.gov
の fred
からの接続は、上に示された
登録のうちのいくつかにマッチするでしょう。
サーバーは、複数の登録にマッチした場合、どのようにしてその中から
使用する登録を選ぶのでしょう?
サーバーは起動後に user
テーブルをソートし、並び換えられた順に
登録を検索することにより、この問題を解決します。
最初にマッチした登録が使用されます。
user
テーブルが以下のようにソートされていた場合:
+-----------+----------+- | Host | User | ... +-----------+----------+- | % | root | ... | % | jeffrey | ... | localhost | root | ... | localhost | | ... +-----------+----------+-
サーバーがこのテーブルを読むと、Host
に値が最も確実に特定できるホストを指定しているエントリを、最初に参照します。
(Host
項の '%'
は ``すべてのホスト'' を意味し、ホスト名をはっきりと特定しているものではありません)
Host
の値が同じエントリがあった場合、もっとも明確に User
の値がユーザーを指定しているエントリを最初に参照します。(User
の値が空の場合、``だれでも'' を意味します)
この結果、user
テーブルは以下のようにソートされます:
+-----------+----------+- | Host | User | ... +-----------+----------+- | localhost | root | ... | localhost | | ... | % | jeffrey | ... | % | root | ... +-----------+----------+-
接続が試みられた場合、サーバーは並び換えられた登録を探し、最初に見つけたものを
使用します。
'localhost'
の jeffrey
からの接続は、まず最初に Host
に localhost
を設定しているエントリにマッチします。
ユーザー名が空のエントリは、ホスト名とユーザー名の両方を指定した接続にもマッチします。
( '%'/'jeffrey'
エントリもマッチします。が、これは最初にはマッチしません。)
もう一例。user
が以下の設定と仮定します:
+----------------+----------+- | Host | User | ... +----------------+----------+- | % | jeffrey | ... | thomas.loc.gov | | ... +----------------+----------+-
これは次のようにソートされます:
+----------------+----------+- | Host | User | ... +----------------+----------+- | thomas.loc.gov | | ... | % | jeffrey | ... +----------------+----------+-
thomas.loc.gov
の jeffrey
からの接続は、最初のエントリにマッチし、
whitehouse.gov
の jeffrey
からの接続は、二つ目のエントリにマッチします。
最初にサーバが,接続のためのマッチを見つけるのを試みるとき,共通の誤解は与えられた ユーザ名に明らかにそのユーザを命名するすべてのエントリが使用されると思うことです. これは単に本当ではありません. jeffreyによるthomas.loc.govからの接続が最初に エントリによってユーザ分野値として‘jeffrey'を含まないいずれのエントリによってる合わ せられる場合,前の例はこれをユーザ名なしで例示します!
よくある考え違いは、ユーザー名を与えた場合、
サーバーが接続にマッチするものを探す際に、
そのユーザーが登録されている全てのルールが、
最初に使用されるだろうと考えることです。これは正しくありません。
前の例でこれを示しましたが、thomas.loc.gov
の jeffrey
からの接続が
最初にマッチするのは、 User
フィールドの値が 'jeffrey'
に
なっているエントリではなく、ユーザー名なし(=だれでも) のエントリの方が
先にマッチします!
もしサーバーへの接続がうまく行かない場合、 user
テーブルを表示し、
マニュアルでソートしてみて、どのエントリに最初にマッチするか探してください。
一度接続か確立されると、サーバーはステージ2に移ります。
このステージでは、サーバーはこの接続から来るそれぞれの要求が許可されているかどうかをチェックします。
チェックは実行しようとしている操作のタイプにより行います。
その操作が許可テーブルのどの権限フィールドに当てはまるかを見ます。
これら権限は user
, db
,host
, tables_priv
か columns_priv
テーブルより導出されます。
許可テーブルは GRANT
コマンドで操作します。
「7.35 GRANT
と REVOKE
構文」節参照.
(You may find it helpful to refer to the table shown earlier that lists
the fields present in each of the grant tables; see 「6.8 特権システムはどのように動くか?」節.)
user
テーブルは全てに対して基本となる権限をユーザーに割り当てます。
たとえカレントのデータベースが許可を与えていなくても、user
テーブルの設定が有効になります。
例えば、user
テーブルで delete を許可した場合、
サーバーにあるどんなデータベースの行も削除できるのです!
いうならば、user
テーブルの権限はスーパーユーザーの権限と言ってもいいでしょう。
この権限はスーパーユーザー(サーバーやデーターベース管理者)のみに与えておく事が賢明です。
他のユーザーは、user
テーブルの権限の設定を 'N'
のままにしておくべきですし、
また、db
テーブルと host
テーブルを利用して、
データベースを指定した上でユーザーに権限を許可すべきです。
db
テーブルと host
テーブルは特定のデータベースに対する権限許可を行います。
スコープフィールドの値は次のように記述されます:
Db
テーブルと Host
フィールドだけに使用できます。
'%'
Host
値は ``あらゆるホスト'' を意味します。
db
テーブルの Host
に空を設定すると、``さらに host
テーブルに許可情報を探しにいく''
となります。
'%'
か 空値を Host
テーブルに設定すると、それは ``あらゆるホスト'' となります。
'%'
か 空値を host
テーブルの Db
フィールドに設定すると、
それは ``あらゆるデータベース'' となります。
User
を空値にすると、匿名ユーザーにマッチします。
サーバー起動時に、db
テーブルと host
テーブルはサーバーに読み込まれます。
(user
テーブルもこの時に同時に読まれます)
db
テーブルは Host
, Db
, User
のフィールドでソートされ、
host
テーブルは Host
, Db
フィールドでソートされます。
user
テーブルは、一番特定できるエントリを最初に、一番特定できないものを最後にソートします。
サーバーはソートされたものの中から、最初にマッチしたものを使用します。
tables_priv
と columns_priv
テーブルは、
特定のテーブルとフィールドに対する権限を許可します。
スコープフィールドの値は、いかにそって記述されます:
Host
フィールドに使用できます。
Host
値を '%'
かブランクにすると、
``any host.'' を意味します。
Db
, Table_name
, Column_name
フィールドはどのテーブルにも
ワイルドカードやブランクは使用できません。
tables_priv
と columns_priv
テーブルは
Host
, Db
, User
フィールドで並び換えられます。
これは db
テーブルのソートに似ていますが、 Host
フィールドだけが
ワイルドカードを含むので、ソートはより単純なものになります。
この要求の承認は次のようにして行います。 もしアクセス承認を決定する部分のソースコードを理解できるなら、 ちょっと変わったアルゴリズムで承認の決定を行っている事に気づくでしょう。
管理者の要求(shutdown, reload, etc.)については、サーバーは
user
テーブルだけを参照します。(user
テーブルだけが管理者権限のフィールドを持つ)。
エントリに許可登録されている操作は受け入れられ、それ以外は拒否されます。
例えば、mysqladmin shutdown
を実行しようとしても、user
テーブルの shutdown 権限が許されていなければ実行できません。この時、db
と host
テーブルはチェックされません。(これらのテーブルには Shutdown_priv
フィールドが無いからです)
データベースへの要求 (insert, update, etc.) において、サーバーはまず最初に、ユーザーのグローバルな権限(スーパーユーザー)を user
の中から探しだします。
もし許可が与えられていれば、アクセスは成功します。
user
テーブルのグローバルな権限の設定が不十分であるなら、サーバーはユーザーのデータベースに対する権限を db
テーブルと host
テーブルから決定します:
db
テーブルの Host
,Db
,User
フィールドを参照します。
Host
と User
フィールドはユーザーの接続時のホスト名と MySQL ユーザー名にマッチします。
Db
フィールドはユーザーがアクセスしたいデータベース名にマッチします。
Host
と User
にマッチするものが無かった場合、アクセスは拒否されます。
db
テーブル内の Host
フィールドが空でないエントリにマッチした場合、
ユーザーの指定されているデータベースに対する権限が定義されます。
Host
フィールドが空値の db
テーブルのエントリにマッチした場合、
どのホストがそのデータベースへアクセスできるかを host
テーブルから探し出します。
この場合、host
テーブル の Host
, Db
フィールドとマッチするものを探し出します。
host
テーブルにエントリがなかった場合、アクセスは拒否されます。
もしマッチすると、ユーザーの特定データベースに対する権限は、
host
テーブルと db
テーブル両方にまたがった権限から割り出されます。
いうならば両方とも 'Y'
である権限。
(この方法を使用すると、まず db
テーブルのエントリに大まかな権限を設定しておき、
それから host
テーブルのエントリを使用して、ホスト情報もとに権限を限定していくという事ができます)
特定データベースに対する権限が db
テーブルと host
テーブルのエントリから決定された後、
サーバーはその割り出された権限に対し、user
テーブルて設定されている権限を加えます。
この結果から得られた権限にマッチした要求は受け入れられます。
そうでなければ、サーバーはユーザーのテーブル、フィールドに対する許可を、
tables_priv
と columns_priv
内に探します。
アクセスはこの結果により、許可、拒否されます。
先のユーザーの権限が計算される方法の記述は、boolean 表記で示すならば、 以下のようになるでしょう:
global privileges OR (database privileges AND host privileges) OR table privileges OR column privileges
これは少し分かりにくいかもしれません。もしグローバルの user
エントリ
権限許可が、リクエストされたオペレーションには不十分だと最初に分かった際、
サーバーがこれらの権限を database-, table-, column-固有の権限の
後に、なぜ、追加してしまうのか。
その理由は、リクエストが1個以上の権限を要求するだろうということです。
例えば、もしあなたが INSERT ... SELECT
構文を実行するなら、
あなたには insert と select 許可が必要です。
あなたの権限が、 user
テーブルエントリで一つの権限が許可され、
db
テーブルで、そのほかの権限が許可されていたとします。
この場合、あなたは、そのリクエストを実行するために、必要な権限を持っています。
しかし、サーバーはどちらのテーブル、それ単体からでは、権限を得ることが出来ません。
権限は、両方のエントリーを合わせなくてはならないのです。
host
テーブルは ``安全な'' ホストのリストを維持するために使用できます。
TcX では、host
テーブルにはローカルネット上の全てのホストが登録されています。
これらのホストは全ての権限が許可されています。
逆に host
table で安全ではないホストを指定することもできます。
public.your.domain
というマシンが安全ではない、公開されている場所にあるとします。
その場合以下のようにして、その公開マシン以外のネットワーク上のホストに対して、アクセスを許可することができます:
+--------------------+----+- | Host | Db | ... +--------------------+----+- | public.your.domain | % | ... (all privileges set to 'N') | %.your.domain | % | ... (all privileges set to 'Y') +--------------------+----+-
権限のテーブル設定は、あなたの思い通りに許可が得られるのか、
常に(mysqlaccess
等を使用して)チェックすべきです。
mysqld
の起動時、全ての許可テーブルはメモリーに読み込まれ、
この時点で有効になります。
GRANT
, REVOKE
, SET PASSWORD
を使用して許可テーブルを
変更した場合、直にサーバに通知されます。
もし手動で許可テーブルを変更した場合(INSERT
, UPDATE
などで)、
FLUSH PRIVILEGES
構文か mysqladmin flush-privileges
コマンド
か mysqladmin reload
コマンドを実行して、
サーバーに許可テーブルの読み込みを指示しなければなりません。
そうしなければ、サーバーを再起動させるまで、変更は反映されません。
権限テーブルを手で変更して、権限のリロードを忘れた場合、変更が何も行なわれ
ないように見えるのがなぜかと不思議に思うでしょう!
サーバーが許可テーブルの変更を通知した場合、既に接続している クライアントは、以下のような影響を受けます:
USE db_name
コマンド以降から
有効になります。
グローバル権限とパスワードの変更は、次のクライアントの接続時から反映されます。
MySQL インストール後、scripts/mysql_install_db
を実行して権限のアクセス許可を初期化します。
「4.7.1 素早いインストールの概要」節参照.
mysql_install_db
スクリプトは mysqld
サーバーを起動し、
以下のように権限を初期化してテーブルに登録します:
root
ユーザーはスーパーユーザーとして登録され、
全ての操作ができます。
localhostからしか接続できません。
注意:
root
のパスワードの初期値は空です。
全ての人が パスワードなしで root
になれ、全ての権限許可を得ることができます。
'test'
あるいは 'test_'
で名前がはじまっているデータベースに対して、
匿名ユーザーでもなんでもできるように許可が与えられます。
これは ローカルホストからの全てのユーザーは パスワード無しで接続ができ、
匿名ユーザーとして扱われるということです。
mysqladmin shutdown
や mysqladmin processlist
を実行できません。
注意: デフォルトの権限は Windows では違います。 「4.13.4 Windows 上で MySQL を実行」節参照.
初期インストールの状態ではかなりアクセスが解放されているので、
インストール後最初にすることは、MySQL root
ユーザーにパスワードを設定することです。
以下のようにします(パスワードは PASSWORD()
関数を使用することをお忘れなく):
shell> mysql -u root mysql mysql> UPDATE user SET Password=PASSWORD('new_password') WHERE user='root'; mysql> FLUSH PRIVILEGES;
MySQL バージョン 3.22 以上では、SET PASSWORD
構文も使用できます:
shell> mysql -u root mysql mysql> SET PASSWORD FOR root=PASSWORD('new_password');
password をセットする他の方法として、mysqladmin
コマンドも使用できます:
shell> mysqladmin -u root password new_password
mysql データベースに書き込み/更新アクセスのあるユーザだけが他のユーザのパ
スワードを変更できます。すべての通常のユーザ(匿名ユーザ以外)は、上記のコマ
ンドか、または SET PASSWORD=PASSWORD('new password')
で、自分のパス
ワードだけを変更できます。
もし最初の方法で user
テーブルのパスワードを直接更新したなら、
サーバーに許可テーブルの再読み込みを行わせなければなりません(FLUSH PRIVILEGES
を使用して)。
一度 root
のパスワードを設定したなら、root
でサーバーに接続する場合は
常にパスワードを与えなければなりません。
追加設定やテストをしているためパスワードを入れたくない場合、
root
パスワードをブランクのままにしておこうと考えるかも知れませんが、
実稼働させる前には必ず設定してください。
どのようにデフォルトの権限を設定しているか、scripts/mysql_install_db
見てみてください。
これは他のユーザーを設定するときに使えるでしょう。
もし権限の初期状態を違うものにして初期化したいなら、
mysql_install_db
を実行する前に編集してもよいでしょう。
もしテーブルを完全に作り直したいなら、mysql
データベースのディレクトリに存在する
全ての `*.frm', `*.MYI', `*.MYD' ファイルを削除します。
(このディレクトリーはデータベースディレクトリーの下に mysql
という名前で存在します。
mysqld --help
とすればデータベースのディレクトリーが表示されます。)
そして好みの許可状態に mysql_install_db
を編集してから実行します。
注意: MySQL 3.22.10 以前のバージョンでは,
`*.frm' ファイルを消してはいけません. もしうっかり消してしまった場合、
mysql_install_db
を実行する前に、 MySQL 配布からコピーしなおさ
なくてはなりません。
ユーザーは2つの違った方法で追加できます:
GRANT
構文を使用して行う方法と、
MySQL の許可テーブルを直接操作する方法とです。
GRANT
構文の使用をお勧めします。
以下の例では、いかにして mysql
クライアントを使用して新規にユーザーを登録するかを示します。
以下の例では、権限は前節で述べたデフォルト値になっているとします。
よって変更を行うためには、あなたは mysqld
が走っているマシン上にログインしていなくてはなりませんし、
かつ、MySQL root
ユーザーで接続していなければなりません。
さらに MySQL root
ユーザーには
mysql
データベースに対して insert 権限を持ち、
reload のアドミニストレーター権限を持っていなければなりません。
もし root
ユーザーのパスワードを変えていたならば、
mysql
コマンドにパスワード指定を与えなくてはなりません。
shell> mysql --user=root mysql mysql> GRANT ALL PRIVILEGES ON *.* TO monty@localhost IDENTIFIED BY 'some_pass' WITH GRANT OPTION; mysql> GRANT ALL PRIVILEGES ON *.* TO monty@"%" IDENTIFIED BY 'some_pass' WITH GRANT OPTION; mysql> GRANT RELOAD,PROCESS ON *.* TO admin@localhost; mysql> GRANT USAGE ON *.* TO dummy@localhost;
これら GRANT
構文では3つの新しいユーザを作ります:
monty
'some_pass'
を
使用する必要があります。
monty@localhost
と monty@"%"
の両方に GRANT
構文を
発行しなくてはならない事に注意してください。
もし localhost
からの許可をした登録がないと、localhost
から接続した時、
mysql_install_db
が自動で作成した localhost
への匿名ユーザーが優先されます。
なぜなら、 Host
フィールドの値が(ブランクやワールドカード以外に)明記されており、
許可登録が MySQL 内部でソートされる時に順番が上にソートされるからです。
admin
localhost
からパスワードなしで接続できますが、reload
, process
の使用だけが許されます。
これは、mysqladmin reload
, mysqladmin refresh
, mysqladmin flush-*
そして
mysqladmin processlist
コマンドの実行がこのユーザーに許可されます。
データベースへのアクセスは許可されていません。
しかしこれは後でテーブル GRANT
構文を発行すれば、
個々のデータベースへのアクセス権限が設定できます。
dummy
'N'
に設定されます。
USAGE
権限は権限無しユーザーの設定を許可する事になります。
これは、特定データーベースに対しての許可を後から与える事を想定しています。
同じアクセス許可を INSERT
構文を使用して直接設定できます。
サーバーに許可テーブルの再読み込みを指示します:
shell> mysql --user=root mysql mysql> 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'); 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;
MySQL のバージョンにより、上の 'Y'
の数が違う事に注意してください。
(3.22.11 以前のバージョンでは項目数が少なくなります).
admin
ユーザーを登録で使用している INSERT
の拡張は
バージョン 3.22.11 以上で可能です。
スーパーユーザーを定義するためには、user
テーブルの許可フィールドを
'Y'
にするだけでかまいません。
db
や host
テーブルに登録は必要無いのです。
user
テーブルの許可フィールドは最後の INSERT
文で(dummy
ユーザーのために)
は設定されていません。これらのフィールドはデフォルト値の 'N'
になります。
これは GRANT USAGE
が行うのと同じものです。
以下は、localhost
, server.domain
, whitehouse.gov
から接続が可能な
custom
ユーザーの追加例です。
custom
ユーザーは bankaccount
データーベースには localhost
からの接続のみを許可され、
expenses
データベースには whitehouse.gov
からのみ接続が許可され、
customer
データベースには全てのホストから接続できます。
custom
ユーザーは、 stupid
というパスワードを全てのホストで使用したいとします。
このユーザーの許可を GRANT
構文で定義するには、以下のようにします:
shell> mysql --user=root mysql mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ON bankaccount.* TO custom@localhost IDENTIFIED BY 'stupid'; mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ON expenses.* TO custom@whitehouse.gov IDENTIFIED BY 'stupid'; mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ON customer.* TO custom@'%' IDENTIFIED BY 'stupid';
許可テーブルを直接変更してこのユーザーの権限を設定するにはいかのようにします
(FLUSH PRIVILEGES
を最後に実行している事に注意):
shell> mysql --user=root mysql mysql> INSERT INTO user (Host,User,Password) VALUES('localhost','custom',PASSWORD('stupid')); mysql> INSERT INTO user (Host,User,Password) VALUES('server.domain','custom',PASSWORD('stupid')); mysql> INSERT INTO user (Host,User,Password) VALUES('whitehouse.gov','custom',PASSWORD('stupid')); 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 ('whitehouse.gov','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('%','customer','custom','Y','Y','Y','Y','Y','Y'); mysql> FLUSH PRIVILEGES;
最初の3つの INSERT
文は、 custom
ユーザーがそれぞれのホストから
パスワードつきで接続できるように user
テーブルに追加しています。
しかしここでは権限は1つも与えられていません(権限のデフォルト値は 'N'
です)。
次の三つの INSERT
文は、bankaccount
, expenses
, customer
データベースに対する該当ホストからのアクセス許可を custom
ユーザーに与えるように、
db
テーブルに追加しています。
許可テーブルが直接変更された場合、これらをサーバーに反映させるために、許可テーブルの
再読み込みを(FLUSH PRIVILEGES
で) サーバーにつげなければなりません。
もし、あるドメインの全てのマシンに接続を許可したい場合、
以下のように GRANT
構文を発行します:
mysql> GRANT ... ON *.* TO myusername@"%.mydomainname.com" IDENTIFIED BY 'mypassword';
許可テーブルを直接変更するには以下のようにします:
mysql> INSERT INTO user VALUES ('%.mydomainname.com', 'myusername', PASSWORD('mypassword'),...); mysql> FLUSH PRIVILEGES;
もちろん、xmysqladmin
, mysql_webadmin
, そして xmysql
を使って
も、権限テーブルへの値の挿入/変更/更新ができます。これらのユーティリティは
Contrib directory of the MySQL
Website.
に見つけることができます。
多くの場合、ユーザ/パスワードを設定するために、GRANT
を使用すべき
です。以下は上級ユーザのためにだけあてはまります。
「7.35 GRANT
と REVOKE
構文」節参照.
前節の例で述べた、とても重要な基本原則:
INSERT
か UPDATE
で空ではないパスワードを設定する場合、
暗号化するために PASSWORD()
関数を使用しなくてはなりません。
これは user
テーブルはプレーンテキストでなく、暗号化されたパスワードであることを要求しているからです。
この原則を忘れてしまった場合、以下のようにしてパスワードをセットしてしまうかもしれません:
shell> mysql -u root mysql mysql> INSERT INTO user (Host,User,Password) VALUES('%','jeffrey','biscuit'); mysql> FLUSH PRIVILEGES;
これは user
テーブルにプレーンテキストの 'biscuit'
をパスワードとして登録してしまいます。
jeffrey
ユーザーでこのパスワードを使用してサーバーに接続しようとすると、
mysql
クライアントは暗号化したパスワードをサーバーに送ります。
サーバーは暗号化されたパスワード('biscuit'
ではありません) と
user
テーブルに登録された値('biscuit'
) を比較します。
その結果、比較は失敗し、サーバーは接続を拒否します:
shell> mysql -u jeffrey -pbiscuit test Access denied
user
テーブルに登録されるパスワードは暗号化されたものでなくてはなりません。
INSERT
構文は以下のようにして使用しなくてはなりません:
mysql> INSERT INTO user (Host,User,Password) VALUES('%','jeffrey',PASSWORD('biscuit'));
SET PASSWORD
構文を使用する場合は、以下のようにしなくてはなりません:
mysql> SET PASSWORD FOR jeffrey@"%" = PASSWORD('biscuit');
もし GRANT ... IDENTIFIED BY
構文や mysqladmin password
コマンド
でパスワードを設定した場合、PASSWORD()
関数は必要ありません。
両方とも、パスワードを暗号化してくれますので、
以下のように'biscuit'
と与えます:
mysql> GRANT USAGE ON *.* TO jeffrey@"%" IDENTIFIED BY 'biscuit'; shell> mysqladmin -u jeffrey password biscuit
注意: PASSWORD()
がパスワードを暗号化することに注意してください。
この暗号化は UNIX のパスワードで使用されている暗号化と違うことにも留意してください。
UNIX パスワードファイルに記録されている暗号と PASSWORD()
が暗号化した物が同じでも、
同じパスワードであるとは思わないでください。
「6.5 MySQL ユーザ名とパスワード」節参照.
Access denied
エラーになるのか
もし、MySQL サーバーに接続しようとして Access denied
エラーに
遭遇してしまったら、以下に記すことが問題の解決のための指標となるでしょう:
mysql_install_db
を実行して
許可テーブルを初期化しましたか?
していなければ実行してください。 「6.12 MySQL 権限許可の初期設定」節参照
権限許可のテーブルが初期化されているかを試すには以下のようにします:
shell> mysql -u root testこれは普通はエラーなしで接続できます。 MySQL データベースディレクトリ内に `user.MYD' ファイルがあるかどうかでもチェックします。 (普通は `PATH/var/mysql/user.MYD' です。ここで
PATH
は MySQL をインストールしたディレクトリーパスを示します。)
shell> mysql -u root mysql初期状態では、MySQL に
root
ユーザーをパスワードなしで登録しているので、
問題なく接続できるはずです。
しかしこれはセキュリティ上危険な状態なので、
他の MySQL ユーザーを登録している時に、
root
のパスワードを設定しておいてください。
もし root
で接続しようとして以下のエラーが出た場合:
Access denied for user: '@unknown' to database mysqlこれは
user
テーブルに、 User
フィールド = root
かつ
mysqld
がリゾルブできなかったホスト名で、クライアントが登録されていないからです。
この場合、 `/etc/hosts' ファイルあるいは `\windows\hosts' ファイルを編集して
ホスト名を追加し、--skip-grant-tables
オプションでサーバーをリスタートします。
shell> mysqladmin -u root -pxxxx ver Access denied for user: 'root@localhost' (Using password: YES)これは間違ったパスワードを使用したことを意味します。 「6.14 パスワードの設定法」節参照. root のパスワードを忘れた場合、
mysqld
を
--skip-grant-tables
で再起動して、パスワードを変更することができま
す。このオプションについての詳細は、マニュアルのこの節の後ろに見つけること
ができます。
パスワードを指定してないのに、上のエラーがでた場合は、my.ini
ファイ
ルに間違ったパスワードがあることを意味します。 「4.16.5 オプションファイル ( my.cnf
)」節参照. このオ
プションファイルは、次のように --no-defaults
オプションで回避できま
す:
shell> mysqladmin --no-defaults -u root ver
mysql_fix_privilege_tables
スクリプトを実行しましたか?
実行していないなら、このエラーになります。
許可テーブルの構造が MySQL バージョン 3.22.11 から変更され、
GRANT
構文が機能しています。
INSERT
, UPDATE
, SET PASSWORD
構文でパスワードを設定するとき
PASSWORD()
関数を使用しなければならないことを思い出してください。
しかし PASSWORD()
関数は、GRANT ... INDENTIFIED BY
構文や
mysqladmin password
コマンドでは不要です。
「6.14 パスワードの設定法」節参照.
localhost
はローカルのホスト名です。
もしクライアントがホストを指定せずに接続してきた場合、localhost
がデフォルトで使用されます。
しかし、 MIT-pthreads を使用している場合、localhost
への接続は失敗します。
(localhost
への接続は、UNIXソケットを使用しますが、 MIT-pthreads が ソケット接続をサポートしていないためです。)
この問題が起きるシステムでは、サーバー名を指定するために --host
オプションを使用すべきです。
これは TCP/IP 接続を使用して mysqld
サーバーに接続します。
この場合、user
テーブルに、サーバーの実ホスト名を登録しておかなくてはなりません。
(これはクライアントプログラムをサーバーと同じホスト上で動かしている場合真となります)
例えば、Using password: NO
を含むエラーメッセージを得た場合、これは
パスワードなしでログインしようとしたことを意味します。
mysql -u user_name db_name
を使用してデータベースに接続しているときに
Access denied
エラーが発生した場合、user
テーブルの設定違いが考えられます。
mysql -u root mysql
を実行し、以下の SQL 文を試してください:
mysql> SELECT * FROM user;
Host
と User
にあなたのコンピュータ名と MySQL ユーザー名にマッチする登録がなされていなければなりません。
Access denied
エラーは、どのユーザーで接続してきたか、どのホストから接続しようとしているか、パスワードを使用しているのかをメッセージに出力します。
通常、エラーになっているホスト名とユーザー名がマッチするエントリが user
テーブルに一つはなければなりません。
user
テーブルにあなたがアクセスしているホストにマッチする行がありません:
Host ... is not allowed to connect to this MySQL server
mysql
コマンドをサーバーのホスト上で使用して、
user
, db
, host
テーブルに接続しようとしている
ユーザー名/ホスト名 を加えて、mysqladmin flush-privileges
を
実行すれば解決できるでしょう。
もしサーバーが MySQL バージョン 3.22 ではなく、接続しようとしている
ホストの IP もホスト名もわからない場合、
user
テーブルの Host
フィールドに '%'
を設定し、
mysqld
を --log
オプションで再起動してください。
そしてクライアントホストから接続すれば、MySQL のログファイルに
そのホストの情報が記録されているはずです。
それがわかれば、先に設定した user
テーブルの Host
フィールドの '%'
を
ログに記録されたホスト名に置き換えます。(しかしこれはシステムを危険にさらします)
Linux 上でこのエラーの他の原因は、あなたの使用しているのと異なる glibc バー
ジョンでコンパイルされた、バイナリ MySQL バージョンを使用している
ことを意味します。この場合、あなたの OS/glibc をアップグレードするか、ソー
ス MySQL バージョンをダウンロードしてコンパイルすべきです。ソース
RPM は、通常コンパイルとインストールは簡単なので、これは大きな問題ではあり
ません。
shell> mysqladmin -u root -pxxxx -h some-hostname ver Access denied for user: 'root' (Using password: YES)これは MySQL が IP をホスト名に解決しようとした時に何かエラーを得 たことを意味します。この場合、
mysqladmin flush-hosts
を実行して、内
部の DNS キャッシュをリセットできます。 「13.2.10 How MySQL uses DNS」節参照.
いくつかの永久的な解決策は:
--skip-name-resolve
で mysqld を起動する。
--skip-host-cache
で mysqld を起動する。
localhost
に
接続する。
/etc/hosts
にクライアントマシン名を置く。
mysql -u root test
は動いたものの mysql -h your_hostname -u root test
が
Access denied
を返した場合、
user
テーブルに正しいホスト名が使用されていないと思われます。
user
テーブルの Host
フィールドにホスト名を確定できる形で指定していないか、
使用しているシステムのリゾルブが FQDN (or vice-versa) を返しているかだと思われます。
例えば、user
テーブルに 'tcx'
ホストの定義があったとして、
DNS が MySQL に 'tcx.subnet.se'
をホスト名として返した場合、
これは動きません。
user
テーブルの Host
フィールドの値に、あなたのホストの IP 番号を加えてください。
(user
テーブルの Host
の値にワイルドカードを使用することができます。'tcx.%'
のように。
しかしホスト名の値を `%' 文字で終わらせる設定は、安全ではなく、推奨されません)
mysql -u user_name test
が動作し mysql -u user_name other_db_name
が
動作しない場合は、db
テーブルに other_db_name
のエントリが
登録されていません。
mysql -u user_name db_name
はザーバー上では動作するが、
mysql -u host_name -u user_name db_name
がクライアントホスト上で動作しない場合、
user
テーブルか db
テーブルにクライアントホストの名前が登録されていません。
Access denied
の原因がもし上記に当てはまらない場合は、
user
テーブルから Host
にワイルドカードを使用しているエントリを全て消去してみてください。(`%' や `_' を含む値です)
よくある間違いは、localhost
に対して localhost
と同じマシン上から
の接続を許可すると考えて
Host
='%'
と User
='some user'
を登録することです。
これは動きません。なぜなら、デフォルトの権限に
Host
='localhost'
と User
=''
が含まれているからです。
Host
の値が 'localhost'
の場合、これは '%'
よりも
具体的に指定されているので、localhost
からの接続にはこちらの方が
使用されるのです! 正しい指定の仕方は、二番目の登録として
Host
='localhost'
と User
='some_user'
を追加するか、
あるいは、Host
='localhost'
と User
=''
を削除することです。
db
か host
テーブルに問題があるのかもしれません。:
Access to database deniedもし
db
テーブルに Host
フィールドが空の登録がある場合には、
host
テーブル中に、db
テーブルに登録されている
ホストを明記した物が一つ以上あるかどうかを確認してください。
もし SELECT ... INTO OUTFILE
や LOAD DATA INFILE
SQL 文を
使用している時にこのエラーが出る場合、
user
テーブルのあなたの登録に file 権限が
許可されていないと思われます。
my.cnf
)」節参照.
もしクライアントをオプションなしで起動していて Access denied
がでるなら、
オプションファイルに古いパスワードが書かれているか確認してください。
「4.16.5 オプションファイル ( my.cnf
)」節参照.
INSERT
または UPDATE
ステートメントを使用して
)直接変更する場合、あなたの変更は無視されたように見えます。サーバに権限テー
ブルを再読み込みさせるために、FLUSH PRIVILEGES
ステートメントの発行
か、mysqladmin flush-privileges
コマンドの実行の必要があることを忘
れないでください。そうでないと、あなたの変更は次回のサーバ再起動まで効果が
ありません。UPDATE
コマンドで root
パスワードを設定後、権限
をフラッシュするまでそれを指定する必要がありません。サーバはまだパスワード
を変更したことを知らないからです!
mysql -u user_name db_name
または mysql -u user_name
-pyour_pass db_name
でサーバへの接続を試してください。mysql
クライ
アントを使用して接続できれば、アクセス権でなく、あなたのプログラムに問題が
あります。(-p
とパスワードの間に空白がないことに注意してください;
パスワードを指定するのに、--password=your_pass
構文も使用できます。
単に -p
オプションを使用すると、MySQL はパスワードの入力を
求めます。)
mysqld
デーモンを --skip-grant-tables
オプショ
ン付きで開始してください。MySQL 権限テーブルを変更し、あなたの変
更が望む効果があるかどうかのチェックに、mysqlaccess
スクリプトを使
用できます。あなたの変更が満足できた時に、mysqladmin
flush-privileges
を実行し、mysqld
サーバに新しい権限テーブルを使用
して開始するように伝えてください。注意: 権限テーブルのリロードは
--skip-grant-tables
オプションを上書きします。これは、サーバを落と
して再起動することなしに、権限テーブルの使用を始めるようにサーバに伝えるこ
とができます。
mysqld
デーモンをデバッグオプションで起動してください。
例えば、--debug=d,general,query
。これはコネクションに試みたホストやユーザーの情報、
また実行したコマンドを表示します。 「I.1 MySQL server のデバッグ」節参照.
mysqldump mysql
コマンドでダンプできます。
いつものように、 mysqlbug
スクリプトでポストしてください。 「2.3 バグや問題を報告する方法」節参照.
ときにはは、 mysqldump
を実行するために、
mysqld
を --skip-grant-tables
オプションで実行しないと
いけないかもしれません。
Go to the first, previous, next, last section, table of contents.