目次
- はじめに
- Audit Log Plugin と Audit Log Filter Plugin の比較
- Audit Log Filter Plugin をインストールしてみる
- Audit Log Filter Plugin を 使ってみる
- 使ってみた感想
はじめに
MySQL で誰がいつどんな操作を行ったのかを確認することができる Audit Log Filter Plugin という機能が Percona Server for MySQL や MySQL Enterprise Edition にあります。
今回は Percona の Audit Log Filter Plugin をインストールしてみたので紹介させていただきます。
この機能は、現時点では Tech Preview 段階です。
Audit Log Plugin と Audit Log Filter Plugin の比較
Percona Server for MySQL では、以前から Audit Log Plugin が実装されていましたが、8.0.34 から新しく Audit Log Filter Plugin が実装されました。
新しくアップグレードされた Audit Log Filter Plugin は、Audit Log Plugin と比較して大幅に改善されており、現在は MySQL Enterprise Audit Plugin の機能を反映しています。
Audit Log Plugin | Audit Log Filter Plugin | |
---|---|---|
監査ログの記録 | 〇 | 〇 |
監査イベントのフィルター | × | 〇 |
特定のユーザーのフィルター | 〇 | 〇 |
ログ形式 | XML, JSON, CSV | XML, JSON |
ログの暗号化 | 〇 | 〇 |
ログの圧縮 | 〇 | 〇 |
ログローテーション | 〇 | 〇 |
対象のデータベース | 指定不可 (全てのデータベースの監査ログを記録) |
指定可 |
Audit Log Plugin はすべての監査イベントのログを記録するため、イベントの記録に多くのリソース (ディスクスペースなど) を必要としますが、Audit Log Filter Plugin はフィルター機能を使って記録するログを細かくカスタマイズできるので使用するリソース量が少なくて済みます。
フィルター機能を使わない場合や CSV 形式で出力したい場合は Audit Log Plugin の使用をおすすめします。
Audit Log Filter Plugin をインストールしてみる
環境情報
- OS : Oracle Linux 8
- Percona Server for MySQL 8.0.36
Percona Server for MySQL のインストール
Audit Log Filter Plugin をインストールするために、まずは Percona の リファレンス から Percona Server for MySQL をインストールしておきます。
Audit Log Filter Plugin のインストール
Percona Server for MySQL のインストール後、/usr/share/mysql
配下の audit_log_filter_linux_install.sql
スクリプトを実行すると Audit Log Filter Plugin のインストールが完了します。
1 2 |
# mysql -u root -p < /usr/share/mysql/audit_log_filter_linux_install.sql Enter password: |
プラグインのインストールを確認するには以下のクエリを実行します。
1 2 3 4 5 6 |
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE 'audit%'; +------------------+---------------+ | PLUGIN_NAME | PLUGIN_STATUS | +------------------+---------------+ | audit_log_filter | ACTIVE | +------------------+---------------+ |
インストールの確認ができました。
MySQL Community Edition に Percona の Audit Log Filter Plugin をインストールできるのか
MySQL Community Edition で Percona の Audit Log Filter Plugin をインストールして動作させることは可能です。
しかし、Percona の Audit Log Filter Plugin を MySQL Community Edition で動作させる場合、互換性の問題が発生する可能性があり、おすすめできないので紹介は省かせていただきます。
Audit Log Filter Plugin を使ってみる
Audit Log Filter Plugin の目玉の機能である、フィルター機能を簡単に使ってみます。
フィルターを設定する
フィルター とは、特定のアクションを指定して監査ログに記録するためのフィルター機能です。
フィルターを使用するために、監査ログに記録するためのフィルタールールを作成 し、それを ユーザーに割り当て ます。
フィルタールール定義には、以下の属性に基づいてイベントを含めたり除外したりします。
- ユーザーアカウント
- 監査イベントクラス
- 監査イベントのサブクラス
- 監査イベントフィールド
これらのフィルタルールを定義するための専用の関数が用意されています。
Audit Log Filter 関数 一覧
フィルタールール定義は、関数呼び出しに基づいて操作できます。
Audit Log Filter 関数 を使用するには AUDIT_ADMIN 権限または SUPER 権限が必要です。
関数 | 説明 |
---|---|
audit_log_filter_flush() | フィルターテーブルを手動でフラッシュする |
audit_log_filter_set_filter() | フィルターを定義する |
audit_log_filter_remove_filter() | フィルターを削除する |
audit_log_filter_set_user() | 特定のユーザーアカウントにフィルターを割り当てる |
audit_log_filter_remove_user() | 特定のユーザーアカウントからフィルターを削除する |
1. フィルターを設定
audit_log_filter_set_filter 関数を使用して test_filter という名前のフィルターを設定しています。
1 2 3 4 5 6 |
mysql> SELECT audit_log_filter_set_filter('test_filter', '{"filter": {"log": true}}'); +-------------------------------------------------------------------------+ | audit_log_filter_set_filter('test_filter', '{"filter": {"log": true}}') | +-------------------------------------------------------------------------+ | OK | +-------------------------------------------------------------------------+ |
設定したフィルターの確認
1 2 3 4 5 6 |
mysql> SELECT * FROM audit_log_filter; +-----------+-------------+---------------------------+ | filter_id | name | filter | +-----------+-------------+---------------------------+ | 1 | test_filter | {"filter": {"log": true}} | +-----------+-------------+---------------------------+ |
2. 特定のユーザーアカウントにフィルターを割り当てる
audit_log_filter_set_user 関数を使用してすべてのユーザーに test_filter という名前のフィルターを適応しています。
1 2 3 4 5 6 |
mysql> SELECT audit_log_filter_set_user('%', 'test_filter'); +-----------------------------------------------+ | audit_log_filter_set_user('%', 'test_filter') | +-----------------------------------------------+ | OK | +-----------------------------------------------+ |
設定したユーザーアカウントのフィルターを確認
1 2 3 4 5 6 |
mysql> SELECT * FROM audit_log_user; +----------+----------+-------------+ | username | userhost | filtername | +----------+----------+-------------+ | % | % | test_filter | +----------+----------+-------------+ |
ユーザー割り当てまで完了すると、デフォルトでデータディレクトリ配下にある audit_filter.log
にすべての監査可能なイベントの記録を開始します。
my.cnf で audit_log_filter_file = 新しいパス/audit_filter.log
を設定し再起動することで出力先の変更が可能です。
https://docs.percona.com/percona-server/8.0/audit-log-filter-security.html
audit_filter.log を確認する
それでは、フィルター機能の動作を実際に確認してみます。
DB にログインし、SHOW DATABASES;
を実行した後、audit_filter.log を確認してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
<AUDIT_RECORD> <NAME>Command Start</NAME> <RECORD_ID>2357_2024-04-12T07:16:31</RECORD_ID> <TIMESTAMP>2024-04-12T07:16:31</TIMESTAMP> <STATUS>0</STATUS> <CONNECTION_ID>1</CONNECTION_ID> <COMMAND_CLASS>query</COMMAND_CLASS> </AUDIT_RECORD> <AUDIT_RECORD> <NAME>Query</NAME> <RECORD_ID>2358_2024-04-12T07:16:31</RECORD_ID> <TIMESTAMP>2024-04-12T07:16:31</TIMESTAMP> <COMMAND_CLASS>show_databases</COMMAND_CLASS> <CONNECTION_ID>142</CONNECTION_ID> <HOST>localhost</HOST> <IP></IP> <USER>root[root] @ localhost []</USER> <OS_LOGIN></OS_LOGIN> <SQLTEXT>show databases</SQLTEXT> <STATUS>0</STATUS> </AUDIT_RECORD> <AUDIT_RECORD> <NAME>Query Start</NAME> <RECORD_ID>2359_2024-04-12T07:16:31</RECORD_ID> <TIMESTAMP>2024-04-12T07:16:31</TIMESTAMP> <STATUS>0</STATUS> <CONNECTION_ID>142</CONNECTION_ID> <COMMAND_CLASS>show_databases</COMMAND_CLASS> <SQLTEXT>show databases</SQLTEXT> </AUDIT_RECORD> <AUDIT_RECORD> <NAME>Query Status End</NAME> <RECORD_ID>2360_2024-04-12T07:16:31</RECORD_ID> <TIMESTAMP>2024-04-12T07:16:31</TIMESTAMP> <STATUS>0</STATUS> <CONNECTION_ID>142</CONNECTION_ID> <COMMAND_CLASS>show_databases</COMMAND_CLASS> <SQLTEXT>show databases</SQLTEXT> </AUDIT_RECORD> <AUDIT_RECORD> <NAME></NAME> <RECORD_ID>2361_2024-04-12T07:16:31</RECORD_ID> <TIMESTAMP>2024-04-12T07:16:31</TIMESTAMP> <COMMAND_CLASS>show_databases</COMMAND_CLASS> <CONNECTION_ID>142</CONNECTION_ID> <HOST>localhost</HOST> <IP></IP> <USER>root[root] @ localhost []</USER> <OS_LOGIN></OS_LOGIN> <SQLTEXT>show databases</SQLTEXT> <STATUS>0</STATUS> </AUDIT_RECORD> <AUDIT_RECORD> <NAME>Query</NAME> <RECORD_ID>2362_2024-04-12T07:16:31</RECORD_ID> <TIMESTAMP>2024-04-12T07:16:31</TIMESTAMP> <COMMAND_CLASS>show_databases</COMMAND_CLASS> <CONNECTION_ID>142</CONNECTION_ID> <HOST>localhost</HOST> <IP></IP> <USER>root[root] @ localhost []</USER> <OS_LOGIN></OS_LOGIN> <SQLTEXT>show databases</SQLTEXT> <STATUS>0</STATUS> </AUDIT_RECORD> <AUDIT_RECORD> <NAME>Command End</NAME> <RECORD_ID>2363_2024-04-12T07:16:31</RECORD_ID> <TIMESTAMP>2024-04-12T07:16:31</TIMESTAMP> <STATUS>0</STATUS> <CONNECTION_ID>1</CONNECTION_ID> <COMMAND_CLASS>query</COMMAND_CLASS> </AUDIT_RECORD> |
セクション名 | セクションの説明 |
---|---|
<NAME> | イベント名 Query, Quit, Connect などのイベント名が含まれる |
<RECORD_ID> | 一意の識別子 |
<TIMESTAMP> | イベントが発生した日時 |
<STATUS> | イベントのステータス 成功は 0、失敗した場合はエラーコードが表示される |
<CONNECTION_ID> | クライアント接続の識別子 各接続には一意のIDが割り当てられる |
<COMMAND_CLASS> | イベントの種類 Query, Quit, Connect などのイベントの種類が含まれる |
<HOST> | クライアントのホスト名またはIPアドレス |
<IP> | クライアントのIPアドレス |
<USER> | 実行したユーザー名 |
<OS_LOGIN> | 実行したユーザーの OS レベルのログイン名 |
<SQLTEXT> | 実行されたSQLクエリや操作のテキスト |
<PRIV_USER> | 特権操作を実行したユーザー名 |
<PROXY_USER> | プロキシユーザー名 |
生ログだと少し見にくいですが SHOW DATABASES;
が正常に実行されたことがわかります。
次に、connection イベント以外を audit_filter.log
に出力しないようにする connection_only フィルターを作成します。
まず、connection イベントのみを記録する設定を作成します。
{"filter": {"log": true}}
で出力されたログからフィルターできそうな定義を自分で確認しました。
1 2 3 4 5 6 7 8 |
mysql> SET @f = '{ "filter": { "class": { "name": "connection" } } }'; mysql> SELECT audit_log_filter_set_filter('connection_only', @f); +----------------------------------------------------+ | audit_log_filter_set_filter('connection_only', @f) | +----------------------------------------------------+ | OK | +----------------------------------------------------+ |
作成した設定を確認します。
1 2 3 4 5 6 7 |
mysql> SELECT * FROM audit_log_filter; +-----------+-------------------+-----------------------------------------------+ | filter_id | name | filter | +-----------+-------------------+-----------------------------------------------+ | 1 | test_filter | {"filter": {"log": true}} | | 2 | connection_only | {"filter": {"class": {"name": "connection"}}} | +-----------+-------------------+-----------------------------------------------+ |
作成した connection_only をすべてのユーザーに適用 (置き換え) します。
ユーザーアカウントはフィルターを 1 つだけ持つことができます。
ユーザーアカウントにすでにフィルターがある場合、この関数は現在のフィルターを置き換えます。
1 2 3 4 5 6 |
mysql> SELECT audit_log_filter_set_user('%', 'connection_only'); +---------------------------------------------------+ | audit_log_filter_set_user('%', 'connection_only') | +---------------------------------------------------+ | OK | +---------------------------------------------------+ |
全てのユーザーに適応できたか確認します。
1 2 3 4 5 6 |
mysql> SELECT * FROM audit_log_user; +----------+----------+-----------------+ | username | userhost | filtername | +----------+----------+-----------------+ | % | % | connection_only | +----------+----------+-----------------+ |
DB にログイン後、任意のクエリを実行してログアウトします。
audit_filter.log を確認すると connection イベント以外のログが記録されていないことがわかります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# ログインとログアウトだけ記録されています <AUDIT_RECORD> <NAME>Connect</NAME> <RECORD_ID>3250_2024-04-24T01:55:57</RECORD_ID> <TIMESTAMP>2024-04-24T01:55:57</TIMESTAMP> <COMMAND_CLASS>Connection</COMMAND_CLASS> <CONNECTION_ID>166</CONNECTION_ID> <HOST>localhost</HOST> <IP></IP> <USER>root</USER> <OS_LOGIN></OS_LOGIN> <PRIV_USER>root</PRIV_USER> <PROXY_USER></PROXY_USER> <DB></DB> <STATUS>0</STATUS> <CONNECTION_TYPE>Socket</CONNECTION_TYPE> <CONNECTION_ATTRIBUTES> <ATTRIBUTE> <NAME>_pid</NAME> <VALUE>26754</VALUE> </ATTRIBUTE> <ATTRIBUTE> <NAME>_platform</NAME> <VALUE>x86_64</VALUE> </ATTRIBUTE> <ATTRIBUTE> <NAME>_os</NAME> <VALUE>Linux</VALUE> </ATTRIBUTE> <ATTRIBUTE> <NAME>_client_name</NAME> <VALUE>libmysql</VALUE> </ATTRIBUTE> <ATTRIBUTE> <NAME>os_sudouser</NAME> <VALUE>vagrant</VALUE> </ATTRIBUTE> <ATTRIBUTE> <NAME>os_user</NAME> <VALUE>root</VALUE> </ATTRIBUTE> <ATTRIBUTE> <NAME>_client_version</NAME> <VALUE>8.0.36-28</VALUE> </ATTRIBUTE> </CONNECTION_ATTRIBUTES> </AUDIT_RECORD> <AUDIT_RECORD> <NAME>Disconnect</NAME> <RECORD_ID>3251_2024-04-24T02:05:07</RECORD_ID> <TIMESTAMP>2024-04-24T02:05:07</TIMESTAMP> <COMMAND_CLASS>Connection</COMMAND_CLASS> <CONNECTION_ID>166</CONNECTION_ID> <HOST>localhost</HOST> <IP></IP> <USER>root</USER> <OS_LOGIN></OS_LOGIN> <PRIV_USER>root</PRIV_USER> <PROXY_USER></PROXY_USER> <DB></DB> <STATUS>0</STATUS> <CONNECTION_TYPE>Socket</CONNECTION_TYPE> <CONNECTION_ATTRIBUTES> <ATTRIBUTE> <NAME>_pid</NAME> <VALUE>26754</VALUE> </ATTRIBUTE> <ATTRIBUTE> <NAME>_platform</NAME> <VALUE>x86_64</VALUE> </ATTRIBUTE> <ATTRIBUTE> <NAME>_os</NAME> <VALUE>Linux</VALUE> </ATTRIBUTE> <ATTRIBUTE> <NAME>_client_name</NAME> <VALUE>libmysql</VALUE> </ATTRIBUTE> <ATTRIBUTE> <NAME>os_sudouser</NAME> <VALUE>vagrant</VALUE> </ATTRIBUTE> <ATTRIBUTE> <NAME>os_user</NAME> <VALUE>root</VALUE> </ATTRIBUTE> <ATTRIBUTE> <NAME>_client_version</NAME> <VALUE>8.0.36-28</VALUE> </ATTRIBUTE> </CONNECTION_ATTRIBUTES> </AUDIT_RECORD> |
使ってみた感想
Audit Log Plugin から大幅にアップグレードされた Audit Log Filter Plugin のフィルター機能を実際に使ってみて、必要なイベントのみを選択して記録することができるため、ログファイルの容量を削減できる点が大きな利点だと感じました。
また、フィルタールールを自由に定義できるため、セキュリティレベルに合わせてログの出力をカスタマイズできる点もよかったです。
Tech Preview 機能ではありますが、Audit Log Filter Plugin を使うためのセットアップも非常に簡単なので、ぜひ使ってみてください。