Security and roles

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

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

  • bdr_superuser —すべてのBDRテーブルとファンクションへのアクセスを持つ最も高い特権のロール。

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

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

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

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

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

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

競合を保護するための手配については、 テーブルへの競合のログ で説明されています。

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

カタログテーブル

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

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

BDRの関数と演算子

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

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

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

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

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

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

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

ロール管理

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

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

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

接続ロール

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

BDRは、これらのDSNでSUPERUSER 権限を持つロールを使用する場合でも権限昇格攻撃を防ぐように注意深く作成されています。

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

・ REPLICATION 属性を持っていること。

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

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

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

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

・ REPLICATION 属性を持っていること。

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

特権制限

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

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

外部キー特権

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

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

トリガー

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

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

  • スーパーユーザー

  • bdr_superuser

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

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

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

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

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

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

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

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

BDRの事前定義されたロールは、 BDR拡張機能のインストール時に作成されます。 BDR拡張機能をデータベースから削除した後も、ロールは引き続き存在するため、必要に応じて手動で削除する必要があります。これにより、 BDRを同じPostgreSQLインスタンスの複数のデータベースで問題なく使用できます。

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

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.state_journal_details

  • bdr.stat_relation

  • bdr.stat_subscription

  • bdr.subscription

  • bdr.subscription_summary

  • bdr.tables

  • bdr.worker_errors

に対するEXECUTE特権

  • bdr.bdr_version

  • bdr.bdr_version_num

  • bdr.conflict_resolution_to_string

  • bdr.conflict_type_to_string

  • 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

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

検証

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

コベリティ

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

  • ミスラC

  • ISO 26262

  • ISO / IEC TS 17961

  • OWASPトップ10

  • CERT C

  • CWEトップ25

  • AUTOSAR

CISベンチマーク

BDRスタックの検証には、2019年12月19日 CIS PostgreSQL Benchmark v1が使用されました。 TPAexecのオプションとして使用可能な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バリアントには追加のパッケージが必要です。