OCI Cloud Shell上のSQL PlusからADBに接続する

__初めに__
冒頭ですが、この記事の位置付けは、次のシリーズ記事の1つです。
[プライベート・サブネット内の Oracle DB/ADB に接続](https://qiita.com/liu-wei/items/10152a4fec813c1b7d98#4-%E3%83%97%E3%83%A9%E3%82%A4%E3%83%99%E3%83%BC%E3%83%88%E3%82%B5%E3%83%96%E3%83%8D%E3%83%83%E3%83%88%E5%86%85%E3%81%AE-oracle-dbadb-%E3%81%AB%E6%8E%A5%E7%B6%9A)

OCI Cloud Shellに、SQL Plusのクライアントが実装されていますので、簡単にAutonomous DBに接続できます。今回は、<font color="blue">PublicとPrivate ADB両方</font>への接続方法をご紹介します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/426a4d78-83a1-3423-f45e-0f3d239fd262.png", width="450">

__検証環境__
|項目|内容|
|--|--|
|OCIリージョン|東京 (他リージョンでもOK)|
|ADBタイプ|Data Warehouse (ATPでもOK)|
|アクセス・タイプ|[1. パブリック・アクセス経由でADBに接続](#1-パブリックアクセス経由でadbに接続) (ADW01)|
||[2. プライベート・エンドポイント経由でADBに接続](#2-プライベートエンドポイント経由でadbに接続) (ADW02)|

ちなみに、SQL DeveloperというGUIツールでAutonomous DBに接続したい場合、以下の記事をご参考ください。
[SQL Developerで様々なDBに接続する方法](https://qiita.com/liu-wei/items/08f2e2f6d90c08549cbf)

# 1. パブリック・アクセス経由でADBに接続
アクセス・タイプはパブリック経由の場合、Cloud Shellからの接続はとても簡単です。

__ステップ__
[1-1. OCIコンソールよりADB Walletを取得](#1-1-ociコンソールよりadb-walletを取得)
[1-2. ADB WalletをOCI Cloud Shellにアップロード](#1-2-adb-walletをoci-cloud-shellにアップロード)
[1-3. 環境変数の設定とsqlnet.oraの編集](#1-3-環境変数の設定とsqlnetoraの編集)
[1-4. ADBに接続する](#1-4-adbに接続する)

## 1-1. OCIコンソールよりADB Walletを取得
ADBの情報詳細画面より、"DB Connection"をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/390cab25-c8f1-d82e-0f5f-23435dacdbbc.png)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/35c72b5b-ecfa-b627-fbf4-8059038bd7b4.png" width="500">

パスワードを作成し、ダウンロードを開始します。
（このパスワードはWallet専用で、ADB作成時の管理者パスワードとは関係ありません。）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/acecc0b1-41a5-1462-a22b-e9aa418595f2.png" width="500">

ダウンロードしたADB Walletは、圧縮ファイルです。(wallet_\<ADB_Name\>.zipのような形式)

## 1-2. ADB WalletをOCI Cloud Shellにアップロード
2021/3/23、OCI Cloud Shellの<font color="blue">ファイル転送機能</font>がリリースされました。
ロカールとCloud Shellの間に、簡単にファイルの転送ができるようになりました。

Cloud Shellにログインし、ローカルのWalletファイルをCloud Shellの画面に"<font color="blue">Drag & Drop</font>"だけでOKです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/b7181f8b-b2ab-3017-03e7-e96a3e7d1dd0.png" width="500">
格納用のディレクトリを作成し、Walletファイルを移動します。
<font color="blue">$HOME/network/admin</font>

```bash
liu_wei@cloudshell:~ (ap-tokyo-1)$ pwd
/home/liu_wei
liu_wei@cloudshell:~ (ap-tokyo-1)$ mkdir -p network/admin
liu_wei@cloudshell:~ (ap-tokyo-1)$ mv wallet_ADW01.zip network/admin
liu_wei@cloudshell:~ (ap-tokyo-1)$ 
```

__圧縮のWalletファイルを解凍__

```bash
liu_wei@cloudshell:admin (ap-tokyo-1)$ pwd
/home/liu_wei/network/admin
liu_wei@cloudshell:admin (ap-tokyo-1)$ unzip wallet_ADW01.zip
Archive:  wallet_ADW01.zip
  inflating: README                  
  inflating: cwallet.sso             
  inflating: tnsnames.ora            
  inflating: truststore.jks          
  inflating: ojdbc.properties        
  inflating: sqlnet.ora              
  inflating: ewallet.p12             
  inflating: keystore.jks            
liu_wei@cloudshell:admin (ap-tokyo-1)$ ll
total 64
-rw-r--r--. 1 liu_wei oci  6725 Apr  2 07:58 cwallet.sso
-rw-r--r--. 1 liu_wei oci  6680 Apr  2 07:58 ewallet.p12
-rw-r--r--. 1 liu_wei oci  3274 Apr  2 07:58 keystore.jks
-rw-r--r--. 1 liu_wei oci   691 Apr  2 07:58 ojdbc.properties
-rw-r--r--. 1 liu_wei oci   317 Apr  2 07:58 README
-rw-r--r--. 1 liu_wei oci   114 Apr  2 07:58 sqlnet.ora
-rw-r--r--. 1 liu_wei oci  1064 Apr  2 07:58 tnsnames.ora
-rw-r--r--. 1 liu_wei oci  3335 Apr  2 07:58 truststore.jks
-rw-r--r--. 1 liu_wei oci 20500 Apr  2 09:46 wallet_ADW01.zip
liu_wei@cloudshell:admin (ap-tokyo-1)$ 
```

## 1-3. 環境変数の設定とsqlnet.oraの編集
__環境変数"ORACLE_HOME"を設定__

```bash
liu_wei@cloudshell:admin (ap-tokyo-1)$ export ORACLE_HOME=/home/liu_wei
liu_wei@cloudshell:admin (ap-tokyo-1)$ echo $ORACLE_HOME
/home/liu_wei
liu_wei@cloudshell:admin (ap-tokyo-1)$
```

ORACLE_HOMEを設定しなければ、以下のエラーが出ますので、ご<font color="blue">注意</font>ください。
ORA-12154: TNS:could not resolve the connect identifier specified

<font color=blue>ヒント</font>: <strong>$HOME/.bashrc</strong>に、`export ORACLE_HOME=<path_name>`を追加すれば、Cloud Shellに再接続した後、環境変数を再定義しなくてよいです。

__sqlnet.oraを編集__
以下の行を編集し、Walletの保存先を置き換えます。
<font color=Magenta>編集前</font>：
```bash
WALLET_LOCATION = (SOURCE = (METHOD = file) (METHOD_DATA = (DIRECTORY="?/network/admin")))
```
<font color=blue>編集後</font>：
```bash
WALLET_LOCATION = (SOURCE = (METHOD = file) (METHOD_DATA = (DIRECTORY="$ORACLE_HOME/network/admin")))
```

__tnsnames.oraの情報を確認__
tnsnames.oraから、接続用のサービス情報を確認します。
通常以下のように、表示されます。(dbname_high, dbname_medium, dbname_low)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/ff0a128d-0d94-f1e7-63d7-15930c40b503.png)

## 1-4. ADBに接続する

コマンド：`sqlplus <ユーザ名>/<パスワード>@<サービス名>`
サービス名は、tnsnames.oraより確認できます。

```sql
liu_wei@cloudshell:admin (ap-tokyo-1)$ sqlplus admin@adw01_high

SQL*Plus: Release 19.0.0.0.0 - Production on Fri Apr 2 09:53:54 2021
Version 19.10.0.0.0

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

Enter password: 

Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.5.0.0.0

SQL> 
```

# 2. プライベート・エンドポイント経由でADBに接続
プライベート・サブネットにADBを作成した場合、<strong>プライベート・エンドポイント</strong>を介してADBにアクセスする必要があります。Cloud Shellから直接にアクセスすることはできませんので、BastionとSSHポート転送は必要です。

<font color=blue>OCI Bastion Service</font>は2021年5月にリリースされました。それを利用し、踏み台サーバ(VM)を作成せずに、プライベート・サブネット内のリソースにアクセスできます。サービス自体は<font color=blue>無料</font>です。これから、OCI Bastionを使用してCloud ShellからプライベートADBにアクセスする方法を紹介します。

__追記 (2022年12月)__
OCI Bastionでの接続方法を投稿した時点(2022年5月)、Cloud Shellのプライベート・アクセス機能がまだリリースされませんでした。2022年8月より、Cloud Shellから<strong>プライベート・アクセス</strong>経由で、プライベート・サブネット内のリソースに接続できるようになりましたので、OCI Bastionを使わなくてもOKです。設定方法は、[「OCI Cloud Shell からプライベート・サブネット内のインスタンスに接続する」](https://qiita.com/liu-wei/items/f28aa9ab2a3e5b49b42d)をご参考ください。

__ステップ__
[2-1. 事前準備](#2-1-事前準備)
[2-2. Bastionの作成](#2-2-bastionの作成)
[2-3. NSGにIngressルールを追加する](#2-3-nsgにingressルールを追加する)
[2-4. tnsnames.oraを編集する](#2-4-tnsnamesoraを編集する)
[2-5. SSH秘密キーをCloud Shellにアップロード](#2-5-ssh秘密キーをcloud-shellにアップロード)
[2-6. Cloud ShellでSSHコマンドを実行する](#2-6-cloud-shellでsshコマンドを実行する)
[2-7. ADBに接続する](#2-7-adbに接続する)

## 2-1. 事前準備
__ADB Walletをダウンロードし、Cloud Shellにアップロード__
「パブリック・アクセス」と同じです。 [Step 1-1](#1-1-ociコンソールよりadb-walletを取得) と [Step 1-2](#1-2-adb-walletをoci-cloud-shellにアップロード)をご参照ください。

__環境変数「ORACLE_HOME」の設定とsqlnet.oraの編集__
「パブリック・アクセス」と同じです。 [Step 1-3](#1-3-環境変数の設定とsqlnetoraの編集)をご参照ください。

__ADBの「プライベート・エンドポイントIP」を確認__
ADBの詳細ページから、「プライベート・エンドポイントIP」を取得できます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/84d51c11-84b9-1095-1aa6-4b2481555037.png", width="350">

## 2-2. Bastionの作成
Identity & Security -> Bastion -> Create Bastion
Bastion名を入力し、ターゲットVCNとサブネットを選択してから、CIDRブロック許可リストを入力します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/77b6a1a8-59c9-e87a-42e6-859fbd41307e.png", width="500">

__注意__
このテストには「0.0.0.0/0」を使用しています。通常なら、CIDRブロックの許可リストを絞り込んだほうがよいです。例えば、 接続元のIPアドレス範囲のみを許可します。

Cloud ShellのパブリックIPを「CIDRブロック許可リスト」に追加するのは可能です。 Cloud Shellで`curl ipinfo.io`を実行すると、IPアドレスを取得できます。

Bastionはアクティブの状態になりましたら、「<strong>プライベート・エンドポイントIP</strong>」は以下の画面から確認できます。このIPが、ターゲット・サブネット内で自動割り当てられます。次のステップでこのIPをNSGの入力ルールに追加します。 「CIDRブロック許可リスト」を編集したい場合は、「編集」ボタンをクリックすればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/9ad98d1d-fa95-f7ef-578d-e1056ca6c3af.png)

__セッションの作成__
Bastion -> Sessions -> Create session
|項目|内容|
|--|--|
|セッション・タイプ|"<font color=blue>SSH port forwarding session</font>"を選択|
|ターゲット・ホストに接続する方法|"IPアドレス"を選択 (デフォルト)|
|IPアドレス|ADBの「プライベート・エンドポイントIP」|
|ポート|<font color=blue>1522</font>
|SSHキー|既存のキーファイルを利用するか、新しいキーペアを生成する。|

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/cc2012de-0fde-1da8-0a92-02057070fac0.png", width="500">

セッションはアクティブの状態になりましたら、次のように、3ドットのメニューをクリックしてSSHコマンドをコピーします。このコマンドは、[STEP 2-6](#2-6-cloud-shellでsshコマンドを実行する)で使用されます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/639cc802-3236-6da3-55e9-a29db10c0599.png">
デフォルトでは、セッションは3時間有効です。Bastionを作成する時に変更できます。

## 2-3. NSGにIngressルールを追加する
プライベートADBを作成する時、ネットワーク・セキュリティ・グループ（NSG）がアタッチされます。ADBにアクセスするため、TCPポート1522を入力ルールに追加するのは必要です。

まだ行っていない場合は、次のようにルールを追加してください。"<strong>Source CIDR</strong>"は、Bastionの「プライベート・エンドポイントIP」です（Bastionの情報ページに表示されます）。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/ef57190b-a6cb-c4c5-dd41-cfd25c24a3e8.png)

## 2-4. tnsnames.oraを編集する
ファイル`tnsnames.ora`に記載されているホスト名は、ADBの「プライベート・エンドポイントURL」です。 BastionサービスのSSHポート転送を使用するため、ローカル（Cloud Shell）からADBへのSSHトンネルを[STEP 2-6](#2-6-cloud-shellでsshコマンドを実行する)で作成します。それで、ホスト名を<font color=blue>localhost</font>に変更する必要があります。

|項目|内容|
|--|--|
|ファイル|$ORACLE_HOME/network/admin/tnsnames.ora|
|編集前|host=<font color=Magenta>\<Private Endpoint URL></font><br>例：`host=xxxxxxxx.adb.ap-tokyo-1.oraclecloud.com`|
|編集後|host=<font color=blue>localhost</font>|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/cf3c5c96-a7d3-bf51-f88f-975ee16e302a.png)

## 2-5. SSH秘密キーをCloud Shellにアップロード
Cloud Shellにログインし、ローカルのSSH秘密キーをCloud Shellの画面に"Drag & Drop"だけでOKです。Walletのアップロードと同じ方法です。ファイル転送はまもなく完了します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/b68daa2b-7a00-0e0c-04fe-bce1af07d7c4.png", width="450">

秘密キーを`$HOME/.ssh`の下に保存することをお勧めします （存在しない場合は作成しておいでください）。デフォルトのファイル・モードは644です。 400（または600）に変更します。

```bash
liu_wei@cloudshell:.ssh (ap-tokyo-1)$ chmod 400 id_rsa
liu_wei@cloudshell:.ssh (ap-tokyo-1)$ ll id_rsa
-r--------. 1 liu_wei oci 1819 Apr 15 11:52 id_rsa
liu_wei@cloudshell:.ssh (ap-tokyo-1)$ 
```

## 2-6. Cloud ShellでSSHコマンドを実行する
SSHコマンド:
```bash
ssh -i <privateKey> -N -L <localPort>:<Private_IP_of_ADB>:1522 -p 22 <bastion_ocid>@host.bastion.ap-tokyo-1.oci.oraclecloud.com
```

* `<privateKey>`を秘密キーのパスとファイル名に置き換えます。
* `<localPort>`を<font color=blue>1522</font>に置き換えます。
* `<Private_IP_of_ADB>`は自動に実のIPが埋められるので、変更する必要はありません。

<font color=blue>ヒント</font>:
* バック・グラウンドで実行するには、最後に`&`を追加します。
* コマンド結果に次のメッセージが表示される場合があります。無視して構いません。これを抑制したい場合は、`-4`パラメータを追加してください。`-4`の意味は、IPv4アドレスのみを使用するようにします。
`bind: Cannot assign requested address`

```bash
liu_wei@cloudshell:admin (ap-tokyo-1)$ ssh -i $HOME/.ssh/id_rsa -N -L 1522:10.0.1.130:1522 -p 22 <bastion_ocid>@host.bastion.ap-tokyo-1.oci.oraclecloud.com -4 &
[1] 1355
FIPS mode initialized
......
liu_wei@cloudshell:admin (ap-tokyo-1)$
```

## 2-7. ADBに接続する
コマンド：`sqlplus <ユーザ名>/<パスワード>@<サービス名>`

```sql
liu_wei@cloudshell:admin (ap-tokyo-1)$ sqlplus admin@adw02_high

SQL*Plus: Release 21.0.0.0.0 - Production on Fri Apr 15 11:59:31 2022
Version 21.5.0.0.0

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

Enter password: 
Last Successful login time: Fri Apr 15 2022 11:59:15 +00:00

Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.15.0.1.0

SQL>
```

OCI Bastionを経由してCloud ShellからプライベートADBへの接続ができました。お疲れ様です！

以上

----
__関連記事__
[オラクル・クラウドの個人ブログ一覧](https://qiita.com/liu-wei/items/10152a4fec813c1b7d98)
[OCI Cloud Shellの概要](https://qiita.com/liu-wei/items/d11aea8865accddbfd90)
[OCI Cloud Shell からプライベート・サブネット内のインスタンスに接続する](https://qiita.com/liu-wei/items/f28aa9ab2a3e5b49b42d)

----

__参考ドキュメント__
[ADBへの接続](https://docs.oracle.com/ja-jp/iaas/Content/Database/Tasks/adbconnecting.htm)