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

Istio 実測ラボ

ルートを替えたら半分しか通じなかった

TT Labで続きを見る

目標

istiodの自己署名ルートを、自分たちで作ったルート・中間CA(プラグインCA)に替え、替える瞬間に片側だけが新しい証明書を受け取ったワークロード間が途切れること、そしてすべて入れ替わった後のチェーン・身元・寿命を、証明書から直接確認します。

なぜ重要なのか

メッシュのmTLSは、すべてのワークロードが同じルートを信頼するという前提の上に立っています。そのルートを組織のPKIに移すことは、セキュリティ上必要ですが、順序を知らずに行うと、サービス間が半分ずつ途切れます。途切れを一度自分で見れば、「2つのルートを一緒に信頼する期間」がなぜ必要かを説明できるようになります。

ステップ

  1. kubectl apply -f /opt/fixtures/istlab/pluginca-app.yamlで材料を載せ、準備ができるまで待ってください。その後、/root/istlab-ca/01-before.txtに3行を書いてください。root_subject=(ネームスペースbankのConfigMapistio-ca-root-certに入っているルートのsubject)、root_sha256=(そのルートのSHA-256フィンガープリント、openssl x509 -fingerprint -sha256の値の部分)、leaf_issuer=(clientのサイドカーが受け取ったワークロード証明書のissuer)です。
  2. /root/istlab-ca/certsで、ディストリビューションに入っている/usr/local/istio-1.31.0/tools/certs/Makefile.selfsigned.mkを使って、ルート(make -f … root-ca)とクラスターcluster1用の中間CA(make -f … cluster1-cacerts)を作ってください。/root/istlab-ca/certs/root-cert.pemと、/root/istlab-ca/certs/cluster1/の下にca-cert.pem・ca-key.pem・root-cert.pem・cert-chain.pemができている必要があります。
  3. istio-systemにSecretのcacertsを作ってください。/root/istlab-ca/certs/cluster1/の4つのファイル(ca-cert.pem・ca-key.pem・root-cert.pem・cert-chain.pem)を、同じ名前のキーで入れます。その後、istiodを再起動して、準備ができるまで待ってください。ワークロードはまだ再起動しません。
  4. webだけを再起動してください。その後、/root/istlab-ca/04-mixed.txtに3行を書いてください。code=(clientからhttp://web/のステータスコード)、client_root=(clientのサイドカーのROOTCAのsubject)、web_leaf_issuer=(webのサイドカーのワークロード証明書のissuer)です。
  5. clientも再起動して、client → webが再び200になるようにしてください。その後、clientのサイドカーのワークロード証明書チェーン(defaultのcertificateChain)をPEMとして/root/istlab-ca/05-chain.pemに保存してください。
  6. /root/istlab-ca/05-chain.pemの最初の証明書(ワークロード証明書)から、SANのURIを/root/istlab-ca/06-identity.txtにspiffe=の形で、そのURIのトラストドメイン(spiffe://の後の最初の部分)をtrust_domain=の形で書いてください。
  7. /root/istlab-ca/07-lifetimes.txtに3行を書いてください。leaf_hours=(ワークロード証明書のnotAfter − notBeforeを時間で、小数点以下切り捨て)、intermediate_days=(中間CAの有効期間を日で)、root_days=(ルートの有効期間を日で)です。
  8. /root/istlab-ca/08-report.mdに5行を書き、その下に学んだことを4行以上書いてください。5行は、old_root_subject=(ステップ1)、new_root_subject=(/root/istlab-ca/certs/root-cert.pemのsubject)、mixed_code=(ステップ4)、after_restart_code=(現在のclient → webのステータスコード)、leaf_hours=(ステップ7)です。

参考

現在のルートは誰が作ったか

kubectl apply -f /opt/fixtures/istlab/pluginca-app.yamlで材料を載せ、準備ができるまで待ってください。その後、/root/istlab-ca/01-before.txtに3行を書いてください。root_subject=(ネームスペースbankのConfigMapistio-ca-root-certに入っているルートのsubject)、root_sha256=(そのルートのSHA-256フィンガープリント、openssl x509 -fingerprint -sha256の値の部分)、leaf_issuer=(clientのサイドカーが受け取ったワークロード証明書のissuer)です。

istiodは、cacertsがなければ自分でルートを作ってistio-system/istio-ca-secretに置き、そのルートをすべてのネームスペースのistio-ca-root-certConfigMapとして配ります。ワークロード証明書は、サイドカーがistiodに要求して受け取り、istioctl proxy-config secret deploy/client -n bank -o jsonのdefault(ワークロード証明書チェーン)とROOTCA(信頼するルート)で見られます。値はbase64で入っています。

ルートとクラスター用の中間CAを作る

/root/istlab-ca/certsで、ディストリビューションに入っている/usr/local/istio-1.31.0/tools/certs/Makefile.selfsigned.mkを使って、ルート(make -f … root-ca)とクラスターcluster1用の中間CA(make -f … cluster1-cacerts)を作ってください。/root/istlab-ca/certs/root-cert.pemと、/root/istlab-ca/certs/cluster1/の下にca-cert.pem・ca-key.pem・root-cert.pem・cert-chain.pemができている必要があります。

Istioのドキュメントが勧める構造は、「ルートはオフラインに置き、クラスターごとにそのルートが署名した中間CAをistiodに渡す」です。そうすれば、クラスター1つの鍵が漏れても、ルートを替える必要がなく、複数のクラスターが同じルートを信頼して、互いのワークロードを信頼できます。このMakefileはデモ用なので、運用ではVaultのようなCAを使うようドキュメントが述べています。作った後、openssl verify -CAfile root-cert.pem cluster1/ca-cert.pemでチェーンを確認してみてください。

cacertsを差し込み、istiodを起動し直す

istio-systemにSecretのcacertsを作ってください。/root/istlab-ca/certs/cluster1/の4つのファイル(ca-cert.pem・ca-key.pem・root-cert.pem・cert-chain.pem)を、同じ名前のキーで入れます。その後、istiodを再起動して、準備ができるまで待ってください。ワークロードはまだ再起動しません。

istiodは起動するときにcacertsがあるかを見て、あれば自分で作ったルートの代わりにその中間CAで署名します。すでに起動しているistiodはSecretができても気づかないので、再起動します。新しく起動したistiodのログに、cacertsからルートを読んだという行が残り、各ネームスペースのistio-ca-root-certが新しいルートに替わります。ところが、すでに起動しているサイドカーが信頼するルートがどうなるかは、ステップ4で見ます。

片側だけが新しい証明書を受け取ると

webだけを再起動してください。その後、/root/istlab-ca/04-mixed.txtに3行を書いてください。code=(clientからhttp://web/のステータスコード)、client_root=(clientのサイドカーのROOTCAのsubject)、web_leaf_issuer=(webのサイドカーのワークロード証明書のissuer)です。

新しいistiodは、新しく起動したwebに、新しい中間CAが署名した証明書を渡します。ところが、再起動していないclientのサイドカーは、相変わらず古いルートだけを信頼しています。mTLSは両側が互いの証明書を検証するので、片側でも相手のルートを知らなければ、接続が張れません。運用でルートを変えるときに、古いルートと新しいルートを一緒に信頼する期間を置く理由がこれです。

全員に新しい証明書を受け取らせる

clientも再起動して、client → webが再び200になるようにしてください。その後、clientのサイドカーのワークロード証明書チェーン(defaultのcertificateChain)をPEMとして/root/istlab-ca/05-chain.pemに保存してください。

再起動したclientは、新しいルートを信頼し、新しい中間CAが署名した証明書を受け取ります。保存したチェーンは、ワークロード証明書 → 中間CA → ルートの順に入っているので、openssl verify -CAfile /root/istlab-ca/certs/root-cert.pem -untrusted /root/istlab-ca/05-chain.pem /root/istlab-ca/05-chain.pemで、自分たちのルートまでつながるかを確認できます。

証明書が語る身元

/root/istlab-ca/05-chain.pemの最初の証明書(ワークロード証明書)から、SANのURIを/root/istlab-ca/06-identity.txtにspiffe=の形で、そのURIのトラストドメイン(spiffe://の後の最初の部分)をtrust_domain=の形で書いてください。

Istioのワークロード証明書はsubjectが空で、身元はSANのURI 1つ(spiffe://<신뢰 도메인>/ns/<네임스페이스>/sa/<서비스어카운트>、プレースホルダーはトラストドメイン、ネームスペース、サービスアカウントです)に入ります。認可ポリシーのprincipalsがまさにこの値(スキームを除いた部分)です。CAを変えても、トラストドメインが同じなら、ポリシーを直す必要はありません。openssl x509 -noout -ext subjectAltNameで見ます。

誰がどれだけ長く生きるか

/root/istlab-ca/07-lifetimes.txtに3行を書いてください。leaf_hours=(ワークロード証明書のnotAfter − notBeforeを時間で、小数点以下切り捨て)、intermediate_days=(中間CAの有効期間を日で)、root_days=(ルートの有効期間を日で)です。

ワークロード証明書は、istiodが短命(デフォルトは24時間)で渡し、サイドカーが期限切れの前に自動で入れ替えます。そのため、漏れても被害の期間が短く、CAを変えた後に再起動していないワークロードも、やがて新しい証明書を受け取ります。ただし、それまでステップ4のような途切れが続くことがあります。中間CAとルートは人が管理するので、長く生きます。日付はopenssl x509 -noout -startdate -enddateで読み、date -dで秒に変えて引けば足ります。

ルートを変えるときの順序を書く

/root/istlab-ca/08-report.mdに5行を書き、その下に学んだことを4行以上書いてください。5行は、old_root_subject=(ステップ1)、new_root_subject=(/root/istlab-ca/certs/root-cert.pemのsubject)、mixed_code=(ステップ4)、after_restart_code=(現在のclient → webのステータスコード)、leaf_hours=(ステップ7)です。

説明の行には、「すでに運用中のメッシュでルートを変えるには、どんな順序が必要か(古いルートと新しいルートを一緒に信頼する期間)」を、自分の言葉で書いておいてください。このラボは、その期間なしで変えて、途切れをわざと見ました。