本稿では監査ログを取得する拡張pgAuditを紹介します。
PowerGres(およびPowerGres Plus)には、pgAuditパッケージが標準で付属しているため、ダウンロードの手間が必要ありません。手軽なステップでpgAudit機能をインストールし利用することが可能です。
pgAuditは、標準のPostgreSQLログ機能を通じて、セッション単位およびオブジェクト単位の詳細な監査ログを提供します。この機能をPowerGres で活用することで、データベースの操作ログを詳細に記録し、セキュリティ監査やコンプライアンス要件への対応に利用できます。
本稿では、PostgreSQLの監査ロギングを実現する拡張機能であるpgAuditについて、基本的な仕組みからインストール方法、実際のログ取得方法までを体系的に解説します。実運用における監査要件に対応するための第一歩として、セッション監査ロギングとオブジェクト監査ロギングの両方を実際に確認していきます。
pgAuditは、PostgreSQLで監査ログを取得するためのオープンソースの拡張機能です。標準のログ機能では取得しづらい詳細な操作履歴を記録することができ、セキュリティ監査や内部統制の要件を満たすために利用されます。
pgAuditの目的は、政府規制、金融要件、またはISO認証への準拠のためにしばしば求められる監査ログを生成する機能を提供することです。
監査(audit)とは、通常、独立した機関によって行われる、個人または組織の会計や活動に対する公式な検査を指します。pgAuditによって収集される情報は、正確には「監査証跡(audit trail)」または「監査ログ(audit log)」と呼ばれます。
pgAuditはPostgreSQLの拡張機能として動作し、設定した監査対象の操作内容は通常のPostgreSQLログに混在して出力されます。そのため、既存のログ運用に統合しやすい点も特徴です。
PostgreSQLの標準ログでもSQL文の記録は可能ですが、監査用途としては不十分なケースがあります。例えば以下のような点が挙げられます。
pgAuditを利用することで、これらの情報を明確にログとして取得できるようになります。
pgAuditには大きく分けて2種類の監査方式があります。
セッション監査は広範囲の監査に向いており、オブジェクト監査は特定対象に絞った詳細な監査に向いています。
pgAuditのログは「AUDIT:」で始まるカンマ区切り形式で出力されます。主な項目は以下の通りです。
これらpgAuditのログ出力は前述の通り、PostgreSQLの通常ログと一体となって出力されますので、必要に応じてlog_line_prefixを設定することで、これに日時やユーザ名などの情報も付加することもできます。
PowerGres では、pgAuditパッケージは標準で付属しているので、ダウンロードの手間は必要ありません。以下の手順でインストールと有効化を行うことで、速やかに利用を始めることができます。
なお、pgAuditパッケージはPowerGres ディレクトリの以下に配置されています。
それではインストールおよび有効化方法を紹介します。
コマンドラインより、以下を実行します。
# cd (パッケージの格納先のディレクトリ) # rpm -ivh powergresplus16-pgaudit-*
ここでは具体例として、/root配下に置いたPowerGres のインストールパッケージ(/root/powergresplus-16update10-3-linuxディレクトリ)から、RPM パッケージをインストールします。
(例) # cd /root/powergresplus-16update10-3-linux/packages/el9-x86_64 # rpm -ivh powergresplus16-pgaudit-16.1-1PGDG.el9.x86_64.rpm Verifying... ################################# [100%] 準備しています... ################################# [100%] 更新中 / インストール中... 1:powergresplus16-pgaudit-16.1-1PGD################################# [100%]
インストール後、監査ログを有効にするために、以下の手順で設定ファイル(postgresql.conf)の編集、SQLでのpgAudit拡張の有効化を行います。
まず、データディレクトリ内の postgresql.conf ファイルをテキストエディタで開き、shared_preload_libraries パラメータに文字列で「pgaudit」と設定します。
shared_preload_libraries = 'pgaudit' # 既存の設定がある場合はカンマ区切りで追加
ここでは併せて、セッション単位の監査ログを出力するため、暫定的に以下の設定を追加します。
pgaudit.log = 'ALL' # すべての操作を監査ログに記録
設定ファイルを保存して閉じ、変更した設定を反映するため、PowerGres サービス(サーバ)を再起動します。この再起動は、PowerGres Administration Toolでの操作でも、コマンドラインでの実行でも構いません。
(例) $ vi /var/lib/pgsql/16/data/postgresql.conf (以下を追記) shared_preload_libraries = 'pgaudit' pgaudit.log = 'ALL' (サーバ再起動) $ /opt/powergresplus16/bin/pg_ctl restart -D /var/lib/pgsql/16/data サーバ停止処理の完了を待っています....完了 サーバは停止しました サーバの起動完了を待っています (中略) 完了 サーバ起動完了
次にpgAudit拡張を有効化するため、データベースにスーパーユーザとして接続し、psql コマンドラインより以下のSQLを実行します。
=# CREATE EXTENSION pgaudit; CREATE EXTENSION
以上でインストールと有効化は完了です。
次に、有効化したpgAudit機能が動作していることを確認します。
psql コマンドラインより以下のSQLを実行します。
=# SELECT 'pgAudit Test'; ?column? -------------- pgAudit Test (1 row)
この操作により、PostgreSQLのログファイルに以下のような監査ログが出力されます。
LOG: AUDIT: SESSION,1,1,READ,SELECT,,,SELECT 'pgAudit Test';,
以上のように動作を確認することができましたら、PowerGres でのpgAuditのインストールおよび有効化は無事完了です。
本章では、pgAuditの基本的な利用方法としてセッション監査ロギングを確認します。
セッション監査ロギングは、データベースに接続したセッション単位で操作を監査する仕組みです。あらかじめpgaudit.logパラメータに監査対象のクラス(READ、WRITE、DDLなど)を設定しておくことで、そのセッション内で実行された該当操作がすべて監査ログとして出力されます。
この方式の特徴は、設定がシンプルで広範囲の操作を一括して記録できる点にあります。一方で、すべての対象操作が記録されるため、環境によってはログ量が非常に多くなる可能性があります。そのため、検証環境ではALLを指定して動作を確認し、本番環境では必要なクラスのみに絞るといった運用が一般的です。
なお、パラメータの変更はpostgresql.confに記述(テキストエディタで追記)するか、SQL(SET文)で動的に行います。ただし、SET文の場合、これはセッション単位の変更となりますのでご留意ください。変更されたpgAuditパラメータはpostgresql.confのリロードで反映されます。pg_ctl reloadやsystemctl reloadの他、SQLでpg_reload_conf関数を実行することで反映してください。
それでは、実際に各種パラメータを設定しながら、どのようにログが出力されるのかを確認していきます。
まずは基本的な運用として、すべての操作を監査ログに記載する設定として、postgresql.confに以下を設定します。この基本確認は前章の最後で行っておりますので、既に実施済の場合は適宜読み飛ばしてください。
pgaudit.log = 'ALL'
設定反映後、SELECT文を実行すると以下のようなログが出力されます。
LOG: AUDIT: SESSION,1,1,READ,SELECT,,,SELECT 'pgAudit Test';,
デフォルトではonになっており、pg_catalogへのアクセスもログに出力されます。psqlの内部クエリも記録されるため、必要に応じてoffに設定することでログのノイズを減らせます。
psql で \d を実行すると、psql が実行した pg_catalog.pg_class と pg_catalog.pg_namespace への SELECT 文が監査ログとして記録されます。これは、pgaudit.log_catalog のデフォルト値が ‘on’ になっており、pg_catalogへのアクセス監査対象としてログに出力されるためです。
デフォルト値のままだと必要な監査ログが埋もれてしまう可能性があるので、こういった pg_catalog への参照をするようなツール使用時に監査ログを取得する場合、pgaudit.log_catalog を ‘off’ に設定することでログのノイズを減らせます。
(例)\d を実行した際のログ出力
LOG: AUDIT: SESSION,2,1,READ,SELECT,,,"SELECT n.nspname as ""Schema"",
c.relname as ""Name"",
CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 't' THEN 'TOAST table' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'partitioned table' WHEN 'I' THEN 'partitioned index' END as ""Type"",
pg_catalog.pg_get_userbyid(c.relowner) as ""Owner""
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_catalog.pg_am am ON am.oid = c.relam
WHERE c.relkind IN ('r','p','v','m','S','f','')
AND n.nspname <> 'pg_catalog'
AND n.nspname !~ '^pg_toast'
AND n.nspname <> 'information_schema'
AND pg_catalog.pg_table_is_visible(c.oid)
ORDER BY 1,2;",<not logged>
pgaudit.log_relationは、SQL文で参照されたリレーション(TABLEやVIEWなど)の情報を監査ログに出力するかどうかを制御するパラメータです。
デフォルト値はoffで、この場合はリレーションに関する情報(どのテーブルを操作したか)はログに含まれません。
onに設定すると、SELECT文やDML文で参照されたリレーションごとにログエントリが出力され、以下の情報が追加されます。
この設定を有効にすることで、どのオブジェクトに対する操作なのかを明確に把握できるようになります。特に同名テーブルが複数スキーマに存在する環境では、有用な情報となります。
(例)offの場合 LOG: AUDIT: SESSION,5,1,READ,SELECT,,,SELECT * FROM test;,<not logged> (例)onの場合 LOG: AUDIT: SESSION,7,1,READ,SELECT,TABLE,public.test,SELECT * FROM test;,<not logged>
pgaudit.log_parameter はSQLのパラメータを出力するかどうかを制御します。この出力は、監査ログの最後のエントリに追記されます。
デフォルト値は ’off’ でパラメータは記録されずに <not logged> と表示されます。
’on’ に設定するとパラメータがあるときは実際のパラメータは記録され、パラメータが無い時は <none> と表示されます。
以下は、「SHOW pgaudit.log_client;」実行時のログ例です。
(例)offの場合 LOG: AUDIT: SESSION,3,1,MISC,SHOW,,,SHOW pgaudit.log_client;,<not logged> (例)onでパラメータがない場合 LOG: AUDIT: SESSION,7,1,MISC,SHOW,,,SHOW pgaudit.log_client;,<none>
pgaudit.log_statement_onceは、監査ログにおいてSQL文(ステートメント)とパラメータ情報を各ログ行にすべて出力するか、それとも最初の1回だけ出力するかを制御するパラメータです。
デフォルト値はoffで、この場合は同一SQLに対する各ログエントリにおいて、SQL文およびパラメータ情報がすべての行に繰り返して出力されます。
一方、onに設定すると、SQL文とパラメータは最初のログエントリにのみ出力され、2行目以降は<previously logged>と表示され、省略されます。
この設定は、特にJOINなどで複数のリレーションが関与し、1つのSQLに対して複数行の監査ログが生成される場合に有用です。
例えば、pgaudit.log_relationをonにした状態でテーブルtable1とtable2をJOINした場合、以下のような違いが発生します。
offの場合、リレーションごとにSQL文とパラメータがすべての行に出力されます。
(例)pgaudit.log_statement_onceがoffの場合
LOG: AUDIT: SESSION,12,1,READ,SELECT,TABLE,public.table1,"SELECT table1.i, table2.i
FROM table1
JOIN table2 ON true;",<not logged>
LOG: AUDIT: SESSION,12,1,READ,SELECT,TABLE,public.table2,"SELECT table1.i, table2.i
FROM table1
JOIN table2 ON true;",<not logged>
onの場合、最初の行のみSQL文とパラメータが出力され、2行目以降は <previously logged>と表示され、重複が省略されます。
(例)onの場合
LOG: AUDIT: SESSION,15,1,READ,SELECT,TABLE,public.table1,"SELECT table1.i, table2.i
FROM table1
JOIN table2 ON true;",<not logged>
LOG: AUDIT: SESSION,15,1,READ,SELECT,TABLE,public.table2,<previously logged>,<previously logged>
このように、log_statement_onceはログの冗長性を抑え、可読性を向上させるための設定です。
pgaudit.log_clientは、監査ログをサーバ側のログファイルだけでなく、クライアント側にも表示するかどうかを制御するパラメータです。通常、pgAuditの監査ログはPostgreSQLサーバのログにのみ出力されますが、pgaudit.log_clientをonに設定すると、psqlなどのクライアント画面にも同じ監査ログが表示されるようになります。デバッグや動作確認の際に、ログファイルを確認せずにその場で監査結果を確認できるため便利です。
デフォルト値はoffであり、通常はクライアントには表示されず、サーバのPostgreSQLログにのみログが出力されます。
また、pgaudit.log_clientをonにした場合にのみ有効になるパラメータとしてpgaudit.log_levelがあります。このパラメータは、クライアント側に出力されるログのレベルを指定するものです。 指定可能なログレベルは以下の通りです。
なお、error、fatal、panicといった重大なレベルは指定できません。
デフォルト値はlogで、通常のログ出力レベルとして扱われます。
このように、pgaudit.log_clientとpgaudit.log_levelを組み合わせることで、監査ログをクライアント側でリアルタイムに確認しながら開発や検証を行うことが可能になります。
本章では、特定のテーブルやカラム単位で監査を行うオブジェクト監査ロギングについて解説します。
オブジェクト監査ロギングは、監査対象となるロール(マスターロール)を定義し、そのロールに対して特定のオブジェクトへの権限を付与することで、その操作のみを監査ログとして記録する仕組みです。セッション監査ロギングとは異なり、対象を限定して詳細な監査が可能である点が大きな特徴です。
この方式は、機密性の高いテーブルや特定のカラムに対するアクセス履歴のみを取得したい場合に特に有効です。不要なログ出力を抑えつつ、必要な情報だけを正確に取得できるため、実運用においては重要な監査手法の一つとなります。
それでは、マスターロールの作成から権限設定、実際の操作と監査ログの出力内容までを順に確認していきます。
まず監査対象となるロールを作成します。
=# CREATE ROLE auditmrole; CREATE ROLE
次にpostgresql.confに以下を設定します。
pgaudit.role = ‘auditmrole’
(例) $ cd $PGDATA $ vi postgresql.conf pgaudit.role = 'auditmrole' $ pg_ctl reload
postgresql.confの変更後は、pg_ctl reloadコマンドやSQLでのpg_reload_conf関数での、設定再読み込みを忘れずに行ってください。
次に、監査対象とするテーブルのテストデータを作成し、テーブルに対して権限を付与します。
ここでは例として、t_mroleテーブルに対して、カラムt1のみを対象にSELECT権限をロールauditmroleに付与します。
(例) =# CREATE TABLE t_mrole (id int, t1 text); CREATE TABLE =# INSERT INTO t_mrole VALUES (1, 'aaa'),(2, 'bbb'); INSERT 0 2 =# SELECT * FROM t_mrole; id | t1 ----+----- 1 | aaa 2 | bbb (2 行) =# GRANT SELECT (t1) ON t_mrole TO auditmrole; GRANT
続いてオブジェクト監査ロギングの動作を確認するため、以下のように操作を実行します。
(例) =# SELECT id FROM t_mrole; id ---- 1 2 (2 行) postgres=# SELECT id,t1 FROM t_mrole; id | t1 ----+----- 1 | aaa 2 | bbb (2 行)
結果として、以下のようにt1カラムを含む操作のみが監査ログに記録されます。
(例) LOG: AUDIT: OBJECT,4,1,READ,SELECT,TABLE,public.t_mrole,SELECT * FROM t_mrole;,<not logged> LOG: AUDIT: OBJECT,5,1,READ,SELECT,TABLE,public.t_mrole,"SELECT id,t1 FROM t_mrole;",<not logged>
auditmroleロールに与えられた権限の通り、t1カラムを含むSELECTは記録されましたが、t1カラムを含まないidカラムのみのSELECT文は記録されませんでした。このようにオブジェクト監査ロギングではauditmroleロールに与えられた権限のみがPostgreSQLログに記録されますので、対象を絞った詳細な監査ログの記録が可能です。
本稿では、pgAuditの基本からインストール方法、さらにセッション監査ロギングおよびオブジェクト監査ロギングの実践方法までを解説しました。
セッション監査ロギングはデータベース全体の幅広い操作を網羅的に記録する用途に適しており、一方でオブジェクト監査ロギングは特定のテーブルやカラムに対するアクセスを詳細に追跡する用途に適しています。これらを適切に使い分けることで、必要な情報を過不足なく取得し、効率的で実用的な監査ログ運用を実現できます。
このように、データベース運用において監査ログの取得が求められる環境では、pgAuditが標準で利用可能なPowerGres や PowerGres Plus は有力な選択肢となります。追加の拡張導入を最小限に抑えつつ、監査機能をすぐに利用できる点は運用上の大きなメリットです。
さらに、PowerGres Plus の透過的データ暗号化機能と組み合わせることで、データの保護とアクセス監査の両面をカバーすることができます。これらの魅力的な機能によりPowerGres Plus は、単なるデータベース基盤にとどまらず、現場運用に耐えうる柔軟かつ強固なデータベース運用環境を提供します。
ぜひ、PowerGres および PowerGres Plus の利用をご検討ください。