mcpField
C
cofounder-ssh-key-rotation

cofounder-ssh-key-rotation

github.com/locawebセキュリティ4109 回インストール4 日前に更新
リポジトリ

cofounder-ssh-key-rotation について

デプロイ済み環境の全 VM を対象に SSH キーをローテーションするスキルです。Agent にキー交換、GitHub Secret とワークフローの更新、アクセス確認を案内し、停止と旧キー失効について事前説明と確認を求めます。

主な機能

  1. 01環境ごとのキー交換
  2. 02実行前の警告と確認
  3. 03GitHub Secret とワークフローの更新案内
  4. 04ローテーション監視とアクセス確認

活用シーン

  1. 01明示的な依頼によるキー交換
  2. 02想定したローカルキーがない場合のアクセス復旧
  3. 03VM のキー交換後のアクセス確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/locaweb/cofounder --skill cofounder-ssh-key-rotation

インストール後、Claude Code で/cofounder-ssh-key-rotationを入力して読み込まれたか確認します。

詳細

SSH キーのローテーション

デプロイ済み環境のすべての VM の SSH キーをローテーションします。ローテーション後は、新しいキーのみでアクセスできます。古いキーはすべての VM から完全に失効します。

使用する場面

  1. 明示的な依頼:ユーザーが SSH キーのローテーション、再生成、または置き換えを依頼した場合。
  2. ローカルキーがない場合:エージェントが VM に SSH 接続する必要がある(ログの確認、デバッグ、データベースへのアクセスなど)ものの、想定されるキーファイルがディスク上に存在しない場合。
キーがないことの検出

SSH 操作の前に、エージェントはキーのパスを解決します。

REPO_NAME=$(gh repo view --json name -q .name)

# Preview environment
SSH_KEY=~/.ssh/$REPO_NAME

# Other environments (e.g., production)
SSH_KEY=~/.ssh/$REPO_NAME-production

ファイルが存在しない場合(test -f "$SSH_KEY" が失敗する場合)、キーがないためローテーションが必要です。

警告(実行前に必ず伝えること)

ローテーションを開始する前に、必ずユーザーに警告します。

  1. ダウンタイム:ローテーションでは各 VM を停止し、SSH キーをリセットしてから再起動します。この処理中、環境内のすべての VM でダウンタイムが発生します(ユーザーへの影響を最小限に抑えるため、最初にアクセサリー、次にワーカー、最後に Web を処理します)。
  2. 古いキーの失効:古い SSH キーは、すべての VM の authorized_keys ファイルから完全に削除されます。古いキーを使用しているユーザーは、すぐにアクセスできなくなります。
  3. 環境はそれぞれ独立:各環境(プレビュー、本番など)には、それぞれ固有の SSH キーがあります。ローテーションの対象は指定した環境のみです。

実行前に、明示的な確認を求めてください。

ローテーションの手順

Step 1:環境を特定する

ローテーションが必要な環境を特定します。

  • ユーザーが環境を指定した場合は、それを使用します。
  • トラブルシューティング中にエージェントがキーがないことを検出した場合は、対象としていた環境を使用します。
  • 環境が不明確な場合は、ユーザーに確認します。
Step 2:新しい SSH キーをローカルで生成する

古いキーファイルが存在する場合は削除し、標準の命名規則に従って新しいキーを生成します。

REPO_NAME=$(gh repo view --json name -q .name)

# Preview environment
rm -f ~/.ssh/$REPO_NAME ~/.ssh/$REPO_NAME.pub
ssh-keygen -t ed25519 -f ~/.ssh/$REPO_NAME -N "" -C "$REPO_NAME-deploy"
chmod 600 ~/.ssh/$REPO_NAME

# Other environments (e.g., production)
rm -f ~/.ssh/$REPO_NAME-production ~/.ssh/$REPO_NAME-production.pub
ssh-keygen -t ed25519 -f ~/.ssh/$REPO_NAME-production -N "" -C "$REPO_NAME-deploy-production"
chmod 600 ~/.ssh/$REPO_NAME-production
Step 3:GitHub シークレットを更新する

新しい秘密鍵を対応する GitHub シークレットにアップロードします。

# Preview
gh secret set SSH_PRIVATE_KEY < ~/.ssh/$REPO_NAME

# Production (or other environment -- suffix matches env_name uppercased)
gh secret set SSH_PRIVATE_KEY_PRODUCTION < ~/.ssh/$REPO_NAME-production
Step 4:ローテーションを呼び出すワークフローを作成して実行する

再利用可能なローテーションワークフローを呼び出すワークフローを作成します。これは、ティアダウンワークフローと同じパターンです。

# .github/workflows/rotate-ssh-key-preview.yml
name: Rotate SSH Key Preview
on:
  workflow_dispatch:

permissions:
  contents: read

jobs:
  rotate:
    uses: locaweb/locaweb-cloud-provision/.github/workflows/rotate-ssh-key.yml@v1
    with:
      env_name: "preview"
    secrets:
      CLOUDSTACK_API_KEY: ${{ secrets.CLOUDSTACK_API_KEY }}
      CLOUDSTACK_SECRET_KEY: ${{ secrets.CLOUDSTACK_SECRET_KEY }}
      SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}

他の環境では、env_name と SSH_PRIVATE_KEY シークレットの参照を変更します。

# .github/workflows/rotate-ssh-key-production.yml
name: Rotate SSH Key Production
on:
  workflow_dispatch:

permissions:
  contents: read

jobs:
  rotate:
    uses: locaweb/locaweb-cloud-provision/.github/workflows/rotate-ssh-key.yml@v1
    with:
      env_name: "production"
    secrets:
      CLOUDSTACK_API_KEY: ${{ secrets.CLOUDSTACK_API_KEY }}
      CLOUDSTACK_SECRET_KEY: ${{ secrets.CLOUDSTACK_SECRET_KEY }}
      SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY_PRODUCTION }}

ワークフローファイルをコミットしてプッシュし、実行を開始します。

git add .github/workflows/rotate-ssh-key-preview.yml
git commit -m "Add SSH key rotation workflow for preview"
git push

# Trigger the workflow
gh workflow run rotate-ssh-key-preview.yml
Step 5:ローテーションを監視する
# Watch the run
gh run list --workflow=rotate-ssh-key-preview.yml --limit=5
gh run watch <run-id>

GitHub UI で確認できる直接リンクをユーザーに提示します。

gh run list --limit=1 --json databaseId,url -q '.[0].url'

ワークフローが失敗した場合は、ログを確認します。

gh run view <run-id> --log-failed
Step 6:SSH アクセスを確認する

ワークフローが正常に完了したら、新しいキーが機能することを確認します。

REPO_NAME=$(gh repo view --json name -q .name)

# Get the web IP from the latest deploy run
rm -rf $HOME/tmp/provision-output
gh run list --workflow=deploy-preview.yml --status=success --limit=1
gh run download <run-id> --name provision-output --dir $HOME/tmp/provision-output
cat $HOME/tmp/provision-output/provision-output.json

# Test SSH with the new key
ssh -i ~/.ssh/$REPO_NAME -o ConnectTimeout=10 root@<web_ip> "echo 'SSH rotation successful'"
Step 7:元のタスクを再開する

トラブルシューティングのためにエージェントが SSH アクセスを必要としてローテーションを開始した場合は、新しいキーを使って元の操作(ログの確認、デバッグ、データベースへのアクセスなど)を再開します。

ワークフローの入力

再利用可能なローテーションワークフロー(rotate-ssh-key.yml@v1)が受け付ける入力:

入力型デフォルト説明
env_namestring"preview"環境名(デプロイ済みの環境名と一致する必要があります)

必須のシークレット:

シークレット説明
CLOUDSTACK_API_KEYCloudStack API キー
CLOUDSTACK_SECRET_KEYCloudStack シークレットキー
SSH_PRIVATE_KEY新しい SSH 秘密鍵(Step 3 で更新済みのもの)

ローテーションで行われる処理(サーバー側)

  1. SSH キーペアとネットワークが CloudStack に存在することを確認します(安全性チェック)
  2. CloudStack から古いキーペアを削除し、同じ名前で新しい公開鍵を登録します
  3. 各 VM に対して(最初にアクセサリー、次にワーカー、最後に Web の順に)以下を実行します。
    • VM を停止します
    • CloudStack API を使って SSH キーをリセットします
    • VM を起動します
    • 新しいキーで SSH 接続し、authorized_keys を新しいキーのみで上書きします
  4. 結果の概要を出力します

キーファイルの命名規則

環境ローカルキーのパスGitHub シークレット
プレビュー(デフォルト)~/.ssh/<repo-name>SSH_PRIVATE_KEY
本番環境~/.ssh/<repo-name>-productionSSH_PRIVATE_KEY_PRODUCTION
その他の <env_name>~/.ssh/<repo-name>-<env_name>SSH_PRIVATE_KEY_<ENV_NAME>(大文字)

コメント