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

CKS — Kubernetesセキュリティスペシャリスト

権限を取り消してもターミナルは動いている

TT Labで続きを見る

目標

新規のexec権限の遮断と、既存の実行接続の終了を、それぞれ検証し、証拠を保全します。

なぜ重要なのか

新しい接続が開かないことだけを確認すると、残っている実行を見逃すことがあります。逆に、無条件にPodを削除すると、調査の資料と業務を失うことがあります。専用VMの無害なACKプログラムでその違いを観察し、指定したUIDだけを終了したあと、対照群と復旧したPodの権限の境界を確認します。

65分のラボです。セッションはデフォルトで60分なので、期限が切れる前に+時間で延長してください。最大180分で、セッションが終了すると、ファイルと実行中の接続は消えます。必要な証拠は、終了する前にダウンロードしてください。

ステップ

  1. inspectでベースラインを読み取り、/root/cks-exec/scope.jsonにnamespace、target_uid、control_uid、identity_methodの4つのフィールドを記録してください。namespaceはcks-terminalで、残りは現在のラボの実際の値です。act 1で調査範囲を保存してください。
  2. /root/cks-exec/allow-role.jsonに、apiVersion=rbac.authorization.k8s.io/v1、kind=Role、metadata.name=terminal、metadata.namespace=cks-terminalを作成してください。最初のルールは、apiGroups=[""]、resources=["pods"]、resourceNames=["target","control"]、verbs=["get"]で、2つ目は、resources=["pods/exec"]、resourceNames=["target"]、verbs=["get","create"]で、apiGroups=[""]です。act 2で適用し、controlの実際のexec拒否を確認してください。
  3. act 3でtargetに実際のexec接続を開き、新しい入力のACKのベースラインを観察してください。/root/cks-exec/evidence/03.jsonのfacts.streamに、nonce・reply・atが保存されます。この接続は後のステップまで維持し、新しい接続に切り替えないでください。
  4. /root/cks-exec/revoke-role.jsonに同じRoleを作成してください。ただし、pods/execのルールだけを削除し、target・controlのGETルールは維持します。act 4で権限を取り消し、evidence/04.jsonのnew_execがまさにpods/execの権限拒否であることを確認してください。
  5. act 5で既存の接続に新しい入力を送ってください。evidence/05.jsonの応答は、ステップ3とは異なるnonceで、時刻はステップ4の保存より後でなければなりません。同じtarget UIDのGET成功と比較して、API全体の障害ではないことを説明してください。
  6. /root/cks-exec/containment.jsonに、namespace=cks-terminal、target=target、実際のtarget_uid、preserve_control_uid、evidence_sha256、action=delete-owned-pod、force=falseを記録してください。ハッシュは、evidence/05.jsonをキーをソートし空白のないUTF-8のJSON(ensure_ascii=False)としてシリアライズしたSHA-256です。act 6で、終了前の計画と証拠を保全してください。
  7. act 7で、計画で検証した元のtarget UIDだけを正常終了してください。evidence/07.jsonで、old_pod_absent=true、stream_rcが実際の整数の終了コード、control_ready=trueと元のcontrol_uidの維持、force=falseを確認してください。ほかのPodやnamespaceを削除しないでください。
  8. /root/cks-exec/report.jsonに、new_exec=denied、existing_exec=responded-after-revocation、実際のold_target_uid・control_uid、containment=owned-pod-terminated、authentication_tested=impersonation-not-token-revocation、evidence_sha256を記録してください。ハッシュは、ステップ7の証拠の同じ方式のSHA-256です。act 8で新しいUIDのtargetを復旧し、Ready・GETの成功、およびexec拒否の維持まで確認してください。

参考

すべての操作は、VM内部のcks-terminalにだけ適用します。helperの使い方は、python3 /opt/fixtures/cks_exec_lab.py inspect、act 1からact 8、grade 1からgrade 8です。actは実際の作業と観測を行い、gradeはファイルだけを読みます。すでに完了したactは、答案を保全して再実行しません。一部の入力も自動的に上書きしないので、自分で直してください。実行の途中で中断されて結果が不確かなステップは、資料を保全して新しいセッションで再現します。

このラボのアイデンティティは、管理者証明書によるSAのimpersonationです。実際のSAトークンの取り消しの実験ではありません。特権・ホストネットワーク・追加のcapabilityを使わないでください。本番のサービスで、この終了手順をそのまま実行せず、所有するコントローラー・ノードの状態・証拠の保全・業務への影響を先に検討してください。

対象と対照群のアイデンティティを調査する

inspectでベースラインを読み取り、/root/cks-exec/scope.jsonにnamespace、target_uid、control_uid、identity_methodの4つのフィールドを記録してください。namespaceはcks-terminalで、残りは現在のラボの実際の値です。act 1で調査範囲を保存してください。

名前は再利用できますが、UIDは今回のリソースのアイデンティティです。トークンの値を探す課題ではありません。

対象のPodにだけターミナル権限を与える

/root/cks-exec/allow-role.jsonに、apiVersion=rbac.authorization.k8s.io/v1、kind=Role、metadata.name=terminal、metadata.namespace=cks-terminalを作成してください。最初のルールは、apiGroups=[""]、resources=["pods"]、resourceNames=["target","control"]、verbs=["get"]で、2つ目は、resources=["pods/exec"]、resourceNames=["target"]、verbs=["get","create"]で、apiGroups=[""]です。act 2で適用し、controlの実際のexec拒否を確認してください。

podsとpods/execを別のルールに分けて、resourceNamesを指定してください。制御用のPodは、参照だけができる状態でなければなりません。

実際の双方向接続のベースライン

act 3でtargetに実際のexec接続を開き、新しい入力のACKのベースラインを観察してください。/root/cks-exec/evidence/03.jsonのfacts.streamに、nonce・reply・atが保存されます。この接続は後のステップまで維持し、新しい接続に切り替えないでください。

nonceとACKが一致して初めて、実際の新しい入力への応答です。画面に残った古い出力だけを見ないでください。

新しいexecリクエストの権限を取り消す

/root/cks-exec/revoke-role.jsonに同じRoleを作成してください。ただし、pods/execのルールだけを削除し、target・controlのGETルールは維持します。act 4で権限を取り消し、evidence/04.jsonのnew_execがまさにpods/execの権限拒否であることを確認してください。

Role全体を空にすると、Pod GETも塞がれて、失敗の原因を区別しにくくなります。実行のsubresourceだけを削除してください。

残っている接続と新しい入力

act 5で既存の接続に新しい入力を送ってください。evidence/05.jsonの応答は、ステップ3とは異なるnonceで、時刻はステップ4の保存より後でなければなりません。同じtarget UIDのGET成功と比較して、API全体の障害ではないことを説明してください。

権限の問い合わせの結果と、すでに開いているプロセスの寿命は別のものです。取り消しの後に生成したnonceと、応答の時刻を見てください。

終了前の証拠と影響範囲を保全する

/root/cks-exec/containment.jsonに、namespace=cks-terminal、target=target、実際のtarget_uid、preserve_control_uid、evidence_sha256、action=delete-owned-pod、force=falseを記録してください。ハッシュは、evidence/05.jsonをキーをソートし空白のないUTF-8のJSON(ensure_ascii=False)としてシリアライズしたSHA-256です。act 6で、終了前の計画と証拠を保全してください。

同じ内容でも、空白やキーの順序が違えば、元のハッシュは変わります。要求された正規のJSONのハッシュを計算してください。

指定したUIDだけを終了して対照群を確認する

act 7で、計画で検証した元のtarget UIDだけを正常終了してください。evidence/07.jsonで、old_pod_absent=true、stream_rcが実際の整数の終了コード、control_ready=trueと元のcontrol_uidの維持、force=falseを確認してください。ほかのPodやnamespaceを削除しないでください。

削除APIの成功、オブジェクトの不在、接続の終了は、それぞれ別の証拠です。対照群のUIDとReadyも残す必要があります。

新しいPodの復旧と対応報告書

/root/cks-exec/report.jsonに、new_exec=denied、existing_exec=responded-after-revocation、実際のold_target_uid・control_uid、containment=owned-pod-terminated、authentication_tested=impersonation-not-token-revocation、evidence_sha256を記録してください。ハッシュは、ステップ7の証拠の同じ方式のSHA-256です。act 8で新しいUIDのtargetを復旧し、Ready・GETの成功、およびexec拒否の維持まで確認してください。

新しいPodのサービスの復旧は、一時的な管理権限の復元ではありません。execは引き続き拒否される必要があります。