はじめに
サポート集計ジョブは顧客のチケットを読み、短い集計結果を公開します。担当者がリポジトリの最新サンプルから API キーを削除しましたが、その値を使ったリクエストは今も成功します。あなたはこの警告を調査する保守担当者です。
まず正常なリクエストの流れを学び、過去の証拠を取得し、認証情報を特定して失効させます。ローカルの教材サービス、準備済みの 2 つのターミナル役割、Key Manager を利用します。基本的なターミナル操作ができれば十分です。Git、API リクエスト、キーの失効はここで説明します。
API でチケットを読む
このステップでは、チケットを読むリクエストを送り、その応答の見方を学びます。
このステップを始めるには、ラボ画面の Workstation タブを選択してください。
認証情報を調べる前に、サポート連携の正常な動作を確認します。サポートチケットは顧客からの問い合わせです。集計ジョブは、チケットのバッチを読み、短い集計結果をサービスへ返す準備済みプログラムです。連携とは、ここではプログラム同士が協働することです。
このラボのローカル教材サービスでは、顧客とキーは架空のものです。API は実際に認証と権限チェックを行いますが、特定のクラウドサービスの複製ではありません。実際のアカウントや外部の対象は使いません。
2 つのターミナル役割を使う
Workstation は保守用ターミナルで、設定サンプルのある /home/labex/project/repository で開きます。Integration は、ジョブの非公開実行時設定を所有する keyworker アカウントで動きます。各コマンドは指定されたターミナルで実行してください。ディレクトリを変えてもアカウントは変わりません。Key Manager タブでは、別のオペレーター認証でキーを管理します。
Workstation タブで pwd は現在のディレクトリ、ls はその中のファイル名を表示します。
次のコマンドを実行する前に、Workstation タブに切り替えてください。
pwd
/home/labex/project/repository
ls
README.md と summary-example.ini が見えるはずです。これらはリポジトリのサンプルで、実行中のジョブが読む非公開ファイルではありません。
リクエストのインターフェースを理解する
API は、プログラムからのリクエストを受けるサービスのインターフェースです。エンドポイントは操作とパスの組み合わせです。ここでは GET /v1/tickets がチケットを読み、POST /v1/summaries が集計を公開します。http://127.0.0.1:8000 はこの VM のローカルサービスを指し、127.0.0.1 はこのマシン、8000 は待ち受けポートです。
リクエストは、プログラムを認証する秘密値である API キーを含みます。キーは、名前付きのリクエストメタデータである Authorization ヘッダーに入れます。このサービスは Bearer の後に秘密値が続く形式を求めます。演習の架空キーを実際の認証情報と混同しないでください。
Workstation タブで読み取りリクエストを送ります。curl は HTTP リクエストを送り、-s は進行表示を隠し、-H はヘッダーを指定します。一重引用符は空白やクエリ区切りの ? を同じ引数に保ちます。batch=demo は練習データを選びます。
curl -s -H 'Authorization: Bearer lab_key_support_exposed' 'http://127.0.0.1:8000/v1/tickets?batch=demo'
応答は名前付きフィールドと値を持つ JSON 形式です。batch はデータセット名、items はリストで、チケットには id と subject があります。request_id は変化する監査識別子で、秘密値ではありません。件名 Delivery question を探してください。
デモ集計を公開する
このステップでは、準備済み worker を使い、読んだチケットをサービスが受信する集計に変換します。前のステップは読み取りだけでしたが、このプログラムは結果の公開も行います。
このステップを始めるには、ラボ画面の Integration タブを選択してください。
Integration タブで同じデモバッチに worker を実行します。python3 は提供された Python プログラムを実行し、パスがプログラムを、引数 demo がバッチを指定します。このコースで Python を書いたり理解したりする必要はありません。
次のコマンドを実行する前に、Integration タブに切り替えてください。
python3 /opt/keylab/worker.py demo
Read batch: demo (1 items)
{"batch":"demo","count":1,"subjects":["Delivery question"]}
Received batch: demo
Receiving key ID: key_support_old
最初のリクエストが入力を読み、次のリクエストが集計を公開しました。Received batch は受信 API が結果を受け付けたことを示します。key_support_old のようなキー ID は非秘密のラベルで、ヘッダー内の秘密値とは異なります。この実行は正常動作の例で、後の復旧ラボで指定されるバッチの完了にはなりません。
過去のキーを見つけて失効させる
このステップでは、過去の認証情報を見つけ、ID をサービス側の記録と照合し、そのキーだけを失効させます。見える行を消しても最新ファイルから隠れるだけで、認証情報は無効になりません。
このステップを始めるには、ラボ画面の Workstation タブを選択してください。
現在を見てから過去を見る
Workstation タブで cat を使い現在のサンプルを表示します。INI ファイルは [integration] のような角括弧のセクションに設定をまとめます。各設定は名前、等号、値で構成されます。
次のコマンドを実行する前に、Workstation タブに切り替えてください。
cat summary-example.ini
[integration]
key_id = key_support_old
api_key = SET_AT_RUNTIME
プレースホルダーは共有用サンプルに適していますが、以前のコピーやサービス側のキー状態については何も示しません。
Git はプロジェクトのスナップショットをコミットとして記録します。リポジトリには現在のファイルとコミット履歴があります。git log は新しい順にコミットを並べ、--oneline は各コミットを短い 1 行にします。グローバルオプション --no-pager は対話型の閲覧画面を開かず、ターミナルへ直接表示します。
git --no-pager log --oneline
Document prepared worker、Remove credential from current example、Add integration example が見えます。左側の短い識別子は変わることがあります。
HEAD は最新コミット、HEAD~2 は 2 つ前です。git show は過去のオブジェクトを表示し、コロンがリビジョンとファイル名を区切ります。
git --no-pager show HEAD~2:summary-example.ini
[integration]
key_id = key_support_old
api_key = lab_key_support_exposed
元の秘密値は今も取得できます。最新サンプルを削除したりローカル履歴を書き換えたりしても、他の人が取得したコピーを信用しないよう API に指示したことにはなりません。
サービス側の記録と対応付ける
Key Manager は、保守用の別の認証情報であるオペレータートークンを使います。アプリケーションキーではキーを管理できません。Workstation タブで準備済みのローカルトークンを表示します。

cat /home/labex/.config/keylab/operator-token
Key Manager タブに切り替え、Operator token に値を貼り付け、Sign in、Open Key Manager の順に選びます。このトークンはリポジトリに保存しないでください。ログインが拒否されたら、同じタブ内の Return to Key Manager を選びます。Workstation タブに切り替えてこの VM のオペレータートークンを再びコピーし、Key Manager タブに戻って再試行します。key_support_old 行と Active 状態を探します。スコープは許可する操作を表し、次のラボで選び方を学びます。
Recent API requests でこのキーの成功リクエストを見つけます。200 は API が読み取りを受け付けた状態です。履歴は漏えいを、リクエストは認証情報が使えることを示しますが、過去の送信者はどちらからも特定できません。報告書やログのコピーは不要です。
特定したキーを失効させる
影響を受けたキーだけを失効させます。拒否と独立した可用性は次のステップで試します。失効はサービスの受け入れ判断を変えますが、秘密値のコピーは消せません。
Workstation タブでデモチケットを再取得し、今度は HTTP 状態を表示します。-w は整形した結果を追加し、\n は改行、%{http_code} は応答状態を挿入します。
curl -s -w '\nHTTP %{http_code}\n' -H 'Authorization: Bearer lab_key_support_exposed' 'http://127.0.0.1:8000/v1/tickets?batch=demo'
応答の末尾は HTTP 200 です。Key Manager タブに切り替え、key_support_old 行で Revoke を選びます。すべてのキーを失効させると他の作業が止まるため、ID を注意深く確認してください。行は Revoked に変わります。

封じ込めと可用性を試す
このステップでは、古い認証情報が拒否され、API と独立した監視が利用可能なことを試します。管理画面の状態も参考になりますが、実際のリクエストでアクセス境界を確かめます。
このステップを始めるには、ラボ画面の Workstation タブを選択してください。
Workstation タブで同じリクエストを繰り返します。
次のコマンドを実行する前に、Workstation タブに切り替えてください。
curl -s -w '\nHTTP %{http_code}\n' -H 'Authorization: Bearer lab_key_support_exposed' 'http://127.0.0.1:8000/v1/tickets?batch=demo'
{"error":"Invalid or revoked key"}
HTTP 401
この API の 401 は、渡された認証情報では認証できないことを意味します。想定どおりの拒否は封じ込めの成功です。接続エラーならサービスに到達できないという別の問題です。サービスを止めても修復にはなりません。
Integration タブで worker をもう一度動かします。
次のコマンドを実行する前に、Integration タブに切り替えてください。
python3 /opt/keylab/worker.py demo
HTTP 401: {"error":"Invalid or revoked key"}
このコマンドは意図どおり失敗して終了します。ジョブは非公開ファイルから失効済みの値を読むため、入力を取得できなくなりました。封じ込め中の一時停止は許容されます。次のラボはこの状態から復旧します。
Workstation タブに戻り独立した監視を試します。専用の認証情報とヘルスエンドポイントを使います。
次のコマンドを実行する前に、Workstation タブに切り替えてください。
curl -s -w '\nHTTP %{http_code}\n' -H 'Authorization: Bearer lab_key_monitor_only' http://127.0.0.1:8000/v1/health
{"status":"ok","integration":"monitor"}
HTTP 200
サービスと独立した連携を維持しながら漏えいキーのアクセスを取り除けました。封じ込めを超えて復旧を進めても構いません。有効な復旧を行ったことを理由に不合格にはしません。
まとめ
正常に動く連携を確認し、キー ID と秘密値を区別し、Git 履歴から秘密値を取得して対応する認証情報を失効させました。実際の拒否と独立した機能の可用性も試しました。行の削除ではキーは無効にならず、失効処理によって無効になりました。次のラボでは専用の権限制限付きキーでジョブを復旧します。



