CP4DaasのWMLにアクセス可能なIPアドレスを制限する

# 0. はじめに
CP4DaaSのWatson Machine Learning（WML)でスコアリングするアプリケーションに、誰からでもアクセスさせないようにIPアドレスの制限をかける方法を解説します。

2024年10月時点では、WMLのサービス自体にはIPアドレスを制限する機能はありませんので、IAMのIPアドレスの制限機能をつかって実現します。

具体的には
1. WMLのサービスをもつAccoutのオーナーであるユーザーAでデプロイメントを準備
1. 別のユーザーBをアカウントに招待し、
1. ユーザーBのAPIキーを作り、
1. そのユーザーBにIAMでIPアドレス制限をかけることで実現します。

ユーザーBのAPIキーはユーザーBと同じ権限を持つ（つまりIPアドレスを制限される）ことを利用しています。

![{0C2A22C8-FC17-4FD1-BF0D-E47926ABF6B4}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/d13686d3-37fd-1553-b5e3-4e2f6900d906.png)


* テスト環境
    * CP4DaaS
    * jp-tok

# 1. 事前準備
以下の記事を参考にユーザーA（この例ではkawa's Account）のアカウントでWMLのオンライン・デプロイメントを作成しておきます。

### 参考: Watson Machine LearningにPython関数をデプロイする #watsonx.ai - Qiita 
https://qiita.com/spssfun2017/items/1a223cb07d8e6c4f86aa

ユーザーA（この例ではkawa's Account）で「Deployment of function」を作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/388b3500-437b-404f-2d7e-54d95d2922ba.png)


# 2. ユーザーBをユーザーAのアカウントに招待する
[IBM CloudのIAMのユーザー](https://cloud.ibm.com/iam/users)で、ユーザーB（この例では2017 testuser）をユーザーAのアカウント（この例ではkawa's Account）に招待をして追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/ca5d3c44-a4a3-e7df-41a4-a2a0746383d7.png)

#### 参考：アカウントへのユーザーの招待
https://cloud.ibm.com/docs/account?topic=account-iamuserinv&locale=ja&interface=ui


# 3. ユーザーBでAPIキーを作成
WMLのオンライン・デプロイメント（Function）の実行をibm_watsonx_aiのAPIで行うのでAPIキーが必要です。

ユーザーBでIBM Cloudにログインします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/af9edc57-f031-2e8f-0c63-42ce18265b8f.png)


[IBM CloudのIAMのAPIキー](https://cloud.ibm.com/iam/apikeys)で、ユーザーB（この例では2017 testuser）のAPIキーを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/ef67c93d-d814-34ec-e426-cfbb87a4e75c.png)

適当な名前をつけて作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/f5aaa346-b17a-1c97-8477-16dcb951b4e8.png)

コピーやダウンロードして保存しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/64586bc2-933c-114c-961b-dcfe2a80754c.png)

## 3-1. ユーザーBのAPIキーでユーザーAのAccountのWMLのオンライン・デプロイメントを実行する。
1で準備したユーザーA（この例ではkawa's Account）の「Deployment of function」をユーザーBのAPIキーで実行します。

以下のようなpythonスクリプトで実行します。ポイントは`api_key`に#3で作ったユーザーB（ここでは2017 testuser）のAPIキー`dcxxxxxxxxxxxxxx`を用いていることです。


```python:DeployableFunctionTest_onlyscore.py
import pprint
from ibm_watsonx_ai import Credentials
from ibm_watsonx_ai import APIClient

# 環境設定
api_key = 'dcxxxxxxxxxxxxxx'  # 2017 testuser
url = 'https://jp-tok.ml.cloud.ibm.com'
space_id = '1bee1486-8dc0-462a-a85d-456133d33ca7'  # 240814dp_kawa
deployment_id = '3fc75bbf-3ebf-4a6f-a267-c55e1f4e8ef4'  # Deployment of function


# WMLへの接続
credentials = Credentials(
    api_key=api_key,
    url=url
)

client_space = APIClient(credentials, space_id=space_id)

# テストスコアリング
scoring_payload = {
    "input_data": [{
        'values': 'test'
    }]
}


response = client_space.deployments.score(deployment_id, scoring_payload)
pprint.pprint(response["predictions"])
```

ちゃんと実行できることがわかります。
```bash:実行結果
C:\Functiontest\Functiontest>py -3.10 DeployableFunctionTest_onlyscore.py
[{'values': [['Just a test']]}]
```

# 4. ユーザーBでIPアドレスのアクセスの制限を行う
ユーザーBのアカウント（ここではtestuser2017's Account）で[IBM CloudのIAMのユーザー](https://cloud.ibm.com/iam/users)で、ユーザーB（ここでは2017 testuser）を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/c21f8db6-4e1b-1b43-981a-573f90a47555.png)

「IPアドレスのアクセス」で「許可されたIPの追加」をします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/4357827d-1c04-e766-6594-7135f66a5ea7.png)

現在のIPアドレスを設定しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/528b9020-aa43-0718-a375-954dd60c0a7b.png)

## 4-1. 許可されたIPからのアクセス
[CMANのサイト](https://www.cman.jp/network/support/go_access.cgi)などで現在のGlobalIPを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/8685f738-3564-07b5-3234-618d2a28e671.png)


許可されたIPからのアクセスなので、ちゃんと実行できることがわかります。
```bash:実行結果
C:\Functiontest\Functiontest>py -3.10 DeployableFunctionTest_onlyscore.py
[{'values': [['Just a test']]}]
```

## 4-2. 許可されたIP外からのアクセス
IPアドレスの違う環境からアクセスしてみます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/62de1d65-6441-12b7-6f2a-6c58bf495889.png)

IPアドレスが許可されたリストに入っていないため、「Error getting IAM Token」のエラーになり実行できません。ちゃんとIPアドレスの制限できたことが確認できました。

```bash:実行結果
C:\Functiontest>py -3.10 DeployableFunctionTest_onlyscore.py
Error getting IAM Token.
Reason: <Response [401]>
Traceback (most recent call last):
  File "C:\Functiontest\DeployableFunctionTest_onlyscore.py", line 23, in <module>
    client_space = APIClient(credentials, space_id=space_id)
  File "C:\Users\dsuser\AppData\Local\Programs\Python\Python310\lib\site-packages\ibm_watsonx_ai\client.py", line 365, in __init__
    self.service_instance: ServiceInstance = ServiceInstance(self)
  File "C:\Users\dsuser\AppData\Local\Programs\Python\Python310\lib\site-packages\ibm_watsonx_ai\service_instance.py", line 56, in __init__
    self._client.token = self._get_token()
  File "C:\Users\dsuser\AppData\Local\Programs\Python\Python310\lib\site-packages\ibm_watsonx_ai\service_instance.py", line 237, in _get_token
    return self._create_token()
  File "C:\Users\dsuser\AppData\Local\Programs\Python\Python310\lib\site-packages\ibm_watsonx_ai\service_instance.py", line 273, in _create_token
    return self._get_IAM_token()
  File "C:\Users\dsuser\AppData\Local\Programs\Python\Python310\lib\site-packages\ibm_watsonx_ai\service_instance.py", line 345, in _get_IAM_token
    raise WMLClientError("Error getting IAM Token.", response)
ibm_watsonx_ai.wml_client_error.WMLClientError: Error getting IAM Token.
Reason: <Response [401]>
```

# 注意
## 注意１:IPアドレスの設定は慎重に
IPの許可リストには必ず接続できるIPアドレスを記載してください。間違ったアドレスをいれるとIBM Cloudのコンソールにもログインできなくなるため、IPの許可リストは修正もできませんし、Caseも起票できなくなります。

どうしても接続できなくなってしまった場合には以下から解除をリクエストしてください。
https://watson.service-now.com/x_ibmwc_open_case_app.do#!/create

## 注意2:制限できるのはIPアドレスを制限したユーザーのAPIキーのみ
制限できるのはIPアドレスを制限したユーザーのAPIキーのみです。例えば、このテストケースで、ユーザーAやまた別のユーザーCでAPIキーを作っていた場合はそのAPIキーでアクセスした場合にはIP制限はかかりません。できるかぎりIP制限をかけていないユーザーでは、APIキーはつくらないような運用を考えることを推奨します。


# 参考
### Cloud Pak for Data as a Service へログイン可能なIPアドレスを制御する #ibmcloud - Qiita 

Watson Studioにアクセス可能なIPアドレスを制限する方法です。

https://qiita.com/1000aki/items/96cc3e3e51a0abce2f16

### Watson Studio(CP4DaaS)へのログイン可能なIPアドレスを制限する場合の注意点 #IPv6 - Qiita 

注意点があります。

https://qiita.com/spssfun2017/items/26aea3e8b5a731f43a9c


### IBM Cloud: IAMにおけるIBM Cloud ConsoleへのIPアドレスによるアクセス制限方法 #ibmcloud - Qiita 

https://qiita.com/testnin2/items/f92a42c2c527f0de9966

### 特定の IP アドレスの許可
https://cloud.ibm.com/docs/account?topic=account-ips&interface=ui

### Watson Machine LearningにPython関数をデプロイする #watsonx.ai - Qiita 
https://qiita.com/spssfun2017/items/1a223cb07d8e6c4f86aa