View a markdown version of this page

Using Amazon RDS delegated extension support for PostgreSQL - Amazon Relational Database Service

Using Amazon RDS delegated extension support for PostgreSQL

Using Amazon RDS delegated extension support for PostgreSQL, you can delegate the extension management to a user who need not be an rds_superuser. With this delegated extension support, a new role called rds_extension is created and you must assign this to a user to manage other extensions. This role can create, update, and drop extensions.

You can specify the extensions that can be installed on your RDS DB instance, by listing them in the rds.allowed_extensions parameter. For more information, see Using PostgreSQL extensions with Amazon RDS for PostgreSQL.

You can restrict the list of extensions available that can be managed by the user with the rds_extension role using rds.allowed_delegated_extensions parameter.

The delegated extension support is available in the following versions:

  • All higher versions

  • 16.4 and higher 16 versions

  • 15.8 and higher 15 versions

  • 14.13 and higher 14 versions

  • 13.16 and higher 13 versions

  • 12.20 and higher 12 versions

Turning on delegate extension support to a user

You must perform the following to enable delegate extension support to a user:

  1. Grant rds_extension role to a user – Connect to the database as rds_superuser and execute the following command:

    Postgres => grant rds_extension to user_name;
  2. Set the list of extensions available for delegated users to manage – The rds.allowed_delegated_extensions allows you to specify a subset of the available extensions using rds.allowed_extensions in the DB cluster parameter. You can perform this at one of the following levels:

    • In the cluster or the instance parameter group, through the AWS Management Console or API. For more information, see Parameter groups for Amazon RDS.

    • Use the following command at the database level:

      alter database database_name set rds.allowed_delegated_extensions = 'extension_name_1, extension_name_2,...extension_name_n';
    • Use the following command at the user level:

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

    You need not restart the database after changing the rds.allowed_delegated_extensions dynamic parameter.

  3. Allow access to the delegated user to objects created during the extension creation process – Certain extensions create objects that require additional permissions to be granted before the user with rds_extension role can access them. The rds_superuser must grant the delegated user access to those objects. One of the options is to use an event trigger to automatically grant permission to the delegated user.

    Example of event trigger

    If you want to allow a delegated user with rds_extension to use extensions that require setting permissions on their objects created by the extension creation, you can customize the below example of an event trigger and add only the extensions for which you want the delegated users to have access to the full functionality. This event trigger can be created on template1 (the default template), therefore all database created from template1 will have that event trigger. When a delegated user installs the extension, this trigger will automatically grant ownership on the objects created by the extension.

    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_catalog.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 pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.us_gaz TO %I WITH GRANT OPTION;', schemaname, databaseowner); EXECUTE pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.us_lex TO %I WITH GRANT OPTION;', schemaname, databaseowner); EXECUTE pg_catalog.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 pg_catalog.format('ALTER TEXT SEARCH DICTIONARY %I.intdict OWNER TO %I;', schemaname, databaseowner); ELSIF r.object_identity = 'pg_partman' THEN EXECUTE pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.part_config TO %I WITH GRANT OPTION;', schemaname, databaseowner); EXECUTE pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.part_config_sub TO %I WITH GRANT OPTION;', schemaname, databaseowner); EXECUTE pg_catalog.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 pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON ALL TABLES IN SCHEMA topology TO %I WITH GRANT OPTION;', databaseowner); EXECUTE pg_catalog.format('GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA topology TO %I WITH GRANT OPTION;', databaseowner); EXECUTE pg_catalog.format('GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA topology TO %I WITH GRANT OPTION;', databaseowner); EXECUTE pg_catalog.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();

Configuration used in RDS delegated extension support for PostgreSQL

Configuration Name Description Default Value Notes Who can modify or grant permission

rds.allowed_delegated_extensions

This parameter limits the extensions a rds_extension role can manage in a database. It must be a subset of rds.allowed_extensions.

empty string

  • By default, this parameter is empty string, which means that no extensions have been delegated to users with rds_extension.

  • Any supported extension can be added if the user has permission to do so. To do this, set the rds.allowed_delegated_extensions parameter to a string of comma-separated extension names. By adding a list of extensions to this parameter, you explicitly identify the extensions that the user with the rds_extension role can install.

  • When set to *, it means that all extensions listed in rds_allowed_extensions are delegated to users with rds_extension role.

To learn more about setting up this parameter, see Turning on delegate extension support to a user.

rds_superuser

rds.allowed_extensions

This parameter lets the customer limit the extensions that can be installed in the RDS DB instance. For more information, see Restricting installation of PostgreSQL extensions

"*"

By default, this parameter is set to "*", which means that all extensions supported on RDS for PostgreSQL and Aurora PostgreSQL are allowed to be created by users with necessary privileges.

Empty means no extensions can be installed in the RDS DB instance.

administrator

rds-delegated_extension_allow_drop_cascade

This parameter controls the ability for user with rds_extension to drop the extension using a cascade option.

off

By default, rds-delegated_extension_allow_drop_cascade is set to off. This means that users with rds_extension are not allowed to drop an extension using the cascade option.

To grant that ability, the rds.delegated_extension_allow_drop_cascade parameter should be set to on.

rds_superuser

Turning off the support for the delegated extension

Turning off partially

The delegated users can’t create new extensions but can still update existing extensions.

  • Reset rds.allowed_delegated_extensions to the default value in the DB cluster parameter group.

  • Use the following command at the database level:

    alter database database_name reset rds.allowed_delegated_extensions;
  • Use the following command at the user level:

    alter user user_name reset rds.allowed_delegated_extensions;
Turning off fully

Revoking rds_extension role from a user will revert the user to standard permissions. The user can no longer create, update, or drop extensions.

postgres => revoke rds_extension from user_name;

Benefits of using Amazon RDS delegated extension support

By using Amazon RDS delegated extension support for PostgreSQL, you securely delegate the extension management to users who do not have the rds_superuser role. This feature provides the following benefits:

  • You can easily delegate extension management to users of your choice.

  • This doesn’t require rds_superuser role.

  • Provides ability to support different set of extensions for different databases in the same DB cluster.

Limitation of Amazon RDS delegated extension support for PostgreSQL

  • Objects created during the extension creation process may require additional privileges for the extension to function properly.

  • Some extensions can't be managed by the delegated extension user by default, including the following: log_fdw, pg_cron, pg_tle, pgactive, pglogical, postgis_raster, postgis_tiger_geocoder, postgis_topology.

Permissions required for certain extensions

In order to create, use, or update the following extensions, the delegated user should have the necessary privileges on the following functions, tables, and schema.

Extensions that need ownership or permissions Function Tables Schema Text Search Dictionary Comment

address_standardizer_data_us

none