権限の取り消しと接続の終了は同じではない
一言でいうと
権限の取り消しは新しいAPIリクエストを止める統制であり、すでに実行中のコマンドの終了は、別に確認すべき対応です。
なぜ必要なのか
運用担当者が一時的にターミナルの権限を開放しました。作業が終わってRoleからexecの権限を削除し、新しいターミナルが開けないことまで確認しました。このとき、既存のウィンドウでも、もうコマンドを実行できないのでしょうか。同じ画面に見えるターミナルでも、新しい接続を作るリクエストと、すでに開いている接続を通じて送る入力は、別々の経路です。対応の完了をあまりに早く宣言すると、実行中のセッションを見逃すことがあります。
LabHubの専用k3s v1.36.4のプローブ検証では、新しいexecが拒否されたあとも、既存のストリームが、そのあとに作成した新しい入力に応答しました。以前の出力が画面に残っているという意味ではありません。権限の取り消しのあとに作って送った、それぞれ異なる乱数とACKを突き合わせて、実際の実行を観察しました。これは確認したバージョン・経路の結果であり、すべてのプロキシやセッション管理ツールの動作を保証するものではありません。
どう動くのか
Kubernetes RBACのRoleは、namespaceの範囲でリクエストを許可します。権限は加算されるため、1つのRoleを絞っても、別のバインディングが同じ権限を与えていれば、リクエストは依然として許可されることがあります。そのため、YAMLだけを見るのではなく、実際のリクエストの成功・拒否も併せて確認する必要があります。
Podの参照とコンテナの実行も、別の権限です。Podはpods、実行はpods/execというsubresourceで指定します。一般的なリソースの作成とは異なり、execのように対象の名前がURLに含まれるsubresourceは、resourceNamesで特定のPodに限定できます。このラボでは、targetとcontrolのGETは許可し、execはtargetにだけ許可します。wildcardを使うと対照群まで開いてしまうため、問題を狭く再現できません。execにget・createを明示するのは、クライアントの接続方式の違いを考慮するためであり、すべての一般的なGETがプロセスを実行するという意味ではありません。
ターミナルは、接続を確立したあと、stdin・stdout・stderrを長い間やり取りします。公式のストリーミングのドキュメントは、HTTP接続をアップグレードして双方向のチャネルとして使う構造を説明しています。したがって、新しいリクエストの拒否と既存のチャネルの終了を、同じ出来事として扱いません。auth can-iは権限を問い合わせるツールであり、既存の接続を切るコマンドでも、実際のexecの成功の代わりになる証拠でもありません。
今回のラボの--asは、管理者証明書でログインしたリクエストを、サービスアカウントのアイデンティティとして代理するimpersonationです。APIサーバーは元のリクエスト元を認証し、代理の権限を確認したうえで、代理アイデンティティで認可します。この方式でRBACを検証できますが、サービスアカウントのbearerトークンの有効期限・取り消しを検証したことにはなりません。そのテーマは、KCSAの実際のトークンのラボで扱います。
現場での姿
インシデント対応では、遮断と保全がぶつかります。先にPodを削除すると、実行の痕跡や一時ファイルを失うことがあり、調査だけをして待っていると、危険な実行が続くことがあります。どの証拠をどこに残し、どの業務への影響を受け入れるかを、先に決める必要があります。ラボのcontainment.jsonは、対象UID・保全する対照群のUID・直前の証拠のハッシュ・措置の範囲を記録する、小さな対応計画です。このハッシュは、事故でファイルが変更されたことを見つける手段であり、rootユーザーが悪意を持って資料全体を作り直した場合まで防ぐ電子署名ではありません。
名前だけを見て削除するのも危険です。削除と再作成の間に、同じ名前で別のPodが入ってくることがあるからです。UIDの前提条件は、調査した対象と、実際に変更する対象を結び付けます。ラボは正常終了の猶予を与え、Podの不在と、既存のexecプロセスの終了の両方を観察します。APIオブジェクトの削除の成功だけで、ノードの実際のプロセスが終わったと断定しません。
本番の対応では、所有するDeploymentがPodを再作成したり、GitOpsが権限を元に戻したりすることもあります。このラボは、健全な単一VMの中の独立したPodだけを使うため、その自動復旧までは模擬しません。実際のサービスでは、望ましい状態を持つコントローラー・Gitの設定も一緒に直す必要があります。対照群を残す理由は、リクエストの遮断がサービス全体の故障によるものかを区別し、措置の範囲が広がっていないかを確認するためです。
復旧が終わっても、権限を元どおりにすべて開放はしません。新しいtargetのUID・ReadyとGETの成功を確認し、execが引き続き拒否されるかを点検します。サービスの復旧と、一時的な管理権限の再付与は、別々の承認です。対応報告書には、新規接続の拒否、既存接続の追加の応答、終了および復旧の結果を、それぞれ書き、1つのグリーン表示で残りを代用しません。
次のラボですること
scopeを調査し、狭いRoleを作成してから、実際のexecストリームを開きます。権限を取り消して、新規リクエストの拒否と、既存の接続の新しい応答を比較します。証拠を保全したあと、指定したUIDだけを終了し、対照群と新しいPodの権限の境界まで確認します。helperは無害なACKプログラムだけを実行します。検査ファイルは永続的な観測を読むため、最後のステップのあとで再採点しても、過去の成功は失われません。途中の実行が不確かな形で切れた場合は、自動的に再起動せず、資料をダウンロードして新しいセッションで再現するよう案内します。