From 7264149f9c0e6b930c1d644aa54e7f1d25ea2b23 Mon Sep 17 00:00:00 2001 From: xuans Date: Fri, 2 Oct 2026 04:09:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BD=BB=E5=BA=95=E7=A7=BB=E9=99=A4=20SSH=20?= =?UTF-8?q?=E5=85=AC=E9=92=A5=E9=83=A8=E7=BD=B2=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 删除远程 authorized_keys 写入、PubkeyAuthentication 配置及客户端公钥部署接口,服务器部署仅保留 SSH 密码认证。 --- backend/internal/deployment/client.go | 1 - backend/internal/deployment/service_test.go | 2 - backend/internal/deployment/ssh.go | 74 --------------------- backend/internal/deployment/ssh_test.go | 26 -------- 4 files changed, 103 deletions(-) diff --git a/backend/internal/deployment/client.go b/backend/internal/deployment/client.go index 3e80e7f..705efbb 100644 --- a/backend/internal/deployment/client.go +++ b/backend/internal/deployment/client.go @@ -17,7 +17,6 @@ type Client interface { Rename(ctx context.Context, source, target string) error Remove(ctx context.Context, path string) error Run(ctx context.Context, command []string) (CommandResult, error) - InstallAuthorizedKey(ctx context.Context, publicKey string) error Close() error } diff --git a/backend/internal/deployment/service_test.go b/backend/internal/deployment/service_test.go index de65ba0..e2e6f92 100644 --- a/backend/internal/deployment/service_test.go +++ b/backend/internal/deployment/service_test.go @@ -145,8 +145,6 @@ func (c *memoryClient) Run(_ context.Context, command []string) (CommandResult, return result, err } -func (c *memoryClient) InstallAuthorizedKey(context.Context, string) error { return nil } - func (c *memoryClient) Close() error { return nil } type memoryFactory struct { diff --git a/backend/internal/deployment/ssh.go b/backend/internal/deployment/ssh.go index 66634a9..f3cc45a 100644 --- a/backend/internal/deployment/ssh.go +++ b/backend/internal/deployment/ssh.go @@ -3,7 +3,6 @@ package deployment import ( "context" "crypto/sha256" - "encoding/base64" "encoding/hex" "errors" "fmt" @@ -396,79 +395,6 @@ func (c *sshClientAdapter) Remove(ctx context.Context, path string) error { }) } -func (c *sshClientAdapter) InstallAuthorizedKey(ctx context.Context, publicKey string) error { - publicKey = strings.TrimSpace(publicKey) - key, _, _, _, err := ssh.ParseAuthorizedKey([]byte(publicKey)) - if err != nil { - return fmt.Errorf("SSH 公钥格式无效:%w", err) - } - encoded := base64.StdEncoding.EncodeToString(ssh.MarshalAuthorizedKey(key)) - script := authorizedKeyInstallScript(encoded) - result, err := c.Run(ctx, []string{"sh", "-c", script}) - if err != nil { - return fmt.Errorf("部署 SSH 公钥失败:%w", err) - } - if result.ExitCode != 0 { - return fmt.Errorf("部署 SSH 公钥失败,远程退出码:%d", result.ExitCode) - } - 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 - -if [ "$(id -u)" -eq 0 ] && command -v sshd >/dev/null 2>&1; then - sshd_config_dir="/etc/ssh/sshd_config.d" - sshd_dropin="$sshd_config_dir/99-scert-pubkey.conf" - install -d -m 755 "$sshd_config_dir" - had_existing=0 - old_config="" - if [ -f "$sshd_dropin" ]; then - had_existing=1 - old_config="$(cat "$sshd_dropin")" - fi - temp_config="$(mktemp "$sshd_config_dir/.scert-pubkey.XXXXXX")" - restore_sshd_config() { - if [ "$had_existing" -eq 1 ]; then - printf '%%s\n' "$old_config" > "$sshd_dropin" - chmod 644 "$sshd_dropin" - else - rm -f "$sshd_dropin" - fi - } - printf '%%s\n' 'PubkeyAuthentication yes' 'AuthorizedKeysFile .ssh/authorized_keys' > "$temp_config" - chmod 644 "$temp_config" - mv -f "$temp_config" "$sshd_dropin" - if ! sshd -t; then - restore_sshd_config - exit 1 - fi - if command -v systemctl >/dev/null 2>&1; then - if ! systemctl reload ssh 2>/dev/null && ! systemctl reload sshd 2>/dev/null; then - restore_sshd_config - ! systemctl reload ssh 2>/dev/null && ! systemctl reload sshd 2>/dev/null - exit 1 - fi - elif command -v service >/dev/null 2>&1; then - if ! service ssh reload 2>/dev/null && ! service sshd reload 2>/dev/null; then - restore_sshd_config - ! service ssh reload 2>/dev/null && ! service sshd reload 2>/dev/null - exit 1 - fi - else - restore_sshd_config - exit 1 - fi -fi`, encoded) -} func (c *sshClientAdapter) Run(ctx context.Context, command []string) (CommandResult, error) { if len(command) == 0 { return CommandResult{}, errors.New("远程命令不能为空") diff --git a/backend/internal/deployment/ssh_test.go b/backend/internal/deployment/ssh_test.go index eb075d6..e2ccebb 100644 --- a/backend/internal/deployment/ssh_test.go +++ b/backend/internal/deployment/ssh_test.go @@ -55,29 +55,3 @@ 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) - } -} -func TestAuthorizedKeyInstallScriptEnablesRootPublicKeyAuthentication(t *testing.T) { - script := authorizedKeyInstallScript("encoded-public-key") - for _, required := range []string{ - "PubkeyAuthentication yes", - "AuthorizedKeysFile .ssh/authorized_keys", - "sshd -t", - "systemctl reload ssh", - } { - if !strings.Contains(script, required) { - t.Fatalf("authorized key script is missing %q: %s", required, script) - } - } -}