DatabricksのIPアクセス制限の設定方法

Databricksのセキュリティ機能の一つであるIPアドレスよるアクセス制限について、動作仕様と設定方法について説明します。

# 概要

Databricksへのアクセスは、基本的にワークスペースURLを介して実施されます。通常のブラウザベースでワークスペースにアクセスする場合に加えて、外部からJDBC接続する場合や、Databricks API/CLIを使う場合においても接続先のエンドポイントはこのワークスペースURLになります。

DatabricksのIPアクセス制限は、このワークスペースURLへのアクセスに関して実行されます。よって、制限の対象は、ブラウザでのアクセス、JDBC/ODBC接続、API/CLI実行に及びます。

また、IPアクセス制限機能は、以下の契約Tierが必要です。

* Databricks on AWS: Enterprise 
* Azure Databricks: Premium
* Databricks on GCP: Premium


# 動作仕様

IPアクセス制限は、全てのアクセスに関して以下のステップで評価されます。
(Blackリスト=ブロックリスト、Whiteリスト=許可リスト)

1. IPアクセス制限機能がON(`enableIpAccessLists == true`)になっている場合に、以下を評価する。
1. アクセス元IPアドレスがBlackリストにある場合は、アクセスを拒否する。
1. Whiteリストが定義されている、かつ、アクセス元IPアドレスがWhiteリストにない場合、アクセスを拒否する。
1. 上記以外の場合は、アクセスを許可する。

[公式ドキュメントページにフローチャート](https://docs.microsoft.com/ja-jp/azure/databricks/security/network/ip-access-list#--feature-details)がありますので参照ください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62653/4bf461cb-1e77-204e-1d37-00f4d1ffdaff.png)


上記だと、ややわかりづらい部分もありますので、評価のステップを疑似コードでも表してみました。

```C
ip_address={接続元のIPアドレス};

if( enableIpAccessLists == "true" ){
	if( BLACK_LIST exists && ip_address in BLACK_LIST ){
		reject();
		exit();
	}

	if( WHITE_LIST exists ){
		if ( ip_address NOT in WHITE_LIST ){
			reject();
			exit();
		}
	} 
}

allow();
exit();
```

注意すべき点として、Whiteリストが一つでもあると、「Whiteリストに載っているIPしか許可しない」動作になります。したがって、誤ったIPが登録されたWhiteリストを反映させてしまうと、アクセスがブロックされてしまう可能性があります。

# 設定手順

## 方針

運用上、Blackリストによる特定のIPからの接続ブロックよりも、Whiteリストによる特定のIPのみ接続許可のケースが多いと思いますので、このパターンの設定方法を見ていきます。特に、IPアクセス制限の設定自体のAPIリクエストもIPアクセス制限の対象になりますので、設定手順を誤ると全アクセスがブロックされ(締め出される)、身動きが取れなくなるので注意が必要です。

(ただし、実際は、IPアクセス制限設定の時に、APIリクエスト元のIPがWhiteリストにない場合はエラーになる仕様になっています。それでも、なお、アクセスできない状況に陥った場合は、サポートチケットによりリカバリをする必要があります。)

以下のステップで設定を見ていきます。

1. IPアドレス制限機能がOFFになっていることを確認する
1. Whiteリストの追加
1. Whiteリストの確認(少なくとも、APIリクエスト元のIPが含まれていることを確認)
1. (上記をダブルチェック)
1. IPアドレス制限機能をONにする
1. 動作確認
    1. 許可リストにないクライアントからのアクセスが拒否されるかを確認
    1. 許可リストに含まれるクライアントからアクセスできるかを確認
1. 完


## 設定作業

IPアクセス制限機能の設定に関しては、APIで設定していきます。ここでは見やすさと汎用性からの観点から`curl`コマンドを使用して実施していきます。RESTful APIですので、他のクライアントでも同様に可能です。

### 0. 事前準備

ここでは、`curl`コマンドが実行できるLinux/Unix/MacOS環境を想定します。

まず、ワークスペースURL、及び、DatabricksのPersonal Access Token(以下、Token)を環境変数として定義します。Tokenはセキュリティ情報ですので、有効期限を1日に設定し、かつ、historyなどに残らないように扱ってください。ここでは簡単のため、通常の`export`コマンドで環境変数を定義します。

> **注意** : Personal Access Tokenは、ワークスペース上の`ユーザー設定`より発行・管理できます。

```sh
$ export WS_URL='https://xxxxxxxxx.cloud.databricks.com' # <= ワークスペースのURL
$ export TOKEN='dapidxxxxxxxxx4b9948f0a38307' # <= DatabricksのToken
```

### 1. IPアドレス制限機能がOFFになっていることを確認する

* 使用するAPI: [Check if IP access list is enabled](https://docs.databricks.com/dev-tools/api/latest/ip-access-list.html#operation/get-status)

```sh
$ curl -X GET \                                                             
     -H "Authorization: Bearer ${TOKEN}" \
     "${WS_URL}/api/2.0/workspace-conf?keys=enableIpAccessLists"

### レスポンス
{"enableIpAccessLists":"false"}
```

初期状態は`{"enableIpAccessLists":"null"}`になっている場合もありますが、それでも問題ありません。



### 2. Whiteリストの追加

Whiteリストに許可するIPを登録していきます。CIDRブロック形式でも登録できます。また、Whiteリストは複数登録できますので、IPリストをグループ化して運用することができます。今回は、1つのWhiteリストを`office2`という名前で作成します。許可するIPアドレスはコマンド内にある通り、JSON配列形式で並べていきます。

* 使用するAPI: [Add an IP access list](https://docs.databricks.com/dev-tools/api/latest/ip-access-list.html#operation/add-list)

```sh
$ curl -X POST \
     -H "Authorization: Bearer ${TOKEN}" \
    "${WS_URL}/api/2.0/ip-access-lists" \
	-d '{
		"label": "office2",
		"list_type": "ALLOW",
		"ip_addresses": [
			"147.192.33.0/24",
			"1.2.3.4",
			"5.6.7.8",
			"44.230.222.179"
		]
	}'

### レスポンス
{
    "ip_access_list": {
        "list_id": "68bb11a5-xxxxxxxxx-xxxxxxxx-dcd7c0231f39",
        "label": "office2",
        "ip_addresses": [
            "147.192.33.0/24",
            "1.2.3.4",
            "5.6.7.8",
            "44.230.222.179"
        ],
        "address_count": 4,
        "list_type": "ALLOW",
        "created_at": 1647924789294,
        "created_by": 1871322770409591,
        "updated_at": 1647924789294,
        "updated_by": 1871322770409591,
        "enabled": true
    }
}
```


### 3. Whiteリストの確認(少なくとも、APIリクエスト元のIPが含まれていることを確認)

上記で登録したWhiteリストを確認します。

* 使用するAPI: [Get all IP access lists](https://docs.databricks.com/dev-tools/api/latest/ip-access-list.html#operation/get-lists)

```sh
$ curl -X GET \
     -H "Authorization: Bearer ${TOKEN}" \
     "${WS_URL}/api/2.0/ip-access-lists"

### レスポンス
{
    "ip_access_lists": [
        {
            "list_id": "68bb11a5-xxxxxxxxx-xxxxxxxx-dcd7c0231f39",
            "label": "office2",
            "ip_addresses": [
                "147.192.33.0/24",
                "1.2.3.4",
                "5.6.7.8",
                "44.230.222.179"
            ],
            "address_count": 4,
            "list_type": "ALLOW",
            "created_at": 1647924789294,
            "created_by": 1871322770409591,
            "updated_at": 1647924789294,
            "updated_by": 1871322770409591,
            "enabled": true
        }
    ]
} 
```


また、同時に、このAPIリクエスト元のIP(つまり上記の`curl`コマンドを実行しているマシンのIP)がWhiteリストに含まれていることを確認します。

```sh
### このマシンのGlobal IPを確認する(方法はさまざま)

$ curl -4 ifconfig.co
147.192.33.83
```

このIPアドレス`147.192.33.83`はWhiteリストに登録してある`147.192.33.0/24`に含まれますので、問題ないことがわかります。


### 4. (上記をダブルチェック)

再度、確認します。本番では、作業者2人でリアルタイムにレビューしながら進めるなど、運用を考えてください。


### 5. IPアドレス制限機能をONにする

最後に、IPアドレス機能をONにします。このAPI実行によって、数分後にIPアドレス制限が有効になります。

* 使用するAPI: [Enable or disable IP access lists for this workspace](https://docs.databricks.com/dev-tools/api/latest/ip-access-list.html#operation/set-status)

```sh
$ curl -X PATCH \
     -H "Authorization: Bearer ${TOKEN}" \
	"${WS_URL}/api/2.0/workspace-conf" \
	-d '{
		"enableIpAccessLists": "true"
	}'
```

ONになったかをAPIで確認します(最初に実行したAPIに同じ)。

* 使用するAPI: [Check if IP access list is enabled](https://docs.databricks.com/dev-tools/api/latest/ip-access-list.html#operation/get-status)

```sh
$ curl -X GET \
     -H "Authorization: Bearer ${TOKEN}" \
     "${WS_URL}/api/2.0/workspace-conf?keys=enableIpAccessLists"

### レスポンス
{"enableIpAccessLists":"true"}
```

API上ではONになったことが確認できました。


### 6. 動作確認

#### 6.1 許可リストにないクライアントからのアクセスが拒否されるかを確認

IPアドレス制限は反映までに数分かかることがあるため、動作確認はブロックされるパターンからテストすると、反映されたことも同時確認できるので効率的です。APIもブロック対象になるので、Whiteリストに登録されていないクライアントを用意して、APIリクエストで確認してみます。

```sh
### WhiteリストにないクライアントのShell

$ export WS_URL='https://xxxxxxxxx.cloud.databricks.com' # <= ワークスペースのURL
$ export TOKEN='dapidxxxxxxxxx4b9948f0a38307' # <= DatabricksのToken

$ curl -X GET \
     -H "Authorization: Bearer ${TOKEN}" \
     "${WS_URL}/api/2.0/workspace-conf?keys=enableIpAccessLists"

### レスポンス
{"error_code":"403","message":"Unauthorized access to Org: 4030176293824898"}
```

リクエストがブロックされていることが確認できました。


#### 6.2 許可リストに含まれるクライアントからアクセスできるかを確認

同様に、許可リストにあるクライアントからの接続を確認します。

```sh
### WhiteリストにあるクライアントのShell

$ export WS_URL='https://xxxxxxxxx.cloud.databricks.com' # <= ワークスペースのURL
$ export TOKEN='dapidxxxxxxxxx4b9948f0a38307' # <= DatabricksのToken

$ curl -X GET \
     -H "Authorization: Bearer ${TOKEN}" \
     "${WS_URL}/api/2.0/workspace-conf?keys=enableIpAccessLists"

### レスポンス
{"enableIpAccessLists":"true"}
```

アクセスできることが確認できました。


# 参考

* [IP Access List API](https://docs.databricks.com/dev-tools/api/latest/ip-access-list.html)
* [IPアクセスリスト](https://docs.microsoft.com/ja-jp/azure/databricks/security/network/ip-access-list)