Implementing Ingress Controls
アーキテクチャ図に示されているように、「catalog」名前空間は「ui」名前空間からのトラフィックのみを受け取り、他の名前空間からは受け取りません。また、「catalog」データベースコンポーネントは「catalog」サービスコンポーネントからのトラフィックのみを受け取ることができます。
「catalog」名前空間へのトラフィックを制御するイングレスネットワークポリシーを実装することから始めましょう。
ポリシーを適用する前に、「catalog」サービスは「ui」コンポーネントからアクセスできます:
Trying XXX.XXX.XXX.XXX:80...
* Connected to catalog.catalog (XXX.XXX.XXX.XXX) port 80 (#0)
> GET /health HTTP/1.1
> Host: catalog.catalog
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 200 OK
...
同様に、「orders」コンポーネントからもアクセスできます:
Trying XXX.XXX.XXX.XXX:80...
* Connected to catalog.catalog (XXX.XXX.XXX.XXX) port 80 (#0)
> GET /health HTTP/1.1
> Host: catalog.catalog
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 200 OK
...
ここで、「ui」コンポーネントからのみ「catalog」サービスコンポーネントへのトラフィックを許可するネットワークポリシーを定義します:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
namespace: catalog
name: allow-catalog-ingress-webservice
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: catalog
app.kubernetes.io/component: service
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ui
podSelector:
matchLabels:
app.kubernetes.io/name: ui
podSelectorは、ラベルapp.kubernetes.io/name: catalogとapp.kubernetes.io/component: serviceを持つポッドをターゲットにします
このingress.from設定は、ラベルapp.kubernetes.io/name: uiを持ち、kubernetes.io/metadata.name: uiで識別されるui名前空間で実行されているポッドからの受信接続のみを許可します
ポリシーを適用しましょう:
これで、「ui」から「catalog」コンポーネントにアクセスできることを確認してポリシーを検証できます:
Trying XXX.XXX.XXX.XXX:80...
* Connected to catalog.catalog (XXX.XXX.XXX.XXX) port 80 (#0)
> GET /health HTTP/1.1
> Host: catalog.catalog
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 200 OK
...
しかし、「orders」コンポーネントからはアクセスできません:
* Trying XXX.XXX.XXX.XXX:80...
* ipv4 connect timeout after 4999ms, move on!
* Failed to connect to catalog.catalog port 80 after 5001 ms: Timeout was reached
* Closing connection 0
curl: (28) Failed to connect to catalog.catalog port 80 after 5001 ms: Timeout was reached
...
上記の出力からわかるように、「ui」コンポーネントだけが「catalog」サービスコンポーネントと通信でき、「orders」サービスコンポーネントはできません。
しかし、これはまだ「catalog」データベースコンポーネントを開放したままにしています。そこで、「catalog」サービスコンポーネントだけが「catalog」データベースコンポーネントと通信できるようにするネットワークポリシーを実装しましょう。
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
namespace: catalog
name: allow-catalog-ingress-db
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: catalog
app.kubernetes.io/component: mysql
ingress:
- from:
- podSelector:
matchLabels:
app.kubernetes.io/name: catalog
app.kubernetes.io/component: service
podSelectorは、ラベルapp.kubernetes.io/name: catalogとapp.kubernetes.io/component: mysqlを持つポッドをターゲットにします
ingress.fromは、ラベルapp.kubernetes.io/name: catalogとapp.kubernetes.io/component: serviceを持つポッドからの受信接続のみを許可します
ポリシーを適用しましょう:
「orders」コンポーネントから「catalog」データベースに接続できないことを確認することで、ネットワークポリシーを検証してみましょう:
* Trying XXX.XXX.XXX.XXX:3306...
* ipv4 connect timeout after 4999ms, move on!
* Failed to connect to catalog-mysql.catalog port 3306 after 5001 ms: Timeout was reached
* Closing connection 0
curl: (28) Failed to connect to catalog-mysql.catalog port 3306 after 5001 ms: Timeout was reached
command terminated with exit code 28
...
しかし、「catalog」ポッドを再起動すると、まだ接続することができます:
上記の出力からわかるように、「catalog」サービスコンポーネントのみが「catalog」データベースコンポーネントと通信できるようになりました。
これで「catalog」名前空間に効果的なイングレスポリシーを実装したので、同じロジックをサンプルアプリケーションの他の名前空間とコンポーネントに拡張し、サンプルアプリケーションの攻撃対象領域を大幅に減らし、ネットワークセキュリティを向上させることができます。