コンテンツにスキップ

ホームごとに鍵を分ける

AWS の配備(ecs / ecs-ec2)だけの機能です。メンバーのホームごとにランダムな鍵を作り、資格情報ストア(secrets.enc)をその鍵で封じます。 AF_MASTER_KEY を持つ人でもストアを開けなくなり、KMS 鍵の無効化でストアを読めなくできます。先に 保存時の鍵を AWS KMS にする が必要です。パラメータは ECS の手順書 にあります。

あなたがやること 起きること
30-ingress を WorkspaceDekRandom=on でデプロイする Control Plane に AF_WORKSPACE_DEK=random が加わり、サービスがローリング更新される
何もしない(メンバーがワークスペースを起動する) 最初の起動でホームの鍵ができ、ワークスペースがストアをその鍵で封じ直す。Control Plane が結果を確かめる
af-cp home-dek-status を実行する 移行中のホームと確認済みのホーム、まだ一度も起動していないホームを数える
ホームを消したあと、取り残された鍵を消す そのホームのストアと写しが、二度と開けなくなる

30-ingress を WorkspaceDekRandom=on と CustodianKmsKeyArn を付けてデプロイします。変わるのは Control Plane のタスク定義だけです。

  • CustodianKmsKeyArn がないと、更新は CloudFormation の実行時にロールバックされます。変更セットは作れてしまうので、スタックのイベントで確かめてください
  • AF_WORKSPACE_DEK=random は AF_KEY_CUSTODIAN=kms のときだけ受け付けます。ほかの組み合わせや別の値では、Control Plane が起動時に止まります
  • 必要な権限は、既存の /af-ws/* への権限で足ります
こと 中身
残してあるホーム このフラグでの最初の起動までは、導いた鍵のままです
SSM パラメータ secret-key-next その起動から、ワークスペースごとに作られます。ホームが確認されたあとの次の起動で削除を試み、失敗はログに残して起動を続けます。Destroy でも消えます
動いているタスク 再起動するまで、今の環境変数を持ち続けます
パラメータを戻すと 止まるのは新しいホームへの鍵の作成だけです。すでに鍵を持つホームはその鍵を使い続け、接続し直しは要りません(無効に戻すとき)
消えないもの まだ起動していないホームと、古いスナップショット・バックアップは、KMS 鍵を無効にしても読めるままです

ホームの鍵ができて確認されるまで

Section titled “ホームの鍵ができて確認されるまで”
  1. 有効にしたあとの最初の起動で、Control Plane がホームの鍵を作り、導いた鍵と並べてワークスペースに渡します
  2. ワークスペースは起動時に secrets.enc をどちらかの鍵で開き、ホームの鍵で封じ直します。どちらでも開けないストアには触りません。ストアがまだないホームには、ホームの鍵で封じた空のストアを作ります
  3. Control Plane は、その起動が立ち上げたワークスペースの報告を待ちます。3 秒ごとに尋ね、最長 15 分待ちます
  4. ワークスペースがホームの鍵で封じ、migrated か current を返したら、ホームを確認済みにします
  5. 次の起動からは、ホームの鍵だけを AF_SECRET_KEY として渡し、導いた鍵は渡しません。ECS ではこの起動で secret-key-next も消します

空のストアを先に作るのは、導いた鍵しか持たない書き手が、あとからその鍵でストアを作れないようにするためです。

ワークスペースの /healthz は、鍵そのものではなく結果だけを返します。

secrets_key 意味 Control Plane がすること
none ストアがない。ホームの鍵を渡したワークスペースは空のストアを作って current を返すので、ふつうは出ません 移行中のまま
current ストアはすでにホームの鍵で封じてある 確認済みにする
migrated この起動でホームの鍵に封じ直した 確認済みにする
derived ホームの鍵に移せず、導いた鍵のまま 移行中のまま。ログに残し、何も消さない
unreadable どちらの鍵でも開けない 移行中のまま。ログに残し、何も消さない
  • secrets_key_next は、ホームの鍵で封じたかどうかを返します
  • Control Plane は起動ごとに新しい識別子(AF_HOME_KEY_START。秘密ではありません)を渡し、ワークスペースはそれを secrets_key_start として返します。以前のタスクや別のワークスペースの応答は無視し、リダイレクトにも従いません
  • 15 分を過ぎたとき、または待っている間に Control Plane が再起動したときは、ホームは移行中のままで、あとの起動で確認されます
  • すでに動いているワークスペースは、再起動するまで両方の鍵を環境変数に持ちます

af-cp home-dek-status が、移行中と確認済みのホームを数えます。ECS では rewrap-keys と同じく単発のタスクとして実行します(ECS の手順書)。

鍵はワークスペースではなくホームのものです。残したホームの上でワークスペースを削除して作り直しても、鍵はそのままです。

鍵が自動で消えるのは、次の 3 つがすべてそろったときだけです。

  • Destroy が終わった
  • どのワークスペースの行も、そのホームを指していない
  • ランタイムが、ホームの全体が消えたことを証明した

ホームの一部が残ったまま鍵を消すと、その部分が読めなくなります。それ以外の答えでは鍵を残します。migrating のままの鍵は、この経路では消えません。

ランタイム 証明できること
ecs / ecs-ec2 今実行した Destroy で、EFS の home タスクが終了コード 0 で終わり、すべてのアクセスポイントがそのタスクの消すディレクトリを指していたときだけ。別の場所を指すアクセスポイントは消さずに報告します。home タスクのない ecs はアクセスポイントだけを消し、再試行しても残りは報告されません
kubernetes 今実行した Destroy で、すべての claim と volume が消えたことを確かめたあとに StatefulSet を消したときだけ
docker / native 証明できません。ディレクトリがないのは、外れたボリュームや誤った WS_DATA でも同じだからです

あとから確かめたり、「残りがない」ことから判断したりはしません。

鍵の行が消えると、ストアと、その鍵で封じたストアの写し(スナップショット・バックアップ)は開けなくなります。ただし home_dek の行が残っているデータベースのバックアップを、KMS 鍵が有効なうちに戻すと開けます。ストアが移る前の写しは、導いた鍵のままです。

自動で消えずに残った鍵(golden の焼き込みの migrating なプローブ、証明できないランタイム、古い Control Plane による破棄)は、自分で消します。

  1. af-cp home-dek-status --orphans で一覧します。読み取りだけで、どのワークスペースの行も指していない鍵が出ます
  2. 一覧に出ただけでは候補です。ホームはワークスペースの行より長く残り得るので、ホームが消えたことを確かめます(EFS のディレクトリ、EBS ボリュームとスナップショット、クラスタの claim、データディレクトリ)
  3. af-cp home-dek-status --remove-orphan <membership-id> --force で消します

--force は「ホームは消えた」というあなたの宣言です。このコマンドには確かめるランタイムがありません。ワークスペースの行が指している鍵と、そのメンバーシップでワークスペースの操作が進行中の鍵は、--force でも消しません。

終了コード 意味
終了コード 0 鍵を消した
終了コード 1 何も消さなかった
終了コード 2 データベースのエラー

ホームが残っているのに鍵を消すと、その secrets.enc は二度と読めません。

ストアが封じ直されたホームは、AF_MASTER_KEY から導いた鍵ではもう開けません。Control Plane のデータ鍵のキャッシュ(AF_KMS_DATA_KEY_CACHE_TTL、既定は 5 分)が切れたあとは、Control Plane はホームの鍵を開けず、次の起動を拒否します。キャッシュの間は起動が成功し得ます。

これだけではストアは消えません。 すでに渡したホームの鍵の写しが残っていて、どれも KMS 鍵とは別のもので守られています。

写し 残る場所
動いているワークスペース 環境変数。Agent・git の資格情報ヘルパー・MCP サーバーは、KMS に問い合わせずにストアを読み書きし続けます
ランタイム側の写し 停止しても残ります。ECS ではワークスペースごとの SSM SecureString(secret-key・secret-key-next)で、アカウントの SSM 用の鍵で暗号化されています。docker ではコンテナの環境、Kubernetes では Secret です

ホームを残したままストアを読めなくするには、次の 3 つを全部やります。自動でやるものはありません。

  1. KMS 鍵を無効にする
  2. ワークスペースを止める
  3. ランタイム側の写しを自分で取り除く

Destroy はこの手順ではありません。ランタイム側の写しを消し、ホームも消そうとします。home タスクのない ecs のスタックでは、アクセスポイントだけを消し、ホームの EFS のディレクトリは残ります。

  • 有効にしてから一度も起動していないホーム。導いた鍵のままです。af-cp home-dek-status がその数を数えます
  • 封じ直す前に作られたホームの写し(ecs-ec2 のスナップショットやバックアップ)。古いファイルが残っていて、AF_MASTER_KEY で開けます

確認済みのホームに、ストアが移る前のスナップショットやバックアップから secrets.enc を戻すと、それは導いた鍵で封じられています。そのホームにはもう渡されない鍵なので、ワークスペースは unreadable を返し、その上には書きません。

  1. Control Plane の環境で af-cp home-dek-status --remigrate <membership-id> を実行します
  2. ワークスペースを再起動します。両方の鍵がまた渡され、戻したストアがホームの鍵で封じ直されます

このコマンドは、そのメンバーシップに確認済みのホームの鍵がないと終了コード 1、データベースのエラーで終了コード 2 で終わります。

AF_WORKSPACE_DEK を外しても、すでに鍵を持つホームにはその鍵を渡し続けます。ストアがその鍵で封じられているかもしれないからです。

ストアが封じ直されたあとに戻すと、戻しかたで結果が違います。

戻しかた 結果
ホームの鍵を知らない Control Plane に戻す、または home_dek 表を失う(ワークスペースイメージは v0.31.0 以降) ストアは開けなくなります。ワークスペースは、資格情報の接続し直しを含め、そのストアへの書き込みをすべて拒否します
v0.31.0 より前のワークスペースイメージ 移ったホームでは起動しないでください。 読めなかったあとの保存が、封じ直したストアの上に空のストアを書き、資格情報が失われ得ます

Control Plane より古いワークスペースイメージは、ストアがまだ封じ直されていなければ何も失いません。ホームの鍵を無視して、導いた鍵を使い続けます。

  1. そのホームでワークスペースを起動する前に、ストアを開けるものを戻します。Control Plane の版、その home_dek の行、KMS 鍵です
  2. 保存していた資格情報をあきらめるときに限り、ワークスペースを止め、読めない secrets.enc をメンバーのエージェント設定ディレクトリ(~/.config/agent-fleet/)から自分で退避します
  3. メンバーに資格情報を接続し直してもらいます
症状 原因と対処
ワークスペースが起動しない KMS がホームの鍵を封じられない・開けないときは、ワークスペースは起動しません。導いた鍵だけで起動する経路はありません。KMS 鍵が有効か、Control Plane のロールが使えるかを確かめます
ホームが移行中のまま ワークスペースが derived か unreadable を返したか、15 分の待ちが切れました。次の起動で確認されます。unreadable が続くなら 移す前の写しを戻したとき を確かめます
資格情報が開けないとメンバーが言う 鍵を知らない Control Plane に戻したか、home_dek 表を失いました。復旧する に進みます

エージェント向け

この指示をエージェントに送ると、このページを読ませられます。

https://agent-fleet.org/docs/ja/operate/keys/home-keys/index.md を読んで