Red Hat OpenShift on IBM Cloud（ROKS）でアクセス元IPアドレスを制限する _ ROKS v4.17向けの実現方法 

# 課題

お客様がROKS v4.14上に構築されたアプリに対して、アクセス元のIPアドレスを制限することを実施していました。
（背景として、お客様にはVPNを利用できない事情があり、ROKSのService EndpointはPublicとPrivateの両方も公開されるのが必要でした。IPアドレスの制限をかかないと、アプリはInternet向けに公開されてしまうことになります。）

その際には、下記の二つの記事を順番に参考して設定し、問題なく実現できました：
1. @hisato_imanishi(Hisato Imanishi)さんのご記事： [「Red Hat OpenShift on IBM Cloudでアクセス元IPアドレスを制限する」](https://qiita.com/hisato_imanishi/items/58b2fe6560e33a8cdf33)
2. 私の記事：[「Red Hat OpenShift on IBM Cloudでアクセス元IPアドレスを制限する方法のご補足：Ingress Degradedエラーの解消方法」](https://qiita.com/xiaojinse/items/6ca6f02261d882918203)

ただし、最近IBM Cloud上の最新版のROKS v4.17を利用する時、上記の手順を実施してもエラーが出て、アプリへの通信が全く出来なくなりました。

この記事は、上記の問題の解決方法、つまり、ROKS v4.17でアクセス元IPアドレスを制限する方法をご説明いたします。
この記事を参照する前に、上記の2つの記事に目を通し、ROKSのセキュリティグループ(Security Group、SG)についての基本設定をご理解しておくことをお勧めします。

# ROKS v4.17のSecurity Groupの説明

4.17のROKS clusterにおいては、デフォルトの自動設定として、下記の図のように四つのSecurity Groupが出ています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2075462/4fcf0a73-7142-414f-8de2-4db1e96cb256.png)

上から順番に：
1. kube-[ROKS cluster ID]
このSGは、ClusterのWorker Nodeに関連付けられます。
ただし、SG の詳細ページでもWorker Nodeが表示されないのは、かなりわかりにくいです。(そもそも、ROKS Worker NodeがVSIとして表示されないためです。）

2. kube-lbaas-[ROKS cluster ID]
このSGは、ALB（Application Load Balancer）に関連付けられます。

3. kube-vpegw-[ROKS cluster ID]
このClusterのAPI Server VPE(Virutal Private Endpoint)に関連付けられます。

4.  kube-vpegw-[VPC ID]
ICOSやRegistryなどのVPE(Virutal Private Endpoint)に関連付けられます。

#3と#4は主にIBM Cloud内部の通信を制御しており、私たちの課題にはあまり関係していません。
#1と#2に対してRule変更が必要です。


# 課題解決のため、必要な設定変更

### まずは、#2のALB用のSGを変更します

Best Practiceとして、デフォルトで作成されているSecurity Groupを変更せず、新しいものを作成し、Load Balancerに置き換えることがお勧めです。手順は：

- Security Groupの詳細画面で、ActionのところにDuplicateという選択肢があり、それをクリックして、新規作成の画面で新しいSGの名前を適当に入力します。私は新SG に「kube-lbaas-whitelist」という名前を付けました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2075462/7dceb338-b56f-4e69-a23b-3a7d59d73e1e.png)

- 複製で作成された「kube-lbaas-whitelist」SGには、既に下記のような二つのOutbound Ruleが存在します。Destination typeがSecurity Groupであり、DestinationがWorker Node用のSG #１です。これは、「全てのWorker Nodeへの通信は、Portが32654か31277であれば、許可する」という意味です。
これらの**Outbound Rulesを変更しない**ことが重要です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2075462/d59d0387-4e50-44f2-bf61-16234d4d7db4.png)

なぜか、Port 32654と31277を許可するかと言いますと、
ClusterのWorker NodeはLoad BalancerのBack-end poolsのService Instancesであります。
つまり、外部からLoad BalancerのPort 443へのhttps requestは、Round robinの方法で一つのWorker NodeのPort 31277に転送します。同じく、Load BalancerのPort 80へのhttps requestは、 Worker NodeのPort 32564に転送します。
各Clusterで使用されるPort番号は必ずしも32654と31277に固定されているわけではありません。30000-32767の範囲からランダムに選択され、Load Balancerの詳細画面で確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2075462/c975260e-953b-4f2f-af48-199aabb7073d.png)


- 「kube-lbaas-whitelist」SGのInbound Rulesを確認と変更しておきます。

デファクトのInbound Rulesは：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2075462/1cf40866-3766-4321-a84c-2c2a77c9d95d.png)

上からの二つは：すべでのIncoming https requestは,Port 80と443で許可しています。
私たちの課題としては、Source IP Addressは社内のIP rangeであれば許可するため、**この二つのInbound Rulesを削除するのが必要**です。

上からの三番目のRuleは、Public Gateway（Floating IPが165.x.x.x）からの通信はPort 443で許可するとの意味です。私の記事[「Red Hat OpenShift on IBM Cloudでアクセス元IPアドレスを制限する方法のご補足：Ingress Degradedエラーの解消方法」](https://qiita.com/xiaojinse/items/6ca6f02261d882918203)での説明とは一致しています。つまり、**このInbound Ruleを変更せずに維持する必要**があります。
（注：
私の検証環境では、Subnetは１つのみで、Public Gatewayも１つだけです。そのため、Public Gateway向けのInbound Ruleも１つになります。
一方、本番環境であれば、３つのDataCenterにWorker Nodeを配置することが多いため、SubnetとPublic Gatewayがそれぞれ３つとなり、こちらのInbound Ruleも３つとなります。）

これから、**追加必要のInbound Rule**として：
 1. ROKS ClusterのControl Planeからの通信を許可するため、
TCP	80	CIDR　東京リージョンのControl IP Subnet（[control-plane-ips-tok.txt](https://github.com/IBM-Cloud/kube-samples/blob/master/control-plane-ips/control-plane-ips-tok.txt)）
    --> v4.14頃の設定方法と同じで、Subnet自体にも変更なしです。

 2. お客様の端末からの通信を許可するため、
TCPかALL 　任意のポート　CIDRかIPAddress 　客様の端末のSubnetかIP Addr

Inbound Ruleの設定結果は、こうなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2075462/6f726221-f013-4f01-8bec-d17064ee79f0.png)

- Load BalancerのSecurity Groupを置き換えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2075462/1ad87b6a-b79f-43b9-a112-35dc0a637a32.png)

### 次に、#1のWorker Node用のSGを変更します

設定変更がここまで進んだら、Load Balancerの状態を確認すると、Back-endが警告ステータスになっているはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2075462/080a05f5-61c0-4698-92ec-bd9ef0689fb9.png)

また、上記のようにLoad BalancerのSecurity Groupを置き換えてから約10分後に、Ingressもエラーの状態になるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2075462/16773e46-dc85-49aa-a3fd-c2d8c69bb652.png)

もちろん、このような状況で、アプリへの通信も止まります。

そのエラーの原因は、下記の図の上から4番目と5番目のように、ROKS v4.17では、Worker Node用のSecurity Groupにも、Load Balancerからの通信を許可するInbound Ruleがありますから。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2075462/b63e2145-f610-4946-9a04-4779063ff3a1.png)

Load BalancerのSecurity Groupを置き換えましたので、ここでの 4 番目と 5 番目のRuleは実際には機能しなくとなります。 (ただし、削除しないことをお勧めします)。これらを参照して、新しい SG 「kube-lbaas-whitelist」のため 2 つのルールを追加する必要があります。設定結果はこうなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2075462/fd9e7699-288a-4dac-9dab-8be71cf9150f.png)

必要な設定変更は完了です。

# 最後に、効果の確認

まずは、Load Balancerとも、Ingressとも、Greenの状態となるはずです。
後は、許可された端末からアプリのWeb URLを訪問でき、他の端末から訪問できないはずです。

以上です。