エグレス TLS オリジネーション
外部サービスへのアクセス6タスクでは、サービスメッシュの外部にあるHTTPおよびHTTPSサービスに、メッシュ内のアプリケーションからアクセスする方法を示しています。このタスクで説明されているように、ServiceEntry
7は、外部サービスへのアクセスを制御する方法でIstioを設定するために使用されます。この例では、外部サービスへのトラフィックに対してTLSオリジネーションを実行するようにIstioを設定する方法を示します。Istioは外部サービスへのHTTPS接続を開き、元のトラフィックはHTTPのままとなります。
ユースケース
外部サイトに対してHTTP呼び出しを実行するレガシーアプリケーションを考えてみましょう。アプリケーションを運用する組織が、すべての外部トラフィックを暗号化する必要があるという新しい要件を受け取ったとします。Istioを使用すると、アプリケーションのコードを変更することなく、構成のみでこの要件を達成できます。アプリケーションは暗号化されていないHTTPリクエストを送信でき、Istioがアプリケーションのためにそれらを暗号化します。
ソースから暗号化されていないHTTPリクエストを送信し、IstioにTLSアップグレードを実行させるもう1つの利点は、Istioがより良いテレメトリーを生成し、暗号化されていないリクエストに対してより多くのルーティング制御を提供できることです。
始める前に
インストールガイド8の指示に従ってIstioをセットアップします。
外部呼び出しのテストソースとして使用されるcurl9サンプルを起動します。
自動サイドカーインジェクションを有効にしている場合は、
curl
アプリケーションをデプロイします。それ以外の場合は、
curl
アプリケーションをデプロイする前に、手動でサイドカーをインジェクトする必要があります。以下の手順では、
exec
およびcurl
を実行できる任意のポッドで実行できます。外部サービスにリクエストを送信するためのソースポッドの名前を保持するシェル変数を作成します。curl9サンプルを使用した場合は、以下を実行します。
外部サービスへのアクセスの構成
まず、外部サービスへのアクセス6タスクで示されているのと同じ手法を使用して、外部サービスedition.cnn.com
へのアクセスを設定することから始めます。ただし、今回は、1つのServiceEntry
を使用して、サービスへのHTTPおよびHTTPSアクセスを両方とも有効にします。
edition.cnn.com
へのアクセスを有効にするためのServiceEntry
を作成します。外部HTTPサービスにリクエストを送信します。
出力は上記と同様になるはずです(一部の詳細は省略記号で置き換えられています)。
curlの-L
フラグに注意してください。これは、curlにリダイレクトに従うように指示します。この場合、サーバーは、http://edition.cnn.com/politics
へのHTTPリクエストに対してリダイレクト応答(301 Moved Permanently11)を返しました。リダイレクト応答は、クライアントに、今回はHTTPSを使用してhttps://edition.cnn.com/politics
に追加のリクエストを送信するように指示します。2番目のリクエストでは、サーバーはリクエストされたコンテンツと200 OKステータスコードを返しました。
curlコマンドはリダイレクトを透過的に処理しましたが、ここでは2つの問題があります。最初の問題は、http://edition.cnn.com/politics
のコンテンツの取得のレイテンシーを2倍にする冗長なリクエストです。2番目の問題は、URLのパス(この場合はpolitics)がクリアテキストで送信されることです。アプリケーションとedition.cnn.com
間の通信を傍受する攻撃者がいる場合、攻撃者はアプリケーションがedition.cnn.com
のどの特定のトピックを取得したかを知ることができます。プライバシー上の理由から、そのような開示を防ぎたい場合があります。
これらの問題は両方とも、IstioがTLSオリジネーションを実行するように構成することで解決できます。
エグレストラフィックのTLSオリジネーション
前のセクションの
ServiceEntry
を再定義して、HTTPリクエストをポート443にリダイレクトし、TLSオリジネーションを実行するためのDestinationRule
を追加します。上記の
DestinationRule
は、ポート80のHTTPリクエストに対してTLSオリジネーションを実行し、ServiceEntry
はポート80のリクエストをターゲットポート443にリダイレクトします。前のセクションと同様に、
http://edition.cnn.com/politics
にHTTPリクエストを送信します。今回は、最初で唯一の応答として200 OKを受け取ります。Istioはcurlに対してTLSオリジネーションを実行したため、元のHTTPリクエストはHTTPSとして
edition.cnn.com
に転送されました。サーバーは、リダイレクトの必要なしに、コンテンツを直接返しました。クライアントとサーバー間の二重のラウンドトリップを排除し、アプリケーションがedition.cnn.com
のpoliticsセクションを取得したという事実を明らかにすることなく、リクエストは暗号化された状態でメッシュを離れました。前のセクションと同じコマンドを使用したことに注意してください。外部サービスにプログラムでアクセスするアプリケーションの場合、コードを変更する必要はありません。コードを1行も変更することなく、Istioを構成することでTLSオリジネーションのメリットを得ることができます。
HTTPSを使用して外部サービスにアクセスするアプリケーションは、以前と同様に動作し続けることに注意してください。
追加のセキュリティに関する考慮事項
アプリケーションポッドとローカルホスト上のサイドカープロキシ間のトラフィックは暗号化されていないため、アプリケーションのノードに侵入できる攻撃者は、ノードのローカルネットワーク上で暗号化されていない通信を見ることができます。一部の環境では、厳格なセキュリティ要件により、ノードのローカルネットワーク上でもすべてのトラフィックを暗号化する必要がある場合があります。このような厳格な要件では、アプリケーションはHTTPS(TLS)のみを使用する必要があります。この例で説明したTLSオリジネーションでは不十分です。
また、アプリケーションによってオリジンされたHTTPSの場合でも、攻撃者はサーバー名表示(SNI)12を調べることで、edition.cnn.com
へのリクエストが送信されていることを知ることができます。SNIフィールドは、TLSハンドシェイク中に暗号化されていない状態で送信されます。HTTPSを使用すると、攻撃者は特定のトピックや記事を知ることを防ぐことができますが、edition.cnn.com
にアクセスしていることを学習することを防ぐことはできません。
TLSオリジネーションの設定のクリーンアップ
作成したIstio構成項目を削除します。
エグレス通信のための相互TLSオリジネーション
このセクションでは、外部サービスに対してTLSオリジネーションを実行するようにサイドカーを構成する方法について説明します。今回は、相互TLSを必要とするサービスを使用します。この例は、次の設定が必要なため、かなり複雑になります。
- クライアントとサーバーの証明書を生成します。
- 相互TLSプロトコルをサポートする外部サービスをデプロイします。
- 手順1で作成したクレデンシャルを使用するようにクライアント(curlポッド)を構成します。
このセットアップが完了したら、TLSオリジネーションを実行するサイドカーを通過するように外部トラフィックを構成できます。
クライアントとサーバーの証明書およびキーの生成
このタスクでは、証明書とキーを生成するために好みのツールを使用できます。以下のコマンドではopenssl13を使用します。
サービスの証明書に署名するためのルート証明書と秘密キーを作成します。
my-nginx.mesh-external.svc.cluster.local
の証明書と秘密キーを作成します。オプションで、宛先のSAN検証を有効にする場合は、証明書に
SubjectAltNames
を追加できます。例えばクライアント証明書と秘密キーを生成します。
相互TLSサーバーのデプロイ
相互TLSプロトコルをサポートする実際の外部サービスをシミュレートするために、NGINX14サーバーをKubernetesクラスターにデプロイしますが、Istioサービスメッシュの外部、つまりIstioサイドカープロキシインジェクションが有効になっていない名前空間で実行します。
Istioメッシュの外部のサービスを表す名前空間(つまり
mesh-external
)を作成します。自動サイドカーインジェクションが有効化されていないため、サイドカープロキシは、この名前空間のポッドに自動的にインジェクトされないことに注意してください。サーバーとCAの証明書を保持するKubernetes Secrets15を作成します。
NGINXサーバーの構成ファイルを作成します。
NGINXサーバーの構成を保持するKubernetes ConfigMap16を作成します。
NGINXサーバーをデプロイします。
クライアント(curlポッド)の設定
クライアントの証明書を保持するKubernetes Secrets15を作成します。
シークレットは、クライアントポッドがデプロイされているのと同じ名前空間(この場合は
default
)に作成する必要があります。上記の手順で作成されたシークレットがクライアントポッド(この場合は
curl
)からアクセスできるように、必要なRBAC
を追加します。
サイドカーでのエグレス通信のための相互TLSオリジネーションの設定
HTTPリクエストをポート443にリダイレクトするための
ServiceEntry
を追加し、相互TLSオリジネーションを実行するためのDestinationRule
を追加します。上記の
DestinationRule
は、ポート80のHTTPリクエストに対してmTLSオリジネーションを実行し、ServiceEntry
はポート80のリクエストをターゲットポート443にリダイレクトします。クレデンシャルがサイドカーに提供され、アクティブであることを確認します。
http://my-nginx.mesh-external.svc.cluster.local
にHTTPリクエストを送信します。リクエストに対応する行について、
curl
ポッドのログを確認します。次のような行が表示されるはずです。
相互TLSオリジネーションの設定のクリーンアップ
作成したKubernetesリソースを削除します。
証明書と秘密キーを削除します。
この例で使用した生成済みの構成ファイルを削除します。
共通設定のクリーンアップ
curl
サービスとデプロイメントを削除します。