TT Lab
はじめる
学ぶ 学習パス コース

Istioサービスメッシュ

PERMISSIVEからSTRICTまで押し上げる

TT Labで続きを見る

目標

mTLSポリシーの3つの範囲と優先順位を実際に手で扱い、稼働中のメッシュを切らずにSTRICTへ引き上げる手順を、計画として残します。

なぜ重要なのか

STRICTへの切り替えは、技術的にはフィールド1つを変える作業ですが、運用では最も事故の多い作業の1つです。理由は単純で、平文で入ってきていた経路が、予告なしにすべて切れるからです。サイドカーのないcron、メッシュの外のバッチ、カスタムプローブは、ダッシュボードにあまり現れず、STRICTを有効にした瞬間に障害として表面化します。そのため定石は、PERMISSIVEのままにして、平文トラフィックの送信元を全数調査したうえで、狭い範囲から引き上げることです。

もう1つ、必ず身につけるべきなのが方向の区別です。PeerAuthenticationは受け取る側(インバウンド)を、DestinationRuleのtrafficPolicy.tlsは送る側(アウトバウンド)を扱います。この2つがずれると接続が失敗しますが、アプリケーションのログには単なる503としか見えません。しかも、この組み合わせはistioctl analyzeが検出してくれません。以前は専用のアナライザーがありましたが、今のバージョンのアナライザー一覧にはありません。そのため、2つのリソースをセットで並べて、人が自分で突き合わせる習慣が、そのままセーフティネットになります。

このラボ環境では実際のハンドシェイクが起こらないため、採点はポリシーの名前・範囲・フィールドと、静的分析の結果を見ます。

ステップ

開始前の準備: ラボのPodはラボごとに新しく起動するため、前のラボのメッシュ設定は残っていません。kubectl get crd peerauthentications.security.istio.ioの結果が空なら、istioctl manifest generate --set profile=minimal > /root/istio/manifest.yamlを実行したあと、kubectl apply -f /root/istio/manifest.yamlを2回実行してください。このマニフェストはistio-systemネームスペースも一緒に作りますが、ステップ2でメッシュ全体のポリシーを置く場所なので、必ず存在している必要があります。そのあと、kubectl create ns mesh-lab && kubectl label ns mesh-lab istio-injection=enabledで作業用のネームスペースを準備してください。

  1. /root/istio/mtls/pa-permissive.yamlを作成してください。ドキュメントが1つだけのPeerAuthenticationで、metadata.nameはdefault、metadata.namespaceはmesh-lab、spec.mtls.modeはPERMISSIVEで、selectorは置かないでください(ネームスペース全体のポリシーです)。作成したら適用してください。
  2. istio-systemネームスペースに、名前がdefaultのPeerAuthenticationをspec.mtls.mode: STRICTで、selectorなしで適用してください。そして、/root/istio/mtls/out/scope-note.txtに、メッシュ全体・ネームスペース・ワークロードの3つの層のうち、より狭く具体的な範囲が優先されるというルールを書いてください。
  3. mesh-labにpaymentsワークロードを作成してください。ServiceAccount payments、Service payments(ポート名httpは8080、http-metricsは9090)、Deployment payments(Podラベルapp: payments、serviceAccountName: payments)です。そのあと、PeerAuthentication legacy-metricsをmesh-labに作成してください。selector.matchLabels.appはpayments、spec.mtls.modeはSTRICTで、portLevelMtlsにはポート9090だけをmode: DISABLEで置いてください。
  4. mesh-labにDestinationRule payments-mtlsを作成してください。spec.hostはpayments、spec.trafficPolicy.tls.modeはISTIO_MUTUALです。そして、/root/istio/mtls/out/direction-note.txtに、PeerAuthenticationは受け取る側(インバウンド)を、DestinationRuleは送る側(クライアント/アウトバウンド)を扱うという違いを書いてください。
  5. /root/istio/mtls/identity.txtに、paymentsワークロードのSPIFFEアイデンティティをちょうど1行で書いてください: spiffe://cluster.local/ns/mesh-lab/sa/payments。そして、/root/istio/mtls/out/identity-note.txtに、メッシュの身元はIPアドレスではなくサービスアカウントであるという要点を書いてください。
  6. mesh-labにRequestAuthentication jwt-paymentsを作成してください。selector.matchLabels.appはpayments、jwtRules[0].issuerはhttps://idp.labhub.example/、jwtRules[0].jwksUriはhttps://idp.labhub.example/.well-known/jwks.jsonです。そして、/root/istio/mtls/out/jwt-note.txtに、このリソースだけではトークンのないリクエストを防げず、AuthorizationPolicyが一緒に必要であることを書いてください。
  7. mesh-labのdefault PeerAuthenticationをSTRICTに変えて適用してください。その状態で、spec.trafficPolicy.tls.mode: DISABLEのDestinationRule(例: payments-plaintext)を適用し、istioctl analyze -n mesh-labの結果を/root/istio/mtls/out/analyze-conflict.txtに保存してください。このバージョンのアナライザー一覧には、mTLSの組み合わせの競合を見るアナライザーがないため、出力にその競合は現れません。何と何がずれているのかを、1行で追記して記録に残してください。そのあと、そのDestinationRuleを削除するかISTIO_MUTUALに直して競合をなくし、もう一度分析して/root/istio/mtls/out/analyze-fixed.txtに保存してください。mesh-labにtls.mode: DISABLEのDestinationRuleが1つも残ってはいけません。
  8. /root/istio/mtls/migration.mdを400バイト以上で書いてください。文書の中で、PERMISSIVEと観測(メトリクス/モニタリング)の話が、STRICTという単語よりも先(上の行)に出てくる必要があり、ネームスペース単位の段階的な適用と、ロールバック(元に戻す)方法を含める必要があります。最後に、mesh-labのdefault PeerAuthenticationがSTRICTの状態で締めくくってください。

参考

ネームスペースの既定ポリシーをPERMISSIVEにする

/root/istio/mtls/pa-permissive.yamlを作成してください。ドキュメントが1つだけのPeerAuthenticationで、metadata.nameはdefault、metadata.namespaceはmesh-lab、spec.mtls.modeはPERMISSIVEで、selectorは置かないでください(ネームスペース全体のポリシーです)。作成したら適用してください。

ネームスペース全体にかかるポリシーは、名前が決まっていて、selectorを置きません。切り替えは、平文と暗号文の両方を受け付ける状態から始めます。

メッシュ全体の既定値をSTRICTに引き上げる

istio-systemネームスペースに、名前がdefaultのPeerAuthenticationをspec.mtls.mode: STRICTで、selectorなしで適用してください。そして、/root/istio/mtls/out/scope-note.txtに、メッシュ全体・ネームスペース・ワークロードの3つの層のうち、より狭く具体的な範囲が優先されるというルールを書いてください。

メッシュ全体のポリシーは、ルートネームスペースに置きます。そして、3つの層の範囲のうち、どれが勝つのかをメモにまとめてください。

1つのワークロードの1つのポートだけを例外として開ける

mesh-labにpaymentsワークロードを作成してください。ServiceAccount payments、Service payments(ポート名httpは8080、http-metricsは9090)、Deployment payments(Podラベルapp: payments、serviceAccountName: payments)です。そのあと、PeerAuthentication legacy-metricsをmesh-labに作成してください。selector.matchLabels.appはpayments、spec.mtls.modeはSTRICTで、portLevelMtlsにはポート9090だけをmode: DISABLEで置いてください。

例外は、できるだけ狭くします。ワークロードはselectorで選び、既定はSTRICTのままにして、問題のあるポートだけを別に指定します。

送る側のmTLSを宣言する

mesh-labにDestinationRule payments-mtlsを作成してください。spec.hostはpayments、spec.trafficPolicy.tls.modeはISTIO_MUTUALです。そして、/root/istio/mtls/out/direction-note.txtに、PeerAuthenticationは受け取る側(インバウンド)を、DestinationRuleは送る側(クライアント/アウトバウンド)を扱うという違いを書いてください。

受け取る側と送る側は、別のリソースが扱います。証明書を直接指定せず、メッシュが発行したものを使うモードが別にあります。

ワークロードの身元を書いてみる

/root/istio/mtls/identity.txtに、paymentsワークロードのSPIFFEアイデンティティをちょうど1行で書いてください: spiffe://cluster.local/ns/mesh-lab/sa/payments。そして、/root/istio/mtls/out/identity-note.txtに、メッシュの身元はIPアドレスではなくサービスアカウントであるという要点を書いてください。

3つの要素が順番に入ります。そして、その身元の根拠となるオブジェクトが、クラスターに実際に存在している必要があります。

エンドユーザーのJWT検証ポリシーを作成する

mesh-labにRequestAuthentication jwt-paymentsを作成してください。selector.matchLabels.appはpayments、jwtRules[0].issuerはhttps://idp.labhub.example/、jwtRules[0].jwksUriはhttps://idp.labhub.example/.well-known/jwks.jsonです。そして、/root/istio/mtls/out/jwt-note.txtに、このリソースだけではトークンのないリクエストを防げず、AuthorizationPolicyが一緒に必要であることを書いてください。

署名を検証するには、発行者と公開鍵の場所の両方が必要です。そして、このリソースだけでは何を防げないのかを、メモに書いてください。

STRICTとDISABLEの競合を作って解消する

mesh-labのdefault PeerAuthenticationをSTRICTに変えて適用してください。その状態で、spec.trafficPolicy.tls.mode: DISABLEのDestinationRule(例: payments-plaintext)を適用し、istioctl analyze -n mesh-labの結果を/root/istio/mtls/out/analyze-conflict.txtに保存してください。このバージョンのアナライザー一覧には、mTLSの組み合わせの競合を見るアナライザーがないため、出力にその競合は現れません。何と何がずれているのかを、1行で追記して記録に残してください。そのあと、そのDestinationRuleを削除するかISTIO_MUTUALに直して競合をなくし、もう一度分析して/root/istio/mtls/out/analyze-fixed.txtに保存してください。mesh-labにtls.mode: DISABLEのDestinationRuleが1つも残ってはいけません。

受け取る側が暗号化を要求しているのに、送る側が平文に固執すると、接続は失敗します。分析結果は、直す前と直した後に分けて残し、ずれた設定は1つも残さないでください。

段階的な切り替え計画を書いて切り替えを終える

/root/istio/mtls/migration.mdを400バイト以上で書いてください。文書の中で、PERMISSIVEと観測(メトリクス/モニタリング)の話が、STRICTという単語よりも先(上の行)に出てくる必要があり、ネームスペース単位の段階的な適用と、ロールバック(元に戻す)方法を含める必要があります。最後に、mesh-labのdefault PeerAuthenticationがSTRICTの状態で締めくくってください。

文書の中で単語が出てくる順序が、そのまま段階の順序です。観測とPERMISSIVEを先に、STRICTを後に書き、元に戻す方法も入れてください。