[OCI]Azure ADのアクセストークンを使用して、Linux上のSQL*PlusからAutonomous Databaseに接続してみた

# はじめに
[こちら]()の記事ではAutonomous Database上のAPEXのユーザ認証にAzure ADを使用する方法を検証しましたが、今回はSQL*PlusからAutonomous Databaseに接続する際のユーザ認証をAzure ADのアクセストークンを使用して行う方法を検証してみました

# 1. Autonomous DatabaseをアプリケーションとしてAzure ADに登録
Azureポータルにアクセスし、「Azure Active Directory」に移動します。
![スクリーンショット 2022-10-06 11.48.43のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/63915ade-7a39-1581-e30f-ca4e0fa7f840.png)
「テナントID」と「プライマリドメイン」をコピーし、メモしておきます。
「テナントID」と「プライマリドメイン」は、それぞれ以下のような形式です。
テナントID：`xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
プライマリドメイン：`yyyyyy.onmicrosoft.com`
![スクリーンショット 2022-10-06 11.54.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/42a1615d-0751-7704-c4af-8b48fa6240a0.png)
左側のメニューから「アプリの登録」に移動します。
![スクリーンショット 2022-10-06 13.34.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/638791de-7258-85f8-4333-a96376f2bcc0.png)
「新規登録」をクリックします。
![スクリーンショット 2022-10-06 12.01.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/75b18c4c-b2da-e0aa-0714-e18f3e07d420.png)
任意の名前（ここでは「Autonomous Database」）を入力し、他の項目はデフォルトのままで「登録」をクリックします。
![スクリーンショット 2022-10-06 12.06.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/feed4b92-b30f-5a7c-c7d6-cb0b943d34c3.png)
アプリケーションが登録されました。
「アプリケーション（クライアント）ID」をコピーし、メモしておきます。
「アプリケーション（クライアント）ID」は`zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz`のような形式です。
![スクリーンショット 2022-10-06 12.08.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/4aa9d6c3-3874-e3dd-3a50-ac77a4551c9b.png)
左側のメニューから「APIの公開」に移動します。
![スクリーンショット 2022-10-06 12.16.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/f59f63fb-cbb2-2e74-5956-0156d5d1f4be.png)
アプリケーションIDのURIの横の「設定」をクリックします。
![スクリーンショット 2022-10-06 12.17.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/57bbb919-5501-3dba-a60b-bf4b370d0fd4.png)
アプリケーションIDのURIに以下の形式の文字列を入力し、「保存」をクリックします。
`https://プライマリドメイン/アプリケーション（クライアント）ID`
実際には以下のような文字列になります。
`https://yyyyyy.onmicrosoft.com/zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz`
![スクリーンショット 2022-10-06 12.24.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/7d4c455f-f42c-1585-a780-e3405662bec1.png)
「Scopeの追加」をクリックします。
![スクリーンショット 2022-10-06 12.30.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/aac1b9b8-8cb3-35e0-d8ab-5dab10111c35.png)
以下の内容を入力し、「スコープの追加」をクリックします。
スコープ名：session:scope:connect
同意できるのはだれですか？：管理者とユーザー
管理者の同意の表示名：任意（ここでは「Connect to Autonomous Database」）
管理者の同意の説明：任意（ここでは「Connect to Autonomous Database」）
ユーザーの同意の表示名：任意（ここでは「Connect to Autonomous Database」）
ユーザーの同意の説明：任意（ここでは「Connect to Autonomous Database」）
状態：有効
![スクリーンショット 2022-10-06 12.33.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/ca99263f-b837-e202-7a86-0ab25b598584.png)
スコープが追加されました。
![スクリーンショット 2022-10-06 12.34.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/6e31ac11-bcb2-9f6f-f76f-cb64d6d35978.png)

# 2. DB接続に使用するAzure ADユーザのアプリケーションへの割り当て

「ホーム」→「Azure Active Directory」と移動し、左側のメニューから「エンタープライズアプリケーション」に移動します。
![スクリーンショット 2022-10-06 12.40.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/d1558a65-1546-3afe-d7c6-6f72dff1935f.png)
作成したアプリケーションの名前（ここでは「Autonomous Database」）をクリックします。
![スクリーンショット 2022-10-06 12.45.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/9cd97fe1-0825-f909-0e14-cceed71b2bab.png)
左側のメニューから「ユーザーとグループ」をクリックします。
![スクリーンショット 2022-10-06 12.48.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/7b9a1ced-1e3c-10d4-6c73-9a0e417ecde7.png)
「ユーザーまたはグループの追加」をクリックします。
![スクリーンショット 2022-10-06 12.51.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/494926fe-df5d-ad1e-c008-bfdd2f48b6bc.png)
「割り当ての追加」の画面が表示されるので、「ユーザー」欄の「選択されていません」をクリックします。
![スクリーンショット 2022-10-06 12.53.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/21608d13-05d3-c16f-9226-dc15a6c2d16a.png)
DBアクセスに使用するユーザを選択して「選択」をクリックします。
![スクリーンショット 2022-10-06 12.57.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/9c62cb3e-6172-3738-8bd1-ef12fda7dc77.png)
「割り当て」をクリックします。
![スクリーンショット 2022-10-06 12.59.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/d06819f4-3b2c-93e6-db29-9e6d5c037e90.png)
アプリケーションにユーザーが割り当てられました。
![スクリーンショット 2022-10-06 13.01.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/ecb28d72-e62a-94ed-5f81-eb5eda3401ae.png)

# 3. Azure ADをAutonomous Databaseの外部アイデンティティ・プロバイダとして登録

DBMS_CLOUD_ADMIN.ENABLE_EXTERNAL_AUTHENTICATIONプロシージャを使用して、Azure ADをAutonomous Databaseの外部アイデンティティ・プロバイダとして登録します。
```
BEGIN
  DBMS_CLOUD_ADMIN.ENABLE_EXTERNAL_AUTHENTICATION(
      type   =>'AZURE_AD',
      params => JSON_OBJECT('tenant_id' VALUE 'テナントID',
                            'application_id' VALUE 'アプリケーション（クライアント）ID',
                            'application_id_uri' VALUE 'アプリケーションIDのURI'),
      force => TRUE
  );
END;
```
実際のコマンドは以下のようになります。
```
BEGIN
	DBMS_CLOUD_ADMIN.ENABLE_EXTERNAL_AUTHENTICATION(
		type   =>'AZURE_AD',
		params => JSON_OBJECT('tenant_id' VALUE 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
							  'application_id' VALUE 'zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz',
							  'application_id_uri' VALUE 'https://yyyyyy.onmicrosoft.com/zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz'),
		force => TRUE
	);
END;
/
```
adminユーザとしてAutonomous Databaseに接続し、DBMS_CLOUD_ADMIN.ENABLE_EXTERNAL_AUTHENTICATIONプロシージャを実行します。
```
SQL> BEGIN
  2  	DBMS_CLOUD_ADMIN.ENABLE_EXTERNAL_AUTHENTICATION(
  3  		type   =>'AZURE_AD',
  4  		params => JSON_OBJECT('tenant_id' VALUE 'a88exxxx-0exx-4bxx-b3xx-5cdbcexxxxxx',
  5  							  'application_id' VALUE 'f940zzzz-3ezz-42zz-89zz-29f3fezzzzzz',
  6  							  'application_id_uri' VALUE 'https://yyyyyy.onmicrosoft.com/f940zzzz-3ezz-42zz-89zz-29f3fezzzzzz'),
  7  		force => TRUE
  8  	);
  9  END;
 10  /

PL/SQLプロシージャが正常に完了しました。
```
Azure ADが外部アイデンティティ・プロバイダとして正しく設定されているかを以下のSQLで確認します。
```
SQL> col name for a30
SQL> col value for a30
SQL> SELECT NAME, VALUE FROM V$PARAMETER WHERE NAME='identity_provider_type';

NAME			               VALUE
------------------------------ ------------------------------
identity_provider_type	       AZURE_AD

SQL> 
```

# 4. Azure ADユーザに対応するDBユーザの作成
CREATE USER文で、先ほどアプリケーションに割り当てたAzure ADユーザに対応するDBユーザ（スキーマ）を作成します。
以下のような構文になります。
```
CREATE USER DBユーザ名 IDENTIFIED GLOBALLY AS
'AZURE_USER=Azure ADのユーザ名';
```
作成するDBユーザ名をadbuser_1、対応するAzure ADユーザを先ほどをアプリケーションに割り当てたADBUSER1としてCREATE USER文を実行します。
```
SQL> CREATE USER adbuser_1 IDENTIFIED GLOBALLY AS
  2  'AZURE_USER=ADBUSER1@yyyyyy.onmicrosoft.com';

ユーザーが作成されました。

SQL>
```
作成したユーザadbuser_1にロールを割り当てます。
```
SQL> GRANT connect, resource TO adbuser_1;

権限付与が成功しました。

SQL>
```

# 5. Azure ADからのアクセストークンの取得

Azure ADからアクセストークンを取得するには、Azure ADにサインインする必要があります。
今回はLinux環境にAzure CLIをインストールし、Azure CLIからAzure ADにサインインします。
Linux環境へのAzure CLIのインストール方法は、[こちら](https://learn.microsoft.com/ja-jp/cli/azure/install-azure-cli-linux?pivots=script)を参照ください。

Azure ADにサインインする際は、以下のコマンドを実行します。
```
az login --allow-no-subscriptions
```
早速実行してみます。
```
[opc@compute1 ~]$ az login --allow-no-subscriptions
To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code SR72XWRPL to authenticate.
```
コマンドを実行すると、サインインするためにはブラウザから https://microsoft.com/devicelogin にアクセスしてコードを入力せよと表示されます。
表示されたURL（ https://microsoft.com/devicelogin ）にブラウザからアクセスします。
![スクリーンショット 2022-10-06 10.36.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/2632b7ae-1bbc-6132-d2eb-3d68756e2c58.png)
表示されたコード（ここではSR72XWRPL）を入力して、「次へ」をクリックします。
![スクリーンショット 2022-10-06 10.36.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/1106c678-e454-f4f9-c0ea-1b70b71c5bbf.png)
Azure ADユーザのユーザ名を入力し、「次へ」をクリックします。
![スクリーンショット 2022-10-06 10.38.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/c644e94d-bd70-b6d4-f31a-1026f4ac5933.png)
Azure ADユーザのパスワードを入力し、「サインイン」をクリックします。
![スクリーンショット 2022-10-06 10.38.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/2b481f3d-514f-be41-53cb-c3202fc77f18.png)
「Microsoft Azure CLIにサインインしますか？」と表示されるので、「続行」をクリックします。
![スクリーンショット 2022-10-06 10.39.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/3791639e-ab9f-295f-abb2-e4011bfa6204.png)
サインインが完了しました。
![スクリーンショット 2022-10-06 10.39.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/01071e66-b7c1-914e-f778-f5d1473d51c3.png)
ターミナルに戻ると、追加の情報が表示され、Azure CLIからのサインインが完了しています。
```
[opc@compute1 ~]$ az login --allow-no-subscriptions
To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code SR72XWRPL to authenticate.
The following tenants don't contain accessible subscriptions. Use 'az login --allow-no-subscriptions' to have tenant level access.
a88exxxx-0exx-4bxx-b3xx-5cdbcexxxxxx 'Default Directory'
[
  {
    "cloudName": "AzureCloud",
    "id": "a88exxxx-0exx-4bxx-b3xx-5cdbcexxxxxx",
    "isDefault": true,
    "name": "N/A(tenant level account)",
    "state": "Enabled",
    "tenantId": "a88exxxx-0exx-4bxx-b3xx-5cdbcexxxxxx",
    "user": {
      "name": "ADBUSER1@yyyyyy.onmicrosoft.com",
      "type": "user"
    }
  }
]
[opc@compute1 ~]$ 
```
以下のコマンドで、Autonomous DatabaseにアクセスするためのトークンをAzure ADから取得します。
```
token=$(az account get-access-token --resource=アプリケーションIDのURI --query accessToken --output tsv)
```
実際には、以下のようなコマンドになります。
```
token=$(az account get-access-token --resource=https://yyyyyy.onmicrosoft.com/f940zzzz-3ezz-42zz-89zz-29f3fezzzzzz --query accessToken --output tsv)
```
初回実行時は以下のようなエラーが表示されます。
```
[opc@compute1 ~]$ token=$(az account get-access-token --resource=https://yyyyyy.onmicrosoft.com/f940zzzz-3ezz-42zz-89zz-29f3fezzzzzz --query accessToken --output tsv)
ERROR: AADSTS65001: The user or administrator has not consented to use the application with ID '04b07795-8ddb-461a-bbee-02f9e1bf7b46' named 'Microsoft Azure CLI'. Send an interactive authorization request for this user and resource.
Trace ID: 09352b7c-e8cf-422b-afef-82797b822900
Correlation ID: fa8284a7-9f8d-42ce-89a2-4f274df4d110
Timestamp: 2022-10-05 09:42:47Z
To re-authenticate, please run:
az login --scope https://yyyyyy.onmicrosoft.com/f940zzzz-3ezz-42zz-89zz-29f3fezzzzzz/.default
[opc@compute1 ~]$ 
```
このエラーは、Azure CLIがAzure ADに登録したアプリケーション（ここでは「Autonomous Database」）の承認済みのクライアントアプリケーションとして登録されていないために発生します。

ということで、エラーメッセージ表示されたクライアントID（ここでは「04b07795-8ddb-461a-bbee-02f9e1bf7b46」）を使用して、Azure CLIをアプリケーション（ここでは「Autonomous Database」）の承認済みのクライアントアプリケーションとして登録します。
Azureポータルで「Azure Active Directory」に移動し、「アプリの登録」に移動します。
![スクリーンショット 2022-10-06 13.15.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/841b851b-b5a0-3664-1aba-3207e763813f.png)
アプリケーション名（ここでは「Autonomous Database」）をクリックします。
![スクリーンショット 2022-10-06 13.16.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/fe9cfdfc-b59c-8ead-f4fe-c737d466747a.png)
「APIの公開」に移動します。
![スクリーンショット 2022-10-06 13.18.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/fd0552f0-ecff-f16b-d0a4-3e6e39f8c71f.png)
「承認済みのクライアントアプリケーション」欄の「クライアントアプリケーションの追加」をクリックします。
![スクリーンショット 2022-10-06 13.19.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/d3a70fea-280c-2208-774b-087f50955d65.png)
以下の内容を入力し、「アプリケーションの追加」をクリックします。
クライアントID：エラーメッセージに表示されたAzure CLIのクライアントID（ここでは「04b07795-8ddb-461a-bbee-02f9e1bf7b46」）
承認済みのスコープ：チェックをオン
![スクリーンショット 2022-10-06 13.23.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/37b67618-c788-afa9-0f13-00622d86b1b6.png)
Azure CLIがアプリケーション（ここでは「Autonomous Database」）承認済みのクライアントアプリケーションとして登録されました。
![スクリーンショット 2022-10-06 13.24.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/9cf27cde-12a3-769c-a7f9-1005584cb4e9.png)
再度、トークンを取得してみます。
```
[opc@compute1 ~]$ token=$(az account get-access-token --resource=https://zakume.onmicrosoft.com/f940f0a4-3e2c-426f-89ab-29f3fe10b4f5 --query accessToken --output tsv)
[opc@compute1 ~]$
```
今度は問題なくコマンドが終了しました。
トークンの内容をtokenというファイル名で保存します。
```
[opc@compute1 ~]$ echo "$token" >> token
[opc@compute1 ~]$
```
Autonomous DatabaseにAzure ADユーザー「ADBUSER1」としてアクセスするためのトークンがtokenというファイル名で保存されました。
```
[opc@compute1 ~]$ ls -l | grep token
-rw-rw-r--. 1 opc opc       1516 Oct  5 09:47 token
[opc@compute1 ~]$
```

# 6. Azure ADのアクセストークンを利用したSQL*PlusからAutonomous Databaseへのアクセス
ADBインスタンスの詳細画面の「DB接続」から接続文字列を取得します。
以下のような形式になっています。（TLS接続の場合）
```
(description= (retry_count=20)(retry_delay=3)
(address=(protocol=tcps)(port=1521)(host=adb.ap-tokyo-1.oraclecloud.com))
(connect_data=(service_name=xxxxxxxxxxxxxxx_adw1_low.adb.oraclecloud.com))
(security=(ssl_server_dn_match=yes)))
```
取得した接続文字列のsecurityの部分に
**(TOKEN_AUTH=OAUTH)(TOKEN_LOCATION="tokenを保存したディレクトリ")**
を追加します。
今回はトークンをopcユーザのホームディレクトリ（/home/opc/）に保存したので、以下のような形になります。
**※トークンを保存する際のファイル名をtoken以外にした場合は、ファイル名を含むフルパスを指定する必要があります。**
```
(description= (retry_count=20)(retry_delay=3)
(address=(protocol=tcps)(port=1521)(host=adb.ap-tokyo-1.oraclecloud.com))
(connect_data=(service_name=xxxxxxxxxxxxxxx_adw1_low.adb.oraclecloud.com))
(security=(ssl_server_dn_match=yes)(TOKEN_AUTH=OAUTH)(TOKEN_LOCATION="/home/opc/")))
```
準備が整ったので、 Azure ADから取得したトークンを使用して、SQL*PlusからAutonomous Databaseにアクセスしてみます。

SQL*Plusから外部認証（ここではAzure AD）を使用してAutonomous Databaseに接続する際は、
```
sqlplus /@接続文字列 
```

先ほど作成した接続文字列とAzure ADのトークンを使用して、Autonomous Databaseにアクセスしてみます。
```
[opc@compute1 ~]$ sqlplus /@(description= (retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1521)(host=adb.ap-tokyo-1.oraclecloud.com))(connect_data=(service_name=xxxxxxxxxxxxxxx_adw1_low.adb.oraclecloud.com))(security=(ssl_server_dn_match=yes)(TOKEN_AUTH=OAUTH)(TOKEN_LOCATION="/home/opc/")))

SQL*Plus: Release 19.0.0.0.0 - Production on 水 10月 5 09:49:10 2022
Version 19.16.0.0.0

Copyright (c) 1982, 2022, Oracle.  All rights reserved.



Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.17.0.1.0
に接続されました。
SQL> 
```

接続しているDBユーザ名を確認してみます。
```
SQL> show user
ユーザーは"ADBUSER_1"です。
SQL> 
```
トークンを取得したAzure ADユーザー「ADBUSER1」に対応するDBユーザー「ADBUSER_1」としてAutonomous Databaseに接続していることが確認できました。

タイムスタンプを検索してみます。
```
SQL> SELECT systimestamp FROM dual;

SYSTIMESTAMP
---------------------------------------------------------------------------
22-10-05 09:53:16.397713 +00:00

SQL>
```
問題なくSQLが発行できることが確認できました。

以上で、Linux上のSQL*PlusからAzure ADのアクセストークンを利用してAutonomous Databaseに接続できることが確認できました。

# 参考資料
・[Autonomous DatabaseのMicrosoft Azure ADユーザーの認証および認可](https://docs.oracle.com/ja-jp/iaas/autonomous-database/doc/authenticate-and-authorize-microsoft-azure-active-directory-users-autonomous-database.html)
・[Authenticating and Authorizing Microsoft Azure Active Directory Users for Oracle Databases](https://docs.oracle.com/en/database/oracle/oracle-database/19/dbseg/authenticating-and-authorizing-microsoft-azure-active-directory-users-oracle-databases.html#GUID-2712902B-DD07-4A61-B336-31C504781D0F)
・[Linux に Azure CLI をインストールする](https://learn.microsoft.com/ja-jp/cli/azure/install-azure-cli-linux?pivots=script)