

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 PostgreSQL 的 Amazon Aurora 委派的延伸模組支援
<a name="Aurora_delegated_ext"></a>

使用 PostgreSQL 的 Amazon Aurora 委派延伸模組支援，您就可以將延伸模組管理委派給不必是 `rds_superuser` 的使用者。系統會透過此委派延伸模組支援，建立名為 `rds_extension` 的新角色，而您必須將此角色指派給使用者以管理其他延伸模組。此角色可以建立、更新和捨棄延伸模組。

您可在 `rds.allowed_extensions` 參數中列出延伸模組，指定可在 Aurora PostgreSQL 資料庫執行個體上安裝的延伸模組。如需詳細資訊，請參閱[將 PostgreSQL 延伸模組與 Amazon RDS for PostgreSQL 搭配使用](https://docs.aws.amazon.com//AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Extensions.html)。

您可以使用 `rds.allowed_delegated_extensions` 參數，限制可由具有 `rds_extension` 角色的使用者所管理的可用延伸模組清單。

您可在下列版本中取得委派的延伸模組支援：
+ 所有更高版本
+ 15.5 版和更新的 15 版本
+ 14.10 版和更新的 14 版本
+ 13.13 版和更新的 13 版本
+ 12.17 版和更新的 12 版本

**Topics**
+ [為使用者開啟委派延伸模組支援](#AuroraPostgreSQL.delegated_ext_mgmt)
+ [在 PostgreSQL 的 Aurora 委派延伸模組支援中使用的組態](#AuroraPostgreSQL.delegated_ext_config)
+ [關閉委派延伸模組的支援](#AuroraPostgreSQL.delegated_ext_disable)
+ [使用 Amazon Aurora 委派延伸模組支援的優勢](#AuroraPostgreSQL.delegated_ext_benefits)
+ [PostgreSQL 的 Aurora 委派延伸模組支援限制](#AuroraPostgreSQL.delegated_ext_limit)
+ [特定延伸模組所需的許可](#AuroraPostgreSQL.delegated_ext_perm)
+ [安全考量](#AuroraPostgreSQL.delegated_ext_sec)
+ [已停用捨棄延伸模組層疊](#AuroraPostgreSQL.delegated_ext_drop)
+ [可使用委派延伸模組支援新增的延伸模組範例](#AuroraPostgreSQL.delegated_ext_support)

## 為使用者開啟委派延伸模組支援
<a name="AuroraPostgreSQL.delegated_ext_mgmt"></a>

您必須執行下列動作，才能將延伸模組支援委派給使用者：

1. **將 `rds_extension` 角色授予使用者**：以 `rds_superuser` 身分連線至資料庫，以及執行下列命令：

   ```
   Postgres => grant rds_extension to user_name;
   ```

1. **設定可供委派使用者管理的延伸模組清單**：`rds.allowed_delegated_extensions` 可讓您在資料庫叢集參數中使用 `rds.allowed_extensions` 指定可用延伸模組子集。您可以在下列其中一個層級執行此操作：
   + 在叢集或執行個體參數群組中，透過 AWS 管理主控台 或 API。如需詳細資訊，請參閱[Amazon Aurora 的參數群組](USER_WorkingWithParamGroups.md)。
   + 在資料庫層級使用以下命令：

     ```
     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` 動態參數後，您就不需要重新啟動資料庫。

1. **允許委派使用者存取在延伸模組建立程序期間建立的物件**：某些延伸模組會建立需要授予額外許可的物件，才能讓具有 `rds_extension` 角色的使用者存取這些物件。`rds_superuser` 必須向委派的使用者授予對那些物件的存取權。其中一個選項是使用事件觸發，自動將許可授予委派的使用者。

   **事件觸發範例**

   如要允許具備 `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_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();
   ```

## 在 PostgreSQL 的 Aurora 委派延伸模組支援中使用的組態
<a name="AuroraPostgreSQL.delegated_ext_config"></a>


| 組態名稱 | Description | 預設值 | 備註 | 誰可以修改或授予許可 | 
| --- | --- | --- | --- | --- | 
| `rds.allowed_delegated_extensions` | 此參數會限制 rds\$1extension 角色可在資料庫中管理的延伸模組。其必須是 rds.allowed\$1extensions 的子集。 | 空字串 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/AmazonRDS/latest/AuroraUserGuide/Aurora_delegated_ext.html) 若要進一步了解如何設定此參數，請參閱[為使用者開啟委派延伸模組支援](#AuroraPostgreSQL.delegated_ext_mgmt)。 | rds\$1superuser | 
| `rds.allowed_extensions` | 此參數可讓客戶限制 Aurora PostgreSQL 資料庫執行個體中可安裝的延伸模組。如需詳細資訊，請參閱[限制安裝 PostgreSQL 延伸模組](https://docs.aws.amazon.com//AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html#PostgreSQL.Concepts.General.FeatureSupport.Extensions.Restriction)。 | "\$1" | 根據預設，此參數會設為「\$1」，這表示具有必要權限的使用者都能夠建立 RDS for PostgreSQL 和 Aurora PostgreSQL 上支援的所有延伸模組。 空白表示無法在 Aurora PostgreSQL 資料庫執行個體中安裝任何延伸模組。 | 管理員 | 
| `rds-delegated_extension_allow_drop_cascade` | 此參數會控制具有 `rds_extension` 的使用者是否能使用層疊選項捨棄延伸模組。 | off | 根據預設，`rds-delegated_extension_allow_drop_cascade` 會設定為 `off`。這表示具有 `rds_extension` 的使用者無法使用層疊選項捨棄延伸模組。 若要授予該能力，則應將 `rds.delegated_extension_allow_drop_cascade` 參數設為 `on`。 | rds\$1superuser | 

## 關閉委派延伸模組的支援
<a name="AuroraPostgreSQL.delegated_ext_disable"></a>

**部分關閉**  
委派的使用者無法建立新的延伸模組，但仍可以更新現有的延伸模組。
+ 將資料庫叢集參數群組中的 `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;
```

## 使用 Amazon Aurora 委派延伸模組支援的優勢
<a name="AuroraPostgreSQL.delegated_ext_benefits"></a>

透過使用 PostgreSQL 的 Amazon Aurora 委派延伸模組支援，您就可以將延伸模組管理安全地委派給不具備 `rds_superuser` 角色的使用者。此功能提供下列優勢：
+ 您可以輕鬆地將延伸模組管理委派給所選的使用者。
+ 這不需要 `rds_superuser` 角色。
+ 提供支援相同資料庫叢集中不同資料庫不同延伸模組集的能力。

## PostgreSQL 的 Aurora 委派延伸模組支援限制
<a name="AuroraPostgreSQL.delegated_ext_limit"></a>
+ 在延伸模組建立程序期間建立的物件可能需要額外的權限，延伸模組才能正常運作。

## 特定延伸模組所需的許可
<a name="AuroraPostgreSQL.delegated_ext_perm"></a>

為了建立、使用或更新下列延伸模組，委派的使用者應具備下列功能、資料表和結構描述的必要權限。


| 需要擁有權或許可的延伸模組 | 函式 | 表格 | 結構描述 | 文字搜尋字典 | Comment | 
| --- | --- | --- | --- | --- | --- | 
| address\$1standardizer\$1data\$1us |  | us\$1gaz、us\$1lex、us\$1lex、I.us\$1rules |   |  |  | 
| amcheck | bt\$1index\$1check、bt\$1index\$1parent\$1check |  |   |  |  | 
| dict\$1int |  |  |  | intdict |  | 
| pg\$1partman |  | custom\$1time\$1partitions、part\$1config、part\$1config\$1sub |  |  |  | 
| pg\$1stat\$1statements |  |  |  |  |  | 
| PostGIS | st\$1tileenvelope | spatial\$1ref\$1sys |  |  |  | 
| postgis\$1raster |  |  |  |  |  | 
| postgis\$1topology |  | 拓撲、層 | 拓撲 |  | 委派使用者必須是資料庫擁有者 | 
| log\$1fdw | create\$1foreign\$1table\$1for\$1log\$1file |  |  |  |  | 
| rds\$1tools | role\$1password\$1encryption\$1type |  |  |  |  | 
| postgis\$1tiger\$1geocoder |  | geocode\$1settings\$1default、geocode\$1settings | tiger |  |  | 
| pg\$1freespacemap | pg\$1freespace |  |  |  |  | 
| pg\$1visibility | pg\$1visibility |  |  |  |  | 

## 安全考量
<a name="AuroraPostgreSQL.delegated_ext_sec"></a>

 請記住，具有 `rds_extension` 角色的使用者將能夠在其具有連線權限的所有資料庫上管理延伸模組。若需讓委派使用者管理單一資料庫的延伸模組，良好做法是撤銷每個資料庫上公有的所有權限，然後明確將該特定資料庫的連線權限授予委派的使用者。

 有多種延伸模組，使用者可透過這些延伸模組從多個資料庫存取資訊。在將這些延伸模組新增至 `rds.allowed_delegated_extensions` 前，請確定您授予 `rds_extension` 的使用者具有跨資料庫功能。例如，`postgres_fdw` 和 `dblink` 會提供在相同執行個體或遠端執行個體上跨資料庫查詢的功能。`log_fdw` 會讀取適用於執行個體中所有資料庫的 postgres 引擎日誌檔案，可能包含來自多個資料庫的緩慢查詢或錯誤訊息。`pg_cron` 會在資料庫執行個體上執行排程背景任務，並可將任務設定為在不同的資料庫中執行。

## 已停用捨棄延伸模組層疊
<a name="AuroraPostgreSQL.delegated_ext_drop"></a>

 具有 `rds_extension` 角色的使用者是否能捨棄具有層疊選項的延伸模組，由 `rds.delegated_extension_allow_drop_cascade` 參數所控制。根據預設，`rds-delegated_extension_allow_drop_cascade` 會設定為 `off`。如以下查詢所示，這表示具有 `rds_extension` 角色的使用者不能使用層疊選項捨棄延伸模組。

```
DROP EXTENSION CASCADE;
```

因為這會自動捨棄相依於延伸模組的物件，進而捨棄所有相依於這些物件的物件。嘗試使用層疊選項將導致錯誤。

 若要授予該能力，則應將 `rds.delegated_extension_allow_drop_cascade` 參數設為 `on`。

 變更 `rds.delegated_extension_allow_drop_cascade` 動態參數不需要重新啟動資料庫。您可以在以下其中一個層級執行此操作：
+ 在叢集或執行個體參數群組中，透過 AWS 管理主控台 或 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';
  ```

## 可使用委派延伸模組支援新增的延伸模組範例
<a name="AuroraPostgreSQL.delegated_ext_support"></a>
+ `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
  ```