

# oracle\$1fdw 拡張機能による Oracle データベースの操作
<a name="postgresql-oracle-fdw"></a>

 RDS for PostgreSQL DB インスタンス から Oracle データベースにアクセスするには、`oracle_fdw` 拡張機能をインストールして、使用します。この拡張機能は、Oracle データベース用の外部データラッパーです。この拡張機能の詳細については、[oracle\$1fdw](https://github.com/laurenz/oracle_fdw) のドキュメントを参照してください。

`oracle_fdw` 拡張機能は、RDS for PostgreSQL のバージョン 12.7、13.3 以上のバージョンでサポートされています。

**Topics**
+ [oracle\$1fdw 拡張機能の有効化](#postgresql-oracle-fdw.enabling)
+ [例: Amazon RDS for Oracle Database にリンクされた外部サーバーの使用](#postgresql-oracle-fdw.example)
+ [転送時の暗号化の使用](#postgresql-oracle-fdw.encryption)
+ [pg\$1user\$1mappings のビューおよび許可を理解する](#postgresql-oracle-fdw.permissions)

## oracle\$1fdw 拡張機能の有効化
<a name="postgresql-oracle-fdw.enabling"></a>

oracle\$1fdw 拡張機能を使用するには、以下の手順を実行します。

**oracle\$1fdw 拡張機能を有効化するには**
+ `rds_superuser` のアクセス許可を持つアカウントを使用して、次のコマンドを実行します。

  ```
  CREATE EXTENSION oracle_fdw;
  ```

## 例: Amazon RDS for Oracle Database にリンクされた外部サーバーの使用
<a name="postgresql-oracle-fdw.example"></a>

以下は、Amazon RDS for Oracle のデータベースにリンクされた外部サーバーの使用例です。

**RDS for Oracle データベースにリンクされた外部サーバーを作成するには**

1. RDS for Oracle DB インスタンスの以下の点を書き留めます。
   + エンドポイント
   + ポート
   + データベース名

1. 外部サーバーを作成します。

   ```
   test=> CREATE SERVER oradb FOREIGN DATA WRAPPER oracle_fdw OPTIONS (dbserver '//endpoint:port/DB_name');
   CREATE SERVER
   ```

1. `rds_superuser` の権限を持たないユーザーに、(例えば `user1` として) 使用を許可します。

   ```
   test=> GRANT USAGE ON FOREIGN SERVER oradb TO user1;
   GRANT
   ```

1. `user1` として接続し、Oracle ユーザーへのマッピングを作成します。

   ```
   test=> CREATE USER MAPPING FOR user1 SERVER oradb OPTIONS (user 'oracleuser', password 'mypassword');
   CREATE USER MAPPING
   ```

1. Oracle テーブルにリンクされた外部テーブルを作成します。

   ```
   test=> CREATE FOREIGN TABLE mytab (a int) SERVER oradb OPTIONS (table 'MYTABLE');
   CREATE FOREIGN TABLE
   ```

1. 外部テーブルに対しクエリを実行します。

   ```
   test=>  SELECT * FROM mytab;
   a
   ---
   1
   (1 row)
   ```

クエリで次のエラーが報告された場合は、セキュリティグループとアクセスコントロールリストをチェックして、両方のインスタンス間で通信が可能なことを確認します。

```
ERROR: connection for foreign table "mytab" cannot be established
DETAIL: ORA-12170: TNS:Connect timeout occurred
```

## 転送時の暗号化の使用
<a name="postgresql-oracle-fdw.encryption"></a>

PostgreSQL から Oracle への転送時における暗号化は、クライアントとサーバーの設定パラメータの組み合わせに基づき構成されます。Oracle 21c の使用例については、Oracle ドキュメントの「[About the Values for Negotiating Encryption and Integrity](https://docs.oracle.com/en/database/oracle/oracle-database/21/dbseg/configuring-network-data-encryption-and-integrity.html#GUID-3A2AF4AA-AE3E-446B-8F64-31C48F27A2B5)」を参照してください。Amazon RDS で oracle\$1fdw 用に使用されるクライアントは、`ACCEPTED` に設定されています。つまり、暗号化は Oracle データベースサーバーの設定に依存しており、暗号化には Oracle Security Library (libnnz) が使用されます。

データベースが RDS for Oracle 上にある場合の暗号化の設定については、「[Oracle ネイティブネットワーク暗号化](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.Oracle.Options.NetworkEncryption.html)」を参照してください。

## pg\$1user\$1mappings のビューおよび許可を理解する
<a name="postgresql-oracle-fdw.permissions"></a>

PostgreSQL カタログ `pg_user_mapping` は、RDS for PostgreSQL ユーザーからのマッピングを外部データ (リモート) サーバー上のユーザーに保存します。カタログへのアクセスは制限されていますが、`pg_user_mappings` ビューをクリックすると、マッピングが表示されます。以下に、Oracle データベースの例で許可がどのように適用されるかを示す例がありますが、この情報は一般的に外部データラッパーに適用されます。

次の出力では、ロールとアクセス許可が、3 つの異なるサンプルユーザーにマップされていることが示されています。ここで、ユーザー `rdssu1` と `rdssu2` は `rds_superuser` ロールのメンバーであり、`user1` はメンバーではありません。この例では、`psql` メタコマンド `\du` を使用して、既存のロールを一覧表示します。

```
test=>  \du
                                                               List of roles
    Role name    |                         Attributes                         |                          Member of
-----------------+------------------------------------------------------------+-------------------------------------------------------------
 rdssu1          |                                                            | {rds_superuser}
 rdssu2          |                                                            | {rds_superuser}
 user1           |                                                            | {}
```

すべてのユーザー (`rds_superuser` 権限を持っているユーザーを含む) は、`pg_user_mappings` テーブルで独自のユーザーマッピング (`umoptions`) を表示することが許可されています。次の例に示すように、`rdssu1` がすべてのユーザーマッピングを取得しようとすると、`rdssu1``rds_superuser` 権限があっても、次のエラーが発生します。

```
test=> SELECT * FROM pg_user_mapping;
ERROR: permission denied for table pg_user_mapping
```

次に例をいくつか示します。

```
test=> SET SESSION AUTHORIZATION rdssu1;
SET
test=> SELECT * FROM pg_user_mappings;
 umid  | srvid | srvname | umuser | usename    |            umoptions
-------+-------+---------+--------+------------+----------------------------------
 16414 | 16411 | oradb   |  16412 | user1      |
 16423 | 16411 | oradb   |  16421 | rdssu1     | {user=oracleuser,password=mypwd}
 16424 | 16411 | oradb   |  16422 | rdssu2     |
 (3 rows)

test=> SET SESSION AUTHORIZATION rdssu2;
SET
test=> SELECT * FROM pg_user_mappings;
 umid  | srvid | srvname | umuser | usename    |            umoptions
-------+-------+---------+--------+------------+----------------------------------
 16414 | 16411 | oradb   |  16412 | user1      |
 16423 | 16411 | oradb   |  16421 | rdssu1     |
 16424 | 16411 | oradb   |  16422 | rdssu2     | {user=oracleuser,password=mypwd}
 (3 rows)

test=> SET SESSION AUTHORIZATION user1;
SET
test=> SELECT * FROM pg_user_mappings;
 umid  | srvid | srvname | umuser | usename    |           umoptions
-------+-------+---------+--------+------------+--------------------------------
 16414 | 16411 | oradb   |  16412 | user1      | {user=oracleuser,password=mypwd}
 16423 | 16411 | oradb   |  16421 | rdssu1     |
 16424 | 16411 | oradb   |  16422 | rdssu2     |
 (3 rows)
```

`information_schema._pg_user_mappings` と `pg_catalog.pg_user_mappings` の間に実装上の違いがあるため、手動で作成された `rds_superuser` が `pg_catalog.pg_user_mappings` 内のパスワードを表示する場合には、追加のアクセス許可が必要となります。

`rds_superuser` が `information_schema._pg_user_mappings` 内のパスワードを表示する際には、追加のアクセス許可は必要ありません。

`rds_superuser` ロールを持たないユーザーの場合、以下の条件の下でのみ、`pg_user_mappings` 内のパスワードを表示できます。
+ 現在のユーザーはマップされているユーザーであり、サーバーの所有者であるか、そのサーバーに対する `USAGE` 権限を保持しています。
+ 現在のユーザーはサーバーの所有者であり、マッピングは `PUBLIC` となっています。