Db2 RESTサービスの権限管理

## 権限設定の必要性

Db2ではREST APIをサポートしていて、以下のようなことができます。
 * １. RESTサービスの作成と実行
     * ユーザーが事前に登録したSQL(SELECT/INSERT/UPDATE/DELETE) をRESTサービスとして実行できる
     * SQLの結果セットはjson形式で受け取る
 * ２. 任意のSQLを実行可能 
     * /v1/services/execsql エンドポイントを使用して SQL を直接実行

ここで、ユーザが作成したRESTサービス(１.) は、作成者とは別のユーザーから利用されることが想定されますが、RESTサービスを作成しただけでは、作成者以外のユーザーから実行することはできません。
サービスの実体となるプロシージャや、実行されるSQLからアクセスされるDBオブジェクト(表、ビュー等)への権限付与が必要となります。

## Db2 RESTサービスの実行権限設定方法（おそらく、2種類あり）

Db2 REST のドキュメントを見ると作成済サービスに対する権限付与/取り消しを行うREST APIが提供されるようですが、2022年9月時点ではコマンドサンプルに誤りがあり、記載通りに実行してもうまくいきません。

一方で、[Db2マニュアル「Db2 で REST エンドポイントを操作するために必要な特権」](https://www.ibm.com/docs/ja/db2/11.5?topic=endpoints-required-privileges)によると、
REST APIによる権限付与については言及されず、REST APIによる権限操作は必須ではないようです。

推測ですが、ユーザが作成したDb2 RESTサービスへの権限付与は以下2種類があり、
どちらか片方だけ実施すれば良いものと思われます。
後半で実際に試してみていますが、(1)だけで他ユーザによる実行が可能になっています。

__権限設定方法(1) Db2サーバ上でDb2 GRANT/REVOKEコマンド実行し、権限設定を行う__
　or
__権限設定方法(2) Db2 RESTサービスコンテナに対してREST API(/grant or /revoke)を実行することで権限設定を行う__


## 作業の流れ
新規OSユーザー「dbuser1」へ、db2inst1ユーザが作成したRESTサービス「sql_max_t2」の実行権限を付与します。
「sql_max_t2」サービスの作成手順/処理内容はこちらに記載の通りです。 → [Link](https://qiita.com/mi-kana/items/3d6636c13b3085eb709f)

Step1. OSユーザ作成
Step2. DBサーバ上でのGRANTによる権限付与
Step3. 権限を与えられた別ユーザからのサービス呼び出し

### 前提
Step2 の権限操作を行うには、以下どちらかの条件を満たしている必要があります。
 * ACCESSCTRL or SECADM　権限を持っている、もしくは
 * WITH GRANT OPTION つきで権限を付与されている

今回は、サービス作成者でもあるインスタンスオーナー db2inst1 にて以下の操作を行います。

### Step1. OSユーザ作成
OS root ユーザにて新規グループを作成します。
```
[root@4c4fd18c3faf /]# groupadd -g 1002 dbgroup
```
上記グループに属する新規ユーザを作成します。
```
[root@4c4fd18c3faf /]# useradd -u 1007 -g 1002 dbuser1
```

### Step2. Db2権限付与(DBサーバ上でのGRANT)
今回作成されたRESTサービス(≒Db2 SQLプロシージャ)実行にあたり必要な権限設定を行います。
Db2コマンドウィンドウから、Db2インスタンスオーナーにて下記３点の操作を実行します。
 * CONNECT権限付与
 * RESTサービスから参照されるテーブルへのSELECT権限付与
 * RESTサービスの実体であるプロシージャのEXECUTE権限付与

いずれも、dbuser1ユーザが属するOSグループである、dbgroup に対して権限付与を行います。

dbgroupグループにCONNECT権限を付与します。
```
[db2inst1@4c4fd18c3faf ~]$ db2 grant CONNECT on database to group dbgroup
DB20000I  The SQL command completed successfully.
```
dbgroupグループに、RESTサービスからアクセスされるオブジェクトへのアクセス権限を付与します。
今回はT1表への参照のみ行う処理であるため、T1表へのSELECT権限を付与しています。
```
[db2inst1@4c4fd18c3faf ~]$ db2 grant SELECT on db2inst1.t1 to group dbgroup
DB20000I  The SQL command completed successfully.
```
RESTサービスの実体となるSQLプロシージャ「DB2INST1.REST_SQL_MAX_T2_1_0」の実行権限を付与します。
```
[db2inst1@4c4fd18c3faf ~]$ db2 grant execute on procedure DB2INST1.REST_SQL_MAX_T2_1_0 to group dbgroup
DB20000I  The SQL command completed successfully.
```
※RESTサービスの実体のプロシージャのスキーマ名とプロシージャ名は、下記SQLにて確認することができます。
  RESTSERVICE表は、Db2 RESTサービスのメタデータを格納するための表です。
```
db2 "select PROCSCHEMA, PROCNAME from db2rest.restservice where name='サービス名'"
```



### Step3. 権限を与えられた別ユーザからのサービス呼び出し
新規作成ユーザ dbuser1 の認証トークンを取得します。
```
kanako@IBM-PF2E8K5F:~$ curl --insecure -X POST \
>   https://localhost:50050/v1/auth \
>   -H "content-type: application/json" \
>   -d '{
>       "dbParms": {
>         "dbHost": "DBサーバホスト名",
>         "dbName": "DB名",
>         "dbPort": DBサーバListenポート,
>         "isSSLConnection": false,
>         "username": "DB接続ユーザ名",
>         "password": "DB接続ユーザパスワード"
>       },
   "exp>       "expiryTime": "24h" }'
{"token":"eyJh..(以下略)"}
```
つづいて、dbuser1のトークンを指定して定義済みサービスを呼び出します。
```
kanako@IBM-PF2E8K5F:~$ curl --insecure -X POST \
>   https://localhost:50050/v1/services/sql_max_t2/1.0 \
>   -H "authorization: eyJh..(以下略)" \
>   -H "content-type: application/json" \
'{
  >   -d '{
>       "sync": true }'
{"jobStatus":4,"jobStatusDescription":"Job is complete","resultSet":[{"1":15000}],"rowCount":1}
kanako@IBM-PF2E8K5F:~$
```

以上の手順で、作成者以外のユーザから Db2 RESTサービスを実行することができました。

## 補足：権限がない場合
権限を与えていないユーザからサービスを実行しようとすると、以下のようなメッセージが出力されます。

```
kanako@IBM-PF2E8K5F:~$ curl --insecure -X POST \
>   https://localhost:50050/v1/services/sql_max_t2/1.0 \
>   -H "authorization: eyJh..(以下略)" \
>   -H "content-type: application/json" \
'{
  >   -d '{
>       "sync": true }'
{"errors":[{"code":"forbidden","message":"[Db2 REST] An error occurred invoking service 'sql_max_t2' version '1.0'.","more_info":"SQLExecute: {42501} [IBM][CLI Driver][DB2/LINUXX8664] SQL0551N  The statement failed because the authorization ID does not have the required authorization or privilege to perform the operation.  Authorization ID: \"DBUSER1\".  Operation: \"EXECUTE\". Object: \"DB2INST1.REST_SQL_MAX_T2_1_0\".  SQLSTATE=42501\n"}],"trace":null}
kanako@IBM-PF2E8K5F:~$
```

SQL0551N / SQLSTATE=42501 とあり権限不足が指摘されています。

> SQL0551N  The statement failed because the authorization ID does not have the required authorization or privilege to perform the operation.  Authorization ID: \"DBUSER1\".  Operation: \"EXECUTE\". Object: \"DB2INST1.REST_SQL_MAX_T2_1_0\".  SQLSTATE=42501\n"}],"trace":null}