修复SSH公钥部署脚本并更新进度

This commit is contained in:
xuans 2026-09-30 16:09:45 +08:00
parent 58e5e52e53
commit 9af39b071e
5 changed files with 54 additions and 9 deletions

View File

@ -351,15 +351,7 @@ func (c *sshClientAdapter) InstallAuthorizedKey(ctx context.Context, publicKey s
return fmt.Errorf("SSH 公钥格式无效:%w", err)
}
encoded := base64.StdEncoding.EncodeToString(ssh.MarshalAuthorizedKey(key))
script := fmt.Sprintf(`set -eu
umask 077
install -d -m 700 "$HOME/.ssh"
touch "$HOME/.ssh/authorized_keys"
chmod 600 "$HOME/.ssh/authorized_keys"
decoded="$(printf '%s' '%s' | base64 -d)"
if ! grep -Fqx -- "$decoded" "$HOME/.ssh/authorized_keys"; then
printf '%%s\\n' "$decoded" >> "$HOME/.ssh/authorized_keys"
fi`, "%s", encoded)
script := authorizedKeyInstallScript(encoded)
result, err := c.Run(ctx, []string{"sh", "-c", script})
if err != nil {
return fmt.Errorf("部署 SSH 公钥失败:%w", err)
@ -369,6 +361,18 @@ fi`, "%s", encoded)
}
return nil
}
func authorizedKeyInstallScript(encoded string) string {
return fmt.Sprintf(`set -eu
umask 077
install -d -m 700 "$HOME/.ssh"
touch "$HOME/.ssh/authorized_keys"
chmod 600 "$HOME/.ssh/authorized_keys"
decoded="$(printf '%%s' '%s' | base64 -d)"
if ! grep -Fqx -- "$decoded" "$HOME/.ssh/authorized_keys"; then
printf '%%s\n' "$decoded" >> "$HOME/.ssh/authorized_keys"
fi`, encoded)
}
func (c *sshClientAdapter) Run(ctx context.Context, command []string) (CommandResult, error) {
if len(command) == 0 {
return CommandResult{}, errors.New("远程命令不能为空")

View File

@ -66,3 +66,16 @@ func TestJoinShellArgsQuotesArguments(t *testing.T) {
t.Fatalf("远程命令参数未正确转义:%s", joined)
}
}
func TestAuthorizedKeyInstallScriptUsesRealNewline(t *testing.T) {
script := authorizedKeyInstallScript("encoded-public-key")
if !strings.Contains(script, "printf '%s' 'encoded-public-key'") {
t.Fatalf("authorized key payload was not inserted safely: %s", script)
}
if !strings.Contains(script, "printf '%s\\n'") {
t.Fatalf("authorized key should be terminated by a real newline: %s", script)
}
if strings.Contains(script, "printf '%s\\\\n'") {
t.Fatalf("authorized key script still writes a literal backslash-n: %s", script)
}
}

View File

@ -971,6 +971,7 @@ func (s *Server) provisionServerSSHKey(ctx context.Context, item deployment.Serv
}
publicKey, err := s.sshKeys.AuthorizedPublicKey(ctx, item.PrivateKeyRef)
if err != nil {
s.logSSHProvisionFailure("authorized_public_key", item, err)
item.SSHKeyStatus = deployment.SSHKeyStatusFailed
item.SSHKeyError = "自动部署 SSH 公钥失败"
return item, err
@ -992,6 +993,7 @@ func (s *Server) provisionServerSSHKey(ctx context.Context, item deployment.Serv
return item, err
}
if err := passwordClient.Close(); err != nil {
s.logSSHProvisionFailure("password_close", item, err)
item.SSHKeyStatus = deployment.SSHKeyStatusFailed
item.SSHKeyError = "自动部署 SSH 公钥失败"
return item, err

View File

@ -1153,3 +1153,16 @@ P0-05 从 `[!]` 调整为 `[~]`,并未标记完成;P0-04 剩余门禁和全
- [~] P0-10 其他任务、跨数据库实机矩阵和统一复审继续进行中。
- [ ] 真实生产数据库、密码 SSH、远端部署、HTTPS/DNS、ACME、Linux/Windows 服务和最终生产门禁仍未完成。
- [!] 不新增 `[✓]`,不以本地结果代替生产验收。
## 本轮开发进度(2026-09-30,P0-03 SSH 公钥部署阻塞修复)
总体验收继续保持 **P0-03:完成,待复审**,本轮仅完成 SSH 公钥部署实现修正与本地回归,不代表生产部署验收通过。
- [x] 已完成,等待复审:修正公钥安装脚本的 `fmt.Sprintf` 参数传递,确保实际编码公钥被写入远端。
- [x] 已完成,等待复审:修正 `authorized_keys` 追加逻辑,使用真实换行,不再写入字面量 `\\n`。
- [x] 已完成,等待复审:补充公钥读取失败、密码连接关闭失败的 SSH 阶段日志。
- [x] 已完成:新增公钥安装脚本回归测试;`go test ./...`、`go test -race ./internal/deployment ./internal/httpapi ./internal/app`、`go vet ./...`、`go build ./...`、`git diff --check` 均通过。
- [~] 进行中:需重新构建正式候选包并部署到实机,通过现有失败服务器记录复测密码连接、公钥写入、私钥回连和状态持久化。
- [ ] 未开始:证书文件推送、Nginx 配置校验/重载、失败回滚、真实多服务器部署和最终生产门禁。
- [!] 第二台真实服务器仍不可用,不以虚构数据替代多服务器生产验收。
- [!] 总体验收不得升级:仍为 **P0-03 完成,待复审**,没有新增 `[✓]`。

View File

@ -1801,3 +1801,16 @@ P0-11 生产验收门禁
- [~] P0-10 其他任务、跨数据库实机矩阵和统一复审继续进行中。
- [ ] 真实生产数据库、密码 SSH、远端部署、HTTPS/DNS、ACME、Linux/Windows 服务和最终生产门禁仍未完成。
- [!] 不新增 `[✓]`,不以本地结果代替生产验收。
## 本轮开发进度(2026-09-30,P0-03 SSH 公钥部署阻塞修复)
总体验收继续保持 **P0-03:完成,待复审**,本轮仅完成 SSH 公钥部署实现修正与本地回归,不代表生产部署验收通过。
- [x] 已完成,等待复审:修正公钥安装脚本的 `fmt.Sprintf` 参数传递,确保实际编码公钥被写入远端。
- [x] 已完成,等待复审:修正 `authorized_keys` 追加逻辑,使用真实换行,不再写入字面量 `\\n`。
- [x] 已完成,等待复审:补充公钥读取失败、密码连接关闭失败的 SSH 阶段日志。
- [x] 已完成:新增公钥安装脚本回归测试;`go test ./...`、`go test -race ./internal/deployment ./internal/httpapi ./internal/app`、`go vet ./...`、`go build ./...`、`git diff --check` 均通过。
- [~] 进行中:需重新构建正式候选包并部署到实机,通过现有失败服务器记录复测密码连接、公钥写入、私钥回连和状态持久化。
- [ ] 未开始:证书文件推送、Nginx 配置校验/重载、失败回滚、真实多服务器部署和最终生产门禁。
- [!] 第二台真实服务器仍不可用,不以虚构数据替代多服务器生产验收。
- [!] 总体验收不得升级:仍为 **P0-03 完成,待复审**,没有新增 `[✓]`。