refactor: rename OutputFormat to FileFormat, OutputKeyPath to FilePathForKey, OutputCertPath to FilePathForCrt

This commit is contained in:
Fu Diwei
2026-05-20 11:45:37 +08:00
committed by RHQYZ
parent f0b1e45669
commit a3dc0b1552
32 changed files with 941 additions and 1243 deletions
+13 -13
View File
@@ -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
})
@@ -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,
})
+12 -12
View File
@@ -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
})
+5 -5
View File
@@ -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"),
+13 -13
View File
@@ -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
})
+1 -1
View File
@@ -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,
+3 -5
View File
@@ -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)
}
@@ -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)
+50 -40
View File
@@ -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
}
}
}
}
@@ -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)
+3 -3
View File
@@ -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)
)
+67 -53
View File
@@ -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
+7 -7
View File
@@ -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)
@@ -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 {
+3 -3
View File
@@ -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)
)
+59 -45
View File
@@ -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)
+11 -11
View File
@@ -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,
+3 -3
View File
@@ -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)
)
+61 -48
View File
@@ -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
+12 -12
View File
@@ -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)
+3 -3
View File
@@ -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)
)
+65 -51
View File
@@ -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)
+7 -7
View File
@@ -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)
@@ -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"]);
@@ -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 (
<>
<Form.Item
name={[parentNamePath, "format"]}
initialValue={initialValues.format}
label={t("workflow_node.deploy.form.ftp_format.label")}
name={[parentNamePath, "fileFormat"]}
initialValue={initialValues.fileFormat}
label={t("workflow_node.deploy.form.shared_file_format.label")}
rules={[formRule]}
>
<Select
options={[FORMAT_PEM, FORMAT_PFX, FORMAT_JKS].map((s) => ({
key: s,
label: t(`workflow_node.deploy.form.ftp_format.option.${s.toLowerCase()}.label`),
label: t(`workflow_node.deploy.form.shared_file_format.option.${s.toLowerCase()}.label`),
value: s,
}))}
placeholder={t("workflow_node.deploy.form.ftp_format.placeholder")}
onSelect={handleFormatSelect}
placeholder={t("workflow_node.deploy.form.shared_file_format.placeholder")}
onSelect={handleFileFormatSelect}
/>
</Form.Item>
<Show when={fieldFormat === FORMAT_PEM}>
<Show when={fieldFileFormat === FORMAT_PEM}>
<Form.Item
name={[parentNamePath, "keyPath"]}
initialValue={initialValues.keyPath}
label={t("workflow_node.deploy.form.ftp_key_path.label")}
extra={t("workflow_node.deploy.form.ftp_key_path.help")}
name={[parentNamePath, "filePathForKey"]}
initialValue={initialValues.filePathForKey}
label={t("workflow_node.deploy.form.shared_file_path_for_key.label")}
extra={t("workflow_node.deploy.form.shared_file_path_for_key.help")}
rules={[formRule]}
>
<Input placeholder={t("workflow_node.deploy.form.ftp_key_path.placeholder")} />
<Input placeholder={t("workflow_node.deploy.form.shared_file_path_for_key.placeholder")} />
</Form.Item>
</Show>
<Form.Item
name={[parentNamePath, "certPath"]}
initialValue={initialValues.certPath}
label={t(`workflow_node.deploy.form.ftp_${fieldFormat === FORMAT_PEM ? "fullchaincert" : "cert"}_path.label`)}
extra={t("workflow_node.deploy.form.ftp_cert_path.help")}
name={[parentNamePath, "filePathForCrt"]}
initialValue={initialValues.filePathForCrt}
label={t(`workflow_node.deploy.form.shared_file_path_for_crt.label`)}
extra={t("workflow_node.deploy.form.shared_file_path_for_crt.help")}
rules={[formRule]}
>
<Input placeholder={t(`workflow_node.deploy.form.ftp_${fieldFormat === FORMAT_PEM ? "fullchaincert" : "cert"}_path.placeholder`)} />
<Input placeholder={t(`workflow_node.deploy.form.shared_file_path_for_crt.placeholder`)} />
</Form.Item>
<Show when={fieldFormat === FORMAT_PEM}>
<Show when={fieldFileFormat === FORMAT_PEM}>
<Form.Item
name={[parentNamePath, "certPathForServerOnly"]}
initialValue={initialValues.certPathForServerOnly}
label={t("workflow_node.deploy.form.ftp_servercert_path.label")}
extra={t("workflow_node.deploy.form.ftp_servercert_path.help")}
name={[parentNamePath, "filePathForCrtOnlyServer"]}
initialValue={initialValues.filePathForCrtOnlyServer}
label={t("workflow_node.deploy.form.shared_file_path_for_servercrt.label")}
extra={t("workflow_node.deploy.form.shared_file_path_for_servercrt.help")}
rules={[formRule]}
>
<Input allowClear placeholder={t("workflow_node.deploy.form.ftp_servercert_path.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.shared_file_path_for_servercrt.placeholder")} />
</Form.Item>
<Form.Item
name={[parentNamePath, "certPathForIntermediaOnly"]}
initialValue={initialValues.certPathForIntermediaOnly}
label={t("workflow_node.deploy.form.ftp_intermediacert_path.label")}
extra={t("workflow_node.deploy.form.ftp_intermediacert_path.help")}
name={[parentNamePath, "filePathForCrtOnlyIntermedia"]}
initialValue={initialValues.filePathForCrtOnlyIntermedia}
label={t("workflow_node.deploy.form.shared_file_path_for_intermediacrt.label")}
extra={t("workflow_node.deploy.form.shared_file_path_for_intermediacrt.help")}
rules={[formRule]}
>
<Input allowClear placeholder={t("workflow_node.deploy.form.ftp_intermediacert_path.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.shared_file_path_for_intermediacrt.placeholder")} />
</Form.Item>
</Show>
<Show when={fieldFormat === FORMAT_PFX}>
<Show when={fieldFileFormat === FORMAT_PFX}>
<Form.Item
label={t("workflow_node.deploy.form.ftp_pfx_password.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ftp_pfx_password.tooltip") }}></span>}
label={t("workflow_node.deploy.form.shared_pfx_password.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.shared_pfx_password.tooltip") }}></span>}
>
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "pfxPassword"]} initialValue={initialValues.pfxPassword} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.ftp_pfx_password.placeholder")} />
<Input placeholder={t("workflow_node.deploy.form.shared_pfx_password.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomPfxPasswordClick}>
@@ -155,24 +115,30 @@ const BizDeployNodeConfigFieldsProviderFTP = () => {
</Form.Item>
</Show>
<Show when={fieldFormat === FORMAT_JKS}>
<Show when={fieldFileFormat === FORMAT_JKS}>
<Form.Item
name={[parentNamePath, "jksAlias"]}
initialValue={initialValues.jksAlias}
label={t("workflow_node.deploy.form.ftp_jks_alias.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ftp_jks_alias.tooltip") }}></span>}
label={t("workflow_node.deploy.form.shared_jks_alias.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.shared_jks_alias.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.ftp_jks_alias.placeholder")} />
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "jksAlias"]} initialValue={initialValues.jksAlias} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.shared_jks_alias.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomJksAliasClick}>
<IconDice6 size="1.25em" />
</Button>
</Tooltip>
</Space.Compact>
</Form.Item>
<Form.Item
label={t("workflow_node.deploy.form.ftp_jks_keypass.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ftp_jks_keypass.tooltip") }}></span>}
label={t("workflow_node.deploy.form.shared_jks_keypass.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.shared_jks_keypass.tooltip") }}></span>}
>
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "jksKeypass"]} initialValue={initialValues.jksKeypass} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.ftp_jks_keypass.placeholder")} />
<Input placeholder={t("workflow_node.deploy.form.shared_jks_keypass.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomJksKeypassClick}>
@@ -183,12 +149,12 @@ const BizDeployNodeConfigFieldsProviderFTP = () => {
</Form.Item>
<Form.Item
label={t("workflow_node.deploy.form.ftp_jks_storepass.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ftp_jks_storepass.tooltip") }}></span>}
label={t("workflow_node.deploy.form.shared_jks_storepass.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.shared_jks_storepass.tooltip") }}></span>}
>
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "jksStorepass"]} initialValue={initialValues.jksStorepass} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.ftp_jks_storepass.placeholder")} />
<Input placeholder={t("workflow_node.deploy.form.shared_jks_storepass.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomJksStorepassClick}>
@@ -204,9 +170,9 @@ const BizDeployNodeConfigFieldsProviderFTP = () => {
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
return {
format: FORMAT_PEM,
keyPath: "/certimate/cert.key",
certPath: "/certimate/cert.crt",
fileFormat: FORMAT_PEM,
filePathForKey: "/certimate/cert.key",
filePathForCrt: "/certimate/cert.crt",
};
};
@@ -215,18 +181,18 @@ const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> })
return z
.object({
format: z.enum([FORMAT_PEM, FORMAT_PFX, FORMAT_JKS]),
keyPath: z.string().max(256).nullish(),
certPath: z.string().max(256).nullish(),
certPathForServerOnly: z.string().max(256).nullish(),
certPathForIntermediaOnly: z.string().max(256).nullish(),
fileFormat: z.enum([FORMAT_PEM, FORMAT_PFX, FORMAT_JKS]),
filePathForKey: z.string().max(256).nullish(),
filePathForCrt: z.string().max(256).nullish(),
filePathForCrtOnlyServer: z.string().max(256).nullish(),
filePathForCrtOnlyIntermedia: z.string().max(256).nullish(),
pfxPassword: z.string().nullish(),
jksAlias: z.string().nullish(),
jksKeypass: z.string().nullish(),
jksStorepass: z.string().nullish(),
})
.superRefine((values, ctx) => {
switch (values.format) {
switch (values.fileFormat) {
case FORMAT_PFX:
{
const scPfxPassword = z.string().nonempty();
@@ -1,6 +1,6 @@
import { getI18n, useTranslation } from "react-i18next";
import { IconBulb, IconChevronDown, IconDice6 } from "@tabler/icons-react";
import { Button, Divider, Form, Input, Popover, Select, Space, Tooltip } from "antd";
import { Button, Divider, Form, type FormInstance, Input, Popover, Select, Space, Tooltip } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
@@ -129,6 +129,92 @@ Set-ItemProperty -Path $rdpCertPath -Name "SSLCertificateSHA1Hash" -Value "$thum
}
};
export const useSharedFormFieldsAndHandlers = (
form: FormInstance,
{
format = "fileFormat",
certPath = "filePathForCrt",
pfxPassword = "pfxPassword",
jksAlias = "jksAlias",
jksKeypass = "jksKeypass",
jksStorepass = "jksStorepass",
}: {
format?: string;
certPath?: string;
pfxPassword?: string;
jksAlias?: string;
jksKeypass?: string;
jksStorepass?: string;
}
) => {
const { parentNamePath } = useFormNestedFieldsContext();
const fieldFormat = Form.useWatch([parentNamePath, format], form);
const fieldCertPath = Form.useWatch([parentNamePath, certPath], form);
const handleChangeFormat = (value: string) => {
if (fieldFormat === value) return;
switch (value) {
case FORMAT_PEM:
{
if (/(.pfx|.jks)$/.test(fieldCertPath)) {
form.setFieldValue([parentNamePath, certPath], fieldCertPath.replace(/(.pfx|.jks)$/, ".crt"));
}
}
break;
case FORMAT_PFX:
{
if (/(.pem|.crt|.jks)$/.test(fieldCertPath)) {
form.setFieldValue([parentNamePath, certPath], fieldCertPath.replace(/(.pem|.crt|.jks)$/, ".pfx"));
}
}
break;
case FORMAT_JKS:
{
if (/(.pem|.crt|.pfx)$/.test(fieldCertPath)) {
form.setFieldValue([parentNamePath, certPath], fieldCertPath.replace(/(.pem|.crt|.pfx)$/, ".jks"));
}
}
break;
}
};
const handleRandomPfxPassword = () => {
const password = randomString();
form.setFieldValue([parentNamePath, pfxPassword], password);
};
const handleRandomJksAlias = () => {
const suffixlen = 6;
const alias = "certimate_" + Math.random().toFixed(suffixlen).slice(-suffixlen);
form.setFieldValue([parentNamePath, jksAlias], alias);
};
const handleRandomJksKeypass = () => {
const password = randomString();
form.setFieldValue([parentNamePath, jksKeypass], password);
};
const handleRandomJksStorepass = () => {
const password = randomString();
form.setFieldValue([parentNamePath, jksStorepass], password);
};
return {
fieldFormat,
fieldCertPath,
handleChangeFormat,
handleRandomPfxPassword,
handleRandomJksAlias,
handleRandomJksKeypass,
handleRandomJksStorepass,
};
};
const BizDeployNodeConfigFieldsProviderLocal = () => {
const { i18n, t } = useTranslation();
@@ -140,53 +226,14 @@ const BizDeployNodeConfigFieldsProviderLocal = () => {
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, {});
const handlePresetPreScriptClick = (key: string) => {
switch (key) {
@@ -194,8 +241,8 @@ const BizDeployNodeConfigFieldsProviderLocal = () => {
case "ps_backup_files":
{
const presetScriptParams = {
certPath: formInst.getFieldValue([parentNamePath, "certPath"]),
keyPath: formInst.getFieldValue([parentNamePath, "keyPath"]),
certPath: formInst.getFieldValue([parentNamePath, "filePathForCrt"]),
keyPath: formInst.getFieldValue([parentNamePath, "filePathForKey"]),
};
formInst.setFieldValue([parentNamePath, "shellEnv"], SHELLENV_SH);
formInst.setFieldValue([parentNamePath, "preCommand"], initPresetScript(key, presetScriptParams));
@@ -218,7 +265,7 @@ const BizDeployNodeConfigFieldsProviderLocal = () => {
case "ps_binding_rdp":
{
const presetScriptParams = {
certPath: formInst.getFieldValue([parentNamePath, "certPath"]),
certPath: formInst.getFieldValue([parentNamePath, "filePathForCrt"]),
pfxPassword: formInst.getFieldValue([parentNamePath, "pfxPassword"]),
};
formInst.setFieldValue([parentNamePath, "shellEnv"], SHELLENV_POWERSHELL);
@@ -235,74 +282,74 @@ const BizDeployNodeConfigFieldsProviderLocal = () => {
</Form.Item>
<Form.Item
name={[parentNamePath, "format"]}
initialValue={initialValues.format}
label={t("workflow_node.deploy.form.local_format.label")}
name={[parentNamePath, "fileFormat"]}
initialValue={initialValues.fileFormat}
label={t("workflow_node.deploy.form.shared_file_format.label")}
rules={[formRule]}
>
<Select
options={[FORMAT_PEM, FORMAT_PFX, FORMAT_JKS].map((s) => ({
key: s,
label: t(`workflow_node.deploy.form.local_format.option.${s.toLowerCase()}.label`),
label: t(`workflow_node.deploy.form.shared_file_format.option.${s.toLowerCase()}.label`),
value: s,
}))}
placeholder={t("workflow_node.deploy.form.local_format.placeholder")}
onSelect={handleFormatSelect}
placeholder={t("workflow_node.deploy.form.shared_file_format.placeholder")}
onSelect={handleFileFormatSelect}
/>
</Form.Item>
<Show when={fieldFormat === FORMAT_PEM}>
<Show when={fieldFileFormat === FORMAT_PEM}>
<Form.Item
name={[parentNamePath, "keyPath"]}
initialValue={initialValues.keyPath}
label={t("workflow_node.deploy.form.local_key_path.label")}
extra={t("workflow_node.deploy.form.local_key_path.help")}
name={[parentNamePath, "filePathForKey"]}
initialValue={initialValues.filePathForKey}
label={t("workflow_node.deploy.form.shared_file_path_for_key.label")}
extra={t("workflow_node.deploy.form.shared_file_path_for_key.help")}
rules={[formRule]}
>
<Input placeholder={t("workflow_node.deploy.form.local_key_path.placeholder")} />
<Input placeholder={t("workflow_node.deploy.form.shared_file_path_for_key.placeholder")} />
</Form.Item>
</Show>
<Form.Item
name={[parentNamePath, "certPath"]}
initialValue={initialValues.certPath}
label={t(`workflow_node.deploy.form.local_${fieldFormat === FORMAT_PEM ? "fullchaincert" : "cert"}_path.label`)}
extra={t("workflow_node.deploy.form.local_cert_path.help")}
name={[parentNamePath, "filePathForCrt"]}
initialValue={initialValues.filePathForCrt}
label={t(`workflow_node.deploy.form.shared_file_path_for_crt.label`)}
extra={t("workflow_node.deploy.form.shared_file_path_for_crt.help")}
rules={[formRule]}
>
<Input placeholder={t(`workflow_node.deploy.form.local_${fieldFormat === FORMAT_PEM ? "fullchaincert" : "cert"}_path.placeholder`)} />
<Input placeholder={t(`workflow_node.deploy.form.shared_file_path_for_crt.placeholder`)} />
</Form.Item>
<Show when={fieldFormat === FORMAT_PEM}>
<Show when={fieldFileFormat === FORMAT_PEM}>
<Form.Item
name={[parentNamePath, "certPathForServerOnly"]}
initialValue={initialValues.certPathForServerOnly}
label={t("workflow_node.deploy.form.local_servercert_path.label")}
extra={t("workflow_node.deploy.form.local_servercert_path.help")}
name={[parentNamePath, "filePathForCrtOnlyServer"]}
initialValue={initialValues.filePathForCrtOnlyServer}
label={t("workflow_node.deploy.form.shared_file_path_for_servercrt.label")}
extra={t("workflow_node.deploy.form.shared_file_path_for_servercrt.help")}
rules={[formRule]}
>
<Input allowClear placeholder={t("workflow_node.deploy.form.local_servercert_path.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.shared_file_path_for_servercrt.placeholder")} />
</Form.Item>
<Form.Item
name={[parentNamePath, "certPathForIntermediaOnly"]}
initialValue={initialValues.certPathForIntermediaOnly}
label={t("workflow_node.deploy.form.local_intermediacert_path.label")}
extra={t("workflow_node.deploy.form.local_intermediacert_path.help")}
name={[parentNamePath, "filePathForCrtOnlyIntermedia"]}
initialValue={initialValues.filePathForCrtOnlyIntermedia}
label={t("workflow_node.deploy.form.shared_file_path_for_intermediacrt.label")}
extra={t("workflow_node.deploy.form.shared_file_path_for_intermediacrt.help")}
rules={[formRule]}
>
<Input allowClear placeholder={t("workflow_node.deploy.form.local_intermediacert_path.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.shared_file_path_for_intermediacrt.placeholder")} />
</Form.Item>
</Show>
<Show when={fieldFormat === FORMAT_PFX}>
<Show when={fieldFileFormat === FORMAT_PFX}>
<Form.Item
label={t("workflow_node.deploy.form.local_pfx_password.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.local_pfx_password.tooltip") }}></span>}
label={t("workflow_node.deploy.form.shared_pfx_password.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.shared_pfx_password.tooltip") }}></span>}
>
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "pfxPassword"]} initialValue={initialValues.pfxPassword} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.local_pfx_password.placeholder")} />
<Input placeholder={t("workflow_node.deploy.form.shared_pfx_password.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomPfxPasswordClick}>
@@ -313,24 +360,30 @@ const BizDeployNodeConfigFieldsProviderLocal = () => {
</Form.Item>
</Show>
<Show when={fieldFormat === FORMAT_JKS}>
<Show when={fieldFileFormat === FORMAT_JKS}>
<Form.Item
name={[parentNamePath, "jksAlias"]}
initialValue={initialValues.jksAlias}
label={t("workflow_node.deploy.form.local_jks_alias.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.local_jks_alias.tooltip") }}></span>}
label={t("workflow_node.deploy.form.shared_jks_alias.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.shared_jks_alias.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.local_jks_alias.placeholder")} />
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "jksAlias"]} initialValue={initialValues.jksAlias} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.shared_jks_alias.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomJksAliasClick}>
<IconDice6 size="1.25em" />
</Button>
</Tooltip>
</Space.Compact>
</Form.Item>
<Form.Item
label={t("workflow_node.deploy.form.local_jks_keypass.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.local_jks_keypass.tooltip") }}></span>}
label={t("workflow_node.deploy.form.shared_jks_keypass.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.shared_jks_keypass.tooltip") }}></span>}
>
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "jksKeypass"]} initialValue={initialValues.jksKeypass} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.local_jks_keypass.placeholder")} />
<Input placeholder={t("workflow_node.deploy.form.shared_jks_keypass.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomJksKeypassClick}>
@@ -341,12 +394,12 @@ const BizDeployNodeConfigFieldsProviderLocal = () => {
</Form.Item>
<Form.Item
label={t("workflow_node.deploy.form.local_jks_storepass.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.local_jks_storepass.tooltip") }}></span>}
label={t("workflow_node.deploy.form.shared_jks_storepass.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.shared_jks_storepass.tooltip") }}></span>}
>
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "jksStorepass"]} initialValue={initialValues.jksStorepass} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.local_jks_storepass.placeholder")} />
<Input placeholder={t("workflow_node.deploy.form.shared_jks_storepass.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomJksStorepassClick}>
@@ -451,9 +504,9 @@ const BizDeployNodeConfigFieldsProviderLocal = () => {
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
return {
format: FORMAT_PEM,
keyPath: "/etc/ssl/certimate/cert.key",
certPath: "/etc/ssl/certimate/cert.crt",
fileFormat: FORMAT_PEM,
filePathForKey: "/etc/ssl/certimate/cert.key",
filePathForCrt: "/etc/ssl/certimate/cert.crt",
shellEnv: SHELLENV_SH,
};
};
@@ -463,11 +516,11 @@ const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> })
return z
.object({
format: z.enum([FORMAT_PEM, FORMAT_PFX, FORMAT_JKS]),
keyPath: z.string().max(256).nullish(),
certPath: z.string().max(256).nullish(),
certPathForServerOnly: z.string().max(256).nullish(),
certPathForIntermediaOnly: z.string().max(256).nullish(),
fileFormat: z.enum([FORMAT_PEM, FORMAT_PFX, FORMAT_JKS]),
filePathForKey: z.string().max(256).nullish(),
filePathForCrt: z.string().max(256).nullish(),
filePathForCrtOnlyServer: z.string().max(256).nullish(),
filePathForCrtOnlyIntermedia: z.string().max(256).nullish(),
pfxPassword: z.string().nullish(),
jksAlias: z.string().nullish(),
jksKeypass: z.string().nullish(),
@@ -477,7 +530,7 @@ const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> })
postCommand: z.string().max(20480).nullish(),
})
.superRefine((values, ctx) => {
switch (values.format) {
switch (values.fileFormat) {
case FORMAT_PFX:
{
const scPfxPassword = z.string().nonempty();
@@ -6,9 +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 { useSharedFormFieldsAndHandlers as _useSharedFormFieldsAndHandlers } from "./BizDeployNodeConfigFieldsProviderLocal";
const FORMAT_PEM = CERTIFICATE_FORMATS.PEM;
const FORMAT_PFX = CERTIFICATE_FORMATS.PFX;
@@ -25,53 +25,14 @@ const BizDeployNodeConfigFieldsProviderS3 = () => {
const formInst = Form.useFormInstance();
const initialValues = getInitialValues();
const fieldFormat = Form.useWatch([parentNamePath, "format"], formInst);
const fieldCertPath = Form.useWatch([parentNamePath, "certObjectKey"], formInst);
const handleFormatSelect = (value: string) => {
if (fieldFormat === value) return;
switch (value) {
case FORMAT_PEM:
{
if (/(.pfx|.jks)$/.test(fieldCertPath)) {
formInst.setFieldValue([parentNamePath, "certObjectKey"], fieldCertPath.replace(/(.pfx|.jks)$/, ".crt"));
}
}
break;
case FORMAT_PFX:
{
if (/(.crt|.jks)$/.test(fieldCertPath)) {
formInst.setFieldValue([parentNamePath, "certObjectKey"], fieldCertPath.replace(/(.crt|.jks)$/, ".pfx"));
}
}
break;
case FORMAT_JKS:
{
if (/(.crt|.pfx)$/.test(fieldCertPath)) {
formInst.setFieldValue([parentNamePath, "certObjectKey"], 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, { certPath: "objectKeyForCrt" });
return (
<>
@@ -94,72 +55,72 @@ const BizDeployNodeConfigFieldsProviderS3 = () => {
</Form.Item>
<Form.Item
name={[parentNamePath, "format"]}
initialValue={initialValues.format}
label={t("workflow_node.deploy.form.s3_format.label")}
name={[parentNamePath, "fileFormat"]}
initialValue={initialValues.fileFormat}
label={t("workflow_node.deploy.form.shared_file_format.label")}
rules={[formRule]}
>
<Select
options={[FORMAT_PEM, FORMAT_PFX, FORMAT_JKS].map((s) => ({
key: s,
label: t(`workflow_node.deploy.form.s3_format.option.${s.toLowerCase()}.label`),
label: t(`workflow_node.deploy.form.shared_file_format.option.${s.toLowerCase()}.label`),
value: s,
}))}
placeholder={t("workflow_node.deploy.form.s3_format.placeholder")}
onSelect={handleFormatSelect}
placeholder={t("workflow_node.deploy.form.shared_file_format.placeholder")}
onSelect={handleFileFormatSelect}
/>
</Form.Item>
<Show when={fieldFormat === FORMAT_PEM}>
<Show when={fieldFileFormat === FORMAT_PEM}>
<Form.Item
name={[parentNamePath, "keyObjectKey"]}
initialValue={initialValues.keyObjectKey}
label={t("workflow_node.deploy.form.s3_key_object_key.label")}
name={[parentNamePath, "objectKeyForKey"]}
initialValue={initialValues.objectKeyForKey}
label={t("workflow_node.deploy.form.s3_object_key_for_key.label")}
rules={[formRule]}
>
<Input placeholder={t("workflow_node.deploy.form.s3_key_object_key.placeholder")} />
<Input placeholder={t("workflow_node.deploy.form.s3_object_key_for_key.placeholder")} />
</Form.Item>
</Show>
<Form.Item
name={[parentNamePath, "certObjectKey"]}
initialValue={initialValues.certObjectKey}
label={t(`workflow_node.deploy.form.s3_${fieldFormat === FORMAT_PEM ? "fullchaincert" : "cert"}_object_key.label`)}
name={[parentNamePath, "objectKeyForCrt"]}
initialValue={initialValues.objectKeyForCrt}
label={t(`workflow_node.deploy.form.s3_object_key_for_crt.label`)}
rules={[formRule]}
>
<Input placeholder={t(`workflow_node.deploy.form.s3_${fieldFormat === FORMAT_PEM ? "fullchaincert" : "cert"}_object_key.placeholder`)} />
<Input placeholder={t(`workflow_node.deploy.form.s3_object_key_for_crt.placeholder`)} />
</Form.Item>
<Show when={fieldFormat === FORMAT_PEM}>
<Show when={fieldFileFormat === FORMAT_PEM}>
<Form.Item
name={[parentNamePath, "certObjectKeyForServerOnly"]}
initialValue={initialValues.certObjectKeyForServerOnly}
label={t("workflow_node.deploy.form.s3_servercert_object_key.label")}
extra={t("workflow_node.deploy.form.s3_servercert_object_key.help")}
name={[parentNamePath, "objectKeyForCrtOnlyServer"]}
initialValue={initialValues.objectKeyForCrtOnlyServer}
label={t("workflow_node.deploy.form.s3_object_key_for_servercrt.label")}
extra={t("workflow_node.deploy.form.s3_object_key_for_servercrt.help")}
rules={[formRule]}
>
<Input allowClear placeholder={t("workflow_node.deploy.form.s3_servercert_object_key.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.s3_object_key_for_servercrt.placeholder")} />
</Form.Item>
<Form.Item
name={[parentNamePath, "certObjectKeyForIntermediaOnly"]}
initialValue={initialValues.certObjectKeyForIntermediaOnly}
label={t("workflow_node.deploy.form.s3_intermediacert_object_key.label")}
extra={t("workflow_node.deploy.form.s3_intermediacert_object_key.help")}
name={[parentNamePath, "objectKeyForCrtOnlyIntermedia"]}
initialValue={initialValues.objectKeyForCrtOnlyIntermedia}
label={t("workflow_node.deploy.form.s3_object_key_for_intermediacrt.label")}
extra={t("workflow_node.deploy.form.s3_object_key_for_intermediacrt.help")}
rules={[formRule]}
>
<Input allowClear placeholder={t("workflow_node.deploy.form.s3_intermediacert_object_key.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.s3_object_key_for_intermediacrt.placeholder")} />
</Form.Item>
</Show>
<Show when={fieldFormat === FORMAT_PFX}>
<Show when={fieldFileFormat === FORMAT_PFX}>
<Form.Item
label={t("workflow_node.deploy.form.s3_pfx_password.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.s3_pfx_password.tooltip") }}></span>}
label={t("workflow_node.deploy.form.shared_pfx_password.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.shared_pfx_password.tooltip") }}></span>}
>
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "pfxPassword"]} initialValue={initialValues.pfxPassword} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.s3_pfx_password.placeholder")} />
<Input placeholder={t("workflow_node.deploy.form.shared_pfx_password.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomPfxPasswordClick}>
@@ -170,24 +131,30 @@ const BizDeployNodeConfigFieldsProviderS3 = () => {
</Form.Item>
</Show>
<Show when={fieldFormat === FORMAT_JKS}>
<Show when={fieldFileFormat === FORMAT_JKS}>
<Form.Item
name={[parentNamePath, "jksAlias"]}
initialValue={initialValues.jksAlias}
label={t("workflow_node.deploy.form.s3_jks_alias.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.s3_jks_alias.tooltip") }}></span>}
label={t("workflow_node.deploy.form.shared_jks_alias.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.shared_jks_alias.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.s3_jks_alias.placeholder")} />
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "jksAlias"]} initialValue={initialValues.jksAlias} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.shared_jks_alias.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomJksAliasClick}>
<IconDice6 size="1.25em" />
</Button>
</Tooltip>
</Space.Compact>
</Form.Item>
<Form.Item
label={t("workflow_node.deploy.form.s3_jks_keypass.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.s3_jks_keypass.tooltip") }}></span>}
label={t("workflow_node.deploy.form.shared_jks_keypass.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.shared_jks_keypass.tooltip") }}></span>}
>
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "jksKeypass"]} initialValue={initialValues.jksKeypass} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.s3_jks_keypass.placeholder")} />
<Input placeholder={t("workflow_node.deploy.form.shared_jks_keypass.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomJksKeypassClick}>
@@ -198,12 +165,12 @@ const BizDeployNodeConfigFieldsProviderS3 = () => {
</Form.Item>
<Form.Item
label={t("workflow_node.deploy.form.s3_jks_storepass.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.s3_jks_storepass.tooltip") }}></span>}
label={t("workflow_node.deploy.form.shared_jks_storepass.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.shared_jks_storepass.tooltip") }}></span>}
>
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "jksStorepass"]} initialValue={initialValues.jksStorepass} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.s3_jks_storepass.placeholder")} />
<Input placeholder={t("workflow_node.deploy.form.shared_jks_storepass.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomJksStorepassClick}>
@@ -221,9 +188,9 @@ const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
return {
region: "",
bucket: "",
format: FORMAT_PEM,
keyObjectKey: ".certimate/cert.key",
certObjectKey: ".certimate/cert.crt",
fileFormat: FORMAT_PEM,
objectKeyForKey: ".certimate/cert.key",
objectKeyForCrt: ".certimate/cert.crt",
};
};
@@ -234,18 +201,18 @@ const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> })
.object({
region: z.string().nonempty(),
bucket: z.string().nonempty(),
format: z.enum([FORMAT_PEM, FORMAT_PFX, FORMAT_JKS]),
keyObjectKey: z.string().max(256).nullish(),
certObjectKey: z.string().max(256).nullish(),
certObjectKeyForServerOnly: z.string().max(256).nullish(),
certObjectKeyForIntermediaOnly: z.string().max(256).nullish(),
fileFormat: z.enum([FORMAT_PEM, FORMAT_PFX, FORMAT_JKS]),
objectKeyForKey: z.string().max(256).nullish(),
objectKeyForCrt: z.string().max(256).nullish(),
objectKeyForCrtOnlyServer: z.string().max(256).nullish(),
objectKeyForCrtOnlyIntermedia: z.string().max(256).nullish(),
pfxPassword: z.string().nullish(),
jksAlias: z.string().nullish(),
jksKeypass: z.string().nullish(),
jksStorepass: z.string().nullish(),
})
.superRefine((values, ctx) => {
switch (values.format) {
switch (values.fileFormat) {
case FORMAT_PFX:
{
const scPfxPassword = z.string().nonempty();
@@ -8,16 +8,18 @@ import CodeTextInput from "@/components/CodeTextInput";
import PresetScriptTemplatesPopselect from "@/components/preset/PresetScriptTemplatesPopselect";
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 {
initPresetScript as _initPresetScript,
useSharedFormFieldsAndHandlers as _useSharedFormFieldsAndHandlers,
} from "./BizDeployNodeConfigFieldsProviderLocal";
const FORMAT_PEM = CERTIFICATE_FORMATS.PEM;
const FORMAT_PFX = CERTIFICATE_FORMATS.PFX;
const FORMAT_JKS = CERTIFICATE_FORMATS.JKS;
const initPresetScript = (
export const initPresetScript = (
key: Parameters<typeof _initPresetScript>[0] | "sh_replace_synologydsm_ssl" | "sh_replace_fnos_ssl" | "sh_replace_qnap_ssl",
params?: Parameters<typeof _initPresetScript>[1]
) => {
@@ -173,53 +175,14 @@ const BizDeployNodeConfigFieldsProviderSSH = () => {
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, {});
const handlePresetPreScriptClick = (key: string) => {
switch (key) {
@@ -227,8 +190,8 @@ const BizDeployNodeConfigFieldsProviderSSH = () => {
case "ps_backup_files":
{
const presetScriptParams = {
certPath: formInst.getFieldValue([parentNamePath, "certPath"]),
keyPath: formInst.getFieldValue([parentNamePath, "keyPath"]),
certPath: formInst.getFieldValue([parentNamePath, "filePathForCrt"]),
keyPath: formInst.getFieldValue([parentNamePath, "filePathForKey"]),
};
formInst.setFieldValue([parentNamePath, "preCommand"], initPresetScript(key, presetScriptParams));
}
@@ -249,10 +212,10 @@ const BizDeployNodeConfigFieldsProviderSSH = () => {
case "sh_replace_qnap_ssl":
{
const presetScriptParams = {
certPath: formInst.getFieldValue([parentNamePath, "certPath"]),
certPathForServerOnly: formInst.getFieldValue([parentNamePath, "certPathForServerOnly"]),
certPathForIntermediaOnly: formInst.getFieldValue([parentNamePath, "certPathForIntermediaOnly"]),
keyPath: formInst.getFieldValue([parentNamePath, "keyPath"]),
certPath: formInst.getFieldValue([parentNamePath, "filePathForCrt"]),
certPathForServerOnly: formInst.getFieldValue([parentNamePath, "filePathForCrtOnlyServer"]),
certPathForIntermediaOnly: formInst.getFieldValue([parentNamePath, "filePathForCrtOnlyIntermedia"]),
keyPath: formInst.getFieldValue([parentNamePath, "filePathForKey"]),
};
formInst.setFieldValue([parentNamePath, "postCommand"], initPresetScript(key, presetScriptParams));
}
@@ -263,7 +226,7 @@ const BizDeployNodeConfigFieldsProviderSSH = () => {
case "ps_binding_rdp":
{
const presetScriptParams = {
certPath: formInst.getFieldValue([parentNamePath, "certPath"]),
certPath: formInst.getFieldValue([parentNamePath, "filePathForCrt"]),
pfxPassword: formInst.getFieldValue([parentNamePath, "pfxPassword"]),
};
formInst.setFieldValue([parentNamePath, "postCommand"], initPresetScript(key, presetScriptParams));
@@ -285,74 +248,74 @@ const BizDeployNodeConfigFieldsProviderSSH = () => {
</Form.Item>
<Form.Item
name={[parentNamePath, "format"]}
initialValue={initialValues.format}
label={t("workflow_node.deploy.form.ssh_format.label")}
name={[parentNamePath, "fileFormat"]}
initialValue={initialValues.fileFormat}
label={t("workflow_node.deploy.form.shared_file_format.label")}
rules={[formRule]}
>
<Select
options={[FORMAT_PEM, FORMAT_PFX, FORMAT_JKS].map((s) => ({
key: s,
label: t(`workflow_node.deploy.form.ssh_format.option.${s.toLowerCase()}.label`),
label: t(`workflow_node.deploy.form.shared_file_format.option.${s.toLowerCase()}.label`),
value: s,
}))}
placeholder={t("workflow_node.deploy.form.ssh_format.placeholder")}
onSelect={handleFormatSelect}
placeholder={t("workflow_node.deploy.form.shared_file_format.placeholder")}
onSelect={handleFileFormatSelect}
/>
</Form.Item>
<Show when={fieldFormat === FORMAT_PEM}>
<Show when={fieldFileFormat === FORMAT_PEM}>
<Form.Item
name={[parentNamePath, "keyPath"]}
initialValue={initialValues.keyPath}
label={t("workflow_node.deploy.form.ssh_key_path.label")}
extra={t("workflow_node.deploy.form.ssh_key_path.help")}
name={[parentNamePath, "filePathForKey"]}
initialValue={initialValues.filePathForKey}
label={t("workflow_node.deploy.form.shared_file_path_for_key.label")}
extra={t("workflow_node.deploy.form.shared_file_path_for_key.help")}
rules={[formRule]}
>
<Input placeholder={t("workflow_node.deploy.form.ssh_key_path.placeholder")} />
<Input placeholder={t("workflow_node.deploy.form.shared_file_path_for_key.placeholder")} />
</Form.Item>
</Show>
<Form.Item
name={[parentNamePath, "certPath"]}
initialValue={initialValues.certPath}
label={t(`workflow_node.deploy.form.ssh_${fieldFormat === FORMAT_PEM ? "fullchaincert" : "cert"}_path.label`)}
extra={t("workflow_node.deploy.form.ssh_cert_path.help")}
name={[parentNamePath, "filePathForCrt"]}
initialValue={initialValues.filePathForCrt}
label={t(`workflow_node.deploy.form.shared_file_path_for_crt.label`)}
extra={t("workflow_node.deploy.form.shared_file_path_for_crt.help")}
rules={[formRule]}
>
<Input placeholder={t(`workflow_node.deploy.form.ssh_${fieldFormat === FORMAT_PEM ? "fullchaincert" : "cert"}_path.placeholder`)} />
<Input placeholder={t(`workflow_node.deploy.form.shared_file_path_for_crt.placeholder`)} />
</Form.Item>
<Show when={fieldFormat === FORMAT_PEM}>
<Show when={fieldFileFormat === FORMAT_PEM}>
<Form.Item
name={[parentNamePath, "certPathForServerOnly"]}
initialValue={initialValues.certPathForServerOnly}
label={t("workflow_node.deploy.form.ssh_servercert_path.label")}
extra={t("workflow_node.deploy.form.ssh_servercert_path.help")}
name={[parentNamePath, "filePathForCrtOnlyServer"]}
initialValue={initialValues.filePathForCrtOnlyServer}
label={t("workflow_node.deploy.form.shared_file_path_for_servercrt.label")}
extra={t("workflow_node.deploy.form.shared_file_path_for_servercrt.help")}
rules={[formRule]}
>
<Input allowClear placeholder={t("workflow_node.deploy.form.ssh_servercert_path.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.shared_file_path_for_servercrt.placeholder")} />
</Form.Item>
<Form.Item
name={[parentNamePath, "certPathForIntermediaOnly"]}
initialValue={initialValues.certPathForIntermediaOnly}
label={t("workflow_node.deploy.form.ssh_intermediacert_path.label")}
extra={t("workflow_node.deploy.form.ssh_intermediacert_path.help")}
name={[parentNamePath, "filePathForCrtOnlyIntermedia"]}
initialValue={initialValues.filePathForCrtOnlyIntermedia}
label={t("workflow_node.deploy.form.shared_file_path_for_intermediacrt.label")}
extra={t("workflow_node.deploy.form.shared_file_path_for_intermediacrt.help")}
rules={[formRule]}
>
<Input allowClear placeholder={t("workflow_node.deploy.form.ssh_intermediacert_path.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.shared_file_path_for_intermediacrt.placeholder")} />
</Form.Item>
</Show>
<Show when={fieldFormat === FORMAT_PFX}>
<Show when={fieldFileFormat === FORMAT_PFX}>
<Form.Item
label={t("workflow_node.deploy.form.ssh_pfx_password.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ssh_pfx_password.tooltip") }}></span>}
label={t("workflow_node.deploy.form.shared_pfx_password.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.shared_pfx_password.tooltip") }}></span>}
>
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "pfxPassword"]} initialValue={initialValues.pfxPassword} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.ssh_pfx_password.placeholder")} />
<Input placeholder={t("workflow_node.deploy.form.shared_pfx_password.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomPfxPasswordClick}>
@@ -363,24 +326,30 @@ const BizDeployNodeConfigFieldsProviderSSH = () => {
</Form.Item>
</Show>
<Show when={fieldFormat === FORMAT_JKS}>
<Show when={fieldFileFormat === FORMAT_JKS}>
<Form.Item
name={[parentNamePath, "jksAlias"]}
initialValue={initialValues.jksAlias}
label={t("workflow_node.deploy.form.ssh_jks_alias.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ssh_jks_alias.tooltip") }}></span>}
label={t("workflow_node.deploy.form.shared_jks_alias.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.shared_jks_alias.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.ssh_jks_alias.placeholder")} />
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "jksAlias"]} initialValue={initialValues.jksAlias} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.shared_jks_alias.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomJksAliasClick}>
<IconDice6 size="1.25em" />
</Button>
</Tooltip>
</Space.Compact>
</Form.Item>
<Form.Item
label={t("workflow_node.deploy.form.ssh_jks_keypass.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ssh_jks_keypass.tooltip") }}></span>}
label={t("workflow_node.deploy.form.shared_jks_keypass.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.shared_jks_keypass.tooltip") }}></span>}
>
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "jksKeypass"]} initialValue={initialValues.jksKeypass} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.ssh_jks_keypass.placeholder")} />
<Input placeholder={t("workflow_node.deploy.form.shared_jks_keypass.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomJksKeypassClick}>
@@ -391,12 +360,12 @@ const BizDeployNodeConfigFieldsProviderSSH = () => {
</Form.Item>
<Form.Item
label={t("workflow_node.deploy.form.ssh_jks_storepass.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ssh_jks_storepass.tooltip") }}></span>}
label={t("workflow_node.deploy.form.shared_jks_storepass.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.shared_jks_storepass.tooltip") }}></span>}
>
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "jksStorepass"]} initialValue={initialValues.jksStorepass} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.ssh_jks_storepass.placeholder")} />
<Input placeholder={t("workflow_node.deploy.form.shared_jks_storepass.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomJksStorepassClick}>
@@ -493,9 +462,9 @@ const BizDeployNodeConfigFieldsProviderSSH = () => {
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
return {
format: FORMAT_PEM,
keyPath: "/etc/ssl/certimate/cert.key",
certPath: "/etc/ssl/certimate/cert.crt",
fileFormat: FORMAT_PEM,
filePathForKey: "/etc/ssl/certimate/cert.key",
filePathForCrt: "/etc/ssl/certimate/cert.crt",
};
};
@@ -505,11 +474,11 @@ const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> })
return z
.object({
useSCP: z.boolean().nullish(),
format: z.enum([FORMAT_PEM, FORMAT_PFX, FORMAT_JKS]),
keyPath: z.string().max(256).nullish(),
certPath: z.string().max(256).nullish(),
certPathForServerOnly: z.string().max(256).nullish(),
certPathForIntermediaOnly: z.string().max(256).nullish(),
fileFormat: z.enum([FORMAT_PEM, FORMAT_PFX, FORMAT_JKS]),
filePathForKey: z.string().max(256).nullish(),
filePathForCrt: z.string().max(256).nullish(),
filePathForCrtOnlyServer: z.string().max(256).nullish(),
filePathForCrtOnlyIntermedia: z.string().max(256).nullish(),
pfxPassword: z.string().nullish(),
jksAlias: z.string().nullish(),
jksKeypass: z.string().nullish(),
@@ -518,7 +487,7 @@ const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> })
postCommand: z.string().max(20480).nullish(),
})
.superRefine((values, ctx) => {
switch (values.format) {
switch (values.fileFormat) {
case FORMAT_PFX:
{
const scPfxPassword = z.string().nonempty();
@@ -91,13 +91,13 @@ const BizDeployNodeConfigForm = ({ node, ...props }: BizDeployNodeConfigFormProp
}, [fieldProvider]);
useEffect(() => {
// 如果未选择部署目标,则清空授权信息
// 如果未选择提供商,则清空授权信息
if (!fieldProvider && fieldProviderAccessId) {
formInst.setFieldValue("providerAccessId", void 0);
return;
}
// 如果已选择部署目标只有一个授权信息,则自动选择该授权信息
// 如果已选择提供商只有一个授权信息,则自动选择该授权信息
if (fieldProvider && !fieldProviderAccessId) {
const availableAccesses = accesses
.filter((access) => accessOptionFilter(access.provider, access))
@@ -115,7 +115,7 @@ const BizDeployNodeConfigForm = ({ node, ...props }: BizDeployNodeConfigFormProp
};
const handleProviderSelect = (value?: string | undefined) => {
// 切换部署目标时重置表单,避免其他部署目标的配置字段影响当前部署目标
// 切换提供商时重置表单,避免其他提供商的配置字段残留
if (initialValues?.provider === value) {
formInst.setFieldValue("providerAccessId", void 0);
formInst.resetFields(["providerConfig"]);
@@ -83,7 +83,7 @@ const BizNotifyNodeConfigForm = ({ node, ...props }: BizNotifyNodeConfigFormProp
};
const handleProviderSelect = (value?: string | undefined) => {
// 切换通知渠道时重置表单,避免其他通知渠道的配置字段影响当前通知渠道
// 切换通知渠道时重置表单,避免其他通知渠道的配置字段残留
if (initialValues?.provider === value) {
formInst.setFieldValue("providerAccessId", void 0);
formInst.resetFields(["providerConfig"]);
+74 -235
View File
@@ -149,16 +149,16 @@
},
"provider_access": {
"label": "Provider credential",
"placeholder": "Please select an credential of provider",
"placeholder": "Please select an credential of the provider",
"button": "Create"
},
"provider_access_dns01": {
"label": "DNS provider credential",
"placeholder": "Please select an credential of DNS provider"
"placeholder": "Please select an credential of the DNS provider"
},
"provider_access_http01": {
"label": "Hosting provider credential",
"placeholder": "Please select an credential of hosting provider"
"placeholder": "Please select an credential of the hosting provider"
},
"key_source": {
"label": "Key source",
@@ -453,15 +453,15 @@
"help": "Notes: The certificate to be deployed comes from the previous nodes of application or upload."
},
"provider": {
"label": "Deployment target",
"placeholder": "Please select deployment target",
"label": "Provider",
"placeholder": "Please select provider",
"search": {
"placeholder": "Search deployment target ..."
"placeholder": "Search provider ..."
}
},
"provider_access": {
"label": "Hosting provider credential",
"placeholder": "Please select an credential of hosting provider",
"label": "Provider credential",
"placeholder": "Please select an credential of the provider",
"button": "Create"
},
"skip_on_last_succeeded": {
@@ -497,6 +497,61 @@
"shared_script_command": {
"vartips": "Supported variables: <br><ol style=\"list-style: disc;\"><li><strong>${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_PATH}</strong>: <br>The path of the certificate file, same as the value of the form related field.</li><li><strong>${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_SERVER_PATH}</strong>: <br>The path of the server certificate file, same as the value of the form related field.</li><li><strong>${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_INTERMEDIA_PATH}</strong>: <br>The path of the intermediate CA certificate file, same as the value of the form related field.</li><li><strong>${CERTIMATE_DEPLOYER_CMDVAR_PRIVATEKEY_PATH}</strong>: <br>The path of the private key file, same as the value of the form related field.</li><li><strong>${CERTIMATE_DEPLOYER_CMDVAR_PFX_PASSWORD}</strong>: <br>The PFX password, same as the value of the form related field.</li><li><strong>${CERTIMATE_DEPLOYER_CMDVAR_JKS_ALIAS}</strong>: <br>The JKS alias, same as the value of the form related field.</li><li><strong>${CERTIMATE_DEPLOYER_CMDVAR_JKS_KEYPASS}</strong>: <br>The JKS key password, same as the value of the form related field.</li><li><strong>${CERTIMATE_DEPLOYER_CMDVAR_JKS_STOREPASS}</strong>: <br>The JKS store password, same as the value of the form related field.</li></ol>"
},
"shared_file_format": {
"label": "File format",
"placeholder": "Please select file format",
"option": {
"pem": {
"label": "PEM (*.pem, *.crt, *.key)"
},
"pfx": {
"label": "PFX (*.pfx, *.p12)"
},
"jks": {
"label": "JKS (*.jks)"
}
}
},
"shared_file_path_for_key": {
"label": "Private key file path",
"placeholder": "Please enter the output file path for private key file",
"help": "Notes: It should include the full file path, not just the directory."
},
"shared_file_path_for_crt": {
"label": "Certificate file path",
"placeholder": "Please enter the output file path for certificate",
"help": "Notes: It should include the full file path, not just the directory."
},
"shared_file_path_for_servercrt": {
"label": "Certificate file (includes the end-entity parts only) path (Optional)",
"placeholder": "Please enter the output file path for server certificate file",
"help": "Notes: It should include the full file path, not just the directory."
},
"shared_file_path_for_intermediacrt": {
"label": "Certificate file (includes the CA parts only) path (Optional)",
"placeholder": "Please enter the output file path for intermediate certificate file",
"help": "Notes: It should include the full file path, not just the directory."
},
"shared_pfx_password": {
"label": "PFX password",
"placeholder": "Please enter PFX password",
"tooltip": "For more information, see <a href=\"https://learn.microsoft.com/en-us/windows-hardware/drivers/install/personal-information-exchange---pfx--files\" target=\"_blank\">https://learn.microsoft.com/en-us/windows-hardware/drivers/install/personal-information-exchange---pfx--files</a>"
},
"shared_jks_alias": {
"label": "JKS alias",
"placeholder": "Please enter JKS alias",
"tooltip": "For more information, see <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"shared_jks_keypass": {
"label": "JKS key password",
"placeholder": "Please enter JKS key password",
"tooltip": "For more information, see <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"shared_jks_storepass": {
"label": "JKS store password",
"placeholder": "Please enter JKS store password",
"tooltip": "For more information, see <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"1panel_node_name": {
"label": "1Panel node name (Optional)",
@@ -607,7 +662,7 @@
"tooltip": "For more information, see <a href=\"https://www.alibabacloud.com/help/en/ssl-certificate/developer-reference/endpoints\" target=\"_blank\">https://www.alibabacloud.com/help/en/ssl-certificate/developer-reference/endpoints</a>"
},
"aliyun_casdeploy": {
"guide": "TIPS: This will invoke Alibaba Cloud OpenAPI <em>CreateDeploymentJob</em> to create an asynchronously deployment task. You need to go to the Alibaba Cloud console to check the actual deployment results by yourself."
"guide": "TIPS: This will invoke Alibaba Cloud OpenAPI <em>CreateDeploymentJob</em> to create an asynchronously deployment task."
},
"aliyun_casdeploy_region": {
"label": "Alibaba Cloud region",
@@ -1250,65 +1305,6 @@
"placeholder": "Please enter Fly.io custom domain name",
"help": "Notes: After importing the custom certificate for the first time, you need to complete domain ownership verification on Fly.io dashboard."
},
"ftp_format": {
"label": "File format",
"placeholder": "Please select file format",
"option": {
"pem": {
"label": "PEM (*.pem, *.crt, *.key)"
},
"pfx": {
"label": "PFX (*.pfx, *.p12)"
},
"jks": {
"label": "JKS (*.jks)"
}
}
},
"ftp_key_path": {
"label": "Private key file path",
"placeholder": "Please enter the remote path for private key file",
"help": "Notes: It should include the full file path, not just the directory."
},
"ftp_cert_path": {
"label": "Certificate file path",
"placeholder": "Please enter the remote path for certificate",
"help": "Notes: It should include the full file path, not just the directory."
},
"ftp_fullchaincert_path": {
"label": "Bundled fullchain certificate file path",
"placeholder": "Please enter the remote path for bundled fullchain certificate"
},
"ftp_servercert_path": {
"label": "Server certificate file path (Optional)",
"placeholder": "Please enter the remote path for server certificate file",
"help": "Notes: It should include the full file path, not just the directory."
},
"ftp_intermediacert_path": {
"label": "Intermediate CA certificate file path (Optional)",
"placeholder": "Please enter the remote path for intermediate CA certificate file",
"help": "Notes: It should include the full file path, not just the directory."
},
"ftp_pfx_password": {
"label": "PFX password",
"placeholder": "Please enter PFX password",
"tooltip": "For more information, see <a href=\"https://learn.microsoft.com/en-us/windows-hardware/drivers/install/personal-information-exchange---pfx--files\" target=\"_blank\">https://learn.microsoft.com/en-us/windows-hardware/drivers/install/personal-information-exchange---pfx--files</a>"
},
"ftp_jks_alias": {
"label": "JKS alias",
"placeholder": "Please enter JKS alias",
"tooltip": "For more information, see <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"ftp_jks_keypass": {
"label": "JKS key password",
"placeholder": "Please enter JKS key password",
"tooltip": "For more information, see <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"ftp_jks_storepass": {
"label": "JKS store password",
"placeholder": "Please enter JKS store password",
"tooltip": "For more information, see <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"gcore_cdn_resource_id": {
"label": "G-Core CDN resource ID",
"placeholder": "Please enter G-Core CDN resource ID",
@@ -1619,65 +1615,6 @@
"local": {
"guide": "If you are running Certimate in Docker, the \"Local\" refers to the container rather than the host."
},
"local_format": {
"label": "File format",
"placeholder": "Please select file format",
"option": {
"pem": {
"label": "PEM (*.pem, *.crt, *.key)"
},
"pfx": {
"label": "PFX (*.pfx, *.p12)"
},
"jks": {
"label": "JKS (*.jks)"
}
}
},
"local_key_path": {
"label": "Private key file path",
"placeholder": "Please enter the local path for private key file",
"help": "Notes: It should include the full file path, not just the directory."
},
"local_cert_path": {
"label": "Certificate file path",
"placeholder": "Please enter the local path for certificate file",
"help": "Notes: It should include the full file path, not just the directory."
},
"local_fullchaincert_path": {
"label": "Bundled fullchain certificate file path",
"placeholder": "Please enter the local path for bundled fullchain certificate"
},
"local_servercert_path": {
"label": "Server certificate file path (Optional)",
"placeholder": "Please enter the local path for server certificate file",
"help": "Notes: It should include the full file path, not just the directory."
},
"local_intermediacert_path": {
"label": "Intermediate CA certificate file path (Optional)",
"placeholder": "Please enter the local path for intermediate CA certificate file",
"help": "Notes: It should include the full file path, not just the directory."
},
"local_pfx_password": {
"label": "PFX password",
"placeholder": "Please enter PFX password",
"tooltip": "For more information, see <a href=\"https://learn.microsoft.com/en-us/windows-hardware/drivers/install/personal-information-exchange---pfx--files\" target=\"_blank\">https://learn.microsoft.com/en-us/windows-hardware/drivers/install/personal-information-exchange---pfx--files</a>"
},
"local_jks_alias": {
"label": "JKS alias",
"placeholder": "Please enter JKS alias",
"tooltip": "For more information, see <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"local_jks_keypass": {
"label": "JKS key password",
"placeholder": "Please enter JKS key password",
"tooltip": "For more information, see <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"local_jks_storepass": {
"label": "JKS store password",
"placeholder": "Please enter JKS store password",
"tooltip": "For more information, see <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"local_shell_env": {
"label": "Shell",
"placeholder": "Please select shell environment",
@@ -1866,63 +1803,24 @@
"label": "Object storage (S3-compatible) bucket",
"placeholder": "Please enter bucket name"
},
"s3_format": {
"label": "File format",
"placeholder": "Please select file format",
"option": {
"pem": {
"label": "PEM (*.pem, *.crt, *.key)"
},
"pfx": {
"label": "PFX (*.pfx, *.p12)"
},
"jks": {
"label": "JKS (*.jks)"
}
}
},
"s3_key_object_key": {
"s3_object_key_for_key": {
"label": "Private key file object key",
"placeholder": "Please enter the object key for private key file"
},
"s3_cert_object_key": {
"s3_object_key_for_crt": {
"label": "Certificate file object key",
"placeholder": "Please enter the object key for certificate"
},
"s3_fullchaincert_object_key": {
"label": "Bundled fullchain certificate object key",
"placeholder": "Please enter the remote path for bundled fullchain certificate"
},
"s3_servercert_object_key": {
"label": "Server certificate object key (Optional)",
"s3_object_key_for_servercrt": {
"label": "Certificate file (includes the end-entity parts only) object key (Optional)",
"placeholder": "Please enter the object key for server certificate file",
"help": ""
},
"s3_intermediacert_object_key": {
"label": "Intermediate CA certificate object key (Optional)",
"placeholder": "Please enter the object key for intermediate CA certificate file",
"s3_object_key_for_intermediacrt": {
"label": "Certificate file (includes the CA parts only) object key (Optional)",
"placeholder": "Please enter the object key for intermediate certificate file",
"help": ""
},
"s3_pfx_password": {
"label": "PFX password",
"placeholder": "Please enter PFX password",
"tooltip": "For more information, see <a href=\"https://learn.microsoft.com/en-us/windows-hardware/drivers/install/personal-information-exchange---pfx--files\" target=\"_blank\">https://learn.microsoft.com/en-us/windows-hardware/drivers/install/personal-information-exchange---pfx--files</a>"
},
"s3_jks_alias": {
"label": "JKS alias",
"placeholder": "Please enter JKS alias",
"tooltip": "For more information, see <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"s3_jks_keypass": {
"label": "JKS key password",
"placeholder": "Please enter JKS key password",
"tooltip": "For more information, see <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"s3_jks_storepass": {
"label": "JKS store password",
"placeholder": "Please enter JKS store password",
"tooltip": "For more information, see <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"safeline": {
"guide": "Requires SafeLine v6.6 or higher."
},
@@ -1953,65 +1851,6 @@
"placeholder": "Please enter SamWAF certificate ID",
"tooltip": "You can find it on SamWAF dashboard."
},
"ssh_format": {
"label": "File format",
"placeholder": "Please select file format",
"option": {
"pem": {
"label": "PEM (*.pem, *.crt, *.key)"
},
"pfx": {
"label": "PFX (*.pfx, *.p12)"
},
"jks": {
"label": "JKS (*.jks)"
}
}
},
"ssh_key_path": {
"label": "Private key file path",
"placeholder": "Please enter the remote path for private key file",
"help": "Notes: It should include the full file path, not just the directory."
},
"ssh_cert_path": {
"label": "Certificate file path",
"placeholder": "Please enter the remote path for certificate",
"help": "Notes: It should include the full file path, not just the directory."
},
"ssh_fullchaincert_path": {
"label": "Bundled fullchain certificate file path",
"placeholder": "Please enter the remote path for bundled fullchain certificate"
},
"ssh_servercert_path": {
"label": "Server certificate file path (Optional)",
"placeholder": "Please enter the remote path for server certificate file",
"help": "Notes: It should include the full file path, not just the directory."
},
"ssh_intermediacert_path": {
"label": "Intermediate CA certificate file path (Optional)",
"placeholder": "Please enter the remote path for intermediate CA certificate file",
"help": "Notes: It should include the full file path, not just the directory."
},
"ssh_pfx_password": {
"label": "PFX password",
"placeholder": "Please enter PFX password",
"tooltip": "For more information, see <a href=\"https://learn.microsoft.com/en-us/windows-hardware/drivers/install/personal-information-exchange---pfx--files\" target=\"_blank\">https://learn.microsoft.com/en-us/windows-hardware/drivers/install/personal-information-exchange---pfx--files</a>"
},
"ssh_jks_alias": {
"label": "JKS alias",
"placeholder": "Please enter JKS alias",
"tooltip": "For more information, see <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"ssh_jks_keypass": {
"label": "JKS key password",
"placeholder": "Please enter JKS key password",
"tooltip": "For more information, see <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"ssh_jks_storepass": {
"label": "JKS store password",
"placeholder": "Please enter JKS store password",
"tooltip": "For more information, see <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"ssh_pre_command": {
"label": "Pre-command (Optional)",
"placeholder": "Please enter command to be executed before uploading files"
@@ -2194,7 +2033,7 @@
"tooltip": "<ul style=\"list-style: disc;\"><li><strong>ssl.intl.tencentcloudapi.com</strong> for Tencent Cloud International</li><li><strong>ssl.tencentcloudapi.com</strong> for Tencent Cloud in China</li></ul>"
},
"tencentcloud_ssldeploy": {
"guide": "TIPS: This will invoke Tencent Cloud OpenAPI <em>DeployCertificateInstance</em> to create an asynchronously deployment task. You need to go to the Tencent Cloud console to check the actual deployment results by yourself."
"guide": "TIPS: This will invoke Tencent Cloud OpenAPI <em>DeployCertificateInstance</em> to create an asynchronously deployment task."
},
"tencentcloud_ssldeploy_endpoint": {
"label": "Tencent Cloud API endpoint (Optional)",
@@ -2225,7 +2064,7 @@
}
},
"tencentcloud_sslupdate": {
"guide": "TIPS: This will invoke Tencent Cloud OpenAPI <em>UpdateCertificateInstance</em> or <em>UploadUpdateCertificateInstance</em> to create an asynchronously deployment task. You need to go to the Tencent Cloud console to check the actual deployment results by yourself."
"guide": "TIPS: This will invoke Tencent Cloud OpenAPI <em>UpdateCertificateInstance</em> or <em>UploadUpdateCertificateInstance</em> to create an asynchronously deployment task."
},
"tencentcloud_sslupdate_endpoint": {
"label": "Tencent Cloud API endpoint (Optional)",
@@ -2712,7 +2551,7 @@
},
"provider_access": {
"label": "Notification provider credential",
"placeholder": "Please select an credential of notification provider",
"placeholder": "Please select an credential of the notification provider",
"button": "Create"
},
"params_config": {
+70 -231
View File
@@ -452,15 +452,15 @@
"help": "提示:待部署证书来自之前的申请或上传节点,如果选项为空请先检查前序节点。"
},
"provider": {
"label": "部署目标",
"placeholder": "请选择部署目标",
"label": "提供商",
"placeholder": "请选择提供商",
"search": {
"placeholder": "搜索部署目标……"
"placeholder": "搜索提供商……"
}
},
"provider_access": {
"label": "主机提供商授权",
"placeholder": "请选择主机提供商授权",
"label": "提供商授权",
"placeholder": "请选择提供商授权",
"button": "新建"
},
"skip_on_last_succeeded": {
@@ -496,6 +496,61 @@
"shared_script_command": {
"vartips": "支持的变量:<br><ol style=\"list-style: disc;\"><li><strong>${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_PATH}</strong>:<br>证书文件路径,等同于表单中相应字段的值。</li><li><strong>${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_SERVER_PATH}</strong>:<br>证书文件(仅含服务器证书)路径,等同于表单中相应字段的值。</li><li><strong>${CERTIMATE_DEPLOYER_CMDVAR_CERTIFICATE_INTERMEDIA_PATH}</strong>:<br>证书文件(仅含中间证书)路径,等同于表单中相应字段的值。</li><li><strong>${CERTIMATE_DEPLOYER_CMDVAR_PRIVATEKEY_PATH}</strong>:<br>私钥文件路径,等同于表单中相应字段的值。</li><li><strong>${CERTIMATE_DEPLOYER_CMDVAR_PFX_PASSWORD}</strong>:<br>PFX 导出密码,等同于表单中相应字段的值。</li><li><strong>${CERTIMATE_DEPLOYER_CMDVAR_JKS_ALIAS}</strong>:<br>JKS 别名,等同于表单中相应字段的值。</li><li><strong>${CERTIMATE_DEPLOYER_CMDVAR_JKS_KEYPASS}</strong>:<br>JKS 私钥访问口令,等同于表单中相应字段的值。</li><li><strong>${CERTIMATE_DEPLOYER_CMDVAR_JKS_STOREPASS}</strong>:<br>JKS 密钥库存储口令,等同于表单中相应字段的值。</li></ol>"
},
"shared_file_format": {
"label": "文件格式",
"placeholder": "请选择文件格式",
"option": {
"pem": {
"label": "PEM 格式(*.pem, *.crt, *.key)"
},
"pfx": {
"label": "PFX 格式(*.pfx, *.p12)"
},
"jks": {
"label": "JKS 格式(*.jks)"
}
}
},
"shared_file_path_for_key": {
"label": "私钥文件输出路径",
"placeholder": "请输入私钥文件输出路径",
"help": "注意:路径需包含完整的文件名,而不是只有目录。"
},
"shared_file_path_for_crt": {
"label": "证书文件输出路径",
"placeholder": "请输入证书文件输出路径",
"help": "注意:路径需包含完整的文件名,而不是只有目录。"
},
"shared_file_path_for_servercrt": {
"label": "证书文件(仅含服务器证书)输出路径(可选)",
"placeholder": "请输入服务器证书文件输出路径",
"help": "注意:路径需包含完整的文件名,而不是只有目录。不填写时将不输出服务器证书。"
},
"shared_file_path_for_intermediacrt": {
"label": "证书文件(仅含中间证书)输出路径(可选)",
"placeholder": "请输入中间证书文件输出路径",
"help": "注意:路径需包含完整的文件名,而不是只有目录。不填写时将不输出中间证书。"
},
"shared_pfx_password": {
"label": "PFX 导出密码",
"placeholder": "请输入 PFX 导出密码",
"tooltip": "这是什么?请参阅 <a href=\"https://learn.microsoft.com/zh-cn/windows-hardware/drivers/install/personal-information-exchange---pfx--files\" target=\"_blank\">https://learn.microsoft.com/zh-cn/windows-hardware/drivers/install/personal-information-exchange---pfx--files</a>"
},
"shared_jks_alias": {
"label": "JKS 别名",
"placeholder": "请输入 JKS 别名",
"tooltip": "这是什么?请参阅 <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"shared_jks_keypass": {
"label": "JKS 私钥访问口令",
"placeholder": "请输入 JKS 私钥访问口令",
"tooltip": "这是什么?请参阅 <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"shared_jks_storepass": {
"label": "JKS 密钥库存储口令",
"placeholder": "请输入 JKS 密钥库存储口令",
"tooltip": "这是什么?请参阅 <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"1panel_node_name": {
"label": "1Panel 子节点名称(可选)",
@@ -606,7 +661,7 @@
"tooltip": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/ssl-certificate/developer-reference/endpoints\" target=\"_blank\">https://help.aliyun.com/zh/ssl-certificate/developer-reference/endpoints</a>"
},
"aliyun_casdeploy": {
"guide": "将通过阿里云 OpenAPI <em>CreateDeploymentJob</em> 接口创建异步部署任务。此部署目标若执行成功仅代表已创建部署任务,实际部署结果需要你自行前往阿里云控制台查询。"
"guide": "将通过阿里云 OpenAPI <em>CreateDeploymentJob</em> 接口创建异步部署任务。"
},
"aliyun_casdeploy_region": {
"label": "阿里云服务地域",
@@ -1246,65 +1301,6 @@
"placeholder": "请输入 Fly.io 自定义域名",
"help": "注意:首次导入自定义证书后,请登录 Fly.io 控制台完成域名所有权验证。"
},
"ftp_format": {
"label": "文件格式",
"placeholder": "请选择文件格式",
"option": {
"pem": {
"label": "PEM 格式(*.pem, *.crt, *.key)"
},
"pfx": {
"label": "PFX 格式(*.pfx, *.p12)"
},
"jks": {
"label": "JKS 格式(*.jks)"
}
}
},
"ftp_key_path": {
"label": "私钥文件保存路径",
"placeholder": "请输入私钥文件远程路径",
"help": "注意:路径需包含完整的文件名,而不是只有目录。"
},
"ftp_cert_path": {
"label": "证书文件保存路径",
"placeholder": "请输入证书文件远程路径",
"help": "注意:路径需包含完整的文件名,而不是只有目录。"
},
"ftp_fullchaincert_path": {
"label": "证书链文件保存路径",
"placeholder": "请输入证书链文件远程路径"
},
"ftp_servercert_path": {
"label": "服务器证书文件保存路径(可选)",
"placeholder": "请输入服务器证书文件远程路径",
"help": "注意:路径需包含完整的文件名,而不是只有目录。不填写时将不上传服务器证书。"
},
"ftp_intermediacert_path": {
"label": "中间证书文件保存路径(可选)",
"placeholder": "请输入中间证书文件远程路径",
"help": "注意:路径需包含完整的文件名,而不是只有目录。不填写时将不上传中间证书。"
},
"ftp_pfx_password": {
"label": "PFX 导出密码",
"placeholder": "请输入 PFX 导出密码",
"tooltip": "这是什么?请参阅 <a href=\"https://learn.microsoft.com/zh-cn/windows-hardware/drivers/install/personal-information-exchange---pfx--files\" target=\"_blank\">https://learn.microsoft.com/zh-cn/windows-hardware/drivers/install/personal-information-exchange---pfx--files</a>"
},
"ftp_jks_alias": {
"label": "JKS 别名",
"placeholder": "请输入 JKS 别名",
"tooltip": "这是什么?请参阅 <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"ftp_jks_keypass": {
"label": "JKS 私钥访问口令",
"placeholder": "请输入 JKS 私钥访问口令",
"tooltip": "这是什么?请参阅 <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"ftp_jks_storepass": {
"label": "JKS 密钥库存储口令",
"placeholder": "请输入 JKS 密钥库存储口令",
"tooltip": "这是什么?请参阅 <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"gcore_cdn_resource_id": {
"label": "G-Core CDN 资源 ID",
"placeholder": "请输入 G-Core CDN 资源 ID",
@@ -1615,65 +1611,6 @@
"local": {
"guide": "如果你正在使用 Docker 运行 Certimate,「本地」指的是容器内而非宿主机。"
},
"local_format": {
"label": "文件格式",
"placeholder": "请选择文件格式",
"option": {
"pem": {
"label": "PEM 格式(*.pem, *.crt, *.key)"
},
"pfx": {
"label": "PFX 格式(*.pfx, *.p12)"
},
"jks": {
"label": "JKS 格式(*.jks)"
}
}
},
"local_key_path": {
"label": "私钥文件保存路径",
"placeholder": "请输入私钥文件本地路径",
"help": "注意:路径需包含完整的文件名,而不是只有目录。"
},
"local_cert_path": {
"label": "证书文件保存路径",
"placeholder": "请输入证书文件本地路径",
"help": "注意:路径需包含完整的文件名,而不是只有目录。"
},
"local_fullchaincert_path": {
"label": "证书链文件保存路径",
"placeholder": "请输入证书链文件本地路径"
},
"local_servercert_path": {
"label": "服务器证书文件保存路径(可选)",
"placeholder": "请输入服务器证书文件本地路径",
"help": "注意:路径需包含完整的文件名,而不是只有目录。不填写时将不会保存服务器证书。"
},
"local_intermediacert_path": {
"label": "中间证书文件保存路径(可选)",
"placeholder": "请输入中间证书文件本地路径",
"help": "注意:路径需包含完整的文件名,而不是只有目录。不填写时将不会保存中间证书。"
},
"local_pfx_password": {
"label": "PFX 导出密码",
"placeholder": "请输入 PFX 导出密码",
"tooltip": "这是什么?请参阅 <a href=\"https://learn.microsoft.com/zh-cn/windows-hardware/drivers/install/personal-information-exchange---pfx--files\" target=\"_blank\">https://learn.microsoft.com/zh-cn/windows-hardware/drivers/install/personal-information-exchange---pfx--files</a>"
},
"local_jks_alias": {
"label": "JKS 别名",
"placeholder": "请输入 JKS 别名",
"tooltip": "这是什么?请参阅 <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"local_jks_keypass": {
"label": "JKS 私钥访问口令",
"placeholder": "请输入 JKS 私钥访问口令",
"tooltip": "这是什么?请参阅 <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"local_jks_storepass": {
"label": "JKS 密钥库存储口令",
"placeholder": "请输入 JKS 密钥库存储口令",
"tooltip": "这是什么?请参阅 <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"local_shell_env": {
"label": "命令执行环境",
"placeholder": "请选择命令执行环境",
@@ -1862,63 +1799,24 @@
"label": "对象存储桶名",
"placeholder": "请输入对象存储桶名"
},
"s3_format": {
"label": "文件格式",
"placeholder": "请选择文件格式",
"option": {
"pem": {
"label": "PEM 格式(*.pem, *.crt, *.key)"
},
"pfx": {
"label": "PFX 格式(*.pfx, *.p12)"
},
"jks": {
"label": "JKS 格式(*.jks)"
}
}
},
"s3_key_object_key": {
"s3_object_key_for_key": {
"label": "私钥文件对象键",
"placeholder": "请输入私钥文件对象键"
},
"s3_cert_object_key": {
"s3_object_key_for_crt": {
"label": "证书文件对象键",
"placeholder": "请输入证书文件对象键"
},
"s3_fullchaincert_object_key": {
"label": "证书链文件对象键",
"placeholder": "请输入证书链文件对象键"
},
"s3_servercert_object_key": {
"label": "服务器证书文件对象键(可选)",
"s3_object_key_for_servercrt": {
"label": "证书文件(仅含服务器证书)对象键(可选)",
"placeholder": "请输入服务器证书文件对象键",
"help": "注意:不填写时将不会上传服务器证书。"
},
"s3_intermediacert_object_key": {
"label": "中间证书文件对象键(可选)",
"s3_object_key_for_intermediacrt": {
"label": "证书文件(仅含中间证书)对象键(可选)",
"placeholder": "请输入中间证书文件对象键",
"help": "注意:不填写时将不会上传中间证书。"
},
"s3_pfx_password": {
"label": "PFX 导出密码",
"placeholder": "请输入 PFX 导出密码",
"tooltip": "这是什么?请参阅 <a href=\"https://learn.microsoft.com/zh-cn/windows-hardware/drivers/install/personal-information-exchange---pfx--files\" target=\"_blank\">https://learn.microsoft.com/zh-cn/windows-hardware/drivers/install/personal-information-exchange---pfx--files</a>"
},
"s3_jks_alias": {
"label": "JKS 别名",
"placeholder": "请输入 JKS 别名",
"tooltip": "这是什么?请参阅 <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"s3_jks_keypass": {
"label": "JKS 私钥访问口令",
"placeholder": "请输入 JKS 私钥访问口令",
"tooltip": "这是什么?请参阅 <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"s3_jks_storepass": {
"label": "JKS 密钥库存储口令",
"placeholder": "请输入 JKS 密钥库存储口令",
"tooltip": "这是什么?请参阅 <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"safeline": {
"guide": "需要雷池 v6.6 或更高版本。"
},
@@ -1949,65 +1847,6 @@
"placeholder": "请输入 SamWAF 证书 ID",
"tooltip": "请登录 SamWAF 控制台查看"
},
"ssh_format": {
"label": "文件格式",
"placeholder": "请选择文件格式",
"option": {
"pem": {
"label": "PEM 格式(*.pem, *.crt, *.key)"
},
"pfx": {
"label": "PFX 格式(*.pfx, *.p12)"
},
"jks": {
"label": "JKS 格式(*.jks)"
}
}
},
"ssh_key_path": {
"label": "私钥文件保存路径",
"placeholder": "请输入私钥文件远程路径",
"help": "注意:路径需包含完整的文件名,而不是只有目录。"
},
"ssh_cert_path": {
"label": "证书文件保存路径",
"placeholder": "请输入证书文件远程路径",
"help": "注意:路径需包含完整的文件名,而不是只有目录。"
},
"ssh_fullchaincert_path": {
"label": "证书链文件保存路径",
"placeholder": "请输入证书链文件远程路径"
},
"ssh_servercert_path": {
"label": "服务器证书文件保存路径(可选)",
"placeholder": "请输入服务器证书文件远程路径",
"help": "注意:路径需包含完整的文件名,而不是只有目录。不填写时将不上传服务器证书。"
},
"ssh_intermediacert_path": {
"label": "中间证书文件保存路径(可选)",
"placeholder": "请输入中间证书文件远程路径",
"help": "注意:路径需包含完整的文件名,而不是只有目录。不填写时将不上传中间证书。"
},
"ssh_pfx_password": {
"label": "PFX 导出密码",
"placeholder": "请输入 PFX 导出密码",
"tooltip": "这是什么?请参阅 <a href=\"https://learn.microsoft.com/zh-cn/windows-hardware/drivers/install/personal-information-exchange---pfx--files\" target=\"_blank\">https://learn.microsoft.com/zh-cn/windows-hardware/drivers/install/personal-information-exchange---pfx--files</a>"
},
"ssh_jks_alias": {
"label": "JKS 别名",
"placeholder": "请输入 JKS 别名",
"tooltip": "这是什么?请参阅 <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"ssh_jks_keypass": {
"label": "JKS 私钥访问口令",
"placeholder": "请输入 JKS 私钥访问口令",
"tooltip": "这是什么?请参阅 <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"ssh_jks_storepass": {
"label": "JKS 密钥库存储口令",
"placeholder": "请输入 JKS 密钥库存储口令",
"tooltip": "这是什么?请参阅 <a href=\"https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html\" target=\"_blank\">https://docs.oracle.com/cd/E19509-01/820-3503/ggfen/index.html</a>"
},
"ssh_pre_command": {
"label": "前置命令(可选)",
"placeholder": "请输入上传文件前执行的命令"
@@ -2190,7 +2029,7 @@
"tooltip": "这是什么?请参阅 <a href=\"https://cloud.tencent.com/document/product/400/41659\" target=\"_blank\">https://cloud.tencent.com/document/product/400/41659</a><br>国际站用户请填写 <em>ssl.intl.tencentcloudapi.com</em>。"
},
"tencentcloud_ssldeploy": {
"guide": "将通过腾讯云 OpenAPI <em>DeployCertificateInstance</em> 接口创建异步部署任务。此部署目标若执行成功仅代表已创建部署任务,实际部署结果需要你自行前往腾讯云控制台查询。"
"guide": "将通过腾讯云 OpenAPI <em>DeployCertificateInstance</em> 接口创建异步部署任务。"
},
"tencentcloud_ssldeploy_endpoint": {
"label": "腾讯云接口端点(可选)",
@@ -2221,7 +2060,7 @@
}
},
"tencentcloud_sslupdate": {
"guide": "将通过腾讯云 OpenAPI <em>UpdateCertificateInstance</em> 或 <em>UploadUpdateCertificateInstance</em> 接口创建异步部署任务。此部署目标若执行成功仅代表已创建部署任务,实际部署结果需要你自行前往腾讯云控制台查询。"
"guide": "将通过腾讯云 OpenAPI <em>UpdateCertificateInstance</em> 或 <em>UploadUpdateCertificateInstance</em> 接口创建异步部署任务。"
},
"tencentcloud_sslupdate_endpoint": {
"label": "腾讯云接口端点(可选)",
@@ -2621,7 +2460,7 @@
"webhook_data": {
"label": "Webhook 回调数据(可选)",
"placeholder": "请输入 Webhook 回调数据以覆盖默认值",
"help": "提示:不填写时,将使用所选部署目标授权的默认 Webhook 回调数据。",
"help": "提示:不填写时,将使用所选提供商授权的默认 Webhook 回调数据。",
"vartips": "支持的变量:<br><ol style=\"list-style: disc;\"><li><strong>${CERTIMATE_DEPLOYER_COMMONNAME}</strong>:<br>证书的主域名或 IP。</li><li><strong>${CERTIMATE_DEPLOYER_SUBJECTALTNAMES}</strong>:<br>证书的多域名或 IP,以半角分号隔开。</li><li><strong>${CERTIMATE_DEPLOYER_CERTIFICATE}</strong>:<br>证书文件 PEM 格式内容。</li><li><strong>${CERTIMATE_DEPLOYER_CERTIFICATE_SERVER}</strong>:<br>证书文件(仅含服务器证书)PEM 格式内容。</li><li><strong>${CERTIMATE_DEPLOYER_CERTIFICATE_INTERMEDIA}</strong>:<br>证书文件(仅含中间证书)PEM 格式内容。</li><li><strong>${CERTIMATE_DEPLOYER_PRIVATEKEY}</strong>:<br>私钥文件 PEM 格式内容。</li></ol>"
},
"webhook_timeout": {