先日、ご紹介させて頂いた、MySQL Enterprise Firewallを利用する事により、
White ListベースのDBアクセス制御(ステートメントベース)をUserアカウントとSQLステートメントの
組み合わせで実装する事が出来ますが、Publicクラウドを含む環境でWebサイトを運用されている場合は、Replication機能と組み合わせてご利用される場合もあるかと思います。
MySQL Enterprise Firewallには、全部で4つのテーブルがありますが、
(Information_Schemaに2つMySQLに2つテーブルが準備されています)
information_schemaにあるテーブルに関しては、レプリケーション対象外なので実際にSlaveに同期されるのは以下の2つのテーブルという事になります。
root@localhost [information_schema]> show tables from mysql like '%fire%'; +--------------------------+ | Tables_in_mysql (%fire%) | +--------------------------+ | firewall_users | | firewall_whitelist | +--------------------------+
また、MySQL Enterprise FirewallのWhite Listはメモリー上にCacheされているので、
スレーブに同期された段階では直ぐにスレーブ側では有効にならないので、
以下のマニュアルに記載されているように、コマンドでメモリーに反映する必要があります。
6.3.15.4 MySQL Enterprise Firewall Reference
実際のMySQL Enterprise FirewallとReplicationの動作をこちらでご紹介します。
既存、White Listに定義を追加してSlave側で確認してみます。
MASTER
root@localhost [mysql]> select * from firewall_whitelist; +-------------------+------------------------------------------------------------------------------+ | USERHOST | RULE | +-------------------+------------------------------------------------------------------------------+ | fw_user@localhost | SELECT `id` , `fname` , `lname` , `cnumber` FROM `card_info` WHERE `id` = ? | +-------------------+------------------------------------------------------------------------------+ 1 row in set (0.00 sec) root@localhost [mysql]> CALL sp_set_firewall_mode('fw_user@localhost','RECORDING'); +-----------------------------------------------+ | read_firewall_whitelist(arg_userhost,FW.rule) | +-----------------------------------------------+ | Imported users: 0 Imported rules: 0 | +-----------------------------------------------+ 1 row in set (0.00 sec) +-------------------------------------------+ | set_firewall_mode(arg_userhost, arg_mode) | +-------------------------------------------+ | OK | +-------------------------------------------+ 1 row in set (0.00 sec) Query OK, 1 row affected (0.00 sec) root@localhost [mysql]> CALL sp_set_firewall_mode('fw_user@localhost','PROTECTING'); +-------------------------------------------+ | set_firewall_mode(arg_userhost, arg_mode) | +-------------------------------------------+ | OK | +-------------------------------------------+ 1 row in set (0.01 sec) Query OK, 3 rows affected (0.01 sec) root@localhost [mysql]> select * from firewall_whitelist; +-------------------+------------------------------------------------------------------------------+ | USERHOST | RULE | +-------------------+------------------------------------------------------------------------------+ | fw_user@localhost | SELECT `id` , `fname` , `lname` , `cnumber` FROM `card_info` WHERE `id` = ? | | fw_user@localhost | SELECT * FROM `card_info` WHERE `id` = ? | | fw_user@localhost | SELECT SYSTEM_USER ( ) | +-------------------+------------------------------------------------------------------------------+ 3 rows in set (0.00 sec) root@localhost [mysql]>
White List対象ユーザーでMasterにアクセスしてWhite ListにSQLステートメントを追加
※ マスター側でRECORDING状態の段階で実行
fw_user@localhost [test]> SELECT * FROM card_info WHERE id = 1; +----+--------+-----------+---------------------+ | id | fname | lname | cnumber | +----+--------+-----------+---------------------+ | 1 | 佐藤 | さとう | 1234-5678-9999-0123 | +----+--------+-----------+---------------------+ 1 row in set (0.00 sec)
SLAVE
White ListはReplicationの機能を使い、同期されているがまだメモリーに反映されていない為、
Master側で追加したSQLステートメントはブロックされる。
fw_user@localhost [test]> SELECT id,fname,lname,cnumber FROM card_info WHERE id = 1; +----+--------+-----------+---------------------+ | id | fname | lname | cnumber | +----+--------+-----------+---------------------+ | 1 | 佐藤 | さとう | 1234-5678-9999-0123 | +----+--------+-----------+---------------------+ 1 row in set (0.00 sec) fw_user@localhost [test]> SELECT * FROM card_info WHERE id = 1; ERROR 1045 (28000): Statement was blocked by Firewall fw_user@localhost [test]>
White List Tableには反映されているが、Slave側ではメモリーに無い為まだBlockされる。
スレーブ側にて以下のコマンドを実施して、最新のWhite Listをメモリーに反映させる。
※ 権限のある、管理ユーザーで実行してください。
※ ここの処理は、マスターのWhite Listを追加する段階でバッチ処理として追加しておいた方が漏れが無くて良さそうです。
root@localhost [mysql]> select * from firewall_whitelist; +-------------------+------------------------------------------------------------------------------+ | USERHOST | RULE | +-------------------+------------------------------------------------------------------------------+ | fw_user@localhost | SELECT SYSTEM_USER ( ) | | fw_user@localhost | SELECT `id` , `fname` , `lname` , `cnumber` FROM `card_info` WHERE `id` = ? | | fw_user@localhost | SELECT * FROM `card_info` WHERE `id` = ? | +-------------------+------------------------------------------------------------------------------+ 3 rows in set (0.00 sec) root@localhost [mysql]> SELECT read_firewall_whitelist('fw_user@localhost', 'RECORDING') FROM mysql.firewall_whitelist; +-----------------------------------------------------------+ | read_firewall_whitelist('fw_user@localhost', 'RECORDING') | +-----------------------------------------------------------+ | Imported users: 0 Imported rules: 1 | +-----------------------------------------------------------+ 1 row in set (0.00 sec) root@localhost [mysql]> SELECT read_firewall_users('fw_user@localhost', 'RECORDING') FROM mysql.firewall_users; +-------------------------------------------------------+ | read_firewall_users('fw_user@localhost', 'RECORDING') | +-------------------------------------------------------+ | Imported users: 0 Updated users: 1 | +-------------------------------------------------------+ 1 row in set (0.01 sec) root@localhost [mysql]>
メモ:以下のいずれかの方法でもMemoryに反映されます。
※ fw_user@localhostは検証用アカウントです、ご利用時は適宜書き換えて下さい。
■ Pattern1
CALL sp_set_firewall_mode(‘fw_user@localhost’,’RECORDING’);
CALL sp_set_firewall_mode(‘fw_user@localhost’,’PROTECTING’);
■ Pattern2
SELECT read_firewall_users(userhost, mode) from mysql.firewall_users;
SELECT read_firewall_whitelist(userhost, rule) from mysql.firewall_whitelist;
■ Pattern3
SELECT read_firewall_users(‘fw_user@localhost’, ‘RECORDING’) FROM mysql.firewall_users;
SELECT read_firewall_whitelist(‘fw_user@localhost’, ‘RECORDING’) FROM mysql.firewall_whitelist;
上記コマンドでSLAVE側に同期れた定義をメモリーにロードする事でSLAVE側でも実行する事が可能になりました。
※再起動でも反映されますが、殆どのケースで、オンラインで実施するのが現実的かと思います。
fw_user@localhost [test]> SELECT * FROM card_info WHERE id = 1; ERROR 1045 (28000): Statement was blocked by Firewall fw_user@localhost [test]> SELECT * FROM card_info WHERE id = 1; +----+--------+-----------+---------------------+ | id | fname | lname | cnumber | +----+--------+-----------+---------------------+ | 1 | 佐藤 | さとう | 1234-5678-9999-0123 | +----+--------+-----------+---------------------+ 1 row in set (0.00 sec) fw_user@localhost [test]>
30日間 トライアル
MySQL Enterprise Edition トライアル
※ Publicクラウド環境などを使われている場合は,IDSやIPSを導入する事が難しく、
WAFを導入したりしている方もいらっしゃると思いますが、MySQLをご利用の場合は、
こちらのEnterprise Firewallを実装する事で、SQL Injectionの対策などがコストを抑えて対応する事が可能になります。
参照:
6.3.15.4 MySQL Enterprise Firewall Reference
MySQL Enterprise Firewall
PlanetMySQL Voting: Vote UP / Vote DOWN