Aurora PostgreSQL pgaudit セッション監査の挙動

  • Audit
  • PostgreSQL
  • RDS
  • SQL
  • セッション監査とは

    今回は Aurora PostgreSQL のセッション監査の詳しい挙動について調べていきたいと思います。

    一般に企業のセキュリティ対策を考える上で、データベースの監査ログ取得は要件の一つに必ず含まれます。

    Aurora PostgreSQL には以下の大きく分けて3つの監査機能があります。

    • ログイン監査(標準機能)
    • セッション監査(pgaudit)
    • オブジェクト監査(pgaudit)

    このうち「セッション監査(pgaudit)」についての挙動を詳しく見ていきたいと思います。

    セッション監査の境界

    セッション監査を考えるときに、データベースにおける境界についての理解が不可欠です。

    以下の図のように、一般的に Aurora PostgreSQL のクラスターにあるデータベースへのコネクションを行う場合、3つの境界を跨ぐことになります。

    postgresql-audit-01

    上記の図のセッションの矢印を見ると、

    1. クラスターの境界
    2. インスタンスの境界
    3. データベースの境界

    セッションはこれらの境界を跨いでから、対象のデータベースの中のデータにアクセスすることとなります。

    セッション監査の優先度

    実は、セッション監査は、クラスターレベル、インスタンスレベル、データベースレベル、ロールレベルで設定が可能です。

    セッション監査の設定における優先度は以下のようになります。

    1. ロールレベル
    2. データベースレベル
    3. インスタンスレベル
    4. クラスターレベル

    対象が限定されていく程、優先度が上がり、上書きされていく仕様です。

    つまり、クラスターレベルでセッション監査の設定を ALL としても、ロールレベルで none とした場合、そのセッション監査は none となってしまうのです。

    セッション監査を検証する その1

    クラスターレベルとインスタンスレベルの優先度を検証

    まず、セッション監査の設定方法ですが、以下のように行います。なお、セッション監査の細かい設定は検証しやすく pgaudit.log = ALL, none のみを使用しています。

    設定レベル 設定内容
    クラスターレベル クラスターパラメータグループ
    shared_preload_libraries = pgaudit
    pgaudit.log = none
    インスタンスレベル パラメータグループ
    pgaudit.log = ALL
    データベースレベル 設定なし
    ロールレベル 設定なし

    create EXTENSION

    pgaudit の拡張機能を有効化するためには、create EXTENSION も行っておく必要があります。

    postgres=> create EXTENSION pgaudit; CREATE EXTENSION postgres=> select * from pg_extension; extname | extowner | extnamespace | extrelocatable | extversion | extconfig | extcondition ---------+----------+--------------+----------------+------------+-----------+-------------- plpgsql | 10 | 11 | f | 1.0 | | pgaudit | 10 | 2200 | t | 1.3 | | (2 rows)

    カタログテーブル pg_settings を確認してみる

    では、実際に接続してセッション監査の設定を確認してみます。

    postgres=> select name,setting,source from pg_settings where name='pgaudit.log'; name | setting | source -------------+---------+-------------------- pgaudit.log | all | configuration file (1 row)

    以下の方法でも確認することは出来ますが、どのレベルの設定が反映されているのか分かりません。

    postgres=> show pgaudit.log; pgaudit.log ------------- all (1 row)

    この結果から、上記の表による設定では、configuration file(設定ファイル)により、pgaudit.log = ALL に設定されていることが分かります。

    つまり、クラスターレベルの設定よりもインスタンスレベルの設定が優先されていることが分かります。

    セッション監査を検証する その2

    インスタンスレベルとデータベースレベルの優先度を検証

    続いては、インスタンスレベルの設定とデータベースレベルの設定のどちらが優先されるか検証します。

    以下の設定を行います。

    設定レベル 設定内容
    クラスターレベル pgaudit.log = none
    インスタンスレベル pgaudit.log = none
    データベースレベル alter database testdb01 set pgaudit.log='ALL';
    ロールレベル 設定なし

    確認してみる

    では、データベースに接続して上記の表に従い確認してみましょう。

    1. postgres では pgaudit.log='none' です。 postgres=> select name,setting,source from pg_settings where name='pgaudit.log'; name | setting | source -------------+---------+-------------------- pgaudit.log | none | configuration file (1 row) 2. testdb01 に移動しても同様に pgaudit.log='none' です。 postgres=> \c testdb01 testdb01=> select name,setting,source from pg_settings where name='pgaudit.log'; name | setting | source -------------+---------+-------------------- pgaudit.log | none | configuration file (1 row) 3. alter database でセッション監査の設定を変更します。 testdb01=> alter database testdb01 set pgaudit.log='ALL'; ALTER DATABASE 4. 設定変更を行った同セッション内では設定は変更されません。 testdb01=> select name,setting,source from pg_settings where name='pgaudit.log'; name | setting | source -------------+---------+-------------------- pgaudit.log | none | configuration file (1 row) 5. データベース testdb01 に入り直します。 testdb01=> \q [emily@ip-10-112-1-139 login]$ ./psql_login_postgres.sh postgres=> \c testdb01 You are now connected to database "testdb01" as user "postgres". 6. 再度、セッション監査の設定を確認します。 testdb01=> select name,setting,source from pg_settings where name='pgaudit.log'; name | setting | source -------------+---------+---------- pgaudit.log | ALL | database (1 row)

    この結果から、上記の表による設定では、database の設定により、pgaudit.log = ALL に設定されていることが分かります。

    つまり、インスタンスレベルの設定よりもデータベースレベルの設定が優先されていることが分かります。

    セッション監査を検証する その3

    データベースレベルとロールレベルの優先度を検証

    今、検証環境が上記で実施した「その2」の状態にありますので、以下のパターンで検証します。

    設定レベル 設定内容
    クラスターレベル pgaudit.log = none
    インスタンスレベル pgaudit.log = none
    データベースレベル alter database testdb01 set pgaudit.log='ALL';
    ロールレベル alter role postgres set pgaudit.log='none';

    確認してみる

    では、データベースに接続して上記の表に従い確認してみましょう。

    1. testdb01 に接続しセッション監査の設定を確認 postgres=> \c testdb01 testdb01=> select name,setting,source from pg_settings where name='pgaudit.log'; name | setting | source -------------+---------+---------- pgaudit.log | ALL | database (1 row) 2. alter role で postgres のセッション監査を none に設定 testdb01=> alter role postgres set pgaudit.log='none'; ALTER ROLE 3. セッション監査の設定を確認 testdb01=> select name,setting,source from pg_settings where name='pgaudit.log'; name | setting | source -------------+---------+---------- pgaudit.log | ALL | database (1 row) 4. 未反映のため、データベースに入り直す testdb01=> \q [emily@ip-10-112-1-139 login]$ ./psql_login_postgres.sh postgres=> \c testdb01 You are now connected to database "testdb01" as user "postgres". 5. 再度、セッション監査の設定を確認 testdb01=> select name,setting,source from pg_settings where name='pgaudit.log'; name | setting | source -------------+---------+-------- pgaudit.log | none | user (1 row)

    この結果から、上記の表による設定では、user の設定により、pgaudit.log = none に設定されていることが分かります。

    つまり、データベースレベルの設定よりもロールレベルの設定が優先されていることが分かります。

    オススメのセッション監査設定

    まとめ セッション監査の優先度

    冒頭でも述べた通り、セッション監査の設定における優先度は以下のようになります。

    1. ロールレベル
    2. データベースレベル
    3. インスタンスレベル
    4. クラスターレベル

    対象が限定されていく程、優先度が上がり、上書きされていく仕様です。

    監査のベストプラクティス

    Aurora PostgreSQL では、セッション監査でインスタンスレベル、データベースレベル、ロールレベルでの設定が行えるし、オブジェクト監査でテーブルに対する DML の監査設定も行えるため、複雑な監査設定もやろうと思えばできてしまいます。

    ミッションクリティカルなシステムで、監査設定によるパフォーマンス影響を最小限に抑えたい場合は、細かく設定するのも良いかもしれません。

    しかし、セッション監査・オブジェクト監査でそれぞれ細かく設定してしまうと、運用がとても大変です。

    オススメのセッション監査設定

    設定が簡単で運用負荷が少ない方法を選びたいところですよね。

    監査対象のデータベース testdb01 に対しては全操作を監査し、alter role, alter database を監査するために クラスターレベルで role, ddl を設定します。

    設定レベル 設定内容
    クラスターレベル pgaudit.log = role,ddl
    インスタンスレベル 設定なし
    データベースレベル alter database testdb01 set pgaudit.log='ALL';
    ロールレベル 設定なし

    可能であれば、監査ログは CloudWatch Logs へ転送して、alter role, alter database を検知したら即時アラートに設定すると良いでしょう。

    上記の設定であれば、ロールが追加されても、テーブルが追加されても、セッション監査の設定は変更しなくて大丈夫です。

    確認してみる

    上記の表のとおりパラメータを設定してからデータベースに接続します。

    1. testdb01 のセッション監査を ALL に設定 postgres=> \c testdb01 testdb01=> alter database testdb01 set pgaudit.log='ALL'; ALTER DATABASE 2. データベースに接続し直す testdb01=> \q [emily@ip-10-112-1-139 login]$ ./psql_login_postgres.sh postgres=> 3. その他のデータベースのセッション監査は role,ddl が設定されている postgres=> select name,setting,source from pg_settings where name='pgaudit.log'; name | setting | source -------------+----------+-------------------- pgaudit.log | role,ddl | configuration file (1 row) 4. 監査対象の testdb01 だけはセッション監査が ALL になっている postgres=> \c testdb01 testdb01=> select name,setting,source from pg_settings where name='pgaudit.log'; name | setting | source -------------+---------+---------- pgaudit.log | ALL | database (1 row)

    最後におまけ

    今回、オブジェクト監査には全く触れない形でオススメの監査設定を紹介しました。

    次回はオブジェクト監査を使ったオススメの監査設定を考えてみたいなと思います。

  • Audit
  • PostgreSQL
  • RDS
  • SQL