Oracle DatabaseのTLS暗号化を設定する

Oracle Databaseのトークン・ベースの認証連携に必要なTLSで接続するためのデータベースとクライアントの設定方法について紹介します。
手順通りに進めれば間違いなく設定できるはずなので、OCIからBase Database 19cとDBに接続するためのVMをそれぞれ新たに作成することをお勧めします。

## Base Database側の設定 
- 作成したBase Databaseで設定 (※2024年1月時点でのversionは19.21)
```shell
#oracleユーザーで接続
#1. TLSのための暗号鍵とサーバー証明書を作成する
$ mkdir /home/oracle/wallet
$ cd /home/oracle/wallet
$ orapki wallet create -wallet . -pwd xxxxx -auto_login
$ orapki wallet add -wallet . -pwd xxxxx -dn "CN=`hostname`" -keysize 2048 -self_signed -validity 3650
$ orapki wallet export -wallet . -pwd xxxxx -dn "CN=`hostname`" -cert dbcert.crt
$ cat dbcert.crt

#2.PDBにTLS接続するようにtnsnamesに追記する
$ vi $ORACLE_HOME/network/admin/tnsnames.ora
接続文字列 = 
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCPS)(HOST = ホスト名)(PORT = 1522))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = PDBのサービス名)
    )
  )

#例
TESTDB_PDB1 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCPS)(HOST = testbase19c)(PORT = 1522))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = testdb_pdb1.sub01120452410.vcnaqua.oraclevcn.com)
    )
  )
#3.sqlnet.oraでネットワーク暗号化に関する以下の3つのパラメータをコメントアウトし、TLSに関する3つのパラメータを追加
#※ TLSは認証と暗号化を両方提供するため、ネットワークのネイティブ暗号とは併用できません。
$ vi $ORACLE_HOME/network/admin/sqlnet.ora  
#SQLNET.ENCRYPTION_SERVER=REQUIRED
#SQLNET.CRYPTO_CHECKSUM_SERVER=REQUIRED
#SQLNET.ENCRYPTION_CLIENT=REQUIRED
SSL_CLIENT_AUTHENTICATION=FALSE
SSL_VERSION=1.2
WALLET_LOCATION=(SOURCE=(METHOD=File)(METHOD_DATA=(DIRECTORY=/home/oracle/wallet)))

#4.opcユーザーにスイッチしてwalletファイルへのアクセス権をgridユーザーに付与
$ sudo setfacl -m u:grid:rwx /home/oracle/
$ sudo setfacl -m u:grid:rwx /home/oracle/wallet
$ sudo setfacl -m u:grid:r /home/oracle/wallet/cwallet.sso
$ sudo setfacl -m u:grid:r /home/oracle/wallet/dbcert.crt
$ sudo setfacl -m u:grid:r /home/oracle/wallet/ewallet.p12

#5.gridユーザーで接続
#listener.oraファイルのLISTENERをコメントアウトして、以下を追記
$ vi /u01/app/19.0.0.0/grid/network/admin/listener.ora

#LISTENER=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER))))  
SSL_CLIENT_AUTHENTICATION=FALSE
SSL_VERSION=1.2
WALLET_LOCATION=(SOURCE=(METHOD=File)(METHOD_DATA=(DIRECTORY=/home/oracle/wallet)))

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCPS)(HOST = ホスト名)(PORT = 1522))
      (ADDRESS = (PROTOCOL = IPC)(KEY = LISTENER))
      (ADDRESS = (PROTOCOL = TcP)(HOST = ホスト名)(PORT = 1521))
    )
  )

#6.リスナー再起動、walletファイルのアクセスエラーが出ていなければOK
$ listener stop
$ listener start

#7.oracleユーザーにスイッチしてDB再起動
#リスナーがTCPS 1522でリスニングできていることを確認
$ lsnrctl status
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 19.0.0.0.0 - Production
Start Date                27-JAN-2024 14:01:09
Uptime                    0 days 0 hr. 4 min. 20 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /u01/app/19.0.0.0/grid/network/admin/listener.ora
Listener Log File         /u01/app/grid/diag/tnslsnr/testbase19c/listener/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=testbase19c.sub01120452410.vcnaqua.oraclevcn.com)(PORT=1522)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=testbase19c.sub01120452410.vcnaqua.oraclevcn.com)(PORT=1521)))

#8.iptablesでポート1522の通信を許可する
$ sudo vi /etc/sysconfig/iptables
#以下を追加
-A INPUT -p tcp -m state --state NEW -m tcp --dport 1522 -j ACCEPT　 
#iptables再起動
$ sudo service iptables restart

#iptablesでポート1522のオープンを確認
$ sudo iptables -L | grep 1522
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:1522

#9.opensslのコマンドで結果がサーバー証明書の結果が返ってくればOK
$ openssl s_client -connect ホスト名:1522

例)
$ openssl s_client -connect testbase19c.sub01120452410.vcnaqua.oraclevcn.com:1522
clevcn.com:1522
CONNECTED(00000003)
depth=0 CN = testbase19c
verify error:num=18:self signed certificate
verify return:1
depth=0 CN = testbase19c
verify return:1
---
Certificate chain
 0 s:CN = testbase19c
   i:CN = testbase19c
---
Server certificate
-----BEGIN CERTIFICATE-----
MIICrzCCAZcCEHDae05JQilcPoH/tVFwUCUwDQYJKoZIhvcNAQELBQAwFjEUMBIG
A1UEAxMLdGVzdGJhc2UxOWMwHhcNMjQwMTI3MTMzODAxWhcNMzQwMTI0MTMzODAx
WjAWMRQwEgYDVQQDEwt0ZXN0YmFzZTE5YzCCASIwDQYJKoZIhvcNAQEBBQADggEP

```

## Oracle Client側の設定
- Oracle Linux 8の1coreの最小のVMを作成
- VMからBaseDBにアクセスできるようにOCIのセキュリティ・リストのイングレスルールにポート:1522を許可しておく

``` shell
#opcで接続
#1.サーバー証明書をBaseDBから取り出しクライアント自身にインポートする
$ openssl s_client -connect ホスト名:1522 2>/dev/null </dev/null |  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > dbcert.crt
$ sudo cp dbcert.crt /etc/pki/ca-trust/source/anchors/
$ sudo update-ca-trust

#2.19cの最新のInstance Clientをインストールする
$ wget https://download.oracle.com/otn_software/linux/instantclient/1920000/oracle-instantclient19.20-sqlplus-19.20.0.0.0-1.x86_64.rpm
$ wget https://download.oracle.com/otn_software/linux/instantclient/1920000/oracle-instantclient19.20-basic-19.20.0.0.0-1.x86_64.rpm
$ sudo yum install -y libnsl
$ sudo rpm -ivh oracle-instantclient19.20-basic-19.20.0.0.0-1.x86_64.rpm 
$ sudo rpm -ivh oracle-instantclient19.20-sqlplus-19.20.0.0.0-1.x86_64.rpm

#3.DB接続するためのOracle Net Serviceの設定
$ mkdir /home/opc/instant19c

#sqlnet.oraに以下2行を追記
$ vi /home/opc/instant19c/sqlnet.ora
SSL_CLIENT_AUTHENTICATION=FALSE
SSL_VERSION=1.2

#Database側で追加したTLSでPDBに接続する箇所をそのままコピーする
vi /home/opc/instant19c/tnsnames.ora
TESTDB_PDB1 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCPS)(HOST = testbase19c)(PORT = 1522))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = testdb_pdb1.sub01120452410.vcnaqua.oraclevcn.com)
    )
  )

#TNS_ADMINを環境変数に設定
$ export TNS_ADMIN=/home/opc/instant19c

#6.SQL*PLUSで接続できればOK
$ sqlplus system/***@TESTDB_PDB1

Connected to:
Oracle Database 19c EE High Perf Release 19.0.0.0.0 - Production
Version 19.21.0.0.0
SQL> 
```

今回は、クラウドのBase Databaseを用いましたが、19c以降のデータベースであればオンプレミス、クラウドに関わらず基本的に設定は同じです。Azure ADと認証連携する場合もオンプレミスのOracle DatabaseはTLSが設定されている必要があります。

これでTLSのデータベースが準備できたので、次は実際にOCI IAMとのトークン・ベースの認証連携の設定をしていきます。