diff --git a/backend/internal/cert/deploy/deploy.go b/backend/internal/cert/deploy/deploy.go index d5b18a9..ebfc5eb 100644 --- a/backend/internal/cert/deploy/deploy.go +++ b/backend/internal/cert/deploy/deploy.go @@ -40,6 +40,9 @@ func Deploy(cfg map[string]any, logger *public.Logger) error { case "aliyun-oss": logger.Debug("部署到阿里云OSS...") return DeployOss(cfg) + case "localhost": + logger.Debug("部署到本地...") + return DeployLocalhost(cfg) default: return fmt.Errorf("不支持的部署: %s", providerName) } diff --git a/backend/internal/cert/deploy/ssh.go b/backend/internal/cert/deploy/ssh.go index ad4e331..b2b062f 100644 --- a/backend/internal/cert/deploy/ssh.go +++ b/backend/internal/cert/deploy/ssh.go @@ -2,10 +2,13 @@ package deploy import ( "ALLinSSL/backend/internal/access" + "ALLinSSL/backend/public" "bytes" "encoding/json" "fmt" "golang.org/x/crypto/ssh" + "os" + "path/filepath" "strconv" ) @@ -14,7 +17,7 @@ type SSHConfig struct { Password string // 可选 PrivateKey string // 可选 Host string - Port float64 + Port any } type RemoteFile struct { @@ -45,7 +48,7 @@ func buildAuthMethods(password, privateKey string) ([]ssh.AuthMethod, error) { } func writeMultipleFilesViaSSH(config SSHConfig, files []RemoteFile, preCmd, postCmd string) error { - addr := fmt.Sprintf("%s:%d", config.Host, int(config.Port)) + addr := fmt.Sprintf("%s:%s", config.Host, config.Port) authMethods, err := buildAuthMethods(config.Password, config.PrivateKey) if err != nil { @@ -164,3 +167,60 @@ func DeploySSH(cfg map[string]any) error { } return nil } + +func DeployLocalhost(cfg map[string]any) error { + cert, ok := cfg["certificate"].(map[string]any) + if !ok { + return fmt.Errorf("证书不存在") + } + // 设置证书 + keyPem, ok := cert["key"].(string) + if !ok { + return fmt.Errorf("证书错误:key") + } + certPem, ok := cert["cert"].(string) + if !ok { + return fmt.Errorf("证书错误:cert") + } + keyPath, ok := cfg["keyPath"].(string) + if !ok { + return fmt.Errorf("参数错误:keyPath") + } + certPath, ok := cfg["certPath"].(string) + if !ok { + return fmt.Errorf("参数错误:certPath") + } + beforeCmd, ok := cfg["beforeCmd"].(string) + if ok { + _, errout, err := public.ExecCommand(beforeCmd) + if err != nil { + return fmt.Errorf("前置命令执行失败: %v, %s", err, errout) + } + } + + dir := filepath.Dir(certPath) + if err := os.MkdirAll(dir, os.ModePerm); err != nil { + panic("创建证书保存目录失败: " + err.Error()) + } + dir = filepath.Dir(keyPath) + if err := os.MkdirAll(dir, os.ModePerm); err != nil { + panic("创建私钥保存目录失败: " + err.Error()) + } + err := os.WriteFile(certPath, []byte(certPem), 0644) + if err != nil { + return fmt.Errorf("写入证书失败: %v", err) + } + err = os.WriteFile(keyPath, []byte(keyPem), 0644) + if err != nil { + return fmt.Errorf("写入私钥失败: %v", err) + } + + afterCmd, ok := cfg["afterCmd"].(string) + if ok { + _, errout, err := public.ExecCommand(afterCmd) + if err != nil { + return fmt.Errorf("后置命令执行失败: %v, %s", err, errout) + } + } + return nil +} diff --git a/backend/public/utils.go b/backend/public/utils.go index 811b86e..c4c8d98 100644 --- a/backend/public/utils.go +++ b/backend/public/utils.go @@ -1,6 +1,7 @@ package public import ( + "bytes" "crypto/rand" "fmt" "github.com/google/uuid" @@ -8,6 +9,8 @@ import ( "math/big" "net" "net/http" + "os/exec" + "runtime" "strings" ) @@ -200,3 +203,23 @@ func ContainsAllIgnoreBRepeats(a, b []string) bool { } return true } + +// ExecCommand 执行系统命令,并返回 stdout、stderr 和错误 +func ExecCommand(command string) (string, string, error) { + var cmd *exec.Cmd + + // 根据操作系统选择解释器 + if runtime.GOOS == "windows" { + cmd = exec.Command("cmd", "/C", command) + } else { + cmd = exec.Command("bash", "-c", command) + } + + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + + err := cmd.Run() + + return stdout.String(), stderr.String(), err +}