修改ssh部署

pull/135/head
zhangchenhao 2025-05-23 17:04:27 +08:00
parent e5634d4992
commit bee46d943f
3 changed files with 49 additions and 28 deletions

4
.gitignore vendored
View File

@ -1 +1,3 @@
.DS_Store .DS_Store
/data/
/logs/

View File

@ -18,6 +18,7 @@ type SSHConfig struct {
PrivateKey string `json:"key"` // 可选 PrivateKey string `json:"key"` // 可选
Host string Host string
Port any Port any
Mode string `json:"mode"`
} }
type RemoteFile struct { type RemoteFile struct {
@ -27,7 +28,7 @@ type RemoteFile struct {
func buildAuthMethods(password, privateKey string) ([]ssh.AuthMethod, error) { func buildAuthMethods(password, privateKey string) ([]ssh.AuthMethod, error) {
var methods []ssh.AuthMethod var methods []ssh.AuthMethod
if privateKey != "" { if privateKey != "" {
signer, err := ssh.ParsePrivateKey([]byte(privateKey)) signer, err := ssh.ParsePrivateKey([]byte(privateKey))
if err != nil { if err != nil {
@ -35,15 +36,15 @@ func buildAuthMethods(password, privateKey string) ([]ssh.AuthMethod, error) {
} }
methods = append(methods, ssh.PublicKeys(signer)) methods = append(methods, ssh.PublicKeys(signer))
} }
if password != "" { if password != "" {
methods = append(methods, ssh.Password(password)) methods = append(methods, ssh.Password(password))
} }
if len(methods) == 0 { if len(methods) == 0 {
return nil, fmt.Errorf("no authentication methods provided") return nil, fmt.Errorf("no authentication methods provided")
} }
return methods, nil return methods, nil
} }
@ -59,58 +60,65 @@ func writeMultipleFilesViaSSH(config SSHConfig, files []RemoteFile, preCmd, post
default: default:
port = "22" port = "22"
} }
IPtype := public.CheckIPType(config.Host)
if IPtype == "IPv6" {
config.Host = "[" + config.Host + "]"
}
addr := fmt.Sprintf("%s:%s", config.Host, port) addr := fmt.Sprintf("%s:%s", config.Host, port)
if config.Mode == "" || config.Mode == "password" {
config.PrivateKey = ""
}
authMethods, err := buildAuthMethods(config.Password, config.PrivateKey) authMethods, err := buildAuthMethods(config.Password, config.PrivateKey)
if err != nil { if err != nil {
return err return err
} }
sshConfig := &ssh.ClientConfig{ sshConfig := &ssh.ClientConfig{
User: config.User, User: config.User,
Auth: authMethods, Auth: authMethods,
HostKeyCallback: ssh.InsecureIgnoreHostKey(), HostKeyCallback: ssh.InsecureIgnoreHostKey(),
} }
client, err := ssh.Dial("tcp", addr, sshConfig) client, err := ssh.Dial("tcp", addr, sshConfig)
if err != nil { if err != nil {
return fmt.Errorf("failed to dial: %v", err) return fmt.Errorf("failed to dial: %v", err)
} }
defer client.Close() defer client.Close()
session, err := client.NewSession() session, err := client.NewSession()
if err != nil { if err != nil {
return fmt.Errorf("会话创建失败: %v", err) return fmt.Errorf("会话创建失败: %v", err)
} }
defer session.Close() defer session.Close()
var script bytes.Buffer var script bytes.Buffer
if preCmd != "" { if preCmd != "" {
script.WriteString(preCmd + " && ") script.WriteString(preCmd + " && ")
} }
for i, file := range files { for i, file := range files {
if i > 0 { if i > 0 {
script.WriteString(" && ") script.WriteString(" && ")
} }
dirCmd := fmt.Sprintf("mkdir -p $(dirname %q)", file.Path) dirCmd := fmt.Sprintf("mkdir -p $(dirname %q)", file.Path)
writeCmd := fmt.Sprintf("printf %%s '%s' > %s", file.Content, file.Path) writeCmd := fmt.Sprintf("printf %%s '%s' > %s", file.Content, file.Path)
script.WriteString(dirCmd + " && " + writeCmd) script.WriteString(dirCmd + " && " + writeCmd)
} }
if postCmd != "" { if postCmd != "" {
script.WriteString(" && " + postCmd) script.WriteString(" && " + postCmd)
} }
cmd := script.String() cmd := script.String()
if err := session.Run(cmd); err != nil { if err := session.Run(cmd); err != nil {
return fmt.Errorf("运行出错: %v", err) return fmt.Errorf("运行出错: %v", err)
} }
return nil return nil
} }
@ -208,7 +216,7 @@ func DeployLocalhost(cfg map[string]any) error {
return fmt.Errorf("前置命令执行失败: %v, %s", err, errout) return fmt.Errorf("前置命令执行失败: %v, %s", err, errout)
} }
} }
dir := filepath.Dir(certPath) dir := filepath.Dir(certPath)
if err := os.MkdirAll(dir, os.ModePerm); err != nil { if err := os.MkdirAll(dir, os.ModePerm); err != nil {
panic("创建证书保存目录失败: " + err.Error()) panic("创建证书保存目录失败: " + err.Error())
@ -225,7 +233,7 @@ func DeployLocalhost(cfg map[string]any) error {
if err != nil { if err != nil {
return fmt.Errorf("写入私钥失败: %v", err) return fmt.Errorf("写入私钥失败: %v", err)
} }
afterCmd, ok := cfg["afterCmd"].(string) afterCmd, ok := cfg["afterCmd"].(string)
if ok { if ok {
_, errout, err := public.ExecCommand(afterCmd) _, errout, err := public.ExecCommand(afterCmd)
@ -241,19 +249,19 @@ func SSHAPITest(providerID string) error {
if err != nil { if err != nil {
return err return err
} }
providerConfigStr, ok := providerData["config"].(string) providerConfigStr, ok := providerData["config"].(string)
if !ok { if !ok {
return fmt.Errorf("api配置错误") return fmt.Errorf("api配置错误")
} }
// 解析 JSON 配置 // 解析 JSON 配置
var providerConfig SSHConfig var providerConfig SSHConfig
err = json.Unmarshal([]byte(providerConfigStr), &providerConfig) err = json.Unmarshal([]byte(providerConfigStr), &providerConfig)
if err != nil { if err != nil {
return err return err
} }
var port string var port string
switch v := providerConfig.Port.(type) { switch v := providerConfig.Port.(type) {
case float64: case float64:
@ -266,30 +274,30 @@ func SSHAPITest(providerID string) error {
port = "22" port = "22"
} }
addr := fmt.Sprintf("%s:%s", providerConfig.Host, port) addr := fmt.Sprintf("%s:%s", providerConfig.Host, port)
authMethods, err := buildAuthMethods(providerConfig.Password, providerConfig.PrivateKey) authMethods, err := buildAuthMethods(providerConfig.Password, providerConfig.PrivateKey)
if err != nil { if err != nil {
return err return err
} }
sshConfig := &ssh.ClientConfig{ sshConfig := &ssh.ClientConfig{
User: providerConfig.User, User: providerConfig.User,
Auth: authMethods, Auth: authMethods,
HostKeyCallback: ssh.InsecureIgnoreHostKey(), HostKeyCallback: ssh.InsecureIgnoreHostKey(),
} }
client, err := ssh.Dial("tcp", addr, sshConfig) client, err := ssh.Dial("tcp", addr, sshConfig)
if err != nil { if err != nil {
return fmt.Errorf("SSH连接失败: %v", err) return fmt.Errorf("SSH连接失败: %v", err)
} }
defer client.Close() defer client.Close()
// 尝试创建会话来验证连接 // 尝试创建会话来验证连接
session, err := client.NewSession() session, err := client.NewSession()
if err != nil { if err != nil {
return fmt.Errorf("SSH会话创建失败: %v", err) return fmt.Errorf("SSH会话创建失败: %v", err)
} }
defer session.Close() defer session.Close()
return nil return nil
} }

View File

@ -220,3 +220,14 @@ func ExecCommand(command string) (string, string, error) {
return stdout.String(), stderr.String(), err return stdout.String(), stderr.String(), err
} }
func CheckIPType(address string) string {
ip := net.ParseIP(address)
if ip == nil {
return "Invalid IP"
}
if ip.To4() != nil {
return "IPv4"
}
return "IPv6"
}