Db2 WarehouseにSSL接続（Windows/Docker上のDb2コマンド環境から接続）

# 1. はじめに
Db2 Warehouseの無料トライアル方法を[別の記事](https://qiita.com/yamasakk/items/35aa085f21a2a4284d49)で紹介しました。Db2 Warehouseにリモート端末（Windows）から接続してコマンドを実行する方法を本記事で説明します。

SSL接続のコマンド構文は[マニュアル](https://www.ibm.com/docs/en/db2-warehouse?topic=cdw-connecting-command-line-processor-clp-call-level-interface-cli)に載っていますが、それに従ったつもりでコマンドを実行してエラーが起きると、何が悪いのかわかりにくいです。本記事で紹介する実行例とエラー例が参考になるかもしれません。

本記事ではコマンド環境をWindowsに直接導入せず、Db2 Warehouseのクライアント機能をパッケージしたコンテナをWindows上のDockerに導入して、そのクライアント機能の一つであるコマンドライン・プロセッサー(CLP)を使います。

目次は次の通りです。
1. はじめに
2. 手順実行の前提
3. 手順概要
4. 手順
5. エラー例
6. 補足）Db2 Warehouseクライアント・コンテナ
7. 参考資料
8. 類似テーマを扱ったQiita記事

# 2. 手順実行の前提
- Db2 Warehouseデータベース・ユーザーのIDとパスワード
[こちらの記事](https://qiita.com/yamasakk/items/35aa085f21a2a4284d49)を参考にしてDb2 WarehouseをUbuntuに導入し、無料トライアルを行うことができます。本記事では管理ユーザー`bluadmin`でDb2 Warehouseにアクセスします。

本記事で用いたデータベースのバージョンは次の通りです。
```
[db2inst1@kuma - Db2wh ~]$ db2level
Informational tokens are "DB2 v11.5.8.0", "special_29494",
"DYN2304181003AMD64_29494", and Fix Pack "0".
```

- Windowsとそこに導入されたDocker Desktop
本記事ではWindows 10を用いましたが、Windows 11でも同様に導入・実行できると思います。Docker Desktopは[そのホームページ](https://www.docker.com/get-started/)からダウンロードして導入します。

本記事で用いたWindowsとDockerのバージョンは次の通りです。
```
PS C:\Users\xxxx> systeminfo
OS 名:                  Microsoft Windows 10 Enterprise
OS バージョン:          10.0.19045 N/A ビルド 19045

PS C:\Users\xxxx> docker --version
Docker version 24.0.6, build ed223bc
```

- IBM CloudのAPIキー
これから入手する方は次のQiita記事を参考にしてください。
    - [IBM Cloud APIKEYの作成(取得)方法](https://qiita.com/nishikyon/items/fa8b951267efbe911fe7)

# 3. 手順概要
次の順序で進めます。
1) Db2 Warehouseクライアント・コンテナを導入
    - https://www.ibm.com/docs/en/db2-warehouse?topic=container-deploying-client-windows-mac
2) コマンドライン・プロセッサー(CLP)で非SSL接続
    - https://www.ibm.com/docs/en/db2-warehouse?topic=cdw-connecting-command-line-processor-clp-call-level-interface-cli
3) コマンドライン・プロセッサー(CLP)でSSL接続
    - https://www.ibm.com/docs/en/db2-warehouse?topic=cdw-connecting-command-line-processor-clp-call-level-interface-cli
4) Db2 Warehouseクライアント・コンテナの停止と起動

本記事で用いたクライアント・コンテナのバージョンは次の通りです。
```
[Db2wh - Client CLI ~]\> db2level
Informational tokens are "DB2 v11.5.8.0", "special_28634",
"DYN2304100649AMD64_28634", and Fix Pack "0".
```

各手順においてDb2 WarehouseサーバーのIPアドレスを`xxx.xxx.xxx.xxx`と表示しています。ご自身の環境に合わせて読み替えてください。コマンド・オプションにおいて任意に指定できる名前として次のものを用いましたが、別の名前を指定することもできます。
    - クライアント・コンテナ名：`db2wc`
    - Db2ノード名：`nd_km1`, `nd_ks2`
    - Db2データベース別名：`db_km1`, `db_ks2`
    - SSL鍵データベース名：`dashclient`

# 4. 手順1) Db2 Warehouseクライアント・コンテナを導入
WindowsスタートメニューからPowerShellを起動し、`docker`コマンドを使ってIBMクラウド・レジストリにログインします。その際、2節（手順実行の前提）で述べたAPIキーをPasswordとして入力します。
```
PS C:\Users\xxxx> docker login -u iamapikey icr.io
Password:
Login Succeeded
```
コンテナ・イメージのダウンロードとデプロイを1つのコマンドで実行し、ログを確認します。コンテナ名を`db2wc`としていますが、他の名前でも構いません。
```
PS C:\Users\xxxx> docker run -d -it --privileged=true --name=db2wc icr.io/obs/hdm/db2wh_ce:v11.5.8.0-db2wh_client-linux
Unable to find image 'icr.io/obs/hdm/db2wh_ce:v11.5.8.0-db2wh_client-linux' locally
v11.5.8.0-db2wh_client-linux: Pulling from obs/hdm/db2wh_ce
4e82652cc702: Pull complete
...
Status: Downloaded newer image for icr.io/obs/hdm/db2wh_ce:v11.5.8.0-db2wh_client-linux
5aaf403dfc6781e5744c0066da96943c581c6a230b69eb2a490551b843b63c3d

PS C:\Users\xxxx> docker logs --follow db2wc
Starting up IBM Db2 Warehouse client container...
Creating Db2 client instance home and setup user environment
Creating client container directory structure and setup access controls
Creating the database client instance ...
#######################################################################
###  IBM Db2 Warehouse client container was deployed successfully   ###
#######################################################################
* If you used docker logs to monitor progress,
  detach from the console by pressing Ctrl+C.
* To get a command line from a prompt on the host,
  issue the following command:
     docker exec -it <client container name> cli
#######################################################################
```

# 4. 手順2) コマンドライン・プロセッサー(CLP)で非SSL接続
PowerShellからクライアント・コンテナー`db2wc`のシェルを起動します。`db2`コマンドを実行するとCLPのプロンプト`db2 =>`が現れます。
```
PS C:\Users\xxxx> docker exec -it db2wc cli
***********************************************************************
*    Welcome to IBM Db2 Warehouse client container interactive CLI    *
***********************************************************************

[Db2wh - Client CLI ~]\> db2
(c) Copyright IBM Corporation 1993,2007
Command Line Processor for DB2 Client 11.5.8.0
db2 =>
```
`catalog`コマンドを使ってDb2 Warehouseへの接続情報を登録します。ノード名を`nd_km1`、データベース別名を`db_km1`としていますが、別の名前でも構いません。
```
db2 => catalog tcpip node nd_km1 remote xxx.xxx.xxx.xxx server 50000
DB20000I  The CATALOG TCPIP NODE command completed successfully.
DB21056W  Directory changes may not be effective until the directory cache is
refreshed.

db2 => catalog db bludb as db_km1 at node nd_km1
DB20000I  The CATALOG DATABASE command completed successfully.
DB21056W  Directory changes may not be effective until the directory cache is
refreshed.

db2 => list node directory
Node 1 entry:
 Node name                      = ND_KM1
 Comment                        =
 Directory entry type           = LOCAL
 Protocol                       = TCPIP
 Hostname                       = xxx.xxx.xxx.xxx
 Service name                   = 50000

db2 => list database directory
Database 1 entry:
 Database alias                       = DB_KM1
 Database name                        = BLUDB
 Node name                            = ND_KM1
 Database release level               = 15.00
 Comment                              =
 Directory entry type                 = Remote
 Catalog database partition number    = -1
 Alternate server hostname            =
 Alternate server port number         =
```
ここで[`terminate`コマンドを実行してキャッシュをリフレッシュして](https://www.ibm.com/docs/en/db2/11.5?topic=commands-uncatalog-node)、再度CLPを起動します。そうしないとエラーSQL30081Nが起きることがあります。
```
db2 => terminate
DB20000I  The TERMINATE command completed successfully.

[Db2wh - Client CLI ~]\> db2
db2 => 
```
Db2 Warehouseデータベースに接続してテーブル作成など動作確認を行います。
```
db2 => connect to db_km1 user bluadmin
Enter current password for bluadmin:
   Database Connection Information
 Database server        = DB2/LINUXX8664 11.5.8.0
 SQL authorization ID   = BLUADMIN
 Local database alias   = DB_KM1

db2 => create table サンプル表1021a (番号 int, 名前 nvarchar(10))
DB20000I  The SQL command completed successfully.

db2 => list tables
Table/View                      Schema          Type  Creation time
------------------------------- --------------- ----- --------------------------
サンプル表1021A                 BLUADMIN        T     2023-10-21-00.02.45.730146

db2 => insert into サンプル表1021a values (1,'黒部'),(2,'五郎')
DB20000I  The SQL command completed successfully.

db2 => select * from サンプル表1021a
番号        名前
----------- --------------------
          1 黒部
          2 五郎

db2 => connect reset
DB20000I  The SQL command completed successfully.
db2 => quit
DB20000I  The QUIT command completed successfully.
```

# 4. 手順3) コマンドライン・プロセッサー(CLP)でSSL接続
Db2 WarehouseのWeb管理画面`https://xxx.xxx.xxx.xxx:8443/`にログインしてSSL証明書をダウンロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700959/461cb373-6aa6-2e7b-57cc-09b1440988fa.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700959/bd168403-cfd2-ee0a-935b-995585098c2b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700959/05940c97-7554-d32a-eba7-a03356b8475c.png)

上の画面でリンク`Download SSL Certificate`をクリックしてSSL証明書`DigiCertGlobalRootCA.crt`をダウンロードします。これをクライアント・コンテナにコピーします。保存用にサブ・ディレクトリ`ssl`を作成しましたが、他の名前を使うこともできます。
```
PS C:\Users\xxxx> cd .\Downloads
PS C:\Users\xxxx\Downloads> ls
Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          2023/10/20    21:03           2009 DigiCertGlobalRootCA.crt

PS C:\Users\xxxx\Downloads> docker cp DigiCertGlobalRootCA.crt db2wc:/mnt/clientdir/clienthome/db2inst1
Successfully copied 3.58kB to db2wc:/mnt/clientdir/clienthome/db2inst1

PS C:\Users\xxxx\Downloads> docker exec -it db2wc cli
[Db2wh - Client CLI ~]\> ls
DigiCertGlobalRootCA.crt
[Db2wh - Client CLI ~]\> mkdir ssl
[Db2wh - Client CLI ~]\> mv DigiCertGlobalRootCA.crt ssl
```
Global Security Kit (GSKit)のコマンド`gsk8capicmd_64`を使ってSSL証明書を鍵データベースに登録します。その名前を`dashclient`としましたが、他の名前を使うことができます。パスワードも任意です。
```
[Db2wh - Client CLI ~]\> cd ssl
[Db2wh - Client CLI ssl]\> gsk8capicmd_64 -keydb -create -db "dashclient.kdb" -pw "passw0rdpw0" -stash
[Db2wh - Client CLI ssl]\> ls
dashclient.crl  dashclient.kdb  dashclient.rdb  dashclient.sth  DigiCertGlobalRootCA.crt

[Db2wh - Client CLI ssl]\> gsk8capicmd_64 -cert -add -db "dashclient.kdb" -pw "passw0rdpw0" -label "DigiCert" -file "DigiCertGlobalRootCA.crt" -format ascii -fips

[Db2wh - Client CLI ssl]\> gsk8capicmd_64 -cert -list -db dashclient.kdb -stashed
Certificates found
* default, - personal, ! trusted, # secret key
!       DigiCert

[Db2wh - Client CLI ssl]\> gsk8capicmd_64 -cert -details -label DigiCert -db dashclient.kdb -stashed
Label : DigiCert
Key Size : 4096
Version : X509 V3
Serial : 00f2ea70259784e205
Issuer : CN=Db2_Warehouse,OU=ICP,O=IBM,L=Toronto,ST=Ontario,C=CA
Subject : CN=Db2_Warehouse,OU=ICP,O=IBM,L=Toronto,ST=Ontario,C=CA
Not Before : October 12, 2023 1:51:12 PM GMT+00:00
Not After : August 1, 2026 1:51:12 PM GMT+00:00
Public Key
    30 82 02 22 30 0D 06 09 2A 86 48 86 F7 0D 01 01
...
```
鍵データベースをDb2の構成に反映します。
```
[Db2wh - Client CLI ssl]\> pwd
/mnt/clientdir/clienthome/db2inst1/ssl

[Db2wh - Client CLI ssl]\> db2 update dbm cfg using SSL_CLNT_KEYDB /mnt/clientdir/clienthome/db2inst1/ssl/dashclient.kdb
DB20000I  The UPDATE DATABASE MANAGER CONFIGURATION command completed
successfully.

[Db2wh - Client CLI ssl]\> db2 update dbm cfg using SSL_CLNT_STASH /mnt/clientdir/clienthome/db2inst1/ssl/dashclient.sth
DB20000I  The UPDATE DATABASE MANAGER CONFIGURATION command completed
successfully.

[Db2wh - Client CLI ssl]\> db2 get dbm cfg
...
 SSL client keydb file                  (SSL_CLNT_KEYDB) = /mnt/clientdir/clienthome/db2inst1/ssl/dashclient.kdb
 SSL client stash file                  (SSL_CLNT_STASH) = /mnt/clientdir/clienthome/db2inst1/ssl/dashclient.sth
```
`catalog`コマンドを使ってDb2 Warehouseへの接続情報（SSL用）を登録し、[`terminate`コマンドでキャッシュをリフレッシュ](https://www.ibm.com/docs/en/db2/11.5?topic=commands-uncatalog-node)します。
```
[Db2wh - Client CLI ssl]\> cd
[Db2wh - Client CLI ~]\> db2
db2 => catalog tcpip node nd_ks2 remote xxx.xxx.xxx.xxx server 50001 security SSL
DB20000I  The CATALOG TCPIP NODE command completed successfully.
DB21056W  Directory changes may not be effective until the directory cache is
refreshed.

db2 => catalog db bludb as db_ks2 at node nd_ks2
DB20000I  The CATALOG DATABASE command completed successfully.
DB21056W  Directory changes may not be effective until the directory cache is
refreshed.

db2 => list node directory
Node 2 entry:
 Node name                      = ND_KS2
 Comment                        =
 Directory entry type           = LOCAL
 Protocol                       = TCPIP
 Hostname                       = xxx.xxx.xxx.xxx
 Service name                   = 50001
 Security type                  = SSL

db2 => list database directory
Database 2 entry:
 Database alias                       = DB_KS2
 Database name                        = BLUDB
 Node name                            = ND_KS2
 Database release level               = 15.00
 Comment                              =
 Directory entry type                 = Remote
 Catalog database partition number    = -1
 Alternate server hostname            =
 Alternate server port number         =

db2 => connect reset
SQL1024N  A database connection does not exist.  SQLSTATE=08003
db2 => terminate
DB20000I  The TERMINATE command completed successfully.
```
再度CLPを起動し、Db2 Warehouseに接続して前節で作成したテーブルにアクセスできることを確認します。
```
[Db2wh - Client CLI ~]\> db2
db2 => connect to db_ks2 user bluadmin
Enter current password for bluadmin:
   Database Connection Information
 Database server        = DB2/LINUXX8664 11.5.8.0
 SQL authorization ID   = BLUADMIN
 Local database alias   = DB_KS2

db2 => select * from サンプル表1021a
番号        名前
----------- --------------------
          1 黒部
          2 五郎

db2 => connect reset
DB20000I  The SQL command completed successfully.
db2 => quit
DB20000I  The QUIT command completed successfully.
[Db2wh - Client CLI ~]\>
```

# 4. 手順4) Db2 Warehouseクライアント・コンテナの停止と起動
Windowsをシャットダウンする前にコンテナを停止します。GUIから操作できますが、コマンドを使う場合は次のようになります。
```
PS C:\Users\xxxx> docker stop db2wc
db2wc
```
Windowsを起動した後はコンテナを起動します。
```
PS C:\Users\xxxx> docker start db2wc
db2wc
```

# 5. エラー例) SQL30081N  Communication error
接続情報を登録し、満を持してconnectコマンドを実行すると次のようなエラーでがっくり、でした。
```
db2 => connect to db_km1 user bluadmin
Enter current password for bluadmin:
SQL30081N  A communication error has been detected. Communication protocol
being used: "TCP/IP".  Communication API being used: "SOCKETS".  Location
where the error was detected: "xxx.xxx.xxx.xxx".  Communication function
detecting the error: "connect".  Protocol specific error code(s): "111", "*",
"*".  SQLSTATE=08001

db2 => connect to db_ks2 user bluadmin
Enter current password for bluadmin:
SQL30081N  A communication error has been detected. Communication protocol
being used: "SSL".  Communication API being used: "SOCKETS".  Location where
the error was detected: "".  Communication function detecting the error:
"sqlccSSLSocketSetup".  Protocol specific error code(s): "414", "*", "*".
SQLSTATE=08001
```
エラー対応は次のようになります。
- 手順2や3で述べたように`terminate`コマンドで[CLPのキャッシュをリフレッシュ](https://www.ibm.com/docs/en/db2/11.5?topic=commands-uncatalog-node)します。
- Db2 Warehouseサーバーのポートに対してクライアント・コンテナから疎通があるか確認します。
```
[Db2wh - Client CLI ~]\> nc -vz xxx.xxx.xxx.xxx 50000
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to xxx.xxx.xxx.xxx:50000.
Ncat: 0 bytes sent, 0 bytes received in 0.01 seconds.

[Db2wh - Client CLI ~]\> nc -vz xxx.xxx.xxx.xxx 50001
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to xxx.xxx.xxx.xxx:50001.
Ncat: 0 bytes sent, 0 bytes received in 0.01 seconds.
```
- Db2 Warehouseサーバーを確認します。ありきたりですが、サーバー・コンテナが起動しているか、オペレーティング・システムのファイアウォールがポートへのアクセスを許可しているか、確認します。

# 6. 補足）Db2 Warehouseクライアント・コンテナ
本記事ではクライアント・コンテナに登録されているDb2コマンドライン・インターフェースCLPを使いました。このクライアント・コンテナにはコマンドライン・インターフェース以外にも[各種管理支援ツール](https://www.ibm.com/docs/en/db2-warehouse?topic=tools-db2-support-overview)が登録されています。支援ツール一覧を`commands`で表示できます。
```
PS C:\Users\xxxx> docker exec -it db2wc cli
[Db2wh - Client CLI ~]\> commands
#######################################################################
#     ----- The IBM Db2 Warehouse client container commands -----     #
#######################################################################
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* CLP: Allows batch SQL scripts to be run against an
IBM Db2 Warehouse database or initiates an interactive
CLP session
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* clpplus: Initiates an interactive CLPPlus session
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* db_catalog: Catalogs or uncatalogs remote dashDB databases or lists the
currently cataloged databases
...
```
例として2つのコマンドを選び実行すると、つぎのような結果が得られます。
```
[Db2wh - Client CLI ~]\> db_ddl_table -db db_ks2 -u bluadmin -pw xxxxxxxx -tb "サンプル表1021A"
-- Database Name: db_km1
-- DDL Statements for Table "BLUADMIN"."サンプル表1021A"
CREATE TABLE "BLUADMIN"."サンプル表1021A"  (
                  "番号" INTEGER ,
                  "名前" VARCHAR(10 CODEUNITS32) )
                 IN "USERSPACE1"
                 ORGANIZE BY COLUMN@

[Db2wh - Client CLI ~]\> db_size -db db_ks2 -u bluadmin -pw xxxxxxxx
  Object   |               Name                |        Bytes         |        KB        |      MB      |     GB     |   TB
-----------+-----------------------------------+----------------------+------------------+--------------+------------+------------
Database   |DB_KS2                             |          828,375,040 |          808,960 |          790 |       .771 |       .001
MQTable    |DB2GSE.GSE_SRS_REPLICATED_AST      |              262,144 |              256 |            0 |       .000 |       .000
Table      |BLUADMIN.サンプル表1012B      |              786,432 |              768 |            1 |       .001 |       .000
Table      |BLUADMIN.サンプル表1021A      |              786,432 |              768 |            1 |       .001 |       .000
Table      |DB2GSE.GSE_AUTHORIZATION           |              262,144 |              256 |            0 |       .000 |       .000
...
-----------------------------------------
DB_KS2   = 790 MB
SUM(SCHEMA) = 748 MB
OTHER METADATA/CACHE/CONFIG FILES = 42 MB
-----------------------------------------
```

# 7. 参考資料
- Qiita記事
    - IBM Cloud APIKEYの作成(取得)方法
    https://qiita.com/nishikyon/items/fa8b951267efbe911fe7
    - パソコンにDb2 Warehouseを導入して無料トライアル
    https://qiita.com/yamasakk/items/35aa085f21a2a4284d49

- Docker
    - Get Started with Docker
    https://www.docker.com/get-started/

- Db2 Warehouseマニュアル
    - Deploying the IBM Db2 Warehouse client container (Windows or Mac)
    https://www.ibm.com/docs/en/db2-warehouse?topic=container-deploying-client-windows-mac
    - Connecting to IBM Db2 Warehouse with the command-line processor (CLP) or Call Level Interface (CLI)
    https://www.ibm.com/docs/en/db2-warehouse?topic=cdw-connecting-command-line-processor-clp-call-level-interface-cli
    - To refresh the CLP's directory cache, use the TERMINATE command.
    https://www.ibm.com/docs/en/db2/11.5?topic=commands-uncatalog-node
    - Db2 support tools overview
    https://www.ibm.com/docs/en/db2-warehouse?topic=tools-db2-support-overview

- Db2 マニュアル
    - Creating a keystore with GSKit（gsk8capicmd_64コマンド）
    https://www.ibm.com/docs/en/db2/11.5?topic=keystores-creating-keystore-gskit

# 8. 類似テーマを扱ったQiita記事
- Db2 docker から Db2 on CloudのDBに接続
https://qiita.com/nishikyon/items/8b2cbbe3846b75ba5103
- Db2 Warehouse Client を導入してみた
https://qiita.com/m1914uk/items/7afe8bef7cf5cf61ea16