mirror of
https://github.com/certimate-go/certimate.git
synced 2026-09-24 23:10:13 +08:00
refactor: rename OutputFormat to FileFormat, OutputKeyPath to FilePathForKey, OutputCertPath to FilePathForCrt
This commit is contained in:
@@ -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,
|
||||
})
|
||||
|
||||
@@ -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
|
||||
})
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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
|
||||
})
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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,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,
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"]);
|
||||
|
||||
+69
-103
@@ -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();
|
||||
|
||||
+158
-105
@@ -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();
|
||||
|
||||
+67
-100
@@ -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();
|
||||
|
||||
+80
-111
@@ -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"]);
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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": {
|
||||
|
||||
Reference in New Issue
Block a user