Service Mesh (ASM) エグレスゲートウェイは、ASM内のトラフィックの統合出口点として機能し、TLS/mTLSリクエストを開始してエンドツーエンドの暗号化通信を実現できます。さらに、エグレスゲートウェイは、よりきめ細かいアクセス制御のための包括的なセキュリティポリシーを実装できます。ASMでは、エグレスゲートウェイはアウトバウンドトラフィックを管理するための理想的な選択肢です。このトピックでは、ASMエグレスゲートウェイを使用してアウトバウンドトラフィックを管理し、mTLS通信を開始する方法について説明します。
ASMイングレスゲートウェイでmTLSサービスを設定し、特定のクライアントアクセスを制限する に記載されているすべての手順を完了していることを確認してください。このトピックでは、ASMおよびContainer Service for Kubernetes (ACK)環境にデプロイされたアプリケーションを外部mTLSサーバーとして使用します。したがって、このトピックの手順を実行するときは、別のASMおよびACK環境をプライマリ環境として作成する必要があります。明確にするために、このトピックの ${ASM gateway IP}
は、ASMイングレスゲートウェイでmTLSサービスを設定し、特定のクライアントアクセスを制限する で使用されているイングレスゲートウェイのIPアドレスを表し、「ACKクラスター」および「ASMインスタンス」はプライマリ環境のリソースを指します。
前提条件
自動サイドカーインジェクションが有効になっています。詳細については、サイドカープロキシインジェクションポリシーを設定する をご参照ください。
手順 1:テストアプリケーション sleep をデプロイする
sleep アプリケーションをデプロイします。詳細については、関連操作 をご参照ください。
ACKクラスターのkubeconfigを使用して、次のコマンドを実行し、別のASMおよびACK環境にデプロイされたHTTPBinサービスへのアクセスをテストします。
kubectl exec deploy/sleep -- curl --header "host:test.com" ${ASM gateway IP}/status/418
期待される出力:
-=[ teapot ]=-
_...._
.' _ _ `.
| ."` ^ `". _,
\_;`"---"`|//
| ;/
\_ _/
`"""`
手順 2:REGISTRY_ONLYを有効にし、ServiceEntryを作成する
サイドカーは、外部アクセスポリシーを REGISTRY_ONLY
として設定することをサポートしています。REGISTRY_ONLY
が有効になると、ポッドはServiceEntryを介して登録されたサービスにのみアクセスできます。この機能を有効にするかどうかを選択できます。詳細については、手順 2:REGISTRY_ONLYを有効にする をご参照ください。この機能が有効になっている場合、未登録のサービスにアクセスすると、502 Bad Gateway
エラーが発生します。
次のコンテンツを使用して、test.comのServiceEntryを設定します。詳細については、外部サービスを作成する をご参照ください。
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: test-com
namespace: default
spec:
endpoints:
- address: ${IP address of the ingress gateway} //イングレスゲートウェイのIPアドレス
hosts:
- test.com
location: MESH_EXTERNAL
ports:
- name: http
number: 80
protocol: HTTP
- name: https
number: 443
protocol: HTTPS
resolution: STATIC
設定が完了すると、sleep ポッドから HTTPBin サービスにアクセスできます。
手順 3:ASMエグレスゲートウェイを作成し、HTTPリクエストをエグレスゲートウェイ経由でルーティングする
エグレスゲートウェイを作成し、ポート 80 で HTTP トラフィック用に設定し、相互 TLS 認証スイッチを有効にします。スイッチが有効になると、ASM内の他のワークロードは、ゲートウェイにトラフィックを送信するときに自動的にmTLSを使用し、mTLS証明書はASMによって一元管理されます。詳細については、エグレスゲートウェイを作成する をご参照ください。
次のコンテンツを使用して、ゲートウェイルールを作成します。詳細については、ゲートウェイルールを作成する をご参照ください。
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: egress-gateway namespace: default spec: selector: istio: egressgateway servers: - hosts: - '*' port: name: http number: 80 protocol: HTTPS // HTTPSプロトコルを使用 tls: mode: ISTIO_MUTUAL
ゲートウェイルールは、エグレスゲートウェイがASMによって提供される証明書を使用して、mTLSを有効にしたポート 80 でリッスンすることを宣言します。
次のコンテンツを使用して、仮想サービスを作成します。
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: egressgateway-vs spec: hosts: - test.com gateways: - egress-gateway # 前の手順で作成したゲートウェイルールの名前。 - mesh http: - match: - gateways: - mesh port: 80 route: - destination: host: istio-egressgateway.istio-system.svc.cluster.local port: number: 80 weight: 100 - match: - gateways: - egress-gateway port: 80 route: - destination: host: test.com port: number: 80 weight: 100
仮想サービスを作成すると、サイドカー内の
test.com
へのトラフィックはエグレスゲートウェイに送信され、test.com
のエグレスゲートウェイで受信されたトラフィックは実際のtest.com
ServiceEntryに送信されます。次のコマンドを実行して、sleep アプリケーションのポッドから
test.com
にアクセスします。kubectl exec deploy/sleep -- curl --header "host:test.com" ${ASM gateway IP}/status/418
期待される出力:
-=[ teapot ]=- _...._ .' _ _ `. | ."` ^ `". _, \_;`"---"`|// | ;/ \_ _/ `"""`
ASMインスタンスのkubeconfigを使用して、次のコマンドを実行します。
kubectl -n istio-system logs ${egress gateway pod name}| tail -1 // ${エグレスゲートウェイ ポッド名}
期待される出力:
{"authority_for":"test.com","bytes_received":"0","bytes_sent":"135","downstream_local_address":"192.168.36.32:80","downstream_remote_address":"192.168.36.29:58146","duration":"8","istio_policy_status":"-","method":"GET","path":"/status/418","protocol":"HTTP/1.1","request_id":"9f7b5475-6e45-4700-a85a-e00835b6b6c0","requested_server_name":"outbound_.80_._.istio-egressgateway.istio-system.svc.cluster.local","response_code":"418","response_flags":"-","route_name":"-","start_time":"2024-07-29T03:05:58.421Z","trace_id":"-","upstream_cluster":"outbound|80||test.com","upstream_host":"${ASM gateway IP}:80","upstream_local_address":"192.168.36.32:52838","upstream_response_time":"7","upstream_service_time":"7","upstream_transport_failure_reason":"-","user_agent":"curl/8.1.2","x_forwarded_for":"192.168.36.29"} // ${ASM gateway IP}
上記のログは、サービスがASMエグレスゲートウェイを通過したことを確認しています。
この例の要求パスは、sleep ポッド --> istio-egressgateway --> istio-ingressgateway --> httpbin
です。その中で:
sleep ポッド --> istio-egressgateway
は mTLS トラフィックです。istio-egressgateway --> istio-ingressgateway
はプレーンテキストトラフィックです。istio-ingressgateway --> httpbin
は mTLS トラフィックです。
プレーンテキストを介した2つのゲートウェイ間のインタラクションは明らかに安全ではありません。サーバー側のゲートウェイは mTLS をサポートしているため、クライアント側のエグレスゲートウェイが mTLS リクエストを開始するように設定するだけで済みます。
手順 4:エグレスゲートウェイで HTTP リクエストを mTLS トラフィックにアップグレードする
次のコンテンツを使用して、仮想サービスを更新します。
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: egressgateway-vs spec: hosts: - test.com gateways: - egress-gateway - mesh http: - match: - gateways: - mesh port: 80 route: - destination: host: istio-egressgateway.istio-system.svc.cluster.local port: number: 80 weight: 100 - match: - gateways: - egress-gateway port: 80 route: - destination: host: test.com port: number: 443 # この行のみが変更されています // ポート443に変更 weight: 100
ここでの更新は、
test.com
ServiceEntryに送信されるトラフィックをポート 80 からポート 443 に変更するだけです。ASMイングレスゲートウェイでmTLSサービスを設定し、特定のクライアントアクセスを制限する で使用されているmTLS証明書をインポートします。インポートされた証明書の名前が
test.client
であることを確認してください。詳細については、ASMの証明書管理機能を使用する をご参照ください。また、kubectlを使用してシークレットを作成して証明書をインポートすることもできます。ACKクラスターのkubeconfigを使用して、次のコマンドを実行します。
// client.key.pem、clientcert.pem、cacert.pem ファイルからシークレットを作成kubectl create -n istio-system secret generic test.client \ --from-file=tls.key=client.key.pem \ --from-file=tls.crt=clientcert.pem \ --from-file=ca.crt=cacert.pem
次のコンテンツを使用して、デスティネーションルールを作成します。
// test.client 証明書を使用して mTLS 接続を確立apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: originate-mtls-for-test-com spec: host: test.com trafficPolicy: loadBalancer: simple: ROUND_ROBIN portLevelSettings: - port: number: 443 tls: mode: MUTUAL credentialName: test.client sni: test.com
次のコマンドを実行して、再度アクセスをテストします。
kubectl exec deployment/sleep -it -- curl --header "host:test.com" ${ASM gateway IP}/status/418
期待される出力:
RBAC: access denied%
リクエストは拒否されます。これは、ここで使用されているクライアント証明書が ASMイングレスゲートウェイでmTLSサービスを設定し、特定のクライアントアクセスを制限する から再利用されており、test.client が
status/418
パスにアクセスすることを禁止するように設定されているためです。次のコマンドを実行して、
status/200
パスにアクセスします。kubectl exec deploy/sleep -it -- curl --header "host:test.com" ${ASM gateway IP}/status/200 -I
期待される出力:
HTTP/1.1 200 OK server: envoy date: Mon, 29 Jul 2024 03:33:50 GMT content-type: text/html; charset=utf-8 access-control-allow-origin: * access-control-allow-credentials: true content-length: 0 x-envoy-upstream-service-time: 5
アクセスは成功です。
次のコマンドを実行して、エグレスゲートウェイのアクセスログを表示します。
kubectl -n istio-system logs ${egress gateway pod name}| tail -1 // ${エグレスゲートウェイ ポッド名}
期待される出力:
{"authority_for":"test.com","bytes_received":"0","bytes_sent":"19","downstream_local_address":"192.168.36.32:80","downstream_remote_address":"192.168.36.29:58146","duration":"3","istio_policy_status":"-","method":"GET","path":"/status/418","protocol":"HTTP/1.1","request_id":"82394ec4-cf13-45cb-ae4c-cb1873fbccda","requested_server_name":"outbound_.80_._.istio-egressgateway.istio-system.svc.cluster.local","response_code":"403","response_flags":"-","route_name":"-","start_time":"2024-07-29T03:34:36.647Z","trace_id":"-","upstream_cluster":"outbound|443||test.com","upstream_host":"${ASM gateway IP}:443","upstream_local_address":"192.168.36.32:42214","upstream_response_time":"2","upstream_service_time":"2","upstream_transport_failure_reason":"-","user_agent":"curl/8.1.2","x_forwarded_for":"192.168.36.29"} // ${ASM gateway IP}
このリクエストは、mTLSサービスのみを提供するイングレスゲートウェイのポート 443 にアクセスしました。
手順 5:後続の設定
sleep ポッドは HTTP リクエストを開始します。サイドカーとエグレスゲートウェイを通過した後、接続全体は mTLS 暗号化で保護され、クライアントID認証の基礎となります。このリクエストフローでは、クライアントの動作を制限するために、2つの場所で許可ポリシーを設定できます。
次のコンテンツを使用して、エグレスゲートウェイで許可ポリシーを設定します。これにより、クラスター内のどのサービスが
test.com
サービスにアクセスできるかを制限できます。apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: labels: gateway: egressgateway name: test namespace: istio-system spec: action: DENY rules: - from: - source: principals: - cluster.local/ns/default/sa/sleep // sleep サービスアカウントからのリクエストを拒否 to: - operation: hosts: - test.com paths: - /headers // /headers パスへのアクセスを拒否 selector: matchLabels: istio: egressgateway
この設定は、sleep ポッドがエグレスゲートウェイを介して
/headers
パスのtest.com
にアクセスすることを制限します。イングレスゲートウェイで許可ポリシーを設定して、イングレスゲートウェイに直接アクセスするクライアントのIDを制限します。手順 4 で設定されたイングレスゲートウェイの許可ポリシーは、現在のエグレスゲートウェイが
/status/418
パスにアクセスすることを禁止します。