IBM Cloud: IBM Cloud Databaseへのprivate endpoint側のアクセス制限方法

# 1. はじめに

IBM Cloud Database(ICD)にアクセスする方法はpublic endpoint（インターネットからのアクセス）とprivate endpoint(プライベートネットワークからのアクセス）の2つ存在する。

## public endpointを利用する場合
（もちろん認証が必須なので誰でもアクセスできるという訳ではないが）認証情報さえ持っていれば、デフォルトでは任意のアクセス元からインターネット経由でアクセスできてしまう。ICDには`Allowlist IPs`というFirewall機能があるため、ここでアクセスを許可するPublic IPを指定するのは、ほぼ必須となるだろう。ただし、`Allowlist IPs`でアドレスを一旦指定すると、今度はそこからしかアクセスできなくなるので、そのままでは仮にprivate endpointを有効にしていてもprivate network経由ではアクセスできなくなる。多くの場合、private endpointも併用したいことが多いため、結局private側でもどのアドレスからアクセスを許可すれば良いのかという情報が必要となる。

## private endpointを利用する場合
インターネットからアクセスされる可能性はないのだから、安心と言えば安心である。しかし、例えば複数VPCを持っていて、VPC-AからのみICDにアクセスを許可し、VPC-BからIBM Cloud Databaseにはアクセスを禁じることはできるのだろうか？VPCは仮想ネットワークなので、VPC-AのサーバーもVPC-Bのサーバーも同じIPアドレスである可能性もある。こういう際のアクセス制御はできるだろうか？

# 2. まずは結論から

結論からまとめてみた（Classic InfrastructureでVRFを有効にしていないとそもそもPrivate Endpointにはアクセスできないので表には記載していない）。

|| Classic Infrastructure(VRFを有効） | ICDに対するVPEを構成していないVPC |  ICDに対するVPEを構成しているVPC|
|:-|:-|:-|:-|
|Private Endpointに対するFQDNを名前解決した際のアドレス|`166.9.xx.xx`(CSE)| `166.9.xx.xx`(CSE)|10.xx.xx.xxなど、VPC上で利用者自身が定義したprivate subnet上のアドレス(VPE)|
|IaaS側からのアクセス許可・禁止の制御|特になし。敢えて行うならば、アクセス元のVSIをVRAに紐付けて、VRAで通信制御を行う等が考えられる|特になし|Network ACLや、VPEに対するSecurity Groupで制御可能|
|ICD側からのAllowlist IPsを使ったアクセス許可・禁止の制御|Classic InfrastrcutureからICDにアクセスする際のsource IPが不明なため困難。もし、アクセス許可を与えるルールを作成する必要があるならば、10.0.0.0/8など広範囲のアドレスをAllowlist IPsに指定する必要がある。|VPCごとに提供されるCloud service endpoint source address(CSE source address)からのアクセスを許可する|VPCごとに提供されるCloud service endpoint source address(CSE source address)からのアクセスを許可する（underlay的にはVPEであってもCSEと同じ経路を通っていると思われる）|

- IBM Cloud Databaseなどのサービスにアクセスする際には、VPCごとに唯一定まるCSE source addressというアドレスがアクセス元になる。**このCSE source addressは、アカウントやリージョンにまたがってVPCごとにユニークなIPであり、ゾーンごとにただ一つのみ定まるものである。もし、VPCが削除されるとこのアドレスは今後新規に作成される別のVPCで再利用される可能性がある。** 
- [IBM Cloud docs](https://cloud.ibm.com/docs/vpc?topic=vpc-vpc-behind-the-curtain&locale=en)には以下のような説明がされている。この絵における`VPC Address`こそが、`CSE source address`に相当するものである。 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/87b1d778-ff15-386e-dc82-9dd698cbff5a.png)

- [Cloud service endpoint source address](https://cloud.ibm.com/docs/vpc?topic=vpc-vpc-behind-the-curtain#cse-source-addresses&locale=en)はVPCの概要画面から確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/c26819cc-29b6-d720-7fd4-fda818988359.png)
- 逆にいうと、VPC上の利用者が個別に定義したIPアドレスがsource IPとなって直接IBM Cloud Databaseにアクセスする訳ではない。VPCごとに独立したPrivate IPアドレスを定義したとしていても、インターネットというGlobalの世界に出ていくときにはGlobal IPがsource addressとなって(NATされて）インターネットの世界での一意性を保っているのと同様に、VPCからprivate endpoint経由でサービスにアクセスする際には、このCSE source addressを使ってIBM Cloud内部で一意性を保っている。
- Classic InfrastructureにはCSE source address情報が提供されていないように見える。

# 3. 検証環境

- IBM Cloud Databases for PostgreSQLを使って確認した。
- VPEを作成する際には、以下のようにIBM Cloud Databases for PostgreSQLに紐づけてVPEを作成した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/4b1fea48-a562-2fab-1fda-6877d65b4b1f.png)



# 4. IBM Cloud Databases for PostgreSQLにログインしてsource IPアドレスを確認する（うまくいかない）

PostgreSQLには`pg_catalog.pg_stat_activity`というカタログ表にある`client_addr`というカラムでsource IPを確認する機能があるので、これでアクセス元を確認できないかを試してみた。
ちなみに、一般ユーザーでは権限がないためか`client_addr`の値は非表示になるため、ユーザーは`admin`でログインする。

```
[root@new-syasuda-tok1-vpc1 ~]# PGPASSWORD=xxxxxxxx PGSSLROOTCERT=631b75c3-4296-4ce9-b0f2-426423c5b0e6 psql "host=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxx.private.databases.appdomain.cloud port=31269 dbname=ibmclouddb user=admin sslmode=verify-full"
psql (12.11, server 12.7)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

ibmclouddb=> select usename, application_name, client_addr, client_port  from pg_catalog.pg_stat_activity;
     usename     |              application_name              |  client_addr   | client_port
-----------------+--------------------------------------------+----------------+-------------
 ibm             |                                            |                |
                 |                                            |                |
 ibm             | Patroni                                    |                |          -1
 ibm-replication | c-80e3ecbb-ae81-4dfc-bb1c-1fd74754c106-m-1 | 172.30.181.139 |       49904
 admin           | psql                                       | 172.30.55.192  |       30852
                 |                                            |                |
                 |                                            |                |
                 |                                            |                |
(8 rows)
```

すると、このように172.30.xx.xxというアドレスが表示されてしまう。これは、IBM Cloud Databases for PostgreSQLがkubernetesで稼働しているため、Ingress/Load Balancerでアクセス元が隠蔽されてしまっているためである。つまり、IBM Cloud Databases for PostgreSQLで直接Source IPを確認することは難しい。


# 5. AllowListを使ったPrivate Endpointに対するアクセス可否の判定
結局、AllowListの設定値によってアクセスできたかどうかで判断するしかなさそうだ。
コマンド結果をずらずらと書くのは退屈なので、nmapに対するポートチェックおよびpsqlコマンドによるログイン可否結果を記載した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/57c6a0c9-d93a-9e02-bb91-4c78e12cccf4.png)


## 5-1. Allowlist IPsに何も設定しない

|| Classic Infrastructure(VRFを有効） | VPE未構成時のVPC |  VPE構成時のVPC|
|:-|:-|:-|:-|
|Private Endpointに対するアクセス可否|OK|OK|OK|

## 5-2. Allowlist IPsにPublic IPのみを設定

|| Classic Infrastructure(VRFを有効） | VPE未構成時のVPC |  VPE構成時のVPC|
|:-|:-|:-|:-|
|Private Endpointに対するアクセス可否|NG|NG|NG|

## 5-3. Allowlist IPsにVPC上のVSIやClassic Infrastucture上のVSIのIPアドレスを設定

|| Classic Infrastructure(VRFを有効） | VPE未構成時のVPC |  VPE構成時のVPC|
|:-|:-|:-|:-|
|Private Endpointに対するアクセス可否|NG|NG|NG|


## 5-4. Allowlist IPsにPublic IPとCSE Source addressを設定

|| Classic Infrastructure(VRFを有効） | VPE未構成時のVPC |  VPE構成時のVPC|
|:-|:-|:-|:-|
|Private Endpointに対するアクセス可否|NG|OK|OK|


## 5-5. Allowlist IPsにCSE Source addressのみを設定

|| Classic Infrastructure(VRFを有効） | VPE未構成時のVPC |  VPE構成時のVPC|
|:-|:-|:-|:-|
|Private Endpointに対するアクセス可否|NG|OK|OK|

## 5-6. Allowlist IPsにCSE Source addressと`10.0.0.0/14`を設定

|| Classic Infrastructure(VRFを有効） | VPE未構成時のVPC |  VPE構成時のVPC|
|:-|:-|:-|:-|
|Private Endpointに対するアクセス可否|NG|OK|OK|

## 5-7. Allowlist IPsに`10.0.0.0/8`を設定

|| Classic Infrastructure(VRFを有効） | VPE未構成時のVPC |  VPE構成時のVPC|
|:-|:-|:-|:-|
|Private Endpointに対するアクセス可否|OK|OK|OK|

# 参考


アクセスできない時は、そもそもpsqlでログインどころか、portにもアクセスできない。


```
[root@new-syasuda-tok1-vpc1 ~]# nmap -Pn xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxx.private.databases.appdomain.cloud -p 31269

Starting Nmap 6.40 ( http://nmap.org ) at 2022-05-15 14:40 JST
Nmap scan report for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxx.private.databases.appdomain.cloud (10.0.0.16)
Host is up (0.00014s latency).
PORT      STATE    SERVICE
31269/tcp filtered unknown
MAC Address: 02:00:0B:02:70:58 (Unknown)

Nmap done: 1 IP address (1 host up) scanned in 0.49 seconds
```