mirror of
https://github.com/certimate-go/certimate.git
synced 2026-06-13 21:01:32 +08:00
feat(provider): new deployment provider: s3
This commit is contained in:
parent
edb858cfec
commit
c0bcf6d0fd
@ -59,7 +59,7 @@ func (s *CertificateService) DownloadArchivedFile(ctx context.Context, req *dtos
|
||||
|
||||
var bytes []byte
|
||||
switch strings.ToUpper(req.CertificateFormat) {
|
||||
case "", "PEM":
|
||||
case "", string(domain.CertificateFormatTypePEM):
|
||||
{
|
||||
serverCertPEM, intermediaCertPEM, err := xcert.ExtractCertificatesFromPEM(certificate.Certificate)
|
||||
if err != nil {
|
||||
@ -114,7 +114,7 @@ func (s *CertificateService) DownloadArchivedFile(ctx context.Context, req *dtos
|
||||
bytes = buf.Bytes()
|
||||
}
|
||||
|
||||
case "PFX":
|
||||
case string(domain.CertificateFormatTypePFX):
|
||||
{
|
||||
const pfxPassword = "certimate"
|
||||
|
||||
@ -151,7 +151,7 @@ func (s *CertificateService) DownloadArchivedFile(ctx context.Context, req *dtos
|
||||
bytes = buf.Bytes()
|
||||
}
|
||||
|
||||
case "JKS":
|
||||
case string(domain.CertificateFormatTypeJKS):
|
||||
{
|
||||
const jksPassword = "certimate"
|
||||
|
||||
|
||||
40
internal/certmgmt/deployers/sp_s3.go
Normal file
40
internal/certmgmt/deployers/sp_s3.go
Normal file
@ -0,0 +1,40 @@
|
||||
package deployers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/certimate-go/certimate/internal/domain"
|
||||
"github.com/certimate-go/certimate/pkg/core/deployer"
|
||||
"github.com/certimate-go/certimate/pkg/core/deployer/providers/s3"
|
||||
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Registries.MustRegister(domain.DeploymentProviderTypeS3, func(options *ProviderFactoryOptions) (deployer.Provider, error) {
|
||||
credentials := domain.AccessConfigForS3{}
|
||||
if err := xmaps.Populate(options.ProviderAccessConfig, &credentials); err != nil {
|
||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||
}
|
||||
|
||||
provider, err := s3.NewDeployer(&s3.DeployerConfig{
|
||||
Endpoint: credentials.Endpoint,
|
||||
AccessKey: credentials.AccessKey,
|
||||
SecretKey: credentials.SecretKey,
|
||||
SignatureVersion: credentials.SignatureVersion,
|
||||
UsePathStyle: credentials.UsePathStyle,
|
||||
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"),
|
||||
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
|
||||
})
|
||||
}
|
||||
@ -112,3 +112,11 @@ func (t CertificateKeyAlgorithmType) KeyType() (certcrypto.KeyType, error) {
|
||||
|
||||
return certcrypto.RSA2048, fmt.Errorf("unsupported key algorithm type: '%s'", t)
|
||||
}
|
||||
|
||||
type CertificateFormatType string
|
||||
|
||||
const (
|
||||
CertificateFormatTypePEM CertificateFormatType = "PEM"
|
||||
CertificateFormatTypePFX CertificateFormatType = "PFX"
|
||||
CertificateFormatTypeJKS CertificateFormatType = "JKS"
|
||||
)
|
||||
|
||||
@ -329,6 +329,7 @@ const (
|
||||
DeploymentProviderTypeRainYunRCDN = DeploymentProviderType(AccessProviderTypeRainYun + "-rcdn")
|
||||
DeploymentProviderTypeRatPanel = DeploymentProviderType(AccessProviderTypeRatPanel)
|
||||
DeploymentProviderTypeRatPanelConsole = DeploymentProviderType(AccessProviderTypeRatPanel + "-console")
|
||||
DeploymentProviderTypeS3 = DeploymentProviderType(AccessProviderTypeS3)
|
||||
DeploymentProviderTypeSafeLine = DeploymentProviderType(AccessProviderTypeSafeLine)
|
||||
DeploymentProviderTypeSSH = DeploymentProviderType(AccessProviderTypeSSH)
|
||||
DeploymentProviderTypeSynologyDSM = DeploymentProviderType(AccessProviderTypeSynologyDSM)
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package s3
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -87,11 +88,11 @@ func NewClient(config *Config) (*Client, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Client) PutObject(ctx context.Context, bucket, key string, reader io.Reader) error {
|
||||
func (c *Client) PutObject(ctx context.Context, bucket, key string, reader io.Reader, size int64) error {
|
||||
putOpts := minio.PutObjectOptions{
|
||||
DisableMultipart: true,
|
||||
}
|
||||
_, err := c.client.PutObject(ctx, bucket, key, reader, 1024*1024*16, putOpts)
|
||||
_, err := c.client.PutObject(ctx, bucket, key, reader, size, putOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -99,6 +100,16 @@ func (c *Client) PutObject(ctx context.Context, bucket, key string, reader io.Re
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) PutObjectString(ctx context.Context, bucket, key string, data string) error {
|
||||
reader := strings.NewReader(data)
|
||||
return c.PutObject(ctx, bucket, key, reader, reader.Size())
|
||||
}
|
||||
|
||||
func (c *Client) PutObjectBytes(ctx context.Context, bucket, key string, data []byte) error {
|
||||
reader := bytes.NewReader(data)
|
||||
return c.PutObject(ctx, bucket, key, reader, reader.Size())
|
||||
}
|
||||
|
||||
func (c *Client) RemoveObject(ctx context.Context, bucket, key string) error {
|
||||
removeOpts := minio.RemoveObjectOptions{}
|
||||
err := c.client.RemoveObject(ctx, bucket, key, removeOpts)
|
||||
|
||||
@ -62,8 +62,7 @@ type provider struct {
|
||||
|
||||
func (p *provider) Present(domain, token, keyAuth string) error {
|
||||
objectKey := strings.Trim(http01.ChallengePath(token), "/")
|
||||
reader := strings.NewReader(keyAuth)
|
||||
if err := p.client.PutObject(context.Background(), p.bucket, objectKey, reader); err != nil {
|
||||
if err := p.client.PutObjectString(context.Background(), p.bucket, objectKey, keyAuth); err != nil {
|
||||
return fmt.Errorf("s3: failed to upload token to s3: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
package local
|
||||
|
||||
const (
|
||||
OUTPUT_FORMAT_PEM = "PEM"
|
||||
OUTPUT_FORMAT_PFX = "PFX"
|
||||
OUTPUT_FORMAT_JKS = "JKS"
|
||||
import (
|
||||
"github.com/certimate-go/certimate/internal/domain"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -11,3 +9,9 @@ const (
|
||||
SHELL_ENV_CMD = "cmd"
|
||||
SHELL_ENV_POWERSHELL = "powershell"
|
||||
)
|
||||
|
||||
const (
|
||||
OUTPUT_FORMAT_PEM = string(domain.CertificateFormatTypePEM)
|
||||
OUTPUT_FORMAT_PFX = string(domain.CertificateFormatTypePFX)
|
||||
OUTPUT_FORMAT_JKS = string(domain.CertificateFormatTypeJKS)
|
||||
)
|
||||
|
||||
@ -104,53 +104,59 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
|
||||
// 写入证书和私钥文件
|
||||
switch d.config.OutputFormat {
|
||||
case OUTPUT_FORMAT_PEM:
|
||||
if err := xfile.WriteString(d.config.OutputCertPath, 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))
|
||||
|
||||
if d.config.OutputServerCertPath != "" {
|
||||
if err := xfile.WriteString(d.config.OutputServerCertPath, serverCertPEM); err != nil {
|
||||
return nil, fmt.Errorf("failed to save server certificate file: %w", err)
|
||||
{
|
||||
if err := xfile.WriteString(d.config.OutputCertPath, certPEM); err != nil {
|
||||
return nil, fmt.Errorf("failed to save certificate file: %w", err)
|
||||
}
|
||||
d.logger.Info("ssl server certificate file saved", slog.String("path", d.config.OutputServerCertPath))
|
||||
}
|
||||
d.logger.Info("ssl certificate file saved", slog.String("path", d.config.OutputCertPath))
|
||||
|
||||
if d.config.OutputIntermediaCertPath != "" {
|
||||
if err := xfile.WriteString(d.config.OutputIntermediaCertPath, intermediaCertPEM); err != nil {
|
||||
return nil, fmt.Errorf("failed to save intermedia certificate file: %w", err)
|
||||
if d.config.OutputServerCertPath != "" {
|
||||
if err := xfile.WriteString(d.config.OutputServerCertPath, 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 intermedia certificate file saved", slog.String("path", d.config.OutputIntermediaCertPath))
|
||||
}
|
||||
|
||||
if err := xfile.WriteString(d.config.OutputKeyPath, privkeyPEM); err != nil {
|
||||
return nil, fmt.Errorf("failed to save private key file: %w", err)
|
||||
if d.config.OutputIntermediaCertPath != "" {
|
||||
if err := xfile.WriteString(d.config.OutputIntermediaCertPath, 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))
|
||||
}
|
||||
|
||||
if err := xfile.WriteString(d.config.OutputKeyPath, 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.OutputKeyPath))
|
||||
|
||||
case OUTPUT_FORMAT_PFX:
|
||||
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")
|
||||
{
|
||||
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 err := xfile.Write(d.config.OutputCertPath, pfxData); err != nil {
|
||||
return nil, fmt.Errorf("failed to save certificate file: %w", err)
|
||||
if err := xfile.Write(d.config.OutputCertPath, 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.OutputCertPath))
|
||||
|
||||
case OUTPUT_FORMAT_JKS:
|
||||
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")
|
||||
{
|
||||
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 err := xfile.Write(d.config.OutputCertPath, jksData); err != nil {
|
||||
return nil, fmt.Errorf("failed to save certificate file: %w", err)
|
||||
if err := xfile.Write(d.config.OutputCertPath, 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.OutputCertPath))
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported output format '%s'", d.config.OutputFormat)
|
||||
|
||||
11
pkg/core/deployer/providers/s3/consts.go
Normal file
11
pkg/core/deployer/providers/s3/consts.go
Normal file
@ -0,0 +1,11 @@
|
||||
package s3
|
||||
|
||||
import (
|
||||
"github.com/certimate-go/certimate/internal/domain"
|
||||
)
|
||||
|
||||
const (
|
||||
OUTPUT_FORMAT_PEM = string(domain.CertificateFormatTypePEM)
|
||||
OUTPUT_FORMAT_PFX = string(domain.CertificateFormatTypePFX)
|
||||
OUTPUT_FORMAT_JKS = string(domain.CertificateFormatTypeJKS)
|
||||
)
|
||||
169
pkg/core/deployer/providers/s3/s3.go
Normal file
169
pkg/core/deployer/providers/s3/s3.go
Normal file
@ -0,0 +1,169 @@
|
||||
package s3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/certimate-go/certimate/internal/tools/s3"
|
||||
"github.com/certimate-go/certimate/pkg/core/deployer"
|
||||
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
|
||||
)
|
||||
|
||||
type DeployerConfig struct {
|
||||
// S3 Endpoint。
|
||||
Endpoint string `json:"endpoint"`
|
||||
// S3 AccessKey。
|
||||
AccessKey string `json:"accessKey"`
|
||||
// S3 SecretKey。
|
||||
SecretKey string `json:"secretKey"`
|
||||
// S3 签名版本。
|
||||
// 可取值 "v2"、"v4"。
|
||||
// 零值时默认值 "v4"。
|
||||
SignatureVersion string `json:"signatureVersion,omitempty"`
|
||||
// 是否使用路径风格。
|
||||
UsePathStyle bool `json:"usePathStyle,omitempty"`
|
||||
// 存储区域。
|
||||
Region string `json:"region"`
|
||||
// 存储桶名。
|
||||
Bucket string `json:"bucket"`
|
||||
// 是否允许不安全的连接。
|
||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
||||
// 输出证书格式。
|
||||
OutputFormat string `json:"outputFormat,omitempty"`
|
||||
// 输出证书文件路径。
|
||||
OutputCertObjectKey string `json:"outputCertObjectKey,omitempty"`
|
||||
// 输出服务器证书文件路径。
|
||||
// 选填。
|
||||
OutputServerCertObjectKey string `json:"outputServerCertObjectKey,omitempty"`
|
||||
// 输出中间证书文件路径。
|
||||
// 选填。
|
||||
OutputIntermediaCertObjectKey string `json:"outputIntermediaCertObjectKey,omitempty"`
|
||||
// 输出私钥文件路径。
|
||||
OutputKeyObjectKey string `json:"outputKeyObjectKey,omitempty"`
|
||||
// PFX 导出密码。
|
||||
// 证书格式为 PFX 时必填。
|
||||
PfxPassword string `json:"pfxPassword,omitempty"`
|
||||
// JKS 别名。
|
||||
// 证书格式为 JKS 时必填。
|
||||
JksAlias string `json:"jksAlias,omitempty"`
|
||||
// JKS 密钥密码。
|
||||
// 证书格式为 JKS 时必填。
|
||||
JksKeypass string `json:"jksKeypass,omitempty"`
|
||||
// JKS 存储密码。
|
||||
// 证书格式为 JKS 时必填。
|
||||
JksStorepass string `json:"jksStorepass,omitempty"`
|
||||
}
|
||||
|
||||
type Deployer struct {
|
||||
config *DeployerConfig
|
||||
logger *slog.Logger
|
||||
s3Client *s3.Client
|
||||
}
|
||||
|
||||
var _ deployer.Provider = (*Deployer)(nil)
|
||||
|
||||
func NewDeployer(config *DeployerConfig) (*Deployer, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("the configuration of the deployer provider is nil")
|
||||
}
|
||||
|
||||
client, err := s3.NewClient(&s3.Config{
|
||||
Endpoint: config.Endpoint,
|
||||
AccessKey: config.AccessKey,
|
||||
SecretKey: config.SecretKey,
|
||||
SignatureVersion: config.SignatureVersion,
|
||||
UsePathStyle: config.UsePathStyle,
|
||||
Region: config.Region,
|
||||
SkipTlsVerify: config.AllowInsecureConnections,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("s3: failed to create s3 client: %w", err)
|
||||
}
|
||||
|
||||
return &Deployer{
|
||||
config: config,
|
||||
logger: slog.Default(),
|
||||
s3Client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *Deployer) SetLogger(logger *slog.Logger) {
|
||||
if logger == nil {
|
||||
d.logger = slog.New(slog.DiscardHandler)
|
||||
} else {
|
||||
d.logger = logger
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*deployer.DeployResult, error) {
|
||||
// 提取服务器证书和中间证书
|
||||
serverCertPEM, intermediaCertPEM, err := xcert.ExtractCertificatesFromPEM(certPEM)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to extract certs: %w", err)
|
||||
}
|
||||
|
||||
// 写入证书和私钥文件
|
||||
switch d.config.OutputFormat {
|
||||
case OUTPUT_FORMAT_PEM:
|
||||
{
|
||||
if err := d.s3Client.PutObjectString(ctx, d.config.Bucket, d.config.OutputCertObjectKey, 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))
|
||||
|
||||
if d.config.OutputServerCertObjectKey != "" {
|
||||
if err := d.s3Client.PutObjectString(ctx, d.config.Bucket, d.config.OutputServerCertObjectKey, 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))
|
||||
}
|
||||
|
||||
if d.config.OutputIntermediaCertObjectKey != "" {
|
||||
if err := d.s3Client.PutObjectString(ctx, d.config.Bucket, d.config.OutputIntermediaCertObjectKey, 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))
|
||||
}
|
||||
|
||||
if err := d.s3Client.PutObjectString(ctx, d.config.Bucket, d.config.OutputKeyObjectKey, 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))
|
||||
}
|
||||
|
||||
case OUTPUT_FORMAT_PFX:
|
||||
{
|
||||
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 err := d.s3Client.PutObjectBytes(ctx, d.config.Bucket, d.config.OutputCertObjectKey, 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))
|
||||
}
|
||||
|
||||
case OUTPUT_FORMAT_JKS:
|
||||
{
|
||||
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 err := d.s3Client.PutObjectBytes(ctx, d.config.Bucket, d.config.OutputCertObjectKey, 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))
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported output format '%s'", d.config.OutputFormat)
|
||||
}
|
||||
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
||||
@ -1,5 +1,9 @@
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"github.com/certimate-go/certimate/internal/domain"
|
||||
)
|
||||
|
||||
const (
|
||||
AUTH_METHOD_NONE = "none"
|
||||
AUTH_METHOD_PASSWORD = "password"
|
||||
@ -7,7 +11,8 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
OUTPUT_FORMAT_PEM = "PEM"
|
||||
OUTPUT_FORMAT_PFX = "PFX"
|
||||
OUTPUT_FORMAT_JKS = "JKS"
|
||||
OUTPUT_FORMAT_PEM = string(domain.CertificateFormatTypePEM)
|
||||
OUTPUT_FORMAT_PFX = string(domain.CertificateFormatTypePFX)
|
||||
OUTPUT_FORMAT_JKS = string(domain.CertificateFormatTypeJKS)
|
||||
)
|
||||
|
||||
|
||||
@ -202,53 +202,59 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
|
||||
// 上传证书和私钥文件
|
||||
switch d.config.OutputFormat {
|
||||
case OUTPUT_FORMAT_PEM:
|
||||
if err := xssh.WriteRemoteString(client, d.config.OutputKeyPath, 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))
|
||||
|
||||
if err := xssh.WriteRemoteString(client, d.config.OutputCertPath, 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))
|
||||
|
||||
if d.config.OutputServerCertPath != "" {
|
||||
if err := xssh.WriteRemoteString(client, d.config.OutputServerCertPath, serverCertPEM, d.config.UseSCP); err != nil {
|
||||
return nil, fmt.Errorf("failed to save server certificate file: %w", err)
|
||||
{
|
||||
if err := xssh.WriteRemoteString(client, d.config.OutputCertPath, certPEM, d.config.UseSCP); err != nil {
|
||||
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
|
||||
}
|
||||
d.logger.Info("ssl server certificate file uploaded", slog.String("path", d.config.OutputServerCertPath))
|
||||
}
|
||||
d.logger.Info("ssl certificate file uploaded", slog.String("path", d.config.OutputCertPath))
|
||||
|
||||
if d.config.OutputIntermediaCertPath != "" {
|
||||
if err := xssh.WriteRemoteString(client, d.config.OutputIntermediaCertPath, intermediaCertPEM, d.config.UseSCP); err != nil {
|
||||
return nil, fmt.Errorf("failed to save intermedia certificate file: %w", err)
|
||||
if d.config.OutputServerCertPath != "" {
|
||||
if err := xssh.WriteRemoteString(client, d.config.OutputServerCertPath, 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 intermedia certificate file uploaded", slog.String("path", d.config.OutputIntermediaCertPath))
|
||||
|
||||
if d.config.OutputIntermediaCertPath != "" {
|
||||
if err := xssh.WriteRemoteString(client, d.config.OutputIntermediaCertPath, 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))
|
||||
}
|
||||
|
||||
if err := xssh.WriteRemoteString(client, d.config.OutputKeyPath, 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))
|
||||
}
|
||||
|
||||
case OUTPUT_FORMAT_PFX:
|
||||
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")
|
||||
{
|
||||
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 err := xssh.WriteRemote(client, d.config.OutputCertPath, pfxData, d.config.UseSCP); err != nil {
|
||||
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
|
||||
if err := xssh.WriteRemote(client, d.config.OutputCertPath, 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.OutputCertPath))
|
||||
|
||||
case OUTPUT_FORMAT_JKS:
|
||||
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")
|
||||
{
|
||||
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 err := xssh.WriteRemote(client, d.config.OutputCertPath, jksData, d.config.UseSCP); err != nil {
|
||||
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
|
||||
if err := xssh.WriteRemote(client, d.config.OutputCertPath, 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.OutputCertPath))
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported output format '%s'", d.config.OutputFormat)
|
||||
|
||||
@ -70,6 +70,7 @@ import BizDeployNodeConfigFieldsProviderQiniuKodo from "./BizDeployNodeConfigFie
|
||||
import BizDeployNodeConfigFieldsProviderQiniuPili from "./BizDeployNodeConfigFieldsProviderQiniuPili";
|
||||
import BizDeployNodeConfigFieldsProviderRainYunRCDN from "./BizDeployNodeConfigFieldsProviderRainYunRCDN";
|
||||
import BizDeployNodeConfigFieldsProviderRatPanel from "./BizDeployNodeConfigFieldsProviderRatPanel.tsx";
|
||||
import BizDeployNodeConfigFieldsProviderS3 from "./BizDeployNodeConfigFieldsProviderS3";
|
||||
import BizDeployNodeConfigFieldsProviderSafeLine from "./BizDeployNodeConfigFieldsProviderSafeLine.tsx";
|
||||
import BizDeployNodeConfigFieldsProviderSSH from "./BizDeployNodeConfigFieldsProviderSSH";
|
||||
import BizDeployNodeConfigFieldsProviderSynologyDSM from "./BizDeployNodeConfigFieldsProviderSynologyDSM";
|
||||
@ -183,6 +184,7 @@ const providerComponentMap: Partial<Record<DeploymentProviderType, React.Compone
|
||||
[DEPLOYMENT_PROVIDERS.QINIU_PILI]: BizDeployNodeConfigFieldsProviderQiniuPili,
|
||||
[DEPLOYMENT_PROVIDERS.RAINYUN_RCDN]: BizDeployNodeConfigFieldsProviderRainYunRCDN,
|
||||
[DEPLOYMENT_PROVIDERS.RATPANEL]: BizDeployNodeConfigFieldsProviderRatPanel,
|
||||
[DEPLOYMENT_PROVIDERS.S3]: BizDeployNodeConfigFieldsProviderS3,
|
||||
[DEPLOYMENT_PROVIDERS.SAFELINE]: BizDeployNodeConfigFieldsProviderSafeLine,
|
||||
[DEPLOYMENT_PROVIDERS.SSH]: BizDeployNodeConfigFieldsProviderSSH,
|
||||
[DEPLOYMENT_PROVIDERS.SYNOLOGYDSM]: BizDeployNodeConfigFieldsProviderSynologyDSM,
|
||||
|
||||
@ -418,8 +418,8 @@ const BizDeployNodeConfigFieldsProviderLocal = () => {
|
||||
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
|
||||
return {
|
||||
format: FORMAT_PEM,
|
||||
certPath: "/etc/ssl/certimate/cert.crt",
|
||||
keyPath: "/etc/ssl/certimate/cert.key",
|
||||
certPath: "/etc/ssl/certimate/cert.crt",
|
||||
shellEnv: SHELLENV_SH,
|
||||
};
|
||||
};
|
||||
|
||||
@ -0,0 +1,286 @@
|
||||
import { getI18n, useTranslation } from "react-i18next";
|
||||
import { Form, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
import { CERTIFICATE_FORMATS } from "@/domain/certificate";
|
||||
|
||||
import { useFormNestedFieldsContext } from "./_context";
|
||||
|
||||
const FORMAT_PEM = CERTIFICATE_FORMATS.PEM;
|
||||
const FORMAT_PFX = CERTIFICATE_FORMATS.PFX;
|
||||
const FORMAT_JKS = CERTIFICATE_FORMATS.JKS;
|
||||
|
||||
const BizDeployNodeConfigFieldsProviderS3 = () => {
|
||||
const { i18n, t } = useTranslation();
|
||||
|
||||
const { parentNamePath } = useFormNestedFieldsContext();
|
||||
const formSchema = z.object({
|
||||
[parentNamePath]: getSchema({ i18n }),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name={[parentNamePath, "region"]}
|
||||
initialValue={initialValues.region}
|
||||
label={t("workflow_node.deploy.form.s3_region.label")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.s3_region.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "bucket"]}
|
||||
initialValue={initialValues.bucket}
|
||||
label={t("workflow_node.deploy.form.s3_bucket.label")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.s3_bucket.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "format"]}
|
||||
initialValue={initialValues.format}
|
||||
label={t("workflow_node.deploy.form.s3_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`),
|
||||
value: s,
|
||||
}))}
|
||||
placeholder={t("workflow_node.deploy.form.s3_format.placeholder")}
|
||||
onSelect={handleFormatSelect}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Show when={fieldFormat === FORMAT_PEM}>
|
||||
<Form.Item
|
||||
name={[parentNamePath, "keyObjectKey"]}
|
||||
initialValue={initialValues.keyObjectKey}
|
||||
label={t("workflow_node.deploy.form.s3_key_object_key.label")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.s3_key_object_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`)}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Input placeholder={t(`workflow_node.deploy.form.s3_${fieldFormat === FORMAT_PEM ? "fullchaincert" : "cert"}_object_key.placeholder`)} />
|
||||
</Form.Item>
|
||||
|
||||
<Show when={fieldFormat === 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")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Input allowClear placeholder={t("workflow_node.deploy.form.s3_servercert_object_key.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")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Input allowClear placeholder={t("workflow_node.deploy.form.s3_intermediacert_object_key.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Show when={fieldFormat === FORMAT_PFX}>
|
||||
<Form.Item
|
||||
name={[parentNamePath, "pfxPassword"]}
|
||||
initialValue={initialValues.pfxPassword}
|
||||
label={t("workflow_node.deploy.form.s3_pfx_password.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.s3_pfx_password.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.s3_pfx_password.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Show when={fieldFormat === 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>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.s3_jks_alias.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "jksKeypass"]}
|
||||
initialValue={initialValues.jksKeypass}
|
||||
label={t("workflow_node.deploy.form.s3_jks_keypass.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.s3_jks_keypass.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.s3_jks_keypass.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "jksStorepass"]}
|
||||
initialValue={initialValues.jksStorepass}
|
||||
label={t("workflow_node.deploy.form.s3_jks_storepass.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.s3_jks_storepass.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.s3_jks_storepass.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
|
||||
return {
|
||||
region: "",
|
||||
bucket: "",
|
||||
format: FORMAT_PEM,
|
||||
keyObjectKey: ".certimate/cert.key",
|
||||
certObjectKey: ".certimate/cert.crt",
|
||||
};
|
||||
};
|
||||
|
||||
const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> }) => {
|
||||
const { t } = i18n;
|
||||
|
||||
return z
|
||||
.object({
|
||||
region: z.string().nonempty(t("workflow_node.deploy.form.s3_region.placeholder")),
|
||||
bucket: z.string().nonempty(t("workflow_node.deploy.form.s3_bucket.placeholder")),
|
||||
format: z.literal([FORMAT_PEM, FORMAT_PFX, FORMAT_JKS], t("workflow_node.deploy.form.s3_format.placeholder")),
|
||||
keyObjectKey: z
|
||||
.string()
|
||||
.max(256, t("common.errmsg.string_max", { max: 256 }))
|
||||
.nullish(),
|
||||
certObjectKey: z
|
||||
.string()
|
||||
.min(1, t("workflow_node.deploy.form.s3_cert_object_key.placeholder"))
|
||||
.max(256, t("common.errmsg.string_max", { max: 256 })),
|
||||
certObjectKeyForServerOnly: z
|
||||
.string()
|
||||
.max(256, t("common.errmsg.string_max", { max: 256 }))
|
||||
.nullish(),
|
||||
certObjectKeyForIntermediaOnly: z
|
||||
.string()
|
||||
.max(256, t("common.errmsg.string_max", { 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) {
|
||||
case FORMAT_PEM:
|
||||
{
|
||||
if (!values.keyObjectKey?.trim()) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: t("workflow_node.deploy.form.s3_key_object_key.placeholder"),
|
||||
path: ["keyObjectKey"],
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FORMAT_PFX:
|
||||
{
|
||||
if (!values.pfxPassword?.trim()) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: t("workflow_node.deploy.form.s3_pfx_password.placeholder"),
|
||||
path: ["pfxPassword"],
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FORMAT_JKS:
|
||||
{
|
||||
if (!values.jksAlias?.trim()) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: t("workflow_node.deploy.form.s3_jks_alias.placeholder"),
|
||||
path: ["jksAlias"],
|
||||
});
|
||||
}
|
||||
|
||||
if (!values.jksKeypass?.trim()) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: t("workflow_node.deploy.form.s3_jks_keypass.placeholder"),
|
||||
path: ["jksKeypass"],
|
||||
});
|
||||
}
|
||||
|
||||
if (!values.jksStorepass?.trim()) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: t("workflow_node.deploy.form.s3_jks_storepass.placeholder"),
|
||||
path: ["jksStorepass"],
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const _default = Object.assign(BizDeployNodeConfigFieldsProviderS3, {
|
||||
getInitialValues,
|
||||
getSchema,
|
||||
});
|
||||
|
||||
export default _default;
|
||||
@ -460,8 +460,8 @@ const BizDeployNodeConfigFieldsProviderSSH = () => {
|
||||
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
|
||||
return {
|
||||
format: FORMAT_PEM,
|
||||
certPath: "/etc/ssl/certimate/cert.crt",
|
||||
keyPath: "/etc/ssl/certimate/cert.key",
|
||||
certPath: "/etc/ssl/certimate/cert.crt",
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -615,6 +615,7 @@ export const DEPLOYMENT_PROVIDERS = Object.freeze({
|
||||
RAINYUN_RCDN: `${ACCESS_PROVIDERS.RAINYUN}-rcdn`,
|
||||
RATPANEL: `${ACCESS_PROVIDERS.RATPANEL}`,
|
||||
RATPANEL_CONSOLE: `${ACCESS_PROVIDERS.RATPANEL}-console`,
|
||||
S3: `${ACCESS_PROVIDERS.S3}`,
|
||||
SAFELINE: `${ACCESS_PROVIDERS.SAFELINE}`,
|
||||
SSH: `${ACCESS_PROVIDERS.SSH}`,
|
||||
SYNOLOGYDSM: `${ACCESS_PROVIDERS.SYNOLOGYDSM}`,
|
||||
@ -690,6 +691,7 @@ export const deploymentProvidersMap: Map<DeploymentProvider["type"] | string, De
|
||||
[DEPLOYMENT_PROVIDERS.SSH, "provider.ssh", DEPLOYMENT_CATEGORIES.OTHER],
|
||||
[DEPLOYMENT_PROVIDERS.WEBHOOK, "provider.webhook", DEPLOYMENT_CATEGORIES.OTHER],
|
||||
[DEPLOYMENT_PROVIDERS.KUBERNETES_SECRET, "provider.kubernetes_secret", DEPLOYMENT_CATEGORIES.OTHER],
|
||||
[DEPLOYMENT_PROVIDERS.S3, "provider.s3_upload", DEPLOYMENT_CATEGORIES.STORAGE],
|
||||
[DEPLOYMENT_PROVIDERS.ALIYUN_OSS, "provider.aliyun_oss", DEPLOYMENT_CATEGORIES.STORAGE],
|
||||
[DEPLOYMENT_PROVIDERS.ALIYUN_CDN, "provider.aliyun_cdn", DEPLOYMENT_CATEGORIES.CDN],
|
||||
[DEPLOYMENT_PROVIDERS.ALIYUN_DCDN, "provider.aliyun_dcdn", DEPLOYMENT_CATEGORIES.CDN],
|
||||
|
||||
@ -159,6 +159,7 @@
|
||||
"provider.ratpanel_console": "AcePanel - Console itself",
|
||||
"provider.rfc2136": "RFC 2136: Dynamic DNS Updates",
|
||||
"provider.s3": "Object storage (S3-compatible)",
|
||||
"provider.s3_upload": "Upload to S3-compatible object storage",
|
||||
"provider.safeline": "SafeLine",
|
||||
"provider.sectigo": "Sectigo",
|
||||
"provider.slackbot": "Slack Bot",
|
||||
|
||||
@ -779,6 +779,39 @@
|
||||
"workflow_node.deploy.form.ratpanel_site_names.tooltip": "You can find it on AcePanel dashboard.",
|
||||
"workflow_node.deploy.form.ratpanel_site_names.multiple_input_modal.title": "Change AcePanel website names",
|
||||
"workflow_node.deploy.form.ratpanel_site_names.multiple_input_modal.placeholder": "Please enter AcePanel website name",
|
||||
"workflow_node.deploy.form.s3_region.label": "Object storage (S3-compatible) region",
|
||||
"workflow_node.deploy.form.s3_region.placeholder": "Please enter region",
|
||||
"workflow_node.deploy.form.s3_bucket.label": "Object storage (S3-compatible) bucket",
|
||||
"workflow_node.deploy.form.s3_bucket.placeholder": "Please enter bucket name",
|
||||
"workflow_node.deploy.form.s3_format.label": "File format",
|
||||
"workflow_node.deploy.form.s3_format.placeholder": "Please select file format",
|
||||
"workflow_node.deploy.form.s3_format.option.pem.label": "PEM (*.pem, *.crt, *.key)",
|
||||
"workflow_node.deploy.form.s3_format.option.pfx.label": "PFX (*.pfx, *.p12)",
|
||||
"workflow_node.deploy.form.s3_format.option.jks.label": "JKS (*.jks)",
|
||||
"workflow_node.deploy.form.s3_key_object_key.label": "Private key file object key",
|
||||
"workflow_node.deploy.form.s3_key_object_key.placeholder": "Please enter the object key for private key file",
|
||||
"workflow_node.deploy.form.s3_cert_object_key.label": "Certificate file object key",
|
||||
"workflow_node.deploy.form.s3_cert_object_key.placeholder": "Please enter the object key for certificate",
|
||||
"workflow_node.deploy.form.s3_fullchaincert_object_key.label": "Bundled fullchain certificate object key",
|
||||
"workflow_node.deploy.form.s3_fullchaincert_object_key.placeholder": "Please enter the remote path for bundled fullchain certificate",
|
||||
"workflow_node.deploy.form.s3_servercert_object_key.label": "Server certificate object key (Optional)",
|
||||
"workflow_node.deploy.form.s3_servercert_object_key.placeholder": "Please enter the object key for server certificate file",
|
||||
"workflow_node.deploy.form.s3_servercert_object_key.help": "",
|
||||
"workflow_node.deploy.form.s3_intermediacert_object_key.label": "Intermediate CA certificate object key (Optional)",
|
||||
"workflow_node.deploy.form.s3_intermediacert_object_key.placeholder": "Please enter the object key for intermediate CA certificate file",
|
||||
"workflow_node.deploy.form.s3_intermediacert_object_key.help": "",
|
||||
"workflow_node.deploy.form.s3_pfx_password.label": "PFX password",
|
||||
"workflow_node.deploy.form.s3_pfx_password.placeholder": "Please enter PFX password",
|
||||
"workflow_node.deploy.form.s3_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>",
|
||||
"workflow_node.deploy.form.s3_jks_alias.label": "JKS alias",
|
||||
"workflow_node.deploy.form.s3_jks_alias.placeholder": "Please enter JKS alias",
|
||||
"workflow_node.deploy.form.s3_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>",
|
||||
"workflow_node.deploy.form.s3_jks_keypass.label": "JKS key password",
|
||||
"workflow_node.deploy.form.s3_jks_keypass.placeholder": "Please enter JKS key password",
|
||||
"workflow_node.deploy.form.s3_jks_keypass.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>",
|
||||
"workflow_node.deploy.form.s3_jks_storepass.label": "JKS store password",
|
||||
"workflow_node.deploy.form.s3_jks_storepass.placeholder": "Please enter JKS store password",
|
||||
"workflow_node.deploy.form.s3_jks_storepass.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>",
|
||||
"workflow_node.deploy.form.safeline_resource_type.option.certificate.label": "Certificate",
|
||||
"workflow_node.deploy.form.safeline_certificate_id.label": "SafeLine certificate ID",
|
||||
"workflow_node.deploy.form.safeline_certificate_id.placeholder": "Please enter SafeLine certificate ID",
|
||||
|
||||
@ -159,6 +159,7 @@
|
||||
"provider.ratpanel_console": "耗子面板 - 面板自身",
|
||||
"provider.rfc2136": "RFC 2136: Dynamic DNS Updates",
|
||||
"provider.s3": "对象存储(S3 兼容)",
|
||||
"provider.s3_upload": "上传到 S3 兼容的对象存储",
|
||||
"provider.safeline": "雷池",
|
||||
"provider.sectigo": "Sectigo",
|
||||
"provider.slackbot": "Slack 机器人",
|
||||
|
||||
@ -777,6 +777,39 @@
|
||||
"workflow_node.deploy.form.ratpanel_site_names.tooltip": "请登录耗子面板查看",
|
||||
"workflow_node.deploy.form.ratpanel_site_names.multiple_input_modal.title": "修改耗子面板网站名称",
|
||||
"workflow_node.deploy.form.ratpanel_site_names.multiple_input_modal.placeholder": "请输入耗子面板网站名称",
|
||||
"workflow_node.deploy.form.s3_region.label": "对象存储区域",
|
||||
"workflow_node.deploy.form.s3_region.placeholder": "请输入对象存储区域",
|
||||
"workflow_node.deploy.form.s3_bucket.label": "对象存储桶名",
|
||||
"workflow_node.deploy.form.s3_bucket.placeholder": "请输入对象存储桶名",
|
||||
"workflow_node.deploy.form.s3_format.label": "文件格式",
|
||||
"workflow_node.deploy.form.s3_format.placeholder": "请选择文件格式",
|
||||
"workflow_node.deploy.form.s3_format.option.pem.label": "PEM 格式(*.pem, *.crt, *.key)",
|
||||
"workflow_node.deploy.form.s3_format.option.pfx.label": "PFX 格式(*.pfx, *.p12)",
|
||||
"workflow_node.deploy.form.s3_format.option.jks.label": "JKS 格式(*.jks)",
|
||||
"workflow_node.deploy.form.s3_key_object_key.label": "私钥文件对象键",
|
||||
"workflow_node.deploy.form.s3_key_object_key.placeholder": "请输入私钥文件对象键",
|
||||
"workflow_node.deploy.form.s3_cert_object_key.label": "证书文件对象键",
|
||||
"workflow_node.deploy.form.s3_cert_object_key.placeholder": "请输入证书文件对象键",
|
||||
"workflow_node.deploy.form.s3_fullchaincert_object_key.label": "证书链文件对象键",
|
||||
"workflow_node.deploy.form.s3_fullchaincert_object_key.placeholder": "请输入证书链文件对象键",
|
||||
"workflow_node.deploy.form.s3_servercert_object_key.label": "服务器证书文件对象键(可选)",
|
||||
"workflow_node.deploy.form.s3_servercert_object_key.placeholder": "请输入服务器证书文件对象键",
|
||||
"workflow_node.deploy.form.s3_servercert_object_key.help": "注意:不填写时将不会上传服务器证书。",
|
||||
"workflow_node.deploy.form.s3_intermediacert_object_key.label": "中间证书文件对象键(可选)",
|
||||
"workflow_node.deploy.form.s3_intermediacert_object_key.placeholder": "请输入中间证书文件对象键",
|
||||
"workflow_node.deploy.form.s3_intermediacert_object_key.help": "注意:不填写时将不会上传中间证书。",
|
||||
"workflow_node.deploy.form.s3_pfx_password.label": "PFX 导出密码",
|
||||
"workflow_node.deploy.form.s3_pfx_password.placeholder": "请输入 PFX 导出密码",
|
||||
"workflow_node.deploy.form.s3_pfx_password.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>",
|
||||
"workflow_node.deploy.form.s3_jks_alias.label": "JKS 别名",
|
||||
"workflow_node.deploy.form.s3_jks_alias.placeholder": "请输入 JKS 别名",
|
||||
"workflow_node.deploy.form.s3_jks_alias.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>",
|
||||
"workflow_node.deploy.form.s3_jks_keypass.label": "JKS 私钥访问口令",
|
||||
"workflow_node.deploy.form.s3_jks_keypass.placeholder": "请输入 JKS 私钥访问口令",
|
||||
"workflow_node.deploy.form.s3_jks_keypass.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>",
|
||||
"workflow_node.deploy.form.s3_jks_storepass.label": "JKS 密钥库存储口令",
|
||||
"workflow_node.deploy.form.s3_jks_storepass.placeholder": "请输入 JKS 密钥库存储口令",
|
||||
"workflow_node.deploy.form.s3_jks_storepass.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>",
|
||||
"workflow_node.deploy.form.safeline_resource_type.option.certificate.label": "替换指定证书",
|
||||
"workflow_node.deploy.form.safeline_certificate_id.label": "雷池证书 ID",
|
||||
"workflow_node.deploy.form.safeline_certificate_id.placeholder": "请输入雷池证书 ID",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user