Calicoネットワーク・ポリシーでIP制御を行う

Openshift環境で、外部からの通信制御をするため、ネットワーク・ポリシーによるトラフィックの制御について調べたので、備忘録としてまとめました。


# ネットワーク・ポリシーとは
ポッドに対し、他ポッドおよび外部エンドポイントへの通信を制御するためのリソース。
Openshift上でのネットワーク・ポリシーには、Kuberentesネットワーク・ポリシーとCalicoネットワーク・ポリシーの2種類がある。

### Kuberentesネットワーク・ポリシー
* ポッドが他のポッドおよび外部エンドポイントと通信する方法を指定する。
* 着信/発信ネットワーク・トラフィックの両方を、プロトコル、ポート、ソース、宛先 IP アドレスに基づいて許可またはブロックできる。 
* トラフィックは、ポッドおよび名前空間ラベルに基づいてフィルタリングすることもできる。 


### Calicoネットワーク・ポリシー
* Kubernetesポッドのソース、宛先IPアドレスやCIDRに関係なく、特定のネットワーク・インターフェース上のネットワーク・トラフィックを許可またはブロックする。
* 複数の名前空間にまたがるポッドのネットワーク・トラフィックを許可またはブロックする。
* Kubernetes LoadBalancer または NodePort サービスへのインバウンド・トラフィックをブロックする。

※詳細は以下のリンクをご参照ください。
　https://cloud.ibm.com/docs/openshift?topic=openshift-network_policies&locale=ja#block_ingress

# OpenshiftでCalicoネットワーク・ポリシーを試す

ここではCalicoのGlobalNetworkPolicyで、IP制御の検証を行います。
#### ＜検証手順＞
1. calicoctlコマンドのインストール
2. サンプル用Pod、NLBをデプロイ
3. すべてのノード・ポートへの着信トラフィックをブロックする
4. アプリを公開している NLB へのすべての着信トラフィックをブロックする
5. 特定の IP からの NLB への着信トラフィックを許可する

#### 1. calicoctlコマンドのインストール
以下手順に従い、calicoctlコマンドをインストールします。
[Calico CLI のインストールおよび構成](https://cloud.ibm.com/docs/openshift?topic=openshift-network_policies&locale=ja#cli_install)

#### 2. サンプル用Pod、NLBをデプロイ
サンプル用のPod、NLBをデプロイします。
以下コマンドを実行し、「EXTERNAL-IP」に表示されているNLBのIPアドレスをメモします。

```
$ oc get services
NAME             TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
nlb-service   LoadBalancer   XXX.XX.XX.XX   XX.XXX.XX.X   XX:XXXXX/TCP   136m
```
ポート番号はサンプルアプリで使用するポート番号をメモします。
以下のcurlコマンドなどでアプリにアクセスできることを確認します。

```
$ curl --connect-timeout 10 http://<NLBのIPアドレス>:<アプリのポート番号>
```


#### 3. すべてのノード・ポートへの着信トラフィックをブロックする

すべてのノード・ポートへの着信トラフィックをブロックするyamlを準備します。

```yaml:deny-nodeport.yaml
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
  name: deny-nodeport
spec:
  applyOnForward: true
  preDNAT: true
  ingress:
    - action: Deny
      destination:
        ports:
        - 30000:32767
      protocol: TCP
      source: {}
    - action: Deny
      destination:
        ports:
        - 30000:32767
      protocol: UDP
      source: {}
  selector: ibm.role=='worker_private'
  order: 1100
  types:
  - Ingress
```

yamlを適用します。

```
$ calicoctl apply -f deny-nodeport.yaml
```
#### 4. アプリを公開している NLB へのすべての着信トラフィックをブロックする
NLB へのすべての着信トラフィックをブロックするyamlを準備します。

```yaml:deny-nlb.yaml
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
  name: deny-nlb
spec:
  applyOnForward: true
  preDNAT: true
  ingress:
  - action: Deny
    destination:
      nets:
      - <NLBのIPアドレス>/32
    protocol: TCP
    source: {}
  - action: Deny
    destination:
      nets:
      - <NLBのIPアドレス>/32
    protocol: UDP
    source: {}
  selector: ibm.role=='worker_private'
  order: 800
  types:
  - Ingress
```
yamlを適用します。

```
$ calicoctl apply -f deny-nlb.yaml
```

以下のcurlコマンドでアプリにアクセスできなくなったことを確認します。

```
$ curl --connect-timeout 10 http://<NLBのIPアドレス>:<アプリのポート番号>
```


#### 5. 特定の IP からの NLB への着信トラフィックを許可する
特定の IP からの NLB への着信トラフィックを許可するyamlを準備します。

```yaml:allow-ip-networkpolicy.yaml
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
  name: networkworkpolicy-allowlist
spec:
  applyOnForward: true
  ingress:
  - action: Allow
    destination:
      nets:
      - <NLBのIPアドレス>/32
      ports:
      - 80
    protocol: TCP
    source:
      nets:
      - <アクセス許可したいIPアドレス>/26
  order: 500
  preDNAT: true
  selector: ibm.role=='worker_private'
  types:
  - Ingress
```
yamlを適用します。

```
$ calicoctl apply -f allow-ip-networkpolicy.yaml
```

GlobalNetworkPolicyが作成されたことを確認します。

```
$ oc get GlobalNetworkPolicy
```

curlコマンドでアクセス確認をします。アクセスを許可しているIPアドレスのサーバーからはアプリにアクセスできること、それ以外のIPアドレスからアクセスを試行するとtimeoutとなることを確認します。

```
$ curl --connect-timeout 10 http://<NLBのIPアドレス>:<アプリのポート番号>
```
# OpenshiftでCalicoのNetworkPolicy設定を入れる際のメモ
* NetworkPolicyとGlobalNetworkPolicyが存在する。対象に合わせて選択する。
    * NetworkPolicy：
        * 名前空間内のPod、コンテナ、VMに適用される名前空間付きリソース
    * GlobalNetworkPolicy：
        * 名前空間に関係なく、あらゆる種類のエンドポイント（Pod、VM等）に適用できる。
* CalicNetworkPolicyでは「order」の設定で適用の優先順位を決定できる。
    * 優先順位を高くしたいものほど低い数字を設定する。
    * 例：orderが「100」と「1000」のyamlがあった場合、 100の方のルールが優先して適用される。


#### 参考
* [クラシック: ネットワーク・ポリシーによるトラフィックの制御](https://cloud.ibm.com/docs/containers?topic=containers-network_policies&locale=ja)
* [Calico ネットワーク・ポリシーを使用したトラフィックのブロック](https://cloud.ibm.com/docs/containers?topic=containers-policy_tutorial&locale=ja)
* [Get started with Calico network policy](https://docs.projectcalico.org/security/calico-network-policy)