diff --git a/internal/certmgmt/deployers/sp_ftp.go b/internal/certmgmt/deployers/sp_ftp.go index c8aaa2326..c73f19903 100644 --- a/internal/certmgmt/deployers/sp_ftp.go +++ b/internal/certmgmt/deployers/sp_ftp.go @@ -17,19 +17,19 @@ func init() { } provider, err := ftp.NewDeployer(&ftp.DeployerConfig{ - FtpHost: credentials.Host, - FtpPort: credentials.Port, - FtpUsername: credentials.Username, - FtpPassword: credentials.Password, - OutputFormat: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "format", ftp.OUTPUT_FORMAT_PEM), - OutputKeyPath: xmaps.GetString(options.ProviderExtendedConfig, "keyPath"), - OutputCertPath: xmaps.GetString(options.ProviderExtendedConfig, "certPath"), - OutputServerCertPath: xmaps.GetString(options.ProviderExtendedConfig, "certPathForServerOnly"), - OutputIntermediaCertPath: xmaps.GetString(options.ProviderExtendedConfig, "certPathForIntermediaOnly"), - PfxPassword: xmaps.GetString(options.ProviderExtendedConfig, "pfxPassword"), - JksAlias: xmaps.GetString(options.ProviderExtendedConfig, "jksAlias"), - JksKeypass: xmaps.GetString(options.ProviderExtendedConfig, "jksKeypass"), - JksStorepass: xmaps.GetString(options.ProviderExtendedConfig, "jksStorepass"), + FtpHost: credentials.Host, + FtpPort: credentials.Port, + FtpUsername: credentials.Username, + FtpPassword: credentials.Password, + FileFormat: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "fileFormat", ftp.FILE_FORMAT_PEM), + FilePathForKey: xmaps.GetString(options.ProviderExtendedConfig, "filePathForKey"), + FilePathForCrt: xmaps.GetString(options.ProviderExtendedConfig, "filePathForCrt"), + FilePathForCrtOnlyServer: xmaps.GetString(options.ProviderExtendedConfig, "filePathForCrtOnlyServer"), + FilePathForCrtOnlyIntermedia: xmaps.GetString(options.ProviderExtendedConfig, "filePathForCrtOnlyIntermedia"), + PfxPassword: xmaps.GetString(options.ProviderExtendedConfig, "pfxPassword"), + JksAlias: xmaps.GetString(options.ProviderExtendedConfig, "jksAlias"), + JksKeypass: xmaps.GetString(options.ProviderExtendedConfig, "jksKeypass"), + JksStorepass: xmaps.GetString(options.ProviderExtendedConfig, "jksStorepass"), }) return provider, err }) diff --git a/internal/certmgmt/deployers/sp_kubernetes_secret.go b/internal/certmgmt/deployers/sp_kubernetes_secret.go index 52d9b746c..1a9b2d34e 100644 --- a/internal/certmgmt/deployers/sp_kubernetes_secret.go +++ b/internal/certmgmt/deployers/sp_kubernetes_secret.go @@ -66,8 +66,8 @@ func init() { Namespace: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "namespace", "default"), SecretName: xmaps.GetString(options.ProviderExtendedConfig, "secretName"), SecretType: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "secretType", "kubernetes.io/tls"), - SecretDataKeyForCrt: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "secretDataKeyForCrt", "tls.crt"), SecretDataKeyForKey: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "secretDataKeyForKey", "tls.key"), + SecretDataKeyForCrt: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "secretDataKeyForCrt", "tls.crt"), SecretAnnotations: secretAnnotations, SecretLabels: secretLabels, }) diff --git a/internal/certmgmt/deployers/sp_local.go b/internal/certmgmt/deployers/sp_local.go index 04294656a..f721eb511 100644 --- a/internal/certmgmt/deployers/sp_local.go +++ b/internal/certmgmt/deployers/sp_local.go @@ -10,18 +10,18 @@ import ( func init() { Registries.MustRegister(domain.DeploymentProviderTypeLocal, func(options *ProviderFactoryOptions) (core.Deployer, error) { provider, err := local.NewDeployer(&local.DeployerConfig{ - ShellEnv: xmaps.GetString(options.ProviderExtendedConfig, "shellEnv"), - PreCommand: xmaps.GetString(options.ProviderExtendedConfig, "preCommand"), - PostCommand: xmaps.GetString(options.ProviderExtendedConfig, "postCommand"), - OutputFormat: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "format", local.OUTPUT_FORMAT_PEM), - OutputCertPath: xmaps.GetString(options.ProviderExtendedConfig, "certPath"), - OutputServerCertPath: xmaps.GetString(options.ProviderExtendedConfig, "certPathForServerOnly"), - OutputIntermediaCertPath: xmaps.GetString(options.ProviderExtendedConfig, "certPathForIntermediaOnly"), - OutputKeyPath: xmaps.GetString(options.ProviderExtendedConfig, "keyPath"), - PfxPassword: xmaps.GetString(options.ProviderExtendedConfig, "pfxPassword"), - JksAlias: xmaps.GetString(options.ProviderExtendedConfig, "jksAlias"), - JksKeypass: xmaps.GetString(options.ProviderExtendedConfig, "jksKeypass"), - JksStorepass: xmaps.GetString(options.ProviderExtendedConfig, "jksStorepass"), + ShellEnv: xmaps.GetString(options.ProviderExtendedConfig, "shellEnv"), + PreCommand: xmaps.GetString(options.ProviderExtendedConfig, "preCommand"), + PostCommand: xmaps.GetString(options.ProviderExtendedConfig, "postCommand"), + FileFormat: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "fileFormat", local.FILE_FORMAT_PEM), + FilePathForKey: xmaps.GetString(options.ProviderExtendedConfig, "filePathForKey"), + FilePathForCrt: xmaps.GetString(options.ProviderExtendedConfig, "filePathForCrt"), + FilePathForCrtOnlyServer: xmaps.GetString(options.ProviderExtendedConfig, "filePathForCrtOnlyServer"), + FilePathForCrtOnlyIntermedia: xmaps.GetString(options.ProviderExtendedConfig, "filePathForCrtOnlyIntermedia"), + PfxPassword: xmaps.GetString(options.ProviderExtendedConfig, "pfxPassword"), + JksAlias: xmaps.GetString(options.ProviderExtendedConfig, "jksAlias"), + JksKeypass: xmaps.GetString(options.ProviderExtendedConfig, "jksKeypass"), + JksStorepass: xmaps.GetString(options.ProviderExtendedConfig, "jksStorepass"), }) return provider, err }) diff --git a/internal/certmgmt/deployers/sp_s3.go b/internal/certmgmt/deployers/sp_s3.go index 755100c6e..a2494f244 100644 --- a/internal/certmgmt/deployers/sp_s3.go +++ b/internal/certmgmt/deployers/sp_s3.go @@ -25,11 +25,11 @@ func init() { AllowInsecureConnections: credentials.AllowInsecureConnections, Region: xmaps.GetString(options.ProviderExtendedConfig, "region"), Bucket: xmaps.GetString(options.ProviderExtendedConfig, "bucket"), - OutputFormat: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "format", s3.OUTPUT_FORMAT_PEM), - OutputCertObjectKey: xmaps.GetString(options.ProviderExtendedConfig, "certObjectKey"), - OutputServerCertObjectKey: xmaps.GetString(options.ProviderExtendedConfig, "certObjectKeyForServerOnly"), - OutputIntermediaCertObjectKey: xmaps.GetString(options.ProviderExtendedConfig, "certObjectKeyForIntermediaOnly"), - OutputKeyObjectKey: xmaps.GetString(options.ProviderExtendedConfig, "keyObjectKey"), + FileFormat: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "fileFormat", s3.FILE_FORMAT_PEM), + ObjectKeyForKey: xmaps.GetString(options.ProviderExtendedConfig, "objectKeyForKey"), + ObjectKeyForCrt: xmaps.GetString(options.ProviderExtendedConfig, "objectKeyForCrt"), + ObjectKeyForCrtOnlyServer: xmaps.GetString(options.ProviderExtendedConfig, "objectKeyForCrtOnlyServer"), + ObjectKeyForCrtOnlyIntermedia: xmaps.GetString(options.ProviderExtendedConfig, "objectKeyForCrtOnlyIntermedia"), PfxPassword: xmaps.GetString(options.ProviderExtendedConfig, "pfxPassword"), JksAlias: xmaps.GetString(options.ProviderExtendedConfig, "jksAlias"), JksKeypass: xmaps.GetString(options.ProviderExtendedConfig, "jksKeypass"), diff --git a/internal/certmgmt/deployers/sp_ssh.go b/internal/certmgmt/deployers/sp_ssh.go index 39a3d0a5c..c82500852 100644 --- a/internal/certmgmt/deployers/sp_ssh.go +++ b/internal/certmgmt/deployers/sp_ssh.go @@ -39,19 +39,19 @@ func init() { SshKey: credentials.Key, SshKeyPassphrase: credentials.KeyPassphrase, }, - JumpServers: jumpServers, - UseSCP: xmaps.GetBool(options.ProviderExtendedConfig, "useSCP"), - PreCommand: xmaps.GetString(options.ProviderExtendedConfig, "preCommand"), - PostCommand: xmaps.GetString(options.ProviderExtendedConfig, "postCommand"), - OutputFormat: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "format", ssh.OUTPUT_FORMAT_PEM), - OutputKeyPath: xmaps.GetString(options.ProviderExtendedConfig, "keyPath"), - OutputCertPath: xmaps.GetString(options.ProviderExtendedConfig, "certPath"), - OutputServerCertPath: xmaps.GetString(options.ProviderExtendedConfig, "certPathForServerOnly"), - OutputIntermediaCertPath: xmaps.GetString(options.ProviderExtendedConfig, "certPathForIntermediaOnly"), - PfxPassword: xmaps.GetString(options.ProviderExtendedConfig, "pfxPassword"), - JksAlias: xmaps.GetString(options.ProviderExtendedConfig, "jksAlias"), - JksKeypass: xmaps.GetString(options.ProviderExtendedConfig, "jksKeypass"), - JksStorepass: xmaps.GetString(options.ProviderExtendedConfig, "jksStorepass"), + JumpServers: jumpServers, + UseSCP: xmaps.GetBool(options.ProviderExtendedConfig, "useSCP"), + PreCommand: xmaps.GetString(options.ProviderExtendedConfig, "preCommand"), + PostCommand: xmaps.GetString(options.ProviderExtendedConfig, "postCommand"), + FileFormat: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "fileFormat", ssh.FILE_FORMAT_PEM), + FilePathForKey: xmaps.GetString(options.ProviderExtendedConfig, "filePathForKey"), + FilePathForCrt: xmaps.GetString(options.ProviderExtendedConfig, "filePathForCrt"), + FilePathForCrtOnlyServer: xmaps.GetString(options.ProviderExtendedConfig, "filePathForCrtOnlyServer"), + FilePathForCrtOnlyIntermedia: xmaps.GetString(options.ProviderExtendedConfig, "filePathForCrtOnlyIntermedia"), + PfxPassword: xmaps.GetString(options.ProviderExtendedConfig, "pfxPassword"), + JksAlias: xmaps.GetString(options.ProviderExtendedConfig, "jksAlias"), + JksKeypass: xmaps.GetString(options.ProviderExtendedConfig, "jksKeypass"), + JksStorepass: xmaps.GetString(options.ProviderExtendedConfig, "jksStorepass"), }) return provider, err }) diff --git a/internal/domain/certificate.go b/internal/domain/certificate.go index cacf5e3f5..659d66099 100644 --- a/internal/domain/certificate.go +++ b/internal/domain/certificate.go @@ -95,7 +95,7 @@ const ( CertificateKeyAlgorithmTypeEC512 = CertificateKeyAlgorithmType("EC512") ) -func (t CertificateKeyAlgorithmType) KeyType() (certcrypto.KeyType, error) { +func (t CertificateKeyAlgorithmType) ToLegoKeyType() (certcrypto.KeyType, error) { keyTypeMap := map[CertificateKeyAlgorithmType]certcrypto.KeyType{ CertificateKeyAlgorithmTypeRSA2048: certcrypto.RSA2048, CertificateKeyAlgorithmTypeRSA3072: certcrypto.RSA3072, diff --git a/internal/tools/ftp/client.go b/internal/tools/ftp/client.go index b8d8b45ea..52930a97b 100644 --- a/internal/tools/ftp/client.go +++ b/internal/tools/ftp/client.go @@ -240,11 +240,9 @@ func (c *Client) StoreBytes(ctx context.Context, path string, data []byte) error return c.Store(ctx, path, reader, 0) } -func (c *Client) Quit(ctx context.Context) error { - _, err := wrapFuncCtx(ctx, func() (struct{}, error) { - c.cli.Logout() - return struct{}{}, c.cli.Quit() - }) +func (c *Client) Quit() error { + c.cli.Logout() + err := c.cli.Quit() if err != nil { return fmt.Errorf("ftp: failed to quit: %w", err) } diff --git a/internal/workflow/engine/executor_bizapply.go b/internal/workflow/engine/executor_bizapply.go index e2d23cc48..46493244e 100644 --- a/internal/workflow/engine/executor_bizapply.go +++ b/internal/workflow/engine/executor_bizapply.go @@ -232,7 +232,7 @@ func (ne *bizApplyNodeExecutor) checkCanSkip(execCtx *NodeExecutionContext, last func (ne *bizApplyNodeExecutor) executeObtain(execCtx *NodeExecutionContext, nodeCfg *domain.WorkflowNodeConfigForBizApply, lastCertificate *domain.Certificate) (*certacme.ObtainCertificateResponse, error) { // 读取私钥算法 // 如果复用私钥,则保持算法一致 - legoKeyType, err := domain.CertificateKeyAlgorithmType(nodeCfg.KeyAlgorithm).KeyType() + legoKeyType, err := domain.CertificateKeyAlgorithmType(nodeCfg.KeyAlgorithm).ToLegoKeyType() if err != nil { return nil, err } else { @@ -241,7 +241,7 @@ func (ne *bizApplyNodeExecutor) executeObtain(execCtx *NodeExecutionContext, nod break case BizApplyKeySourceReuse: if lastCertificate != nil { - legoKeyType, _ = lastCertificate.KeyAlgorithm.KeyType() + legoKeyType, _ = lastCertificate.KeyAlgorithm.ToLegoKeyType() } case BizApplyKeySourceCustom: privkey, err := xcert.ParsePrivateKeyFromPEM(nodeCfg.KeyContent) diff --git a/migrations/1779206400_upgrade_v0.4.23.go b/migrations/1779206400_upgrade_v0.4.23.go index 56a9a25ff..c840d5c2e 100644 --- a/migrations/1779206400_upgrade_v0.4.23.go +++ b/migrations/1779206400_upgrade_v0.4.23.go @@ -26,49 +26,59 @@ func init() { nodeCfg := node.Data.Config switch nodeCfg["provider"] { - case - "1panel", - "aliyun-alb", - "aliyun-clb", - "aliyun-ga", - "aliyun-nlb", - "apisix", - "baiducloud-appblb", - "baiducloud-blb", - "baishan-cdn", - "cdnfly", - "cpanel", - "ctcccloud-elb", - "flexcdn", - "goedge", - "huaweicloud-apig", - "huaweicloud-elb", - "huaweicloud-waf", - "jdcloud-alb", - "kong", - "ksyun-cdn", - "ksyun-slb", - "lecdn", - "netlify", - "nginxproxymanager", - "ratpanel", - "safeline", - "samwaf", - "tencentcloud-clb", - "tencentcloud-gaap", - "ucloud-uclb", - "volcengine-alb", - "volcengine-clb", - "zenlayer-cdn", - "zenlayer-ga": + case "1panel", "aliyun-alb", "aliyun-clb", "aliyun-ga", "aliyun-nlb", "apisix", "baiducloud-appblb", "baiducloud-blb", "baishan-cdn", "cdnfly", "cpanel", "ctcccloud-elb", "flexcdn", "goedge", "huaweicloud-apig", "huaweicloud-elb", "huaweicloud-waf", "jdcloud-alb", "kong", "ksyun-cdn", "ksyun-slb", "lecdn", "netlify", "nginxproxymanager", "ratpanel", "safeline", "samwaf", "tencentcloud-clb", "tencentcloud-gaap", "ucloud-uclb", "volcengine-alb", "volcengine-clb", "zenlayer-cdn", "zenlayer-ga": { if providerCfg, ok := nodeCfg["providerConfig"].(map[string]any); ok { - providerCfg["deployTarget"] = providerCfg["resourceType"] - delete(providerCfg, "resourceType") - nodeCfg["providerConfig"] = providerCfg + if providerCfg["resourceType"] != nil && providerCfg["resourceType"].(string) != "" { + providerCfg["deployTarget"] = providerCfg["resourceType"] + delete(providerCfg, "resourceType") + nodeCfg["providerConfig"] = providerCfg - _changed = true - return + _changed = true + return + } + } + } + case "ftp", "local", "ssh": + { + if providerCfg, ok := nodeCfg["providerConfig"].(map[string]any); ok { + if providerCfg["format"] != nil && providerCfg["format"].(string) != "" { + providerCfg["fileFormat"] = providerCfg["format"] + providerCfg["filePathForKey"] = providerCfg["keyPath"] + providerCfg["filePathForCrt"] = providerCfg["certPath"] + providerCfg["filePathForCrtOnlyServer"] = providerCfg["certPathForServerOnly"] + providerCfg["filePathForCrtOnlyIntermedia"] = providerCfg["certPathForIntermediaOnly"] + delete(providerCfg, "format") + delete(providerCfg, "keyPath") + delete(providerCfg, "certPath") + delete(providerCfg, "certPathForServerOnly") + delete(providerCfg, "certPathForIntermediaOnly") + nodeCfg["providerConfig"] = providerCfg + + _changed = true + return + } + } + } + case "s3": + { + if providerCfg, ok := nodeCfg["providerConfig"].(map[string]any); ok { + if providerCfg["format"] != nil && providerCfg["format"].(string) != "" { + providerCfg["fileFormat"] = providerCfg["format"] + providerCfg["objectKeyForKey"] = providerCfg["keyObjectKey"] + providerCfg["objectKeyForCrt"] = providerCfg["certObjectKey"] + providerCfg["objectKeyForCrtOnlyServer"] = providerCfg["certObjectKeyForServerOnly"] + providerCfg["objectKeyForCrtOnlyIntermedia"] = providerCfg["certObjectKeyForIntermediaOnly"] + delete(providerCfg, "format") + delete(providerCfg, "keyObjectKey") + delete(providerCfg, "certObjectKey") + delete(providerCfg, "certObjectKeyForServerOnly") + delete(providerCfg, "certObjectKeyForIntermediaOnly") + nodeCfg["providerConfig"] = providerCfg + + _changed = true + return + } } } } diff --git a/pkg/core/certifier/challengers/http01/ftp/ftp.go b/pkg/core/certifier/challengers/http01/ftp/ftp.go index b94809e29..b1f743722 100644 --- a/pkg/core/certifier/challengers/http01/ftp/ftp.go +++ b/pkg/core/certifier/challengers/http01/ftp/ftp.go @@ -46,7 +46,7 @@ func (p *provider) Present(domain, token, keyAuth string) error { return fmt.Errorf("ftp: failed to create FTP client: %w", err) } - defer client.Quit(ctx) + defer client.Quit() challengePath := filepath.Join(p.config.WebRootPath, http01.ChallengePath(token)) challengeDir := filepath.Dir(challengePath) @@ -72,7 +72,7 @@ func (p *provider) CleanUp(domain, token, keyAuth string) error { return fmt.Errorf("ftp: failed to create FTP client: %w", err) } - defer client.Quit(ctx) + defer client.Quit() challengePath := filepath.Join(p.config.WebRootPath, http01.ChallengePath(token)) challengeDir := filepath.Dir(challengePath) diff --git a/pkg/core/deployer/providers/ftp/consts.go b/pkg/core/deployer/providers/ftp/consts.go index 5c529b343..ba4a439de 100644 --- a/pkg/core/deployer/providers/ftp/consts.go +++ b/pkg/core/deployer/providers/ftp/consts.go @@ -5,7 +5,7 @@ import ( ) const ( - OUTPUT_FORMAT_PEM = string(domain.CertificateFormatTypePEM) - OUTPUT_FORMAT_PFX = string(domain.CertificateFormatTypePFX) - OUTPUT_FORMAT_JKS = string(domain.CertificateFormatTypeJKS) + FILE_FORMAT_PEM = string(domain.CertificateFormatTypePEM) + FILE_FORMAT_PFX = string(domain.CertificateFormatTypePFX) + FILE_FORMAT_JKS = string(domain.CertificateFormatTypeJKS) ) diff --git a/pkg/core/deployer/providers/ftp/ftp.go b/pkg/core/deployer/providers/ftp/ftp.go index ee384e442..d862f3fd6 100644 --- a/pkg/core/deployer/providers/ftp/ftp.go +++ b/pkg/core/deployer/providers/ftp/ftp.go @@ -21,29 +21,29 @@ type DeployerConfig struct { FtpUsername string `json:"ftpUsername,omitempty"` // FTP 登录密码。 FtpPassword string `json:"ftpPassword,omitempty"` - // 输出证书格式。 - OutputFormat string `json:"outputFormat,omitempty"` - // 输出私钥文件路径。 - OutputKeyPath string `json:"outputKeyPath,omitempty"` - // 输出证书文件路径。 - OutputCertPath string `json:"outputCertPath,omitempty"` - // 输出服务器证书文件路径。 + // 证书格式。 + FileFormat string `json:"fileFormat"` + // 私钥文件路径。 + FilePathForKey string `json:"filePathForKey,omitempty"` + // 证书文件路径。 + FilePathForCrt string `json:"filePathForCrt,omitempty"` + // 证书文件(仅含服务器证书)路径。 // 选填。 - OutputServerCertPath string `json:"outputServerCertPath,omitempty"` - // 输出中间证书文件路径。 + FilePathForCrtOnlyServer string `json:"filePathForCrtOnlyServer,omitempty"` + // 证书文件(仅含中间证书)路径。 // 选填。 - OutputIntermediaCertPath string `json:"outputIntermediaCertPath,omitempty"` + FilePathForCrtOnlyIntermedia string `json:"filePathForCrtOnlyIntermedia,omitempty"` // PFX 导出密码。 - // 证书格式为 PFX 时必填。 + // 证书格式为 [FILE_FORMAT_PFX] 时必填。 PfxPassword string `json:"pfxPassword,omitempty"` // JKS 别名。 - // 证书格式为 JKS 时必填。 + // 证书格式为 [FILE_FORMAT_JKS] 时必填。 JksAlias string `json:"jksAlias,omitempty"` // JKS 密钥密码。 - // 证书格式为 JKS 时必填。 + // 证书格式为 [FILE_FORMAT_JKS] 时必填。 JksKeypass string `json:"jksKeypass,omitempty"` // JKS 存储密码。 - // 证书格式为 JKS 时必填。 + // 证书格式为 [FILE_FORMAT_JKS] 时必填。 JksStorepass string `json:"jksStorepass,omitempty"` } @@ -80,117 +80,131 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep return nil, fmt.Errorf("failed to extract certs: %w", err) } - client, err := createFtpClient(*d.config) + // 连接到 FTP + ftpClient, err := createFtpClient(*d.config) if err != nil { - return nil, fmt.Errorf("ftp: failed to create FTP client: %w", err) + return nil, fmt.Errorf("failed to create FTP client: %w", err) } - + defer ftpClient.Quit() d.logger.Info("ftp connected") - defer client.Quit(context.Background()) // 上传证书和私钥文件 - switch d.config.OutputFormat { - case OUTPUT_FORMAT_PEM: + switch d.config.FileFormat { + case FILE_FORMAT_PEM: { - if d.config.OutputKeyPath != "" { - if err := client.MkdirAll(ctx, filepath.Dir(d.config.OutputKeyPath)); err != nil { + if d.config.FilePathForKey != "" { + if err := ftpClient.MkdirAll(ctx, filepath.Dir(d.config.FilePathForKey)); err != nil { return nil, fmt.Errorf("failed to upload private key file: %w", err) } - if err := client.ChangeDir(ctx, filepath.Dir(d.config.OutputKeyPath)); err != nil { + if err := ftpClient.ChangeDir(ctx, filepath.Dir(d.config.FilePathForKey)); err != nil { return nil, fmt.Errorf("failed to upload private key file: %w", err) } - if err := client.StoreString(ctx, filepath.Base(d.config.OutputKeyPath), privkeyPEM); err != nil { + if err := ftpClient.StoreString(ctx, filepath.Base(d.config.FilePathForKey), privkeyPEM); err != nil { return nil, fmt.Errorf("failed to upload private key file: %w", err) } - d.logger.Info("ssl private key file uploaded", slog.String("path", d.config.OutputKeyPath)) + d.logger.Info("ssl private key file uploaded", slog.String("path", d.config.FilePathForKey)) } - if d.config.OutputCertPath != "" { - if err := client.MkdirAll(ctx, filepath.Dir(d.config.OutputCertPath)); err != nil { + if d.config.FilePathForCrt != "" { + if err := ftpClient.MkdirAll(ctx, filepath.Dir(d.config.FilePathForCrt)); err != nil { return nil, fmt.Errorf("failed to upload certificate file: %w", err) } - if err := client.ChangeDir(ctx, filepath.Dir(d.config.OutputCertPath)); err != nil { + if err := ftpClient.ChangeDir(ctx, filepath.Dir(d.config.FilePathForCrt)); err != nil { return nil, fmt.Errorf("failed to upload certificate file: %w", err) } - if err := client.StoreString(ctx, filepath.Base(d.config.OutputCertPath), certPEM); err != nil { + if err := ftpClient.StoreString(ctx, filepath.Base(d.config.FilePathForCrt), certPEM); err != nil { return nil, fmt.Errorf("failed to upload certificate file: %w", err) } - d.logger.Info("ssl certificate file uploaded", slog.String("path", d.config.OutputCertPath)) + d.logger.Info("ssl certificate file uploaded", slog.String("path", d.config.FilePathForCrt)) } - if d.config.OutputServerCertPath != "" { - if err := client.MkdirAll(ctx, filepath.Dir(d.config.OutputServerCertPath)); err != nil { + if d.config.FilePathForCrtOnlyServer != "" { + if err := ftpClient.MkdirAll(ctx, filepath.Dir(d.config.FilePathForCrtOnlyServer)); err != nil { return nil, fmt.Errorf("failed to upload server certificate file: %w", err) } - if err := client.ChangeDir(ctx, filepath.Dir(d.config.OutputServerCertPath)); err != nil { + if err := ftpClient.ChangeDir(ctx, filepath.Dir(d.config.FilePathForCrtOnlyServer)); err != nil { return nil, fmt.Errorf("failed to upload server certificate file: %w", err) } - if err := client.StoreString(ctx, filepath.Base(d.config.OutputServerCertPath), serverCertPEM); err != nil { + if err := ftpClient.StoreString(ctx, filepath.Base(d.config.FilePathForCrtOnlyServer), serverCertPEM); err != nil { return nil, fmt.Errorf("failed to upload server certificate file: %w", err) } - d.logger.Info("ssl server certificate file uploaded", slog.String("path", d.config.OutputServerCertPath)) + d.logger.Info("ssl server certificate file uploaded", slog.String("path", d.config.FilePathForCrtOnlyServer)) } - if d.config.OutputIntermediaCertPath != "" { - if err := client.MkdirAll(ctx, filepath.Dir(d.config.OutputIntermediaCertPath)); err != nil { + if d.config.FilePathForCrtOnlyIntermedia != "" { + if err := ftpClient.MkdirAll(ctx, filepath.Dir(d.config.FilePathForCrtOnlyIntermedia)); err != nil { return nil, fmt.Errorf("failed to upload intermedia certificate file: %w", err) } - if err := client.ChangeDir(ctx, filepath.Dir(d.config.OutputIntermediaCertPath)); err != nil { + if err := ftpClient.ChangeDir(ctx, filepath.Dir(d.config.FilePathForCrtOnlyIntermedia)); err != nil { return nil, fmt.Errorf("failed to upload intermedia certificate file: %w", err) } - if err := client.StoreString(ctx, filepath.Base(d.config.OutputIntermediaCertPath), intermediaCertPEM); err != nil { + if err := ftpClient.StoreString(ctx, filepath.Base(d.config.FilePathForCrtOnlyIntermedia), intermediaCertPEM); err != nil { return nil, fmt.Errorf("failed to upload intermedia certificate file: %w", err) } - d.logger.Info("ssl intermedia certificate file uploaded", slog.String("path", d.config.OutputIntermediaCertPath)) + d.logger.Info("ssl intermedia certificate file uploaded", slog.String("path", d.config.FilePathForCrtOnlyIntermedia)) } } - case OUTPUT_FORMAT_PFX: + case FILE_FORMAT_PFX: { + if d.config.PfxPassword == "" { + return nil, fmt.Errorf("config `pfxPassword` is required") + } + pfxData, err := xcert.TransformCertificateFromPEMToPFX(certPEM, privkeyPEM, d.config.PfxPassword) if err != nil { return nil, fmt.Errorf("failed to transform certificate to PFX: %w", err) } d.logger.Info("ssl certificate transformed to pfx") - if d.config.OutputCertPath != "" { - if err := client.MkdirAll(ctx, filepath.Dir(d.config.OutputCertPath)); err != nil { + if d.config.FilePathForCrt != "" { + if err := ftpClient.MkdirAll(ctx, filepath.Dir(d.config.FilePathForCrt)); err != nil { return nil, fmt.Errorf("failed to upload certificate file: %w", err) } - if err := client.ChangeDir(ctx, filepath.Dir(d.config.OutputCertPath)); err != nil { + if err := ftpClient.ChangeDir(ctx, filepath.Dir(d.config.FilePathForCrt)); err != nil { return nil, fmt.Errorf("failed to upload certificate file: %w", err) } - if err := client.StoreBytes(ctx, filepath.Base(d.config.OutputCertPath), pfxData); err != nil { + if err := ftpClient.StoreBytes(ctx, filepath.Base(d.config.FilePathForCrt), pfxData); err != nil { return nil, fmt.Errorf("failed to upload certificate file: %w", err) } - d.logger.Info("ssl certificate file uploaded", slog.String("path", d.config.OutputCertPath)) + d.logger.Info("ssl certificate file uploaded", slog.String("path", d.config.FilePathForCrt)) } } - case OUTPUT_FORMAT_JKS: + case FILE_FORMAT_JKS: { + if d.config.JksAlias == "" { + return nil, fmt.Errorf("config `jksAlias` is required") + } + if d.config.JksKeypass == "" { + return nil, fmt.Errorf("config `jksKeypass` is required") + } + if d.config.JksStorepass == "" { + return nil, fmt.Errorf("config `jksStorepass` is required") + } + jksData, err := xcert.TransformCertificateFromPEMToJKS(certPEM, privkeyPEM, d.config.JksAlias, d.config.JksKeypass, d.config.JksStorepass) if err != nil { return nil, fmt.Errorf("failed to transform certificate to JKS: %w", err) } d.logger.Info("ssl certificate transformed to jks") - if d.config.OutputCertPath != "" { - if err := client.MkdirAll(ctx, filepath.Dir(d.config.OutputCertPath)); err != nil { + if d.config.FilePathForCrt != "" { + if err := ftpClient.MkdirAll(ctx, filepath.Dir(d.config.FilePathForCrt)); err != nil { return nil, fmt.Errorf("failed to upload certificate file: %w", err) } - if err := client.ChangeDir(ctx, filepath.Dir(d.config.OutputCertPath)); err != nil { + if err := ftpClient.ChangeDir(ctx, filepath.Dir(d.config.FilePathForCrt)); err != nil { return nil, fmt.Errorf("failed to upload certificate file: %w", err) } - if err := client.StoreBytes(ctx, filepath.Base(d.config.OutputCertPath), jksData); err != nil { + if err := ftpClient.StoreBytes(ctx, filepath.Base(d.config.FilePathForCrt), jksData); err != nil { return nil, fmt.Errorf("failed to upload certificate file: %w", err) } - d.logger.Info("ssl certificate file uploaded", slog.String("path", d.config.OutputCertPath)) + d.logger.Info("ssl certificate file uploaded", slog.String("path", d.config.FilePathForCrt)) } } default: - return nil, fmt.Errorf("unsupported output format '%s'", d.config.OutputFormat) + return nil, fmt.Errorf("unsupported file format '%s'", d.config.FileFormat) } return &deployer.DeployResult{}, nil diff --git a/pkg/core/deployer/providers/ftp/ftp_test.go b/pkg/core/deployer/providers/ftp/ftp_test.go index 13190a224..df56a92a8 100644 --- a/pkg/core/deployer/providers/ftp/ftp_test.go +++ b/pkg/core/deployer/providers/ftp/ftp_test.go @@ -15,8 +15,8 @@ var ( fFtpPort int64 fFtpUsername string fFtpPassword string - fOutputCertPath string - fOutputKeyPath string + fFilePathForCrt string + fFilePathForKey string ) func init() { @@ -26,8 +26,8 @@ func init() { fp.DefineInt64(&fFtpPort, "FTPPORT") fp.DefineString(&fFtpUsername, "FTPUSERNAME") fp.DefineString(&fFtpPassword, "FTPPASSWORD") - fp.DefineString(&fOutputCertPath, "OUTPUTCERTPATH") - fp.DefineString(&fOutputKeyPath, "OUTPUTKEYPATH") + fp.DefineString(&fFilePathForCrt, "OUTPUTCERTPATH") + fp.DefineString(&fFilePathForKey, "OUTPUTKEYPATH") } /* @@ -52,9 +52,9 @@ func TestProvider(t *testing.T) { FtpPort: int32(fFtpPort), FtpUsername: fFtpUsername, FtpPassword: fFtpPassword, - OutputFormat: impl.OUTPUT_FORMAT_PEM, - OutputCertPath: fOutputCertPath + ".pem", - OutputKeyPath: fOutputKeyPath + ".pem", + FileFormat: impl.FILE_FORMAT_PEM, + FilePathForCrt: fFilePathForCrt + ".pem", + FilePathForKey: fFilePathForKey + ".pem", }) if err != nil { t.Errorf("err: %+v", err) diff --git a/pkg/core/deployer/providers/k8s-secret/k8s_secret.go b/pkg/core/deployer/providers/k8s-secret/k8s_secret.go index 93e23f75c..55755a643 100644 --- a/pkg/core/deployer/providers/k8s-secret/k8s_secret.go +++ b/pkg/core/deployer/providers/k8s-secret/k8s_secret.go @@ -26,10 +26,10 @@ type DeployerConfig struct { SecretName string `json:"secretName"` // Kubernetes Secret 类型。 SecretType string `json:"secretType"` - // Kubernetes Secret 中用于存放证书的 Key。 - SecretDataKeyForCrt string `json:"secretDataKeyForCrt,omitempty"` - // Kubernetes Secret 中用于存放私钥的 Key。 + // Kubernetes Secret 中用于存放私钥的键。 SecretDataKeyForKey string `json:"secretDataKeyForKey,omitempty"` + // Kubernetes Secret 中用于存放证书的键。 + SecretDataKeyForCrt string `json:"secretDataKeyForCrt,omitempty"` // Kubernetes Secret 注解。 SecretAnnotations map[string]string `json:"secretAnnotations,omitempty"` // Kubernetes Secret 标签。 @@ -72,12 +72,6 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep if d.config.SecretType == "" { return nil, fmt.Errorf("config `secretType` is required") } - if d.config.SecretDataKeyForCrt == "" { - return nil, fmt.Errorf("config `secretDataKeyForCrt` is required") - } - if d.config.SecretDataKeyForKey == "" { - return nil, fmt.Errorf("config `secretDataKeyForKey` is required") - } certX509, err := xcert.ParseCertificateFromPEM(certPEM) if err != nil { @@ -130,8 +124,12 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep Type: k8score.SecretType(d.config.SecretType), } secretPayload.Data = make(map[string][]byte) - secretPayload.Data[d.config.SecretDataKeyForCrt] = []byte(certPEM) - secretPayload.Data[d.config.SecretDataKeyForKey] = []byte(privkeyPEM) + if d.config.SecretDataKeyForKey != "" { + secretPayload.Data[d.config.SecretDataKeyForKey] = []byte(privkeyPEM) + } + if d.config.SecretDataKeyForCrt != "" { + secretPayload.Data[d.config.SecretDataKeyForCrt] = []byte(certPEM) + } secretPayload, err = client.Secrets(d.config.Namespace).Create(ctx, secretPayload, meta.CreateOptions{}) d.logger.Debug("kubernetes operate 'Secrets.Create'", slog.String("namespace", d.config.Namespace), slog.Any("secret", secretPayload)) @@ -161,8 +159,12 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep if secretPayload.Data == nil { secretPayload.Data = make(map[string][]byte) } - secretPayload.Data[d.config.SecretDataKeyForCrt] = []byte(certPEM) - secretPayload.Data[d.config.SecretDataKeyForKey] = []byte(privkeyPEM) + if d.config.SecretDataKeyForKey != "" { + secretPayload.Data[d.config.SecretDataKeyForKey] = []byte(privkeyPEM) + } + if d.config.SecretDataKeyForCrt != "" { + secretPayload.Data[d.config.SecretDataKeyForCrt] = []byte(certPEM) + } secretPayload, err = client.Secrets(d.config.Namespace).Update(ctx, secretPayload, meta.UpdateOptions{}) d.logger.Debug("kubernetes operate 'Secrets.Update'", slog.String("namespace", d.config.Namespace), slog.Any("secret", secretPayload)) if err != nil { diff --git a/pkg/core/deployer/providers/local/consts.go b/pkg/core/deployer/providers/local/consts.go index 0d0ab86ef..d3c3cdae0 100644 --- a/pkg/core/deployer/providers/local/consts.go +++ b/pkg/core/deployer/providers/local/consts.go @@ -11,7 +11,7 @@ const ( ) const ( - OUTPUT_FORMAT_PEM = string(domain.CertificateFormatTypePEM) - OUTPUT_FORMAT_PFX = string(domain.CertificateFormatTypePFX) - OUTPUT_FORMAT_JKS = string(domain.CertificateFormatTypeJKS) + FILE_FORMAT_PEM = string(domain.CertificateFormatTypePEM) + FILE_FORMAT_PFX = string(domain.CertificateFormatTypePFX) + FILE_FORMAT_JKS = string(domain.CertificateFormatTypeJKS) ) diff --git a/pkg/core/deployer/providers/local/local.go b/pkg/core/deployer/providers/local/local.go index d91d55630..9052ef99b 100644 --- a/pkg/core/deployer/providers/local/local.go +++ b/pkg/core/deployer/providers/local/local.go @@ -22,29 +22,29 @@ type DeployerConfig struct { PreCommand string `json:"preCommand,omitempty"` // 后置命令。 PostCommand string `json:"postCommand,omitempty"` - // 输出证书格式。 - OutputFormat string `json:"outputFormat,omitempty"` - // 输出证书文件路径。 - OutputCertPath string `json:"outputCertPath,omitempty"` - // 输出服务器证书文件路径。 + // 证书格式。 + FileFormat string `json:"fileFormat"` + // 私钥文件路径。 + FilePathForKey string `json:"filePathForKey,omitempty"` + // 证书文件路径。 + FilePathForCrt string `json:"filePathForCrt,omitempty"` + // 证书文件(仅含服务器证书)路径。 // 选填。 - OutputServerCertPath string `json:"outputServerCertPath,omitempty"` - // 输出中间证书文件路径。 + FilePathForCrtOnlyServer string `json:"filePathForCrtOnlyServer,omitempty"` + // 证书文件(仅含中间证书)路径。 // 选填。 - OutputIntermediaCertPath string `json:"outputIntermediaCertPath,omitempty"` - // 输出私钥文件路径。 - OutputKeyPath string `json:"outputKeyPath,omitempty"` + FilePathForCrtOnlyIntermedia string `json:"filePathForCrtOnlyIntermedia,omitempty"` // PFX 导出密码。 - // 证书格式为 PFX 时必填。 + // 证书格式为 [FILE_FORMAT_PFX] 时必填。 PfxPassword string `json:"pfxPassword,omitempty"` // JKS 别名。 - // 证书格式为 JKS 时必填。 + // 证书格式为 [FILE_FORMAT_JKS] 时必填。 JksAlias string `json:"jksAlias,omitempty"` // JKS 密钥密码。 - // 证书格式为 JKS 时必填。 + // 证书格式为 [FILE_FORMAT_JKS] 时必填。 JksKeypass string `json:"jksKeypass,omitempty"` // JKS 存储密码。 - // 证书格式为 JKS 时必填。 + // 证书格式为 [FILE_FORMAT_JKS] 时必填。 JksStorepass string `json:"jksStorepass,omitempty"` } @@ -84,10 +84,10 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep // 执行前置命令 if d.config.PreCommand != "" { command := d.config.PreCommand - command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_PATH}", d.config.OutputCertPath) - command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_SERVER_PATH}", d.config.OutputServerCertPath) - command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_INTERMEDIA_PATH}", d.config.OutputIntermediaCertPath) - command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_PRIVATEKEY_PATH}", d.config.OutputKeyPath) + command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_PATH}", d.config.FilePathForCrt) + command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_SERVER_PATH}", d.config.FilePathForCrtOnlyServer) + command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_INTERMEDIA_PATH}", d.config.FilePathForCrtOnlyIntermedia) + command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_PRIVATEKEY_PATH}", d.config.FilePathForKey) command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_PFX_PASSWORD}", d.config.PfxPassword) command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_JKS_ALIAS}", d.config.JksAlias) command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_JKS_KEYPASS}", d.config.JksKeypass) @@ -101,81 +101,95 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep } // 写入证书和私钥文件 - switch d.config.OutputFormat { - case OUTPUT_FORMAT_PEM: + switch d.config.FileFormat { + case FILE_FORMAT_PEM: { - if d.config.OutputKeyPath != "" { - if err := xfile.WriteString(d.config.OutputKeyPath, privkeyPEM); err != nil { + if d.config.FilePathForKey != "" { + if err := xfile.WriteString(d.config.FilePathForKey, privkeyPEM); err != nil { return nil, fmt.Errorf("failed to save private key file: %w", err) } - d.logger.Info("ssl private key file saved", slog.String("path", d.config.OutputKeyPath)) + d.logger.Info("ssl private key file saved", slog.String("path", d.config.FilePathForKey)) } - if d.config.OutputCertPath != "" { - if err := xfile.WriteString(d.config.OutputCertPath, certPEM); err != nil { + if d.config.FilePathForCrt != "" { + if err := xfile.WriteString(d.config.FilePathForCrt, certPEM); err != nil { return nil, fmt.Errorf("failed to save certificate file: %w", err) } - d.logger.Info("ssl certificate file saved", slog.String("path", d.config.OutputCertPath)) + d.logger.Info("ssl certificate file saved", slog.String("path", d.config.FilePathForCrt)) } - if d.config.OutputServerCertPath != "" { - if err := xfile.WriteString(d.config.OutputServerCertPath, serverCertPEM); err != nil { + if d.config.FilePathForCrtOnlyServer != "" { + if err := xfile.WriteString(d.config.FilePathForCrtOnlyServer, serverCertPEM); err != nil { return nil, fmt.Errorf("failed to save server certificate file: %w", err) } - d.logger.Info("ssl server certificate file saved", slog.String("path", d.config.OutputServerCertPath)) + d.logger.Info("ssl server certificate file saved", slog.String("path", d.config.FilePathForCrtOnlyServer)) } - if d.config.OutputIntermediaCertPath != "" { - if err := xfile.WriteString(d.config.OutputIntermediaCertPath, intermediaCertPEM); err != nil { + if d.config.FilePathForCrtOnlyIntermedia != "" { + if err := xfile.WriteString(d.config.FilePathForCrtOnlyIntermedia, intermediaCertPEM); err != nil { return nil, fmt.Errorf("failed to save intermedia certificate file: %w", err) } - d.logger.Info("ssl intermedia certificate file saved", slog.String("path", d.config.OutputIntermediaCertPath)) + d.logger.Info("ssl intermedia certificate file saved", slog.String("path", d.config.FilePathForCrtOnlyIntermedia)) } } - case OUTPUT_FORMAT_PFX: + case FILE_FORMAT_PFX: { + if d.config.PfxPassword == "" { + return nil, fmt.Errorf("config `pfxPassword` is required") + } + pfxData, err := xcert.TransformCertificateFromPEMToPFX(certPEM, privkeyPEM, d.config.PfxPassword) if err != nil { return nil, fmt.Errorf("failed to transform certificate to PFX: %w", err) } d.logger.Info("ssl certificate transformed to pfx") - if d.config.OutputCertPath != "" { - if err := xfile.Write(d.config.OutputCertPath, pfxData); err != nil { + if d.config.FilePathForCrt != "" { + if err := xfile.Write(d.config.FilePathForCrt, pfxData); err != nil { return nil, fmt.Errorf("failed to save certificate file: %w", err) } - d.logger.Info("ssl certificate file saved", slog.String("path", d.config.OutputCertPath)) + d.logger.Info("ssl certificate file saved", slog.String("path", d.config.FilePathForCrt)) } } - case OUTPUT_FORMAT_JKS: + case FILE_FORMAT_JKS: { + if d.config.JksAlias == "" { + return nil, fmt.Errorf("config `jksAlias` is required") + } + if d.config.JksKeypass == "" { + return nil, fmt.Errorf("config `jksKeypass` is required") + } + if d.config.JksStorepass == "" { + return nil, fmt.Errorf("config `jksStorepass` is required") + } + jksData, err := xcert.TransformCertificateFromPEMToJKS(certPEM, privkeyPEM, d.config.JksAlias, d.config.JksKeypass, d.config.JksStorepass) if err != nil { return nil, fmt.Errorf("failed to transform certificate to JKS: %w", err) } d.logger.Info("ssl certificate transformed to jks") - if d.config.OutputCertPath != "" { - if err := xfile.Write(d.config.OutputCertPath, jksData); err != nil { + if d.config.FilePathForCrt != "" { + if err := xfile.Write(d.config.FilePathForCrt, jksData); err != nil { return nil, fmt.Errorf("failed to save certificate file: %w", err) } - d.logger.Info("ssl certificate file saved", slog.String("path", d.config.OutputCertPath)) + d.logger.Info("ssl certificate file saved", slog.String("path", d.config.FilePathForCrt)) } } default: - return nil, fmt.Errorf("unsupported output format '%s'", d.config.OutputFormat) + return nil, fmt.Errorf("unsupported file format '%s'", d.config.FileFormat) } // 执行后置命令 if d.config.PostCommand != "" { command := d.config.PostCommand - command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_PATH}", d.config.OutputCertPath) - command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_SERVER_PATH}", d.config.OutputServerCertPath) - command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_INTERMEDIA_PATH}", d.config.OutputIntermediaCertPath) - command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_PRIVATEKEY_PATH}", d.config.OutputKeyPath) + command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_PATH}", d.config.FilePathForCrt) + command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_SERVER_PATH}", d.config.FilePathForCrtOnlyServer) + command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_INTERMEDIA_PATH}", d.config.FilePathForCrtOnlyIntermedia) + command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_PRIVATEKEY_PATH}", d.config.FilePathForKey) command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_PFX_PASSWORD}", d.config.PfxPassword) command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_JKS_ALIAS}", d.config.JksAlias) command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_JKS_KEYPASS}", d.config.JksKeypass) diff --git a/pkg/core/deployer/providers/local/local_test.go b/pkg/core/deployer/providers/local/local_test.go index d61d438ce..e190985f9 100644 --- a/pkg/core/deployer/providers/local/local_test.go +++ b/pkg/core/deployer/providers/local/local_test.go @@ -11,8 +11,8 @@ var ( fp = tester.Args("LOCAL_") fTestCertPath string fTestKeyPath string - fOutputCertPath string - fOutputKeyPath string + fFilePathForCrt string + fFilePathForKey string fPfxPassword string fJksAlias string fJksKeypass string @@ -25,8 +25,8 @@ var ( func init() { fp.DefineString(&fTestCertPath, "TESTCERTPATH") fp.DefineString(&fTestKeyPath, "TESTKEYPATH") - fp.DefineString(&fOutputCertPath, "OUTPUTCERTPATH") - fp.DefineString(&fOutputKeyPath, "OUTPUTKEYPATH") + fp.DefineString(&fFilePathForCrt, "OUTPUTCERTPATH") + fp.DefineString(&fFilePathForKey, "OUTPUTKEYPATH") fp.DefineString(&fPfxPassword, "PFXPASSWORD") fp.DefineString(&fJksAlias, "JKSALIAS") fp.DefineString(&fJksKeypass, "JKSKEYPASS") @@ -57,9 +57,9 @@ func TestProvider(t *testing.T) { t.Run("Deploy_PEM", func(t *testing.T) { provider, err := impl.NewDeployer(&impl.DeployerConfig{ - OutputFormat: impl.OUTPUT_FORMAT_PEM, - OutputCertPath: fOutputCertPath + ".pem", - OutputKeyPath: fOutputKeyPath + ".pem", + FileFormat: impl.FILE_FORMAT_PEM, + FilePathForCrt: fFilePathForCrt + ".pem", + FilePathForKey: fFilePathForKey + ".pem", ShellEnv: fShellEnv, PreCommand: fPreCommand, PostCommand: fPostCommand, @@ -74,8 +74,8 @@ func TestProvider(t *testing.T) { t.Run("Deploy_PFX", func(t *testing.T) { provider, err := impl.NewDeployer(&impl.DeployerConfig{ - OutputFormat: impl.OUTPUT_FORMAT_PFX, - OutputCertPath: fOutputCertPath + ".pfx", + FileFormat: impl.FILE_FORMAT_PFX, + FilePathForCrt: fFilePathForCrt + ".pfx", PfxPassword: fPfxPassword, }) if err != nil { @@ -88,8 +88,8 @@ func TestProvider(t *testing.T) { t.Run("Deploy_JKS", func(t *testing.T) { provider, err := impl.NewDeployer(&impl.DeployerConfig{ - OutputFormat: impl.OUTPUT_FORMAT_JKS, - OutputCertPath: fOutputCertPath + ".jks", + FileFormat: impl.FILE_FORMAT_JKS, + FilePathForCrt: fFilePathForCrt + ".jks", JksAlias: fJksAlias, JksKeypass: fJksKeypass, JksStorepass: fJksStorepass, diff --git a/pkg/core/deployer/providers/s3/consts.go b/pkg/core/deployer/providers/s3/consts.go index 4caf33f99..b9fab2660 100644 --- a/pkg/core/deployer/providers/s3/consts.go +++ b/pkg/core/deployer/providers/s3/consts.go @@ -5,7 +5,7 @@ import ( ) const ( - OUTPUT_FORMAT_PEM = string(domain.CertificateFormatTypePEM) - OUTPUT_FORMAT_PFX = string(domain.CertificateFormatTypePFX) - OUTPUT_FORMAT_JKS = string(domain.CertificateFormatTypeJKS) + FILE_FORMAT_PEM = string(domain.CertificateFormatTypePEM) + FILE_FORMAT_PFX = string(domain.CertificateFormatTypePFX) + FILE_FORMAT_JKS = string(domain.CertificateFormatTypeJKS) ) diff --git a/pkg/core/deployer/providers/s3/s3.go b/pkg/core/deployer/providers/s3/s3.go index 481603c0c..d35ab58e8 100644 --- a/pkg/core/deployer/providers/s3/s3.go +++ b/pkg/core/deployer/providers/s3/s3.go @@ -29,36 +29,35 @@ type DeployerConfig struct { Bucket string `json:"bucket"` // 是否允许不安全的连接。 AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` - // 输出证书格式。 - OutputFormat string `json:"outputFormat,omitempty"` - // 输出证书文件路径。 - OutputCertObjectKey string `json:"outputCertObjectKey,omitempty"` - // 输出服务器证书文件路径。 + // 证书格式。 + FileFormat string `json:"fileFormat"` + // 私钥文件对象键。 + ObjectKeyForKey string `json:"objectKeyForKey,omitempty"` + // 证书文件对象键。 + ObjectKeyForCrt string `json:"objectKeyForCrt,omitempty"` + // 证书文件(仅含服务器证书)对象键。 // 选填。 - OutputServerCertObjectKey string `json:"outputServerCertObjectKey,omitempty"` - // 输出中间证书文件路径。 + ObjectKeyForCrtOnlyServer string `json:"objectKeyForCrtOnlyServer,omitempty"` + // 证书文件(仅含中间证书)对象键。 // 选填。 - OutputIntermediaCertObjectKey string `json:"outputIntermediaCertObjectKey,omitempty"` - // 输出私钥文件路径。 - OutputKeyObjectKey string `json:"outputKeyObjectKey,omitempty"` + ObjectKeyForCrtOnlyIntermedia string `json:"objectKeyForCrtOnlyIntermedia,omitempty"` // PFX 导出密码。 - // 证书格式为 PFX 时必填。 + // 证书格式为 [FILE_FORMAT_PFX] 时必填。 PfxPassword string `json:"pfxPassword,omitempty"` // JKS 别名。 - // 证书格式为 JKS 时必填。 + // 证书格式为 [FILE_FORMAT_JKS] 时必填。 JksAlias string `json:"jksAlias,omitempty"` // JKS 密钥密码。 - // 证书格式为 JKS 时必填。 + // 证书格式为 [FILE_FORMAT_JKS] 时必填。 JksKeypass string `json:"jksKeypass,omitempty"` // JKS 存储密码。 - // 证书格式为 JKS 时必填。 + // 证书格式为 [FILE_FORMAT_JKS] 时必填。 JksStorepass string `json:"jksStorepass,omitempty"` } type Deployer struct { - config *DeployerConfig - logger *slog.Logger - s3Client *s3.Client + config *DeployerConfig + logger *slog.Logger } var _ deployer.Provider = (*Deployer)(nil) @@ -68,15 +67,9 @@ func NewDeployer(config *DeployerConfig) (*Deployer, error) { return nil, fmt.Errorf("the configuration of the deployer provider is nil") } - client, err := createS3Client(*config) - if err != nil { - return nil, fmt.Errorf("s3: failed to create S3 client: %w", err) - } - return &Deployer{ - config: config, - logger: slog.Default(), - s3Client: client, + config: config, + logger: slog.Default(), }, nil } @@ -95,73 +88,93 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep return nil, fmt.Errorf("failed to extract certs: %w", err) } + // 连接到 S3 + s3Client, err := createS3Client(*d.config) + if err != nil { + return nil, fmt.Errorf("failed to create S3 client: %w", err) + } + // 写入证书和私钥文件 - switch d.config.OutputFormat { - case OUTPUT_FORMAT_PEM: + switch d.config.FileFormat { + case FILE_FORMAT_PEM: { - if d.config.OutputKeyObjectKey != "" { - if err := d.s3Client.PutObjectString(ctx, d.config.Bucket, d.config.OutputKeyObjectKey, privkeyPEM); err != nil { + if d.config.ObjectKeyForKey != "" { + if err := s3Client.PutObjectString(ctx, d.config.Bucket, d.config.ObjectKeyForKey, privkeyPEM); err != nil { return nil, fmt.Errorf("failed to upload private key file: %w", err) } - d.logger.Info("ssl private key file uploaded", slog.String("bucket", d.config.Bucket), slog.String("object", d.config.OutputKeyObjectKey)) + d.logger.Info("ssl private key file uploaded", slog.String("bucket", d.config.Bucket), slog.String("object", d.config.ObjectKeyForKey)) } - if d.config.OutputCertObjectKey != "" { - if err := d.s3Client.PutObjectString(ctx, d.config.Bucket, d.config.OutputCertObjectKey, certPEM); err != nil { + if d.config.ObjectKeyForCrt != "" { + if err := s3Client.PutObjectString(ctx, d.config.Bucket, d.config.ObjectKeyForCrt, certPEM); err != nil { return nil, fmt.Errorf("failed to upload certificate file: %w", err) } - d.logger.Info("ssl certificate file uploaded", slog.String("bucket", d.config.Bucket), slog.String("object", d.config.OutputCertObjectKey)) + d.logger.Info("ssl certificate file uploaded", slog.String("bucket", d.config.Bucket), slog.String("object", d.config.ObjectKeyForCrt)) } - if d.config.OutputServerCertObjectKey != "" { - if err := d.s3Client.PutObjectString(ctx, d.config.Bucket, d.config.OutputServerCertObjectKey, serverCertPEM); err != nil { + if d.config.ObjectKeyForCrtOnlyServer != "" { + if err := s3Client.PutObjectString(ctx, d.config.Bucket, d.config.ObjectKeyForCrtOnlyServer, serverCertPEM); err != nil { return nil, fmt.Errorf("failed to upload server certificate file: %w", err) } - d.logger.Info("ssl server certificate file uploaded", slog.String("bucket", d.config.Bucket), slog.String("object", d.config.OutputServerCertObjectKey)) + d.logger.Info("ssl server certificate file uploaded", slog.String("bucket", d.config.Bucket), slog.String("object", d.config.ObjectKeyForCrtOnlyServer)) } - if d.config.OutputIntermediaCertObjectKey != "" { - if err := d.s3Client.PutObjectString(ctx, d.config.Bucket, d.config.OutputIntermediaCertObjectKey, intermediaCertPEM); err != nil { + if d.config.ObjectKeyForCrtOnlyIntermedia != "" { + if err := s3Client.PutObjectString(ctx, d.config.Bucket, d.config.ObjectKeyForCrtOnlyIntermedia, intermediaCertPEM); err != nil { return nil, fmt.Errorf("failed to upload intermedia certificate file: %w", err) } - d.logger.Info("ssl intermedia certificate file uploaded", slog.String("bucket", d.config.Bucket), slog.String("object", d.config.OutputIntermediaCertObjectKey)) + d.logger.Info("ssl intermedia certificate file uploaded", slog.String("bucket", d.config.Bucket), slog.String("object", d.config.ObjectKeyForCrtOnlyIntermedia)) } } - case OUTPUT_FORMAT_PFX: + case FILE_FORMAT_PFX: { + if d.config.PfxPassword == "" { + return nil, fmt.Errorf("config `pfxPassword` is required") + } + pfxData, err := xcert.TransformCertificateFromPEMToPFX(certPEM, privkeyPEM, d.config.PfxPassword) if err != nil { return nil, fmt.Errorf("failed to transform certificate to PFX: %w", err) } d.logger.Info("ssl certificate transformed to pfx") - if d.config.OutputCertObjectKey != "" { - if err := d.s3Client.PutObjectBytes(ctx, d.config.Bucket, d.config.OutputCertObjectKey, pfxData); err != nil { + if d.config.ObjectKeyForCrt != "" { + if err := s3Client.PutObjectBytes(ctx, d.config.Bucket, d.config.ObjectKeyForCrt, pfxData); err != nil { return nil, fmt.Errorf("failed to upload certificate file: %w", err) } - d.logger.Info("ssl certificate file uploaded", slog.String("bucket", d.config.Bucket), slog.String("object", d.config.OutputCertObjectKey)) + d.logger.Info("ssl certificate file uploaded", slog.String("bucket", d.config.Bucket), slog.String("object", d.config.ObjectKeyForCrt)) } } - case OUTPUT_FORMAT_JKS: + case FILE_FORMAT_JKS: { + if d.config.JksAlias == "" { + return nil, fmt.Errorf("config `jksAlias` is required") + } + if d.config.JksKeypass == "" { + return nil, fmt.Errorf("config `jksKeypass` is required") + } + if d.config.JksStorepass == "" { + return nil, fmt.Errorf("config `jksStorepass` is required") + } + jksData, err := xcert.TransformCertificateFromPEMToJKS(certPEM, privkeyPEM, d.config.JksAlias, d.config.JksKeypass, d.config.JksStorepass) if err != nil { return nil, fmt.Errorf("failed to transform certificate to JKS: %w", err) } d.logger.Info("ssl certificate transformed to jks") - if d.config.OutputCertObjectKey != "" { - if err := d.s3Client.PutObjectBytes(ctx, d.config.Bucket, d.config.OutputCertObjectKey, jksData); err != nil { + if d.config.ObjectKeyForCrt != "" { + if err := s3Client.PutObjectBytes(ctx, d.config.Bucket, d.config.ObjectKeyForCrt, jksData); err != nil { return nil, fmt.Errorf("failed to upload certificate file: %w", err) } - d.logger.Info("ssl certificate file uploaded", slog.String("bucket", d.config.Bucket), slog.String("object", d.config.OutputCertObjectKey)) + d.logger.Info("ssl certificate file uploaded", slog.String("bucket", d.config.Bucket), slog.String("object", d.config.ObjectKeyForCrt)) } } default: - return nil, fmt.Errorf("unsupported output format '%s'", d.config.OutputFormat) + return nil, fmt.Errorf("unsupported file format '%s'", d.config.FileFormat) } return &deployer.DeployResult{}, nil diff --git a/pkg/core/deployer/providers/s3/s3_test.go b/pkg/core/deployer/providers/s3/s3_test.go index 5c5cd62d0..3a43a6623 100644 --- a/pkg/core/deployer/providers/s3/s3_test.go +++ b/pkg/core/deployer/providers/s3/s3_test.go @@ -16,8 +16,8 @@ var ( fSecretKey string fRegion string fBucket string - fOutputCertPath string - fOutputKeyPath string + fFilePathForCrt string + fFilePathForKey string ) func init() { @@ -28,8 +28,8 @@ func init() { fp.DefineString(&fSecretKey, "SECRETKEY") fp.DefineString(&fRegion, "REGION") fp.DefineString(&fBucket, "BUCKET") - fp.DefineString(&fOutputCertPath, "OUTPUTCERTPATH") - fp.DefineString(&fOutputKeyPath, "OUTPUTKEYPATH") + fp.DefineString(&fFilePathForCrt, "OUTPUTCERTPATH") + fp.DefineString(&fFilePathForKey, "OUTPUTKEYPATH") } /* @@ -51,14 +51,14 @@ func TestProvider(t *testing.T) { t.Run("Deploy_PEM", func(t *testing.T) { provider, err := impl.NewDeployer(&impl.DeployerConfig{ - Endpoint: fSshHost, - AccessKey: fAccessKey, - SecretKey: fSecretKey, - Region: fRegion, - Bucket: fBucket, - OutputFormat: impl.OUTPUT_FORMAT_PEM, - OutputCertObjectKey: fOutputCertPath + ".pem", - OutputKeyObjectKey: fOutputKeyPath + ".pem", + Endpoint: fSshHost, + AccessKey: fAccessKey, + SecretKey: fSecretKey, + Region: fRegion, + Bucket: fBucket, + FileFormat: impl.FILE_FORMAT_PEM, + ObjectKeyForCrt: fFilePathForCrt + ".pem", + ObjectKeyForKey: fFilePathForKey + ".pem", }) if err != nil { t.Errorf("err: %+v", err) diff --git a/pkg/core/deployer/providers/ssh/consts.go b/pkg/core/deployer/providers/ssh/consts.go index 7b7ff5b47..468e9d56a 100644 --- a/pkg/core/deployer/providers/ssh/consts.go +++ b/pkg/core/deployer/providers/ssh/consts.go @@ -5,7 +5,7 @@ import ( ) const ( - OUTPUT_FORMAT_PEM = string(domain.CertificateFormatTypePEM) - OUTPUT_FORMAT_PFX = string(domain.CertificateFormatTypePFX) - OUTPUT_FORMAT_JKS = string(domain.CertificateFormatTypeJKS) + FILE_FORMAT_PEM = string(domain.CertificateFormatTypePEM) + FILE_FORMAT_PFX = string(domain.CertificateFormatTypePFX) + FILE_FORMAT_JKS = string(domain.CertificateFormatTypeJKS) ) diff --git a/pkg/core/deployer/providers/ssh/ssh.go b/pkg/core/deployer/providers/ssh/ssh.go index 1d94350fb..ffa8cf30b 100644 --- a/pkg/core/deployer/providers/ssh/ssh.go +++ b/pkg/core/deployer/providers/ssh/ssh.go @@ -44,29 +44,29 @@ type DeployerConfig struct { PreCommand string `json:"preCommand,omitempty"` // 后置命令。 PostCommand string `json:"postCommand,omitempty"` - // 输出证书格式。 - OutputFormat string `json:"outputFormat,omitempty"` - // 输出私钥文件路径。 - OutputKeyPath string `json:"outputKeyPath,omitempty"` - // 输出证书文件路径。 - OutputCertPath string `json:"outputCertPath,omitempty"` - // 输出服务器证书文件路径。 + // 证书格式。 + FileFormat string `json:"fileFormat"` + // 私钥文件路径。 + FilePathForKey string `json:"filePathForKey,omitempty"` + // 证书文件路径。 + FilePathForCrt string `json:"filePathForCrt,omitempty"` + // 证书文件(仅含服务器证书)路径。 // 选填。 - OutputServerCertPath string `json:"outputServerCertPath,omitempty"` - // 输出中间证书文件路径。 + FilePathForCrtOnlyServer string `json:"filePathForCrtOnlyServer,omitempty"` + // 证书文件(仅含中间证书)路径。 // 选填。 - OutputIntermediaCertPath string `json:"outputIntermediaCertPath,omitempty"` + FilePathForCrtOnlyIntermedia string `json:"filePathForCrtOnlyIntermedia,omitempty"` // PFX 导出密码。 - // 证书格式为 PFX 时必填。 + // 证书格式为 [FILE_FORMAT_PFX] 时必填。 PfxPassword string `json:"pfxPassword,omitempty"` // JKS 别名。 - // 证书格式为 JKS 时必填。 + // 证书格式为 [FILE_FORMAT_JKS] 时必填。 JksAlias string `json:"jksAlias,omitempty"` // JKS 密钥密码。 - // 证书格式为 JKS 时必填。 + // 证书格式为 [FILE_FORMAT_JKS] 时必填。 JksKeypass string `json:"jksKeypass,omitempty"` // JKS 存储密码。 - // 证书格式为 JKS 时必填。 + // 证书格式为 [FILE_FORMAT_JKS] 时必填。 JksStorepass string `json:"jksStorepass,omitempty"` } @@ -103,27 +103,27 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep return nil, fmt.Errorf("failed to extract certs: %w", err) } - client, err := createSshClient(*d.config) + // 连接到 SSH + sshClient, err := createSshClient(*d.config) if err != nil { - return nil, fmt.Errorf("ssh: failed to create SSH client: %w", err) + return nil, fmt.Errorf("failed to create SSH client: %w", err) } - + defer sshClient.Close() d.logger.Info("ssh connected") - defer client.Close() // 执行前置命令 if d.config.PreCommand != "" { command := d.config.PreCommand - command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_PATH}", d.config.OutputCertPath) - command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_SERVER_PATH}", d.config.OutputServerCertPath) - command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_INTERMEDIA_PATH}", d.config.OutputIntermediaCertPath) - command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_PRIVATEKEY_PATH}", d.config.OutputKeyPath) + command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_PATH}", d.config.FilePathForCrt) + command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_SERVER_PATH}", d.config.FilePathForCrtOnlyServer) + command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_INTERMEDIA_PATH}", d.config.FilePathForCrtOnlyIntermedia) + command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_PRIVATEKEY_PATH}", d.config.FilePathForKey) command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_PFX_PASSWORD}", d.config.PfxPassword) command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_JKS_ALIAS}", d.config.JksAlias) command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_JKS_KEYPASS}", d.config.JksKeypass) command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_JKS_STOREPASS}", d.config.JksStorepass) - stdout, stderr, err := xssh.RunCommand(client.RawClient(), command) + stdout, stderr, err := xssh.RunCommand(sshClient.RawClient(), command) d.logger.Debug("run pre-command", slog.String("stdout", stdout), slog.String("stderr", stderr)) if err != nil { return nil, fmt.Errorf("failed to execute pre-command (stdout: %s, stderr: %s): %w ", stdout, stderr, err) @@ -131,39 +131,43 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep } // 上传证书和私钥文件 - switch d.config.OutputFormat { - case OUTPUT_FORMAT_PEM: + switch d.config.FileFormat { + case FILE_FORMAT_PEM: { - if d.config.OutputKeyPath != "" { - if err := xssh.WriteRemoteString(client.RawClient(), d.config.OutputKeyPath, privkeyPEM, d.config.UseSCP); err != nil { + if d.config.PfxPassword == "" { + return nil, fmt.Errorf("config `pfxPassword` is required") + } + + if d.config.FilePathForKey != "" { + if err := xssh.WriteRemoteString(sshClient.RawClient(), d.config.FilePathForKey, privkeyPEM, d.config.UseSCP); err != nil { return nil, fmt.Errorf("failed to upload private key file: %w", err) } - d.logger.Info("ssl private key file uploaded", slog.String("path", d.config.OutputKeyPath)) + d.logger.Info("ssl private key file uploaded", slog.String("path", d.config.FilePathForKey)) } - if d.config.OutputCertPath != "" { - if err := xssh.WriteRemoteString(client.RawClient(), d.config.OutputCertPath, certPEM, d.config.UseSCP); err != nil { + if d.config.FilePathForCrt != "" { + if err := xssh.WriteRemoteString(sshClient.RawClient(), d.config.FilePathForCrt, certPEM, d.config.UseSCP); err != nil { return nil, fmt.Errorf("failed to upload certificate file: %w", err) } - d.logger.Info("ssl certificate file uploaded", slog.String("path", d.config.OutputCertPath)) + d.logger.Info("ssl certificate file uploaded", slog.String("path", d.config.FilePathForCrt)) } - if d.config.OutputServerCertPath != "" { - if err := xssh.WriteRemoteString(client.RawClient(), d.config.OutputServerCertPath, serverCertPEM, d.config.UseSCP); err != nil { + if d.config.FilePathForCrtOnlyServer != "" { + if err := xssh.WriteRemoteString(sshClient.RawClient(), d.config.FilePathForCrtOnlyServer, serverCertPEM, d.config.UseSCP); err != nil { return nil, fmt.Errorf("failed to save server certificate file: %w", err) } - d.logger.Info("ssl server certificate file uploaded", slog.String("path", d.config.OutputServerCertPath)) + d.logger.Info("ssl server certificate file uploaded", slog.String("path", d.config.FilePathForCrtOnlyServer)) } - if d.config.OutputIntermediaCertPath != "" { - if err := xssh.WriteRemoteString(client.RawClient(), d.config.OutputIntermediaCertPath, intermediaCertPEM, d.config.UseSCP); err != nil { + if d.config.FilePathForCrtOnlyIntermedia != "" { + if err := xssh.WriteRemoteString(sshClient.RawClient(), d.config.FilePathForCrtOnlyIntermedia, intermediaCertPEM, d.config.UseSCP); err != nil { return nil, fmt.Errorf("failed to save intermedia certificate file: %w", err) } - d.logger.Info("ssl intermedia certificate file uploaded", slog.String("path", d.config.OutputIntermediaCertPath)) + d.logger.Info("ssl intermedia certificate file uploaded", slog.String("path", d.config.FilePathForCrtOnlyIntermedia)) } } - case OUTPUT_FORMAT_PFX: + case FILE_FORMAT_PFX: { pfxData, err := xcert.TransformCertificateFromPEMToPFX(certPEM, privkeyPEM, d.config.PfxPassword) if err != nil { @@ -171,47 +175,57 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep } d.logger.Info("ssl certificate transformed to pfx") - if d.config.OutputCertPath != "" { - if err := xssh.WriteRemote(client.RawClient(), d.config.OutputCertPath, pfxData, d.config.UseSCP); err != nil { + if d.config.FilePathForCrt != "" { + if err := xssh.WriteRemote(sshClient.RawClient(), d.config.FilePathForCrt, pfxData, d.config.UseSCP); err != nil { return nil, fmt.Errorf("failed to upload certificate file: %w", err) } - d.logger.Info("ssl certificate file uploaded", slog.String("path", d.config.OutputCertPath)) + d.logger.Info("ssl certificate file uploaded", slog.String("path", d.config.FilePathForCrt)) } } - case OUTPUT_FORMAT_JKS: + case FILE_FORMAT_JKS: { + if d.config.JksAlias == "" { + return nil, fmt.Errorf("config `jksAlias` is required") + } + if d.config.JksKeypass == "" { + return nil, fmt.Errorf("config `jksKeypass` is required") + } + if d.config.JksStorepass == "" { + return nil, fmt.Errorf("config `jksStorepass` is required") + } + jksData, err := xcert.TransformCertificateFromPEMToJKS(certPEM, privkeyPEM, d.config.JksAlias, d.config.JksKeypass, d.config.JksStorepass) if err != nil { return nil, fmt.Errorf("failed to transform certificate to JKS: %w", err) } d.logger.Info("ssl certificate transformed to jks") - if d.config.OutputCertPath != "" { - if err := xssh.WriteRemote(client.RawClient(), d.config.OutputCertPath, jksData, d.config.UseSCP); err != nil { + if d.config.FilePathForCrt != "" { + if err := xssh.WriteRemote(sshClient.RawClient(), d.config.FilePathForCrt, jksData, d.config.UseSCP); err != nil { return nil, fmt.Errorf("failed to upload certificate file: %w", err) } - d.logger.Info("ssl certificate file uploaded", slog.String("path", d.config.OutputCertPath)) + d.logger.Info("ssl certificate file uploaded", slog.String("path", d.config.FilePathForCrt)) } } default: - return nil, fmt.Errorf("unsupported output format '%s'", d.config.OutputFormat) + return nil, fmt.Errorf("unsupported file format '%s'", d.config.FileFormat) } // 执行后置命令 if d.config.PostCommand != "" { command := d.config.PostCommand - command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_PATH}", d.config.OutputCertPath) - command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_SERVER_PATH}", d.config.OutputServerCertPath) - command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_INTERMEDIA_PATH}", d.config.OutputIntermediaCertPath) - command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_PRIVATEKEY_PATH}", d.config.OutputKeyPath) + command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_PATH}", d.config.FilePathForCrt) + command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_SERVER_PATH}", d.config.FilePathForCrtOnlyServer) + command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_INTERMEDIA_PATH}", d.config.FilePathForCrtOnlyIntermedia) + command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_PRIVATEKEY_PATH}", d.config.FilePathForKey) command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_PFX_PASSWORD}", d.config.PfxPassword) command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_JKS_ALIAS}", d.config.JksAlias) command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_JKS_KEYPASS}", d.config.JksKeypass) command = strings.ReplaceAll(command, "${CERTIMATE_DEPLOYER_CMDVAR_JKS_STOREPASS}", d.config.JksStorepass) - stdout, stderr, err := xssh.RunCommand(client.RawClient(), command) + stdout, stderr, err := xssh.RunCommand(sshClient.RawClient(), command) d.logger.Debug("run post-command", slog.String("stdout", stdout), slog.String("stderr", stderr)) if err != nil { return nil, fmt.Errorf("failed to execute post-command (stdout: %s, stderr: %s): %w ", stdout, stderr, err) diff --git a/pkg/core/deployer/providers/ssh/ssh_test.go b/pkg/core/deployer/providers/ssh/ssh_test.go index cd1e02452..4123b73e9 100644 --- a/pkg/core/deployer/providers/ssh/ssh_test.go +++ b/pkg/core/deployer/providers/ssh/ssh_test.go @@ -15,8 +15,8 @@ var ( fSshPort int64 fSshUsername string fSshPassword string - fOutputCertPath string - fOutputKeyPath string + fFilePathForCrt string + fFilePathForKey string ) func init() { @@ -26,8 +26,8 @@ func init() { fp.DefineInt64(&fSshPort, "SSHPORT") fp.DefineString(&fSshUsername, "SSHUSERNAME") fp.DefineString(&fSshPassword, "SSHPASSWORD") - fp.DefineString(&fOutputCertPath, "OUTPUTCERTPATH") - fp.DefineString(&fOutputKeyPath, "OUTPUTKEYPATH") + fp.DefineString(&fFilePathForCrt, "OUTPUTCERTPATH") + fp.DefineString(&fFilePathForKey, "OUTPUTKEYPATH") } /* @@ -54,9 +54,9 @@ func TestProvider(t *testing.T) { SshUsername: fSshUsername, SshPassword: fSshPassword, }, - OutputFormat: impl.OUTPUT_FORMAT_PEM, - OutputCertPath: fOutputCertPath + ".pem", - OutputKeyPath: fOutputKeyPath + ".pem", + FileFormat: impl.FILE_FORMAT_PEM, + FilePathForCrt: fFilePathForCrt + ".pem", + FilePathForKey: fFilePathForKey + ".pem", }) if err != nil { t.Errorf("err: %+v", err) diff --git a/ui/src/components/workflow/designer/forms/BizApplyNodeConfigForm.tsx b/ui/src/components/workflow/designer/forms/BizApplyNodeConfigForm.tsx index c7f0f85e9..54e89590c 100644 --- a/ui/src/components/workflow/designer/forms/BizApplyNodeConfigForm.tsx +++ b/ui/src/components/workflow/designer/forms/BizApplyNodeConfigForm.tsx @@ -262,7 +262,7 @@ const BizApplyNodeConfigForm = ({ node, ...props }: BizApplyNodeConfigFormProps) }; const handleProviderSelect = (value?: string | undefined) => { - // 切换质询提供商时重置表单,避免其他提供商的配置字段影响当前提供商 + // 切换质询提供商时重置表单,避免其他提供商的配置字段残留 if (initialValues?.provider === value) { formInst.setFieldValue("providerAccessId", void 0); formInst.resetFields(["providerConfig"]); diff --git a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderFTP.tsx b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderFTP.tsx index f23357511..5718438d5 100644 --- a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderFTP.tsx +++ b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderFTP.tsx @@ -6,10 +6,9 @@ import { z } from "zod"; import Show from "@/components/Show"; import { CERTIFICATE_FORMATS } from "@/domain/certificate"; -import { randomString } from "@/utils/random"; import { useFormNestedFieldsContext } from "./_context"; -import { initPresetScript as _initPresetScript } from "./BizDeployNodeConfigFieldsProviderLocal"; +import { useSharedFormFieldsAndHandlers as _useSharedFormFieldsAndHandlers } from "./BizDeployNodeConfigFieldsProviderLocal"; const FORMAT_PEM = CERTIFICATE_FORMATS.PEM; const FORMAT_PFX = CERTIFICATE_FORMATS.PFX; @@ -26,125 +25,86 @@ const BizDeployNodeConfigFieldsProviderFTP = () => { const formInst = Form.useFormInstance(); const initialValues = getInitialValues(); - const fieldFormat = Form.useWatch([parentNamePath, "format"], formInst); - const fieldCertPath = Form.useWatch([parentNamePath, "certPath"], formInst); - - const handleFormatSelect = (value: string) => { - if (fieldFormat === value) return; - - switch (value) { - case FORMAT_PEM: - { - if (/(.pfx|.jks)$/.test(fieldCertPath)) { - formInst.setFieldValue([parentNamePath, "certPath"], fieldCertPath.replace(/(.pfx|.jks)$/, ".crt")); - } - } - break; - - case FORMAT_PFX: - { - if (/(.crt|.jks)$/.test(fieldCertPath)) { - formInst.setFieldValue([parentNamePath, "certPath"], fieldCertPath.replace(/(.crt|.jks)$/, ".pfx")); - } - } - break; - - case FORMAT_JKS: - { - if (/(.crt|.pfx)$/.test(fieldCertPath)) { - formInst.setFieldValue([parentNamePath, "certPath"], fieldCertPath.replace(/(.crt|.pfx)$/, ".jks")); - } - } - break; - } - }; - - const handleRandomPfxPasswordClick = () => { - const password = randomString(); - formInst.setFieldValue([parentNamePath, "pfxPassword"], password); - }; - - const handleRandomJksKeypassClick = () => { - const password = randomString(); - formInst.setFieldValue([parentNamePath, "jksKeypass"], password); - }; - - const handleRandomJksStorepassClick = () => { - const password = randomString(); - formInst.setFieldValue([parentNamePath, "jksStorepass"], password); - }; + const { + fieldFormat: fieldFileFormat, + handleChangeFormat: handleFileFormatSelect, + handleRandomPfxPassword: handleRandomPfxPasswordClick, + handleRandomJksAlias: handleRandomJksAliasClick, + handleRandomJksKeypass: handleRandomJksKeypassClick, + handleRandomJksStorepass: handleRandomJksStorepassClick, + } = _useSharedFormFieldsAndHandlers(formInst, {}); return ( <>