すべてのプロダクト
Search
ドキュメントセンター

Alibaba Cloud Service Mesh:ASMエグレスゲートウェイを使用して外部mTLSサービスにアクセスする

最終更新日:Jan 13, 2025

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リクエストをエグレスゲートウェイ経由でルーティングする

  1. エグレスゲートウェイを作成し、ポート 80 で HTTP トラフィック用に設定し、相互 TLS 認証スイッチを有効にします。スイッチが有効になると、ASM内の他のワークロードは、ゲートウェイにトラフィックを送信するときに自動的にmTLSを使用し、mTLS証明書はASMによって一元管理されます。詳細については、エグレスゲートウェイを作成する をご参照ください。

  2. 次のコンテンツを使用して、ゲートウェイルールを作成します。詳細については、ゲートウェイルールを作成する をご参照ください。

    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 でリッスンすることを宣言します。

  3. 次のコンテンツを使用して、仮想サービスを作成します。

    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に送信されます。

  4. 次のコマンドを実行して、sleep アプリケーションのポッドから test.com にアクセスします。

    kubectl exec deploy/sleep -- curl --header "host:test.com" ${ASM gateway IP}/status/418

    期待される出力:

        -=[ teapot ]=-
    
           _...._
         .'  _ _ `.
        | ."` ^ `". _,
        \_;`"---"`|//
          |       ;/
          \_     _/
            `"""`
  5. 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 トラフィックにアップグレードする

  1. 次のコンテンツを使用して、仮想サービスを更新します。

    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 に変更するだけです。

  2. ASMイングレスゲートウェイでmTLSサービスを設定し、特定のクライアントアクセスを制限する で使用されているmTLS証明書をインポートします。インポートされた証明書の名前が test.client であることを確認してください。詳細については、ASMの証明書管理機能を使用する をご参照ください。また、kubectlを使用してシークレットを作成して証明書をインポートすることもできます。ACKクラスターのkubeconfigを使用して、次のコマンドを実行します。

    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
    
    // client.key.pem、clientcert.pem、cacert.pem ファイルからシークレットを作成
  3. 次のコンテンツを使用して、デスティネーションルールを作成します。

    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
    // test.client 証明書を使用して mTLS 接続を確立
  4. 次のコマンドを実行して、再度アクセスをテストします。

    kubectl exec deployment/sleep -it -- curl --header "host:test.com" ${ASM gateway IP}/status/418

    期待される出力:

    RBAC: access denied%

    リクエストは拒否されます。これは、ここで使用されているクライアント証明書が ASMイングレスゲートウェイでmTLSサービスを設定し、特定のクライアントアクセスを制限する から再利用されており、test.client が status/418 パスにアクセスすることを禁止するように設定されているためです。

  5. 次のコマンドを実行して、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

    アクセスは成功です。

  6. 次のコマンドを実行して、エグレスゲートウェイのアクセスログを表示します。

    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つの場所で許可ポリシーを設定できます。

  1. 次のコンテンツを使用して、エグレスゲートウェイで許可ポリシーを設定します。これにより、クラスター内のどのサービスが 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 にアクセスすることを制限します。

  2. イングレスゲートウェイで許可ポリシーを設定して、イングレスゲートウェイに直接アクセスするクライアントのIDを制限します。手順 4 で設定されたイングレスゲートウェイの許可ポリシーは、現在のエグレスゲートウェイが /status/418 パスにアクセスすることを禁止します。