彻底移除 SSH 公钥部署路径
删除远程 authorized_keys 写入、PubkeyAuthentication 配置及客户端公钥部署接口,服务器部署仅保留 SSH 密码认证。
This commit is contained in:
parent
7778aa5ced
commit
7264149f9c
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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("远程命令不能为空")
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user