Anthos Service Mesh の例: mTLS


Anthos Service Mesh 1.5 以降では、自動相互 TLS(自動 mTLS)がデフォルトで有効になっています。自動 mTLS の場合、クライアント サイドカー プロキシがサーバーにサイドカーがあるかどうかを自動的に検出します。クライアント サイドカーは、サイドカーを含むワークロードには mTLS を送信し、サイドカーを含まないワークロードには平文を送信します。ただし、サービスは平文と mTLS トラフィックの両方を受け入れます。Pod にサイドカー プロキシを挿入する際に、mTLS トラフィックのみを受け入れるようにサービスも構成することをおすすめします。

Anthos Service Mesh では、単一の YAML ファイルを適用することで、アプリケーション コードの外部で mTLS を適用できます。Anthos Service Mesh には、サービス メッシュ全体、名前空間、個々のワークロードに認証ポリシーを適用できる柔軟性があります。

相互 mTLS

費用

このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。 新しい Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

このチュートリアルの終了時に、作成したリソースを削除することで以降の費用の発生を回避できます。詳しくは、クリーンアップをご覧ください。

始める前に

このチュートリアルでは、Online Boutique のサンプル アプリケーションを使用して、Anthos Service Mesh がインストールされている GKE クラスタで mTLS を構成する方法について説明します。

  • このチュートリアル用に GKE クラスタを設定する必要がある場合は、Anthos Service Mesh クイックスタートをご覧ください。クラスタの設定、Anthos Service Mesh のインストール、demo 名前空間への Online Boutique のサンプルのデプロイについて説明しています。

  • Anthos Service Mesh がインストールされた GKE クラスタがあり、サンプルが必要な場合は、Online Boutiquedemo 名前空間へのサンプルのデプロイ方法を確認します。

Online Boutique にアクセスする

  1. kubectl の現在のコンテキストを、Online Boutique をデプロイしたクラスタに設定します。

    gcloud container clusters get-credentials CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION
    
  2. Online Boutique サービスのリストを取得します。

    kubectl get services -n demo
    

    frontend-externalLoadBalancer であり、外部 IP アドレスがあります。サンプル アプリケーションには、Anthos Service Mesh を使用せずに GKE にデプロイできるようにロードバランサのサービスが含まれています。

  3. frontend-external サービスの外部 IP アドレスを使用して、ブラウザでアプリケーションにアクセスします。

    http://FRONTEND_EXTERNAL_IP/
    
  4. Anthos Service Mesh は、istio-ingressgateway と呼ばれるデフォルトの Ingress ゲートウェイを備えています。Online Boutique には、istio-ingressgateway の外部 IP アドレスを使用してアクセスすることもできます。istio-ingressgateway の外部 IP を取得します。

    kubectl get service istio-ingressgateway -n istio-system
    
  5. ブラウザで別のタブを開き、istio-ingressgateway の外部 IP アドレスを使用してアプリケーションにアクセスします。

    http://INGRESS_GATEWAY_EXTERNAL_IP/
    
  6. 次のコマンドで、demo 名前空間の別の Pod からプレーンな HTTP を使用して、frontend サービスに curl を実行します。

    kubectl exec \
      $(kubectl get pod -l app=productcatalogservice -n demo -o jsonpath={.items..metadata.name}) \
      -c istio-proxy -n demo -- \
      curl http://frontend:80/ -o /dev/null -s -w '%{http_code}\n'
    

    デフォルトでは TLS と平文の両方のトラフィックが受け入れられるため、ステータス 200 でリクエストが成功します。

名前空間ごとに相互 TLS を有効にする

mTLS を適用するには、kubectlPeerAuthentication ポリシーを適用します。

  1. 次の認証ポリシーを適用して、mTLS のみを受け入れるように demo 名前空間内のすべてのサービスを構成します。

    kubectl apply -f - <<EOF
    apiVersion: "security.istio.io/v1beta1"
    kind: "PeerAuthentication"
    metadata:
      name: "namespace-policy"
      namespace: "demo"
    spec:
      mtls:
        mode: STRICT
    EOF
    

    予想される出力:

    peerauthentication.security.istio.io/namespace-policy created

    YAML の mode: STRICT 行は、mTLS のみを受け入れるようにサービスを構成します。デフォルトでは、modePERMISSIVE であり、平文と mTLS の両方を受け入れるようにサービスを構成します。

  2. ブラウザで、frontend-external サービスの外部 IP アドレスを使用して Online Boutique にアクセスし、ページを更新します。ブラウザに次のエラーが表示されます。

    サイトにアクセスできません

    ページを更新すると、平文が frontend サービスに送信されます。STRICT 認証ポリシーにより、サイドカー プロキシはサービスに対するリクエストをブロックします。

  3. ブラウザのタブから、istio-ingressgateway の外部 IP アドレスを使用して Online Boutique にアクセスし、ページを更新して正常に表示します。istio-ingressgateway を使用して Online Boutique にアクセスする場合、リクエストは次のパスを取ります。

    相互 mTLS

    mTLS 認証フロー:

    1. ブラウザが平文の HTTP リクエストをサーバーに送信します。
    2. istio-ingressgateway プロキシ コンテナがリクエストをインターセプトします。
    3. istio-ingressgateway プロキシは、サーバー側プロキシ(この例ではフロントエンド サービス)を使用して TLS handshake を実行します。この handshake には、証明書交換が含まれています。これらの証明書は、Anthos Service Mesh によってプロキシ コンテナにあらかじめ読み込まれています。
    4. istio-ingressgateway プロキシは、サーバーの証明書に対して安全な名前チェックを実行し、認可された ID がサーバーで実行されていることを確認します。
    5. istio-ingressgateway とサーバー プロキシは相互 TLS 接続を確立し、サーバー プロキシがリクエストをサーバー アプリケーション コンテナ(フロントエンド サービス)に転送します。
  4. 次のコマンドで、demo 名前空間の別の Pod からプレーンな HTTP を使用して、frontend サービスに curl を実行します。

    kubectl exec \
      $(kubectl get pod -l app=productcatalogservice -n demo -o jsonpath={.items..metadata.name}) \
      -c istio-proxy -n demo -- \
      curl http://frontend:80/ -o /dev/null -s -w '%{http_code}\n'
    

    demo 名前空間のすべてのサービスが STRICT mTLS に設定され、サイドカー プロキシがサービスに対するリクエストをブロックするため、リクエストは失敗します。

    予想される出力:

    000
    command terminated with exit code 56

mTLS のステータスを表示する

Google Cloud コンソールで、認証ポリシーを含め、Anthos セキュリティ機能のステータスを確認できます。

  1. Google Cloud コンソールで、[GKE Enterprise Security] ページに移動します。

    [GKE Enterprise Security] に移動

  2. メニューバーのプルダウン リストから Google Cloud プロジェクトを選択します。

    [ポリシーの概要] には、mTLS などのアプリケーション セキュリティのステータスが表示されます。

  3. [ポリシー監査] をクリックして、各クラスタと名前空間のワークロード ポリシーのステータスを表示します。[mTLS ステータス] カードには概要が表示されます。[ワークロード] リストに、各ワークロードの mTLS ステータスが表示されます。

    すべてのサービス(厳密な mTLS)

認証ポリシーを検索して削除する

  1. サービス メッシュ内のすべての PeerAuthentication ポリシーの一覧を表示するには、次のコマンドを実行します。

    kubectl get peerauthentication --all-namespaces
    
  2. 認証ポリシーを削除します。

    kubectl delete peerauthentication -n demo namespace-policy
    

    予想される出力:

    peerauthentication.security.istio.io "namespace-policy" deleted
  3. frontend-external サービスの外部 IP アドレスを使用して Online Boutique にアクセスし、ページを更新します。ページが想定どおりに表示されます。

  4. 次のコマンドで、demo 名前空間の別の Pod からプレーンな HTTP を使用して、frontend サービスに curl を実行します。

    kubectl exec \
      $(kubectl get pod -l app=productcatalogservice -n demo -o jsonpath={.items..metadata.name}) \
      -c istio-proxy -n demo -- \
      curl http://frontend:80/ -o /dev/null -s -w '%{http_code}\n'
    

    デフォルトでは TLS と平文の両方のトラフィックが受け入れられるため、ステータス 200 でリクエストが成功します。

Google Cloud コンソールで [ワークロード] リストが表示されたページを更新すると、mTLS ステータスが Permissive と表示されます。

ワークロードごとに相互 TLS を有効にする

特定のワークロードに PeerAuthentication ポリシーを設定するには、selector セクションを構成し、目的のワークロードに一致するラベルを指定する必要があります。ただし、Anthos Service Mesh は、サービスへの送信 mTLS トラフィックのワークロード レベルのポリシーを集計できません。この動作を管理するには、宛先ルールを構成する必要があります。

  1. demo 名前空間の特定のワークロードに認証ポリシーを適用します。次のポリシーでは、ラベルとセレクタを使用して特定の frontend デプロイをターゲットにしていることを確認してください。

    cat <<EOF | kubectl apply -n demo -f -
    apiVersion: "security.istio.io/v1beta1"
    kind: "PeerAuthentication"
    metadata:
      name: "frontend"
      namespace: "demo"
    spec:
      selector:
        matchLabels:
          app: frontend
      mtls:
        mode: STRICT
    EOF
    

    予想される出力:

    peerauthentication.security.istio.io/frontend created
  2. 一致する宛先ルールを構成します。

    cat <<EOF | kubectl apply -n demo -f -
    apiVersion: "networking.istio.io/v1alpha3"
    kind: "DestinationRule"
    metadata:
      name: "frontend"
    spec:
      host: "frontend.demo.svc.cluster.local"
      trafficPolicy:
        tls:
          mode: ISTIO_MUTUAL
    EOF
    

    予想される出力:

    destinationrule.networking.istio.io/frontend created
  3. frontend-external サービスの外部 IP アドレスを使用して Online Boutique にアクセスし、ページを更新します。frontend serviceSTRICT mTLS に設定され、サイドカー プロキシがリクエストをブロックしているため、このページは表示されません。

  4. 次のコマンドで、demo 名前空間の別の Pod からプレーンな HTTP を使用して、frontend サービスに curl を実行します。

    kubectl exec \
      $(kubectl get pod -l app=productcatalogservice -n demo -o jsonpath={.items..metadata.name}) \
      -c istio-proxy -n demo -- \
      curl http://frontend:80/ -o /dev/null -s -w '%{http_code}\n'
    

    リクエストが失敗し、ステータス コード 56 が表示されます。

    Google Cloud コンソールで [ワークロード] リストが表示されたページを更新すると、frontend サービスの mTLS ステータスが Strict と表示され、他のサービスは Permissive に設定されます。

    フロントエンド サービスのみが厳密な mTLS

  5. 認証ポリシーと宛先ルールを削除します。

    kubectl delete peerauthentication -n demo frontend
    kubectl delete destinationrule -n demo frontend
    

メッシュ全体の mTLS を適用する

メッシュ内のすべてのサービスが平文トラフィックを受け入れるのを防ぐには、mTLS モードを STRICT に設定してメッシュ全体の PeerAuthentication ポリシーを設定します。メッシュ全体の PeerAuthentication ポリシーにはセレクタがないため、このポリシーはルート名前空間 istio-system に適用する必要があります。ポリシーをデプロイすると、コントロール プレーンが TLS 証明書を自動的にプロビジョニングし、ワークロードの相互認証を可能にします。

  1. メッシュ全体の mTLS を適用します。

    kubectl apply -f - <<EOF
    apiVersion: "security.istio.io/v1beta1"
    kind: "PeerAuthentication"
    metadata:
      name: "mesh-wide"
      namespace: "istio-system"
    spec:
      mtls:
        mode: STRICT
    EOF
    

    予想される出力:

    peerauthentication.security.istio.io/mesh-wide created

  2. frontend-external サービスの外部 IP アドレスを使用して Online Boutique にアクセスし、ページを更新します。ページは表示されません。

  3. 次のコマンドで、demo 名前空間の別の Pod からプレーンな HTTP を使用して、frontend サービスに curl を実行します。

    kubectl exec \
      $(kubectl get pod -l app=productcatalogservice -n demo -o jsonpath={.items..metadata.name}) \
      -c istio-proxy -n demo -- \
      curl http://frontend:80/ -o /dev/null -s -w '%{http_code}\n'
    

    リクエストが失敗し、ステータス コード 56 が表示されます。

  4. mesh-wide ポリシーを削除します。

    kubectl delete peerauthentication -n istio-system mesh-wide
    

Google Cloud コンソールでページを更新すると、すべてのサービスの mTLS の詳細に Permissive が表示されます。

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

  • 追加料金の発生を回避するには、クラスタを削除します。

    gcloud container clusters delete  CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION
    
  • クラスタを維持して Online Boutique のサンプルを削除するには:

    kubectl delete namespaces demo
    

次のステップ