forked from pgaudit/pgaudit
-
Notifications
You must be signed in to change notification settings - Fork 4
ToDo and Design of refactored branch
masahiko edited this page Feb 13, 2017
·
26 revisions
できているもの、できていないもの関係なく設計のメモ。
議論中の新フォーマットはこちら
- 9.6系
設定ファイルはpostgresql.confとは別に用意する。これは、悪意を持ったユーザが故意にログ出力設定を変更し、証跡を消すことを防ぐため。
pgaudit.config_fileに指定されたファイルをパースして、メモリに展開する。
pgaudit_scan.lで定義。
対応するフォーマットは以下の通り。
[output] # outputセクション
logger = 'serverlog'
:
[options] # optionsセクション
role = 'audit_role'
log_parameter = on # comment 2
log_catalog = off
:
[rule] # ruleセクション1
format = 'AUDIT SESSION-1: %p ...'
class = 'MISC'
database = 'postgres, hoge_db'
:
[rule] # ruleセクション2
format = 'AUDIT SESSION-2 : %p ...'
class = 'READ, WRITE,FUNCTION'
database = 'postgres, hoge_db'
timestamp = '00:00:00 - 12:00:00, 13:00:00-14:00:00'
remote_port = '5432, 6543'
:
以下、詳細な設計。
- 設定ファイルは
options,output,ruleの3つのセクションを持つことが可能。-
output,optionsは設定ファイル内で一つだけ指定可能 -
ruleは複数指定可能
-
- 各設定値は、
- 論理値を入れるパラメータ(log_parameterなど)→
on, off, true, false, 1, 0で設定- シングルクォーテーションなしで記載
- 例)
log_parameter = on
- その他→シングルクォーテーションで囲む(例、'5432, 5555'とか'postgres, hoge_database')
- 数値であってもカンマ区切りで複数指定する可能性があるため、シングルクォーテーションで囲む。
- 例)
remote_port = '5432'
-
timestampについてはHH:MM:SS-HH:MM:SSを一塊として、カンマ区切りで指定する。- 例) timestamp = '00:00:00 - 12:00:00, 13:00:00-14:00:00'
- 間のスペースはすべて無視される。 - 日付のフォーマットに合わなかったら、パースエラーとする。
- 大文字、小文字の区別はしない。
- ただし、formatについては大文字、小文字を意識して出力する。
- 論理値を入れるパラメータ(log_parameterなど)→
- 演算子は、
-
=→ ルールに一致するものをログに出す -
!=→ ルールに一致しないものをログに出す- 例)
object_id != 'public.hoge_table'
- 例)
-
-
#で始まる行はコメントとして扱う。- コメントは行の途中でも可能。
設定値関連の関数はconfig.c、config.hに定義。
-
output、optionsセクションについては、既存のpgauditの変数に格納する。(例えば、[options]のroleはauditRoleに格納する) -
ruleセクションについては複数設定可能なので、ruleConigsにリスト形式でルール情報を格納。(詳細は後述)
- ルールはフィールドによって4つのタイプに分類する。また、ルールのタイプ毎にルールに当てはまるかどうかを判定する関数がある。(apply_XXX_rule()関数)
- AUDIT_RULE_TYPE_STRING
- 文字列を格納するフィールド。
databaseとかobject_idとか - apply_string_rule()で判定する
- 文字列を格納するフィールド。
- AUDIT_RULE_TYPE_TIMESTAMP
- タイムスタンプを格納するフィールド。
timestampのみ - apply_timestamp_rule()で判定する。
- タイムスタンプを格納するフィールド。
- AUDIT_RULE_TYPE_BITMAP
- 文字列で格納するけど、内部ではBitmapで持つもの。
classとobject_type。 - apply_bitmap_rule()で判定する
- 文字列で格納するけど、内部ではBitmapで持つもの。
- AUDIT_RULE_TYPE_STRING
- apply_XXX_rule()を抽象化する関数として、
apply_one_rule()がある。- 第一引数に判定対象の値へのポインタ、第二引数にルールの構造体を入れる。
- 各ルールは、
auditRule構造体で持っていて、配列でまとまっている。- 各ルールの添字は、
AUDIT_RULE_XXXと一致する。
- 各ルールの添字は、
/* 各ルールは「ルール名、設定値、=か!=か、設定値の個数、ルールのタイプ」の順で格納 */
struct AuditRule rules_template[] =
{
{"timestamp", NULL, false, 0, AUDIT_RULE_TYPE_TIMESTAMP},
{"database", NULL, false, 0, AUDIT_RULE_TYPE_STRING},
{"audit_role", NULL, false, 0, AUDIT_RULE_TYPE_STRING},
{"class", NULL, false, 0, AUDIT_RULE_TYPE_BITMAP},
{"object_type", NULL, false, 0, AUDIT_RULE_TYPE_BITMAP},
{"object_id", NULL, false, 0, AUDIT_RULE_TYPE_STRING},
{"application_name", NULL, false, 0, AUDIT_RULE_TYPE_STRING},
{"remote_host", NULL, false, 0, AUDIT_RULE_TYPE_STRING}
};処理のメインとなる関数(hook等)をpgaudit.c、pgaudit.hに定義(個人的にはここも用途別にファイルを分けたい。。)
ログ出力の設計は以下のとおり。
- 出力内部関数
- SESSIONログはlog_audit_eventまたは、emit_log_hookで出力する。
-
log_audit_event()関数- 基本的にすべてのイベントはlog_audit_eventを通り、
- apply_all_rules()がtrue かつ
- stackItem->granted == false のイベントがSESSIONログとして出力される。
- 基本的にすべてのイベントはlog_audit_eventを通り、
-
-
emit_log_hook()関数- emit_log_hookですべてのログを引っ掛けて、目的のログかどうかを文字列一致で判定して、出力する。(advancedでやっている方法踏襲)
- なにか他にいい方法があれば採用したい。
- pgaudit内でのログ出力はEREPORT(ereport相当)、ELOG(elog相当)を使用する - これは、emit_log_hookの無限ループにならないようにするために用意した関数。
- SESSIONログはlog_audit_eventまたは、emit_log_hookで出力する。
- 監査ログ以外のサーバログの扱い
- 設定ファイルで
log_levelが設定できるが、これは監査ログのみを対象とする。通常の運用で出すpgauditのログには適用されないようにする。
- 設定ファイルで
- 監査ログの内容
- 監査に必要な固定の内容のデータを出力。(いつ、誰が、どこから、何をした、など)
- 出力形式は、
optionsセクションでcsv、ssv(スペース区切り)、key-value(auditdの出力形式にあわせて)から選択可能。- csvの例) ap_srv,10000,SELECT,TABLE,SELECT * FROM rel;
- key-vauleの例) host=ap_srv port=10000 command=SELECT kind=TABLE sql=SELECT * FROM rel;
- ssvの例) ap_srv 10000 SELECT TABLE "SELECT * FROM rel;"
基本方針は、
-
「ルールが未定儀=出力」 。これはオリジナルpgauditと仕様が異なる所なので注意。(例えば、ruleにclassがない場合はすべてのclassを出力することになる)
-
ルールセクション自体の記述がない場合は、ルールがないということになるので監査ログ出力はしない。
-
指定されているルールが全部一致した場合に監査ログを出力する。
- 複数のルールにマッチしたイベントは、マッチした分だけのログが出力される - なので一つのSQLで複数の監査ログが出力される可能性もある。
-
例1 (ruleセクションのみ→全ログを出力)
$ cat audit.conf
:
[rule]
$
- 例2(ruleセクションにルールの記載あり→databaseとclassに一致した監査ログを出力)
$ cat audit.conf
:
[rule]
database = 'hogedb'
class = 'READ, WRITE'
基本的にはadvancedブランチにあるやり方を踏襲すれば良いはず。
- 全般
- 設定ファイルの対応
- ルール判定のインフラ(apply_ruleまわり)
- 接続、切断、レプリケーションコマンド等もログに出すようなインフラの整備(emit_log_hook)
- 設定ファイルのコメント対応
- ルール対応
- database
- object_id
- class
- その他
- ドキュメント更新
- 全般
- エラーコード整備、エラー対応(ereportやelogの出力)★
- syslog対応★
- 設定値のパース部分だけはできてる。
- 複数の形式で監査ログを出力できるようにする。csv、ssv、key-valueなど。最低でもcsvはサポートする。
- 監査ログがどのルールによって出力されているかわからないので、「適用されたルール番号」を出しても良いかも。
- ルール対応(各種ルールを判定できるようにする。優先度高順)
- audit_role★
- ユーザ名の一致で判別する機能は追加済み。以下の項目は改善項目として検討する。
- 指定されたロールに所属するユーザが監査ログの出力対象になる。ユーザ名ではなく、ロールを指定するところが大切。
- ロールを使って監査ユーザを判別できるようにする。優先度高。
- command_tag
- SELECT, INSERT, ALTERのレベルでフィルタをする。
- 便利だけど、class(READ, WRITEでフィルタする)とかぶっている部分もあるので、優先度低。
- audit_role★
- その他
- テスト★
- 機能を追加するときは対応するテストと一緒にPRしてください。
- advancedブランチのregression testを取り込む。
- スタンバイサーバ上でも問題なく動くかを確認。
- できればテストケースとして入れたい。
- テスト★