[OCI]Autonomous DatabaseからAmazon S3にARNを用いたロールベースの認証でアクセスしてデータ連携してみた

# はじめに

Autonomous Databaseは、Amazon S3上にあるデータを直接参照できます。

今回は、ARNのロールベースの認証を利用してAutonomous DatabaseからAmazon S3にアクセスし、バケットの内のオブジェクトの表示と、バケット内のオブジェクト（ファイル）をもとにした外部表の作成を試してみました。

ARNのロールベースの認証を利用すると、IAMアクセスキーを使用した認証の場合と比較して、安全かつ柔軟にデータ連携を行うことができます。

# 1. ARNを用いたロールベースの認証の有効化
Autonomous DatabaseでARNのロールベースの認証を使用するクレデンシャルを有効にするには、以下のような構文でDBMS_CLOUD_ADMIN.ENABLE_AWS_ARNプロシージャを使用します。
```
EXEC DBMS_CLOUD_ADMIN.ENABLE_AWS_ARN(username => 'DBユーザ名'); 
```
有効化するユーザにadminを指定して、上記を実行してみます。
```
SQL> EXEC DBMS_CLOUD_ADMIN.ENABLE_AWS_ARN(username => 'admin'); 

PL/SQLプロシージャが正常に完了しました。

SQL>
```
adminユーザで、ARNのロールベースの認証を使用するクレデンシャルが有効になりました。

cloud_integrationsビューを検索してaws_user_arnの値を確認します。
```
SELECT param_name, param_value FROM cloud_integrations WHERE param_name LIKE 'aws%';
```
上記のSQLを実行してみます。
```
SQL> SELECT param_name, param_value FROM cloud_integrations WHERE param_name LIKE 'aws%';

PARAM_NAME	    PARAM_VALUE
--------------- --------------------------------------------------
aws_user_arn	arn:aws:iam::XXXXXXXXXXXX:user/xxxxxxxx

SQL>
```
aws_user_arnの値をメモしておきます。

v$pdbsビューを検索してcloud_identity列内にあるDATABASE_OCIDの値を確認します。
```
SELECT json_value(cloud_identity, '$.DATABASE_OCID') database_ocid FROM v$pdbs;
```
DATABASE_OCIDの値をメモしておきます。

```
SQL> SELECT json_value(cloud_identity, '$.DATABASE_OCID') database_ocid FROM v$pdbs;

DATABASE_OCID
--------------------------------------------------------------------------------
OCID1.AUTONOMOUSDATABASE.OC1.AP-TOKYO-1.ANXHILJRSSL65IQAWFH2EIJ5VHOBLMBBC32F3WUR
6DBQPOKUDJPXP74X3X4Q


SQL>
```

# 2. AWSのポリシーとロールの設定

必要に応じて、Autonomous Databaseに付与するアクセス権限を含むポリシーを作成します。
今回はS3へのフルアクセスが可能な既存のポリシー「AmazonS3FullAccess」を使用します。
（実際は、最低限必要なアクセス権限を含むポリシーを作成してください。）

次にAutonomous DatabaseからS3にアクセスするためのロールを作成し、ポリシーをアタッチします。
AWS管理コンソールから「Identity and Access Management (IAM)」にアクセスし、「ロール」に移動します。
![スクリーンショット 2022-10-14 13.45.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/a78d4d7e-d812-f486-c5c5-09a0ccd2c33b.png)
「ロールの作成」をクリックします。
![スクリーンショット 2022-10-14 13.44.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/2b1453a1-2c9b-2ad3-d149-544df75c3e27.png)
信頼されたエンティティタイプとして「AWSアカウント」を選択します。
![スクリーンショット 2022-10-14 13.48.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/8c54c8da-fce6-293d-572c-6ae47d67113f.png)
AWSアカウントとして「このアカウント」を選択し、オプションの「外部IDを要求する」のチェックをオンにします。
「外部ID」に1.で取得したAutonomous DatabaseのOCID（DATABASE_OCID）を入力し、「次へ」をクリックします。
![スクリーンショット 2022-10-14 14.11.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/2e58909c-05e0-6ec2-a4c0-b49e2ed50ff6.png)
許可ポリシーに「AmazonS3FullAccess」を選択して、「次へ」をクリックします。
![スクリーンショット 2022-10-14 14.51.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/85db4b0a-0478-41f5-aafe-a9e6700c309d.png)
任意のロール名（ここでは「Role_for_ADB」）を入力して、「ロールを作成」をクリックします。
![スクリーンショット 2022-10-14 14.53.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/77730bd4-777e-96c1-6125-1e488af19ee4.png)
ロールが作成されたら、「ロールを表示」をクリックします。
![スクリーンショット 2022-10-14 14.56.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/9f7d170f-e895-9a54-fc07-cedff6745d82.png)
ロールのARNをコピーし、メモしておきます。
![スクリーンショット 2022-10-14 14.58.35のコピー2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/f8026306-dade-f639-e077-1e5c06f955b5.png)
「信頼関係」をクリックします。
![スクリーンショット 2022-10-14 14.58.35のコピー3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/e3465094-599d-456f-7a90-e17121d2c8ec.png)
「信頼ポリシーを編集」をクリックします。
![スクリーンショット 2022-10-14 15.05.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/d0d1dfa9-6ba7-a580-1559-d03bd99d73a0.png)
信頼ポリシーの編集画面が表示されます。
7行目のプリンシパルのパラメータ「AWS」の値を、1.で取得したaws_user_arnの値に変更し、「ポリシーの更新」をクリックします。
![スクリーンショット 2022-10-14 15.17.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/c4c24126-90b1-106b-19ab-4f2f678cfded.png)

# 3. Amazon S3の準備
以下のようなファイル「testdata.txt」を作成し、S3のバケットにアップロードします。

```text:testdata.txt
1,Paul
2,John
3,George
4,Ringo
```

# 4. ARNを使用したクレデンシャルの作成

Autonomous DatabaseからAmazon S3にアクセスする際に使用するクレデンシャルを作成します。
ARNのロールベースの認証を使用してAmazon S3にアクセするためのクレデンシャルを作成するには、こちらのような構文でDBMS_CLOUD.CREATE_CREDENTIALプロシージャを実行します。
```
BEGIN
  DBMS_CLOUD.CREATE_CREDENTIAL(
    credential_name => '作成するクレデンシャルの名前',
    params =>
        JSON_OBJECT('aws_role_arn' value '2.で作成したロール「Role_for_ADB」のARN',          
                    'external_id_type' value 'database_ocid')
  );
END;
/
```
DBMS_CLOUD.CREATE_CREDENTIALを実行して、クレデンシャル「MY_S3_ARN_CRED」を作成します。
```
SQL> BEGIN
  2    DBMS_CLOUD.CREATE_CREDENTIAL(
  3      credential_name => 'MY_S3_ARN_CRED',
  4      params =>
  5          JSON_OBJECT('aws_role_arn' value　'arn:aws:iam::XXXXXXXXXXXX:role/Role_for_ADB',                                            
  6                      'external_id_type' value 'database_ocid')
  7    );
  8  END;
  9  /

PL/SQLプロシージャが正常に完了しました。

SQL>
```
ARNを使用したクレデンシャル「MY_S3_ARN_CRED」が作成できました。

# 5. ARNを使用したAmazon S3へのアクセス
4.で作成したクレデンシャルを使用して、Autonomous DatabaseからAmazon S3のバケットにアクセスし、バケット内のオブジェクト一覧を取得してみます。

Amazon S3のバケット内のオブジェクト一覧を取得するには、以下のような構文でDBMS_CLOUD.LIST_OBJECTSファンクションを使用します。
クレデンシャルには、4.で作成したクレデンシャルを指定します。
location_uriには、以下のような形式でS3のバケットを指定します。
`https://バケット名.s3.AWSのリージョン識別子.amazonaws.com/`
```
SELECT object_name FROM DBMS_CLOUD.LIST_OBJECTS(
           credential_name => '使用するクレデンシャル名',
           location_uri    => 'https://バケット名.s3.AWSのリージョン識別子.amazonaws.com/');
```

クレデンシャル名とバケットのURIを指定して、上記のSQLを実行してみます。
```	   
SQL> SELECT object_name FROM DBMS_CLOUD.LIST_OBJECTS(
  2             credential_name => 'MY_S3_ARN_CRED',
  3             location_uri    => 'https://your_bucket_name.s3.ap-northeast-1.amazonaws.com/');

OBJECT_NAME
--------------------------------------------------------------------------------
testdata.txt

SQL>
```
ARNのロールベースの認証に使用してAmazon S3のバケットにアクセスし、3.で先ほどアップロードしたtestdata.txtが格納されていることが確認できました。

次に、DBMS_CLOUD.CREATE_EXTERNAL_TABLEプロシージャでAmazon S3のバケット内にあるオブジェクト（ファイル）「testdata.txt」をもとにした外部表を作成し、testdata.txt内のデータをAutonomous Databaseから参照してみます。

クレデンシャルには、4.で作成したクレデンシャルを指定します。
file_uri_listには、以下のようなト形式でバケット内のオブジェクト（ファイル）を指定します。
`https://バケット名.s3.AWSのリージョン識別子.amazonaws.com/オブジェクト（ファイル）名`
```
BEGIN
    DBMS_CLOUD.CREATE_EXTERNAL_TABLE(
        table_name =>'作成するテーブル名',
        credential_name =>'使用するクレデンシャル名',
        file_uri_list =>'https://バケット名.s3.リージョン識別子.amazonaws.com/ファイル名',
        format => json_object('delimiter' value ','), -- ファイル内の列のデリミタを指定
        column_list => 'ID NUMBER, name VARCHAR2(20)' -- 表の列定義を指定
    );
END;
/
```

テーブル名をmemberとし、クレデンシャル名とオブジェクトのURIを指定して、上記のSQLを実行してみます。
```
SQL> BEGIN
  2      DBMS_CLOUD.CREATE_EXTERNAL_TABLE(
  3          table_name =>'member',
  4          credential_name =>'MY_S3_ARN_CRED',
  5          file_uri_list =>'https://test-s3bucket-for-adb.s3.ap-northeast-1.amazonaws.com/testdata.txt',
  6          format => json_object('delimiter' value ','),
  7          column_list => 'ID NUMBER, name VARCHAR2(20)'
  8      );
  9  END;
 10  /

PL/SQLプロシージャが正常に完了しました。

SQL>
```
ARNのロールベースの認証に使用して、Amazon S3のバケット内にあるオブジェクト（ファイル）「testdata.txt」をもとにした外部表「member」が作成できました。

外部表「member」の内容を確認してみます。

```
SQL> SELECT * FROM member;

	    ID NAME
---------- --------------------
	     1 Paul
	     2 John
	     3 George
	     4 Ringo

SQL>
```

ARNのロールベースの認証を使用して作成した外部表「member」経由で、Amazon S3のバケット内にあるオブジェクト（ファイル）「testdata.txt」の内容を参照できることが確認できました。

#参考使用
[Use Amazon Resource Names (ARNs) to Access AWS Resources](https://docs.oracle.com/en/cloud/paas/autonomous-database/adbsa/amazon-arn.html#GUID-BDEE5519-3807-4699-9C53-546EFD2F3A17)