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. 03指导更新 GitHub 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. 本地密钥缺失:Agent 需要通过 SSH 连接 VM(用于查看日志、调试、访问数据库等),但预期的密钥文件在磁盘上不存在。
检测密钥是否缺失

执行任何 SSH 操作前,Agent 会解析密钥路径:

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 密钥。轮换只会影响指定的环境。

继续操作前,请征得用户明确确认。

轮换流程

步骤 1:确定环境

确定需要轮换的环境:

  • 如果用户指定了环境,则使用该环境。
  • 如果 Agent 在排查问题时发现密钥缺失,则使用当时目标操作所针对的环境。
  • 如果环境不明确,请询问用户。
步骤 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
步骤 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
步骤 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
步骤 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
步骤 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'"
步骤 7:恢复原任务

如果触发轮换是因为 Agent 需要 SSH 访问权限来排查问题,则使用新密钥继续原操作(查看日志、调试、访问数据库等)。

工作流输入

可复用轮换工作流(rotate-ssh-key.yml@v1)接受以下输入:

输入类型默认值描述
env_namestring"preview"环境名称(必须与已部署的环境一致)

必需的密钥:

密钥描述
CLOUDSTACK_API_KEYCloudStack API 密钥
CLOUDSTACK_SECRET_KEYCloudStack 密钥
SSH_PRIVATE_KEY新的 SSH 私钥(已在步骤 3 中更新)

轮换操作内容(服务端)

  1. 验证 CloudStack 中存在 SSH 密钥对和网络(安全检查)
  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>(大写)

评论

支持 Markdown