Security and roles

スーパーユーザーのみがBDR拡張機能を作成できます。ただし、必要に応じて、 pgextwlist 拡張機能を設定し、非スーパーユーザーがBDR拡張機能を作成できるように構成できます。

PGDの構成と管理にスーパーユーザーアクセスは必要ありません。 PGDに必要な特権は、PostgreSQLのデフォルトおよび事前定義ロールと同様に名前付けされた、次のデフォルトおよび事前定義ロールに分割されます。

  • bdr_superuser —すべてのPGDテーブルと関数へのアクセスを持つ最も高い特権のロール。

  • bdr_read_all_stats — PGDの状態を理解するのに十分な、テーブル、ビュー、および関数への読み取り専用アクセスを持つロール。

  • bdr_monitor —現時点では、bdr_read_all_statsと同じ。後日延長予定。

  • bdr_application— PGDを実行するアプリケーションに必要な最小限の特権。

  • bdr_read_all_conflicts — bdr.conflict_history のすべての競合を表示できます。

これらのPGDロールは、 BDR拡張機能のインストール時に作成されます。詳細については、 PGD default roles を参照してください。

PGDを管理するために、管理者がユーザーデータにアクセスする必要はありません。

紛争を保護するための手配は、 競合をテーブルに記録する で議論されています。

BDR.conflict_history_summary ビューを使用して、競合を監視できます。

カタログテーブル

システムカタログおよび情報スキーマテーブルは、PGDによるレプリケーションから常に除外されます。

さらに、拡張機能が所有するテーブルはレプリケーションから除外されます。

PGD関数と演算子

すべてのPGD関数はbdr スキーマで公開されています。これらの関数への呼び出しは、search_pathにbdr を置くのではなく、スキーマ修飾する必要があります。

すべてのPGD演算子は pg_catalog スキーマを介して利用可能であるため、ユーザーはsearch_pathからpublic スキーマを問題なく除外できます。

カタログオブジェクトに対する特権の付与

管理者は、テーブル、ビュー、関数などのカタログオブジェクトに対する明示的な特権を付与してはなりません。

PGD default roles で説明されているロールのいずれかを付与して、これらのオブジェクトへのアクセスを管理します。

この要件は、参加のいずれかの側のノードが完全に同じバージョンのPGD、したがってPGDカタログのバージョンを持たない場合でも、ノードグループに参加できる柔軟性の結果です。

より正確には、個々のカタログオブジェクトに対する特権が明示的に付与された場合、 bdr.join_node_group() プロシージャは失敗する可能性があります。結合されるノードから抽出された対応する GRANT ステートメントは、参加するノードに適用されない可能性があるためです。

ロール管理

ユーザーはPostgreSQLインスタンスのグローバルオブジェクトです。 CREATE USER およびCREATE ROLE コマンドは、PGDが実行されており、 bdr.role_replication がオンになっているデータベースで実行される場合、自動的に複製されます。ただし、これらのコマンドが同じPostgreSQLインスタンス内の他のデータベースで実行された場合、それらのユーザーがPGDデータベースに対する権限を持っている場合でも、それらはレプリケートされません。

新しいPGDノードがPGDグループに参加すると、bdr_init_physical を使用してノードが追加されない限り、既存のユーザーは自動的にコピーされません。この動作は意図的なものであり、重要なセキュリティ機能です。 PostgreSQLでは、ユーザーが複数のデータベースにアクセスできます。デフォルトでは、任意のデータベースにアクセスできます。 PGDは、各ユーザーがデータベースに持っているアクセスを知らないため、新しいノードにコピーするユーザーを安全に決定できません。

PostgreSQLでは、次のコマンドを使用してすべてのユーザーをダンプできます。

pg_dumpall --roles-only > roles.sql

次に、新しく作成したノードで再実行する前に、ファイルroles.sql を編集して不要なユーザーを削除できます。 IDとアクセス管理ソリューション(IAM)に応じて、他のメカニズムも可能ですが、現時点では自動化されていません。

ロールとレプリケーション

ユーザーが実行したDDL変更は、各ノードで同じユーザーとして適用されます。

テーブルへのDML変更は、ターゲットノードでテーブル所有ユーザーとしてレプリケートされます。各ノードで同じユーザーがテーブルを所有することをお勧めしますが、強制はしません。

テーブルAがnode1のユーザーXが所有し、node2のユーザーYが所有しているとします。ユーザーYがユーザーXよりも高い特権を持っている場合、これは特権エスカレーションと見なされる場合があります。一部のノードにはさまざまなユースケースがあるため、これを許可しますが、セキュリティ管理者がこの状況を計画および監査できるように警告します。

行レベルのセキュリティポリシーが有効になっているテーブルでは、適用時にポリシーを再適用せずに変更がレプリケートされます。この動作は、 FORCE ROW LEVEL SECURITY が指定されている場合でも、 NO FORCE ROW LEVEL SECURITY として適用される変更と同等です。これが望ましくない場合は、すべての行の複製を回避するrow_filterを指定します。すべてのノードの行セキュリティポリシーが同一であるか、少なくとも互換性があることをお勧めしますが、強制はしません。

ユーザー bdr_superuser は、PGDのレプリケーションを制御し、レプリケーションセットにテーブルを追加または削除できます。 bdr_superuserには、個々のテーブルに対する特権は必要なく、お勧めしません。レプリケーションセットファンクションへのアクセスを制限する必要がある場合は、これらのファンクションの制限バージョンを SECURITY DEFINER ファンクションとして実装し、適切なユーザーに付与できます。

接続ロール

新しいPGDノードを割り当てるとき、 bdr.create_node のlocal_dsn 引数およびbdr.join_node_group のjoin_target_dsn にDSNで指定されたユーザーは、データベースオブジェクトの参照、作成、管理に頻繁に使用されます。

PGDは、これらのDSNでSUPERUSER 権限を持つロールを使用する場合でも、特権エスカレーション攻撃を防ぐように慎重に作成されています。

攻撃対象領域をさらに減らすには、上記のDSNでより制限されたユーザーを指定できます。少なくとも、そのようなユーザーには、次の規定が満たされるように、すべてのノードに対する権限を付与する必要があります。

  • ユーザーがREPLICATION 属性を持っています。

  • データベースに対するCREATE 権限が付与されています。

・ bdr_superuserロールを継承します。

  • 直接または所有者ロールの権限から、レプリケートするすべてのデータベースオブジェクトを所有しています。

すべてのノードが参加したら、権限をさらに次のように減らして、DMLおよびDDLレプリケーションを引き続き許可できます。

  • ユーザーがREPLICATION 属性を持っています。

・ bdr_superuserロールを継承します。

特権制限

PGDは追加の制限を適用し、 TRIGGERまたはREFERENCES特権のみに依存するDDLの使用を効果的に防止します。

GRANT ALL は引き続き TRIGGER 特権と REFERENCES 特権の両方を付与するため、特権を明示的に述べることをお勧めします。たとえば、 ALL の代わりにGRANT SELECT, INSERT, UPDATE, DELETE, TRUNCATE を使用します。

外部キー特権

ALTER TABLE ... ADD FOREIGN KEY は、ユーザーが参照先のテーブルに対するSELECT権限を持っている場合、または参照先のテーブルで現在のユーザーがバイパスできないRLS制限が有効になっている場合にのみサポートされます。

したがって、 REFERENCES 特権は、PGDで外部キーを作成するのに十分ではありません。 REFERENCES特権のみに依存することは、テーブルスキャンではなくトリガーを使用して検証チェックを実行するため、通常は役に立ちません。通常、正常に使用するには高すぎます。

トリガー

PostgreSQLでは、テーブルの所有者とTRIGGER権限を付与された人の両方がトリガーを作成できます。非テーブル所有者によって付与されたトリガーは、PGDでテーブル所有者として実行され、セキュリティ問題が発生する可能性があります。 TRIGGER権限はめったに使用されません。 PostgreSQLコアチームは、「個別のTRIGGER権限は、廃止されたと考えるものです」と述べています。

PGDは、テーブルでトリガーを作成できるユーザーに関するより厳しいルールを使用することにより、この問題を軽減します。

  • スーパーユーザー。

  • bdr_superuser。

  • テーブルの所有者は、PostgreSQLと同じルールに従ってトリガーを作成できます(トリガーで使用される関数のEXECUTE権限が必要です)。

  • テーブルのTRIGGER権限を持つユーザーは、テーブルと同じ所有者が所有する関数を使用してトリガーを作成し、標準のPostgreSQLルールを満たしている場合にのみトリガーを作成できます。 (ファンクションに対するEXECUTE特権が必要です。)テーブルとファンクションの両方が同じ所有者を持ち、所有者がユーザにテーブルに対するTRIGGER特権とファンクションに対するEXECUTE特権の両方を与えることにしたとします。その場合、そのユーザーはこの関数を使用してそのテーブルにトリガーを作成してもよいと想定されます。

  • 表のTRIGGER権限を持つユーザーは、EXECUTE権限を持っている場合、 SECURITY DEFINER句で定義された関数を使用してトリガーを作成できます。この句により、標準のPostgreSQLとPGDの両方で、関数が常に関数の所有者のコンテキストで実行されます。

このロジックは、PostgreSQLでは、トリガーの所有者はそれを作成したユーザーではなく、そのトリガーで使用される関数の所有者であるという事実に基づいています。

同じルールが既存のテーブルに適用され、既存のテーブルにテーブルの所有者が所有していないトリガーがあり、 SECURITY DEFINER 関数を使用しない場合、レプリケーションセットに追加できません。

これらのチェックはPGD 3.6.19で追加されました。以前のバージョンの動作に依存するアプリケーションは、 bdr.backwards_compatibility を30618以下に設定して、以前のバージョンと同様に動作できます。

PGDレプリケーションの適用は、システムレベルのデフォルトのsearch_pathのみを使用します。レプリカトリガー、ストリームトリガー、およびインデックス式関数は、他のsearch_path設定を想定し、適用時に実行すると失敗する場合があります。これが発生しないようにするには、デフォルトのsearch_pathのみを使用してオブジェクト参照を明確に解決するか、影響を受ける関数のALTER FUNCTION ... SET search_path = ... を使用して関数の検索パスを設定します。デフォルトのsearch_pathを使用する場合は、常にオブジェクトへの完全修飾参照(schema.objectnameなど)を使用します。

PGDのデフォルト/事前定義されたロール

PGDの事前定義された役割は、 BDR拡張機能のインストール時に作成されます。 BDR拡張機能がデータベースから削除された後、ロールは引き続き存在します。ドロップが必要な場合は、手動でドロップする必要があります。このプラクティスにより、PGDを同じPostgreSQLインスタンス上の複数のデータベースで問題なく使用できます。

GRANT ROLE DDLステートメントは、PGDレプリケーションに参加しません。したがって、クラスターの各ノードでこれを実行します。

bdr_superuser

  • スキーマBDRのすべてのテーブルのすべての特権

  • スキーマBDRのすべてのルーチンのすべての特権

bdr_read_all_stats

以下に対するSELECT特権:

  • bdr.conflict_history_summary

  • bdr.ddl_epoch

  • bdr.ddl_replication

  • bdr.global_consensus_journal_details

  • bdr.global_lock

  • bdr.global_locks

  • bdr.local_consensus_state

  • bdr.local_node_summary

  • bdr.node

  • bdr.node_catchup_info

  • bdr.node_conflict_resolvers

  • bdr.node_group

  • bdr.node_local_info

  • bdr.node_peer_progress

  • bdr.node_slots

  • bdr.node_summary

  • bdr.replication_sets

  • bdr.sequences

  • bdr.stat_relation

  • bdr.stat_subscription

  • bdr.subscription

  • bdr.subscription_summary

  • bdr.tables

以下に対するEXECUTE特権:

  • bdr.bdr_version

  • bdr.bdr_version_num

  • bdr.decode_message_payload

  • bdr.get_global_locks

  • bdr.get_raft_status

  • bdr.get_relation_stats

  • bdr.get_slot_flush_timestamp

  • bdr.get_sub_progress_timestamp

  • bdr.get_subscription_stats

  • bdr.peer_state_name

  • bdr.show_subscription_status

bdr_monitor

bdr_read_all_stats からのすべての特権。

また、以下に対するEXECUTE特権:

  • bdr.monitor_group_versions

  • bdr.monitor_group_raft

  • bdr.monitor_local_replslots

bdr_application

以下に対するEXECUTE特権:

  • column_timestampsデータ型のすべての関数

  • CRDTデータ型のすべての関数

  • bdr.alter_sequence_set_kind

  • bdr.create_conflict_trigger

  • bdr.create_transform_trigger

  • bdr.drop_trigger

  • bdr.get_configured_camo_partner

  • bdr.global_lock_table

  • bdr.is_camo_partner_connected

  • bdr.is_camo_partner_ready

  • bdr.logical_transaction_status

  • bdr.ri_fkey_trigger

  • bdr.seq_nextval

  • bdr.seq_currval

  • bdr.seq_lastval

  • bdr.trigger_get_committs

  • bdr.trigger_get_conflict_type

  • bdr.trigger_get_origin_node_id

  • bdr.trigger_get_row

  • bdr.trigger_get_type

  • bdr.trigger_get_xid

  • bdr.wait_for_camo_partner_queue

  • bdr.wait_slot_confirm_lsn

これらの機能の多くは、使用する前に追加の特権が必要です。たとえば、 bdr.alter_sequence_set_kind を正常に実行するには、テーブルの所有者である必要があります。これらの追加ルールについては、特定の機能ごとに説明します。

bdr_read_all_conflicts

PGDは、競合をbdr.conflict_history テーブルにログ記録します。競合はテーブルの所有者にのみ表示されるため、競合履歴を読み取るために追加の特権は必要ありません。すべてのテーブルの競合を確認できるユーザーが便利な場合は、オプションでそのユーザーにロール bdr_read_all_conflicts を付与できます。

検証

PGDは、次のツールとアプローチを使用して検証されました。

コベリティ

Coverity Scanは、次のルールとコーディング標準を使用して、脆弱性に対するカバレッジを提供するPGDスタックを検証するために使用されました。

  • ミスラC

  • ISO 26262

  • ISO / IEC TS 17961

  • OWASPトップ10

  • CERT C

  • CWEトップ25

  • AUTOSAR

CISベンチマーク

CIS PostgreSQL Benchmark v1、2019年12月19日は、PGDスタックの検証に使用されました。 Trusted Postgres Architectのオプションとして利用可能なcis_policy.yml 構成を使用すると、 Scoredテストで次の結果が得られます。

Result

Description

1.4

PASS

systemdサービスファイルが有効になっていることを確認します

1.5

PASS

データクラスターが正常に初期化されたことを確認する

2.1

PASS

ファイルのアクセス許可マスクが正しいことを確認します

2.2

PASS

PostgreSQL pg_wheelグループメンバーシップが正しいことを確認します

3.1.2

PASS

ログの宛先が正しく設定されていることを確認します

3.1.3

PASS

ロギングコレクターが有効になっていることを確認します

3.1.4

PASS

ログファイルの宛先ディレクトリが正しく設定されていることを確認します

3.1.5

PASS

ログファイルのファイル名パターンが正しく設定されていることを確認します

3.1.6

PASS

ログファイルのアクセス許可が正しく設定されていることを確認します

3.1.7

PASS

「log_truncate_on_rotation」が有効になっていることを確認します

3.1.8

PASS

ログファイルの最大存続期間が正しく設定されていることを確認します

3.1.9

PASS

最大ログファイルサイズが正しく設定されていることを確認します

3.1.10

PASS

正しいsyslog機能が選択されていることを確認します

3.1.11

PASS

PostgreSQL syslogメッセージのプログラム名が正しいことを確認します

3.1.14

PASS

「debug_print_parse」が無効になっていることを確認します

3.1.15

PASS

「debug_print_rewriting」が無効になっていることを確認します

3.1.16

PASS

「debug_print_plan」が無効になっていることを確認します

3.1.17

PASS

「debug_pretty_print」が有効になっていることを確認します

3.1.18

PASS

「log_connections」が有効になっていることを確認します

3.1.19

PASS

「log_disconnections」が有効になっていることを確認します

3.1.21

PASS

'log_hostname'が正しく設定されていることを確認します

3.1.23

PASS

「log_statement」が正しく設定されていることを確認します

3.1.24

PASS

「log_timezone」が正しく設定されていることを確認します

3.2

PASS

PostgreSQL Audit Extension(pgAudit)が有効になっていることを確認します

4.1

PASS

sudoが正しく構成されていることを確認します

4.2

PASS

過剰な管理権限が取り消されていることを確認する

4.3

PASS

過剰な機能特権が取り消されていることを確認する

4.4

PASS

テスト済み 過剰なDML権限が取り消されていることを確認する

5.2

Not Tested

「host」TCP / IPソケットを介したログインが正しく構成されていることを確認します

6.2

PASS

「バックエンド」ランタイムパラメーターが正しく構成されていることを確認します

6.7

Not Tested

FIPS 140-2 OpenSSL暗号化が使用されていることを確認する

6.8

PASS

SSLが有効になっており、正しく構成されていることを確認します

7.3

PASS

WALアーカイブが構成され、機能していることを確認します

テスト5.2は、手動で監査するとPASSする可能性がありますが、自動テストはありません。

テスト6.7は、CentOSを使用したデフォルトの展開で成功しますが、Debianバリアントには追加のパッケージが必要です。