イングレスアクセス制御
このタスクでは、承認ポリシーを使用してIstioイングレスゲートウェイでIPベースのアクセス制御を強制する方法を示します。
始める前に
このタスクを開始する前に、次の手順を実行してください。
Istioの承認に関する概念をお読みください。
Istioインストールガイドを使用してIstioをインストールします。
サイドカーインジェクションが有効になっている名前空間
foo
にワークロードhttpbin
をデプロイします。$ kubectl create ns foo $ kubectl label namespace foo istio-injection=enabled $ kubectl apply -f @samples/httpbin/httpbin.yaml@ -n foo
イングレスゲートウェイを介して
httpbin
を公開します。
次のコマンドを使用して、
httpbin
ワークロードとイングレスゲートウェイが期待通りに動作していることを確認します。$ curl "$INGRESS_HOST:$INGRESS_PORT"/headers -s -o /dev/null -w "%{http_code}\n" 200
KubernetesとIstioへのトラフィックの取り込み
Kubernetesにトラフィックを取り込むすべての方法は、すべてのワーカーノードでポートを開くことを含みます。これを実現する主な機能は、NodePort
サービスとLoadBalancer
サービスです。KubernetesのIngress
リソースでさえ、NodePort
サービスまたはLoadBalancer
サービスを作成するイングレスコントローラーによってバックアップされる必要があります。
NodePort
は、各ワーカーノードの30000〜32767の範囲でポートを開き、ラベルセレクターを使用してトラフィックを送信するPodを識別します。ワーカーノードの前に何らかのロードバランサーを手動で作成するか、ラウンドロビンDNSを使用する必要があります。LoadBalancer
はNodePort
と似ていますが、ワーカーノードへのトラフィックの分散を処理するための環境固有の外部ロードバランサーも作成します。たとえば、AWS EKSでは、LoadBalancer
サービスはワーカーノードをターゲットとして持つClassic ELBを作成します。Kubernetes環境にLoadBalancer
の実装がない場合は、NodePort
のように動作します。IstioイングレスゲートウェイはLoadBalancer
サービスを作成します。
NodePort
またはLoadBalancer
からのトラフィックを処理しているPodが、トラフィックを受信したワーカーノードで実行されていない場合はどうなりますか?Kubernetesには、パケットを受信して正しいノードに転送するkube-proxyと呼ばれる独自の内部プロキシがあります。
元のクライアントの送信元IPアドレス
パケットが外部プロキシロードバランサーとkube-proxyを通過する場合、クライアントの元の送信元IPアドレスは失われます。次のセクションでは、さまざまなロードバランサーの種類について、ログ記録またはセキュリティの目的で元のクライアントIPを保持するためのいくつかの戦略について説明します。
参考までに、一般的なマネージドKubernetes環境でLoadBalancer
サービスを使用してIstioによって作成されるロードバランサーの種類を以下に示します。
クラウドプロバイダー | ロードバランサー名 | ロードバランサーの種類 |
---|---|---|
AWS EKS | Classic Elastic Load Balancer | TCPプロキシ |
GCP GKE | TCP/UDPネットワークロードバランサー | ネットワーク |
Azure AKS | Azureロードバランサー | ネットワーク |
IBM IKS/ROKS | ネットワークロードバランサー | ネットワーク |
DO DOKS | ロードバランサー | ネットワーク |
TCP/UDPプロキシロードバランサー
TCP/UDPプロキシ外部ロードバランサー(AWS Classic ELB)を使用している場合は、PROXYプロトコルを使用して、元のクライアントIPアドレスをパケットデータに埋め込むことができます。動作させるには、外部ロードバランサーとIstioイングレスゲートウェイの両方がPROXYプロトコルをサポートする必要があります。
AWS EKSでイングレスゲートウェイがPROXYプロトコルをサポートするようにする方法を示すサンプル構成を以下に示します。
ネットワークロードバランサー
クライアントIPアドレスを保持するTCP/UDPネットワークロードバランサー(AWSネットワークロードバランサー、GCP外部ネットワークロードバランサー、Azureロードバランサー)を使用している場合、またはラウンドロビンDNSを使用している場合は、externalTrafficPolicy: Local
設定を使用して、kube-proxyをバイパスし、他のノードへのトラフィックの送信を防ぐことで、Kubernetes内部でもクライアントIPを保持できます。
次のコマンドを使用して、イングレスゲートウェイを更新し、externalTrafficPolicy: Local
を設定して、イングレスゲートウェイで元のクライアント送信元IPを保持します。
HTTP/HTTPSロードバランサー
HTTP/HTTPS外部ロードバランサー(AWS ALB、GCPなど)を使用している場合は、元のクライアントIPアドレスをX-Forwarded-Forヘッダーに配置できます。Istioは、いくつかの設定を行うことで、このヘッダーからクライアントIPアドレスを抽出できます。ゲートウェイネットワークトポロジの設定を参照してください。Kubernetesの前に単一のロードバランサーを使用する場合の簡単な例
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
accessLogEncoding: JSON
accessLogFile: /dev/stdout
defaultConfig:
gatewayTopology:
numTrustedProxies: 1
IPベースの許可リストと拒否リスト
ipBlocks
とremoteIpBlocks
を使用する場合:X-Forwarded-For HTTPヘッダーまたはPROXYプロトコルを使用して元のクライアントIPアドレスを決定する場合は、AuthorizationPolicy
でremoteIpBlocks
を使用する必要があります。externalTrafficPolicy: Local
を使用する場合は、AuthorizationPolicy
でipBlocks
を使用する必要があります。
ロードバランサーの種類 | クライアントIPのソース | ipBlocks とremoteIpBlocks |
---|---|---|
TCPプロキシ | PROXYプロトコル | remoteIpBlocks |
ネットワーク | パケット送信元アドレス | ipBlocks |
HTTP/HTTPS | X-Forwarded-For | remoteIpBlocks |
- 次のコマンドは、Istioイングレスゲートウェイの承認ポリシー
ingress-policy
を作成します。次のポリシーは、action
フィールドをALLOW
に設定して、ipBlocks
に指定されたIPアドレスがイングレスゲートウェイにアクセスできるようにします。リストにないIPアドレスは拒否されます。ipBlocks
は、単一のIPアドレスとCIDR表記の両方をサポートします。
イングレスゲートウェイへの要求が拒否されることを確認します。
$ curl "$INGRESS_HOST:$INGRESS_PORT"/headers -s -o /dev/null -w "%{http_code}\n" 403
元のクライアントIPアドレスをenv変数に割り当てます。わからない場合は、次のコマンドを使用してEnvoyログで確認できます。
- クライアントIPアドレスを含むように
ingress-policy
を更新します。
イングレスゲートウェイへの要求が許可されることを確認します。
$ curl "$INGRESS_HOST:$INGRESS_PORT"/headers -s -o /dev/null -w "%{http_code}\n" 200
ingress-policy
承認ポリシーを更新して、action
キーをDENY
に設定し、ipBlocks
に指定されたIPアドレスがイングレスゲートウェイにアクセスできないようにします。
イングレスゲートウェイへの要求が拒否されることを確認します。
$ curl "$INGRESS_HOST:$INGRESS_PORT"/headers -s -o /dev/null -w "%{http_code}\n" 403
オンラインプロキシサービスを使用して、別のクライアントIPを使用してイングレスゲートウェイにアクセスし、要求が許可されていることを確認できます。
期待する応答が得られない場合は、RBACデバッグ情報が表示されるイングレスゲートウェイログを表示します。
クリーンアップ
- 承認ポリシーの削除
名前空間
foo
の削除$ kubectl delete namespace foo