PostgreSQL での Amazon RDS 委任拡張機能サポートの使用 - Amazon Relational Database Service

PostgreSQL での Amazon RDS 委任拡張機能サポートの使用

PostgreSQL に対して Amazon RDS 委任拡張機能のサポートを使用すると、拡張機能管理を rds_superuser である必要のないユーザーに委任できます。この委任拡張機能のサポートにより、rds_extension という新しいロールが作成され、他の拡張機能を管理するには、これをユーザーに割り当てる必要があります。このロールは、拡張機能を作成、更新、削除できます。

RDS DB インスタンスにインストール可能な拡張機能は、rds.allowed_extensions パラメータにそれらをリストアップして指定することができます。詳細については、「Amazon RDS for PostgreSQL で PostgreSQL 拡張機能を使用する」を参照してください。

rds.allowed_delegated_extensions パラメータを使用して、rds_extension ロールでユーザーが管理できる拡張機能のリストを制限できます。

委任拡張機能のサポートは、次のバージョンで利用できます。

  • すべての上位バージョン

  • 16.4 以降の 16 バージョン

  • 15.8 以降の 15 バージョン

  • 14.13 以降の 14 バージョン

  • 13.16 以降の 13 バージョン

  • 12.20 以降の 12 バージョン

ユーザーに対する委任拡張機能のサポートの有効化

ユーザーに対して委任拡張機能のサポートを有効にするには、以下を実行する必要があります。

  1. ユーザーに rds_extension ロールを付与するrds_superuser としてデータベースに接続し、次のコマンドを実行します。

    Postgres => grant rds_extension to user_name;
  2. 委任されたユーザーが管理できる拡張機能のリストを設定するrds.allowed_delegated_extensions では、DB クラスターパラメータで rds.allowed_extensions を使用して、使用可能な拡張機能のサブセットを指定できます。これは、次のいずれかのレベルで実行できます。

    • クラスターまたはインスタンスパラメータグループで、AWS Management Console または API を使用します。詳細については、「Amazon RDS のパラメータグループ」を参照してください。

    • データベースレベルで次のコマンドを使用します。

      alter database database_name set rds.allowed_delegated_extensions = 'extension_name_1, extension_name_2,...extension_name_n';
    • ユーザーレベルで次のコマンドを使用します。

      alter user user_name set rds.allowed_delegated_extensions = 'extension_name_1, extension_name_2,...extension_name_n';
    注記

    rds.allowed_delegated_extensions 動的パラメータを変更した後にデータベースを再起動する必要はありません。

  3. 拡張機能の作成プロセス中に作成されたオブジェクトへのアクセスを委任されたユーザーに許可する – 特定の拡張機能では、rds_extension ロールを持つユーザーがオブジェクトにアクセスする前に、追加のアクセス許可を付与する必要があるオブジェクトが作成されます。rds_superuser は、それらのオブジェクトへのアクセス権を委任されたユーザーに付与する必要があります。オプションの 1 つは、イベントトリガーを使用して、委任されたユーザーにアクセス許可を自動的に付与することです。詳細については、「委任拡張機能のサポートの無効化」のイベントトリガーの例を参照してください。

PostgreSQL での RDS 委任拡張機能サポートで使用される設定

設定名 説明 デフォルト値 メモ アクセス許可を変更または付与できるユーザー

rds.allowed_delegated_extensions

このパラメータは、rds_extension ロールがデータベースで管理できる拡張機能を制限します。rds.allowed_extensions のサブセットである必要があります。

空の文字列

  • デフォルトでは、このパラメータは空の文字列です。つまり、rds_extension を持つユーザーに拡張機能が委任されていません。

  • ユーザーにアクセス許可がある場合は、サポートされている拡張機能を追加できます。これを実行するためには、rds.allowed_delegated_extensions パラメータをカンマで区切った拡張子名の文字列に設定します。このパラメータに拡張機能のリストを追加すると、rds_extension ロールのあるユーザーがインストールできる拡張機能を明示的に特定できます。

  • * に設定すると、rds_allowed_extensions にリストされているすべての拡張機能が rds_extension ロールを持つユーザーに委任されます。

このパラメータの設定の詳細については、「ユーザーに対する委任拡張機能のサポートの有効化」を参照してください。

rds_superuser

rds.allowed_extensions

このパラメータにより、カスタマーは RDS DB インスタンスにインストールできる拡張機能を制限できます。詳細については、「PostgreSQL 拡張機能のインストールの制限」を参照してください。

"*"

デフォルトでは、このパラメータは「*」に設定されています。つまり、RDS for PostgreSQL および Aurora PostgreSQL でサポートされているすべての拡張機能は、必要な権限を持つユーザーが作成できます。

空の場合、RDS DB インスタンスに拡張機能をインストールできないことを意味します。

管理者

rds-delegated_extension_allow_drop_cascade

このパラメータは、rds_extension を持つユーザーがカスケードオプションを使用して拡張機能を削除する機能を制御します。

オフ

デフォルトで、rds-delegated_extension_allow_drop_cascadeoff に設定されています。つまり、rds_extension を持つユーザーは、カスケードオプションを使用して拡張機能を削除することはできません。

その機能を許可するには、rds.delegated_extension_allow_drop_cascade パラメータを on に設定する必要があります。

rds_superuser

委任拡張機能のサポートの無効化

部分的にオフにする

委任されたユーザーは、新しい拡張機能を作成することはできませんが、既存の拡張機能を更新することはできます。

  • DB クラスターパラメータグループでデフォルト値に rds.allowed_delegated_extensions をリセットします。

  • データベースレベルで次のコマンドを使用します。

    alter database database_name reset rds.allowed_delegated_extensions;
  • ユーザーレベルで次のコマンドを使用します。

    alter user user_name reset rds.allowed_delegated_extensions;
すべてオフにする

ユーザーから rds_extension ロールを取り消すと、ユーザーは標準のアクセス許可に戻ります。ユーザーは拡張機能を作成、更新、削除できなくなります。

postgres => revoke rds_extension from user_name;
イベントトリガーの例

rds_extension を持つ委任ユーザーに、拡張機能の作成によって作成されたオブジェクトに対するアクセス許可の設定を必要とする拡張機能の使用を許可する場合は、次のイベントトリガーの例をカスタマイズし、委任されたユーザーに完全な機能へのアクセスを許可する拡張機能のみを追加できます。このイベントトリガーは template1 (デフォルトのテンプレート) で作成できるため、template1 から作成されたすべてのデータベースにそのイベントトリガーがあります。委任されたユーザーが拡張機能をインストールすると、このトリガーは拡張機能によって作成されたオブジェクトの所有権を自動的に付与します。

CREATE OR REPLACE FUNCTION create_ext() RETURNS event_trigger AS $$ DECLARE schemaname TEXT; databaseowner TEXT; r RECORD; BEGIN IF tg_tag = 'CREATE EXTENSION' and current_user != 'rds_superuser' THEN RAISE NOTICE 'SECURITY INVOKER'; RAISE NOTICE 'user: %', current_user; FOR r IN SELECT * FROM pg_event_trigger_ddl_commands() LOOP CONTINUE WHEN r.command_tag != 'CREATE EXTENSION' OR r.object_type != 'extension'; schemaname = ( SELECT n.nspname FROM pg_catalog.pg_extension AS e INNER JOIN pg_catalog.pg_namespace AS n ON e.extnamespace = n.oid WHERE e.oid = r.objid ); databaseowner = ( SELECT pg_catalog.pg_get_userbyid(d.datdba) FROM pg_catalog.pg_database d WHERE d.datname = current_database() ); RAISE NOTICE 'Record for event trigger %, objid: %,tag: %, current_user: %, schema: %, database_owenr: %', r.object_identity, r.objid, tg_tag, current_user, schemaname, databaseowner; IF r.object_identity = 'address_standardizer_data_us' THEN EXECUTE format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.us_gaz TO %I WITH GRANT OPTION;', schemaname, databaseowner); EXECUTE format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.us_lex TO %I WITH GRANT OPTION;', schemaname, databaseowner); EXECUTE format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.us_rules TO %I WITH GRANT OPTION;', schemaname, databaseowner); ELSIF r.object_identity = 'dict_int' THEN EXECUTE format('ALTER TEXT SEARCH DICTIONARY %I.intdict OWNER TO %I;', schemaname, databaseowner); ELSIF r.object_identity = 'pg_partman' THEN EXECUTE format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.part_config TO %I WITH GRANT OPTION;', schemaname, databaseowner); EXECUTE format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.part_config_sub TO %I WITH GRANT OPTION;', schemaname, databaseowner); EXECUTE format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.custom_time_partitions TO %I WITH GRANT OPTION;', schemaname, databaseowner); ELSIF r.object_identity = 'postgis_topology' THEN EXECUTE format('GRANT SELECT, UPDATE, INSERT, DELETE ON ALL TABLES IN SCHEMA topology TO %I WITH GRANT OPTION;', databaseowner); EXECUTE format('GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA topology TO %I WITH GRANT OPTION;', databaseowner); EXECUTE format('GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA topology TO %I WITH GRANT OPTION;', databaseowner); EXECUTE format('GRANT USAGE ON SCHEMA topology TO %I WITH GRANT OPTION;', databaseowner); END IF; END LOOP; END IF; END; $$ LANGUAGE plpgsql SECURITY DEFINER; CREATE EVENT TRIGGER log_create_ext ON ddl_command_end EXECUTE PROCEDURE create_ext();

Amazon RDS 委任拡張機能サポートの使用のメリット

PostgreSQL に対して Amazon RDS 委任拡張機能のサポートを使用すると、拡張機能管理を rds_superuser ロールを持たないユーザーに対してセキュアに委任できます。この機能には次の利点があります。

  • 選択したユーザーに拡張機能管理を簡単に委任できます。

  • これには rds_superuser ロールは不要です。

  • 同じ DB クラスター内の異なるデータベースに対して、異なる拡張機能セットをサポートする機能を提供します。

PostgreSQL での Amazon RDS 委任拡張機能サポートの制限

  • 拡張機能の作成プロセス中に作成されたオブジェクトは、拡張機能が正しく機能するために追加の権限が必要になる場合があります。

  • 一部の拡張機能は、デフォルトで log_fdwpg_cronpg_tlepgactivepglogicalpostgis_rasterpostgis_tiger_geocoderpostgis_topology などの委任された拡張機能ユーザーが管理することはできません。

特定の拡張機能に必要なアクセス許可

次の拡張機能を作成、使用、または更新するには、委任されたユーザーに次の関数、テーブル、スキーマに対する必要な権限が必要です。

所有権またはアクセス許可が必要な拡張機能 機能 テーブル Schema テキスト検索ディクショナリ コメント

address_standardizer_data_us

なし

us_gaz、us_lex、us_lex、I.us_rules

なし

なし

なし

amcheck

bt_index_check、bt_index_parent_check

なし

なし

なし

なし

dict_int

なし

なし

なし

intdict

なし

pg_partman

なし

custom_time_partitions、part_config、part_config_sub

なし

なし

なし

pg_stat_statements

なし

なし

なし

なし

なし

PostGIS

st_tileenvelope

spatial_ref_sys

なし

なし

なし

postgis_raster

なし

なし

なし

なし

なし

postgis_topology

なし

トポロジ、レイヤー

トポロジ

なし

委任されたユーザーはデータベース所有者であること

log_fdw

create_foreign_table_for_log_file

なし

なし

なし

なし

rds_tools

role_password_encryption_type

なし

なし

なし

なし

postgis_tiger_geocoder

なし

geocode_settings_default, geocode_settings

tiger

なし

なし

pg_freespacemap

pg_freespace

なし

なし

なし

なし

pg_visibility

pg_visibility

なし

なし

なし

なし

セキュリティに関する考慮事項

rds_extension ロールを持つユーザーは、接続権限を持つすべてのデータベースの拡張機能を管理できることに注意してください。委任されたユーザーが 1 つのデータベースの拡張機能を管理する場合は、各データベースのパブリックからすべての権限を取り消し、その特定のデータベースの接続権限を委任されたユーザーに明示的に付与することをお勧めします。

ユーザーが複数のデータベースから情報にアクセスできる拡張機能がいくつかあります。これらの拡張機能を rds.allowed_delegated_extensions に追加する前に、rds_extension を付与するユーザーにクロスデータベース機能があることを確認してください。例えば、postgres_fdwdblink は、同じインスタンスまたはリモートインスタンス上のデータベース間でクエリを実行する機能を提供します。log_fdw は postgres エンジンのログファイルを読み取ります。これらは、インスタンス内のすべてのデータベース用であり、複数のデータベースからのスロークエリやエラーメッセージが含まれている可能性があります。pg_cron は、DB インスタンスでスケジュールされたバックグラウンドジョブの実行を有効にし、別のデータベースで実行するようにジョブを設定できます。

DROP EXTENSION CASCADE を無効化

rds_extension ロールを持つユーザーがカスケードオプションを使用して拡張機能を削除する機能は、rds.delegated_extension_allow_drop_cascade パラメータによって制御されます。デフォルトで、rds-delegated_extension_allow_drop_cascadeoff に設定されています。つまり、rds_extension ロールを持つユーザーは、以下のクエリに示すように、カスケードオプションを使用して拡張機能を削除することはできません。

DROP EXTENSION CASCADE;

これにより、拡張機能に依存するオブジェクト、およびそれらのオブジェクトに依存するすべてのオブジェクトが自動的に削除されます。カスケードオプションを使用しようとすると、エラーが発生します。

その機能を許可するには、rds.delegated_extension_allow_drop_cascade パラメータを on に設定する必要があります。

rds.delegated_extension_allow_drop_cascade 動的パラメータを変更しても、データベースを再起動する必要はありません。これは、次のいずれかのレベルで実行できます。

  • クラスターまたはインスタンスパラメータグループで、AWS Management Console または API を使用します。

  • データベースレベルで次のコマンドを使用する。

    alter database database_name set rds.delegated_extension_allow_drop_cascade = 'on';
  • ユーザーレベルで次のコマンドを使用する。

    alter role tenant_user set rds.delegated_extension_allow_drop_cascade = 'on';

委任拡張機能サポートを使用して追加できる拡張機能の例

  • rds_tools

    extension_test_db=> create extension rds_tools; CREATE EXTENSION extension_test_db=> SELECT * from rds_tools.role_password_encryption_type() where rolname = 'pg_read_server_files'; ERROR: permission denied for function role_password_encryption_type
  • amcheck

    extension_test_db=> CREATE TABLE amcheck_test (id int); CREATE TABLE extension_test_db=> INSERT INTO amcheck_test VALUES (generate_series(1,100000)); INSERT 0 100000 extension_test_db=> CREATE INDEX amcheck_test_btree_idx ON amcheck_test USING btree (id); CREATE INDEX extension_test_db=> create extension amcheck; CREATE EXTENSION extension_test_db=> SELECT bt_index_check('amcheck_test_btree_idx'::regclass); ERROR: permission denied for function bt_index_check extension_test_db=> SELECT bt_index_parent_check('amcheck_test_btree_idx'::regclass); ERROR: permission denied for function bt_index_parent_check
  • pg_freespacemap

    extension_test_db=> create extension pg_freespacemap; CREATE EXTENSION extension_test_db=> SELECT * FROM pg_freespace('pg_authid'); ERROR: permission denied for function pg_freespace extension_test_db=> SELECT * FROM pg_freespace('pg_authid',0); ERROR: permission denied for function pg_freespace
  • pg_visibility

    extension_test_db=> create extension pg_visibility; CREATE EXTENSION extension_test_db=> select * from pg_visibility('pg_database'::regclass); ERROR: permission denied for function pg_visibility
  • postgres_fdw

    extension_test_db=> create extension postgres_fdw; CREATE EXTENSION extension_test_db=> create server myserver foreign data wrapper postgres_fdw options (host 'foo', dbname 'foodb', port '5432'); ERROR: permission denied for foreign-data wrapper postgres_fdw