diff --git a/go.mod b/go.mod
index f9742529..27529ef8 100644
--- a/go.mod
+++ b/go.mod
@@ -9,6 +9,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.0
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates v1.4.0
github.com/G-Core/gcorelabscdn-go v1.0.35
+ github.com/KscSDK/ksc-sdk-go v0.14.0
github.com/alibabacloud-go/alb-20200616/v2 v2.2.9
github.com/alibabacloud-go/apig-20240327/v5 v5.0.1
github.com/alibabacloud-go/cas-20200407/v4 v4.0.3
@@ -27,6 +28,7 @@ require (
github.com/alibabacloud-go/vod-20170321/v4 v4.10.0
github.com/alibabacloud-go/waf-openapi-20211001/v6 v6.7.0
github.com/aliyun/alibabacloud-oss-go-sdk-v2 v1.3.0
+ github.com/aws/aws-sdk-go v1.40.45
github.com/aws/aws-sdk-go-v2/service/acm v1.37.10
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.55.3
github.com/aws/aws-sdk-go-v2/service/iam v1.49.1
diff --git a/go.sum b/go.sum
index 3613e26b..12c973f5 100644
--- a/go.sum
+++ b/go.sum
@@ -71,6 +71,8 @@ github.com/G-Core/gcorelabscdn-go v1.0.35/go.mod h1:iSGXaTvZBzDHQW+rKFS918BgFVpO
github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
+github.com/KscSDK/ksc-sdk-go v0.14.0 h1:3bw0XicOLDNfxhljsTCtf1Ya93ZBxRtFtp5gD31bsjs=
+github.com/KscSDK/ksc-sdk-go v0.14.0/go.mod h1:isHlJZi429ff5JLemSc10h7nznNgzJAY4MmNM8u7SBo=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/sarama v1.30.1/go.mod h1:hGgx05L/DiW8XYBXeJdKIN6V2QUy2H6JqME5VT1NLRw=
@@ -216,6 +218,8 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3d
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0=
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
+github.com/aws/aws-sdk-go v1.25.3/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
+github.com/aws/aws-sdk-go v1.40.45 h1:QN1nsY27ssD/JmW4s83qmSb+uL6DG4GmCDzjmJB4xUI=
github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
github.com/aws/aws-sdk-go-v2 v1.39.5 h1:e/SXuia3rkFtapghJROrydtQpfQaaUgd1cUvyO1mp2w=
@@ -568,6 +572,7 @@ github.com/jdcloud-api/jdcloud-sdk-go v1.64.0/go.mod h1:UrKjuULIWLjHFlG6aSPunArE
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jinzhu/copier v0.3.4 h1:mfU6jI9PtCeUjkjQ322dlff9ELjGDu975C2p/nrubVI=
github.com/jinzhu/copier v0.3.4/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
+github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
diff --git a/internal/certdeploy/deployers/sp_ksyun_cdn.go b/internal/certdeploy/deployers/sp_ksyun_cdn.go
new file mode 100644
index 00000000..b7bd8362
--- /dev/null
+++ b/internal/certdeploy/deployers/sp_ksyun_cdn.go
@@ -0,0 +1,29 @@
+package deployers
+
+import (
+ "fmt"
+
+ "github.com/certimate-go/certimate/internal/domain"
+ "github.com/certimate-go/certimate/pkg/core"
+ ksyuncdn "github.com/certimate-go/certimate/pkg/core/ssl-deployer/providers/ksyun-cdn"
+ xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
+)
+
+func init() {
+ if err := Registries.Register(domain.DeploymentProviderTypeKsyunCDN, func(options *ProviderFactoryOptions) (core.SSLDeployer, error) {
+ credentials := domain.AccessConfigForKsyun{}
+ if err := xmaps.Populate(options.ProviderAccessConfig, &credentials); err != nil {
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ }
+
+ provider, err := ksyuncdn.NewSSLDeployerProvider(&ksyuncdn.SSLDeployerProviderConfig{
+ AccessKeyId: credentials.AccessKeyId,
+ SecretAccessKey: credentials.SecretAccessKey,
+ Domain: xmaps.GetString(options.ProviderExtendedConfig, "domain"),
+ CertificateId: xmaps.GetString(options.ProviderExtendedConfig, "certificateId"),
+ })
+ return provider, err
+ }); err != nil {
+ panic(err)
+ }
+}
diff --git a/internal/domain/access.go b/internal/domain/access.go
index 972c7fd3..31d2255d 100644
--- a/internal/domain/access.go
+++ b/internal/domain/access.go
@@ -298,6 +298,11 @@ type AccessConfigForKubernetes struct {
KubeConfig string `json:"kubeConfig,omitempty"`
}
+type AccessConfigForKsyun struct {
+ AccessKeyId string `json:"accessKeyId"`
+ SecretAccessKey string `json:"secretAccessKey"`
+}
+
type AccessConfigForLarkBot struct {
WebhookUrl string `json:"webhookUrl"`
Secret string `json:"secret,omitempty"`
diff --git a/internal/domain/provider.go b/internal/domain/provider.go
index c640c55b..0ebd173d 100644
--- a/internal/domain/provider.go
+++ b/internal/domain/provider.go
@@ -64,7 +64,7 @@ const (
AccessProviderTypeIONOS = AccessProviderType("ionos")
AccessProviderTypeJDCloud = AccessProviderType("jdcloud")
AccessProviderTypeKong = AccessProviderType("kong")
- AccessProviderTypeKsyun = AccessProviderType("ksyun") // 金山云(预留)
+ AccessProviderTypeKsyun = AccessProviderType("ksyun")
AccessProviderTypeKubernetes = AccessProviderType("k8s")
AccessProviderTypeLarkBot = AccessProviderType("larkbot")
AccessProviderTypeLeCDN = AccessProviderType("lecdn")
@@ -290,6 +290,7 @@ const (
DeploymentProviderTypeJDCloudVOD = DeploymentProviderType(AccessProviderTypeJDCloud + "-vod")
DeploymentProviderTypeKong = DeploymentProviderType(AccessProviderTypeKong)
DeploymentProviderTypeKubernetesSecret = DeploymentProviderType(AccessProviderTypeKubernetes + "-secret")
+ DeploymentProviderTypeKsyunCDN = DeploymentProviderType(AccessProviderTypeKsyun + "-cdn")
DeploymentProviderTypeLeCDN = DeploymentProviderType(AccessProviderTypeLeCDN)
DeploymentProviderTypeLocal = DeploymentProviderType(AccessProviderTypeLocal)
DeploymentProviderTypeNetlifySite = DeploymentProviderType(AccessProviderTypeNetlify + "-site")
diff --git a/pkg/core/ssl-deployer/providers/ksyun-cdn/ksyun_cdn.go b/pkg/core/ssl-deployer/providers/ksyun-cdn/ksyun_cdn.go
new file mode 100644
index 00000000..ead9dbc5
--- /dev/null
+++ b/pkg/core/ssl-deployer/providers/ksyun-cdn/ksyun_cdn.go
@@ -0,0 +1,174 @@
+package ksyuncdn
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "log/slog"
+ "strings"
+ "time"
+
+ "github.com/KscSDK/ksc-sdk-go/ksc"
+ ksccdnv1 "github.com/KscSDK/ksc-sdk-go/service/cdnv1"
+ "github.com/go-viper/mapstructure/v2"
+
+ "github.com/certimate-go/certimate/pkg/core"
+)
+
+type SSLDeployerProviderConfig struct {
+ // 金山云 AccessKeyId。
+ AccessKeyId string `json:"accessKeyId"`
+ // 金山云 SecretAccessKey。
+ SecretAccessKey string `json:"secretAccessKey"`
+ // 加速域名(支持泛域名)。
+ Domain string `json:"domain"`
+ // 证书 ID。
+ // 选填。零值时表示新建证书;否则表示更新证书。
+ CertificateId string `json:"certificateId,omitempty"`
+}
+
+type SSLDeployerProvider struct {
+ config *SSLDeployerProviderConfig
+ logger *slog.Logger
+ sdkClient *ksccdnv1.Cdnv1
+}
+
+var _ core.SSLDeployer = (*SSLDeployerProvider)(nil)
+
+func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProvider, error) {
+ if config == nil {
+ return nil, errors.New("the configuration of the ssl deployer provider is nil")
+ }
+
+ client, err := createSDKClient(config.AccessKeyId, config.SecretAccessKey)
+ if err != nil {
+ return nil, fmt.Errorf("could not create sdk client: %w", err)
+ }
+
+ return &SSLDeployerProvider{
+ config: config,
+ logger: slog.Default(),
+ sdkClient: client,
+ }, nil
+}
+
+func (d *SSLDeployerProvider) SetLogger(logger *slog.Logger) {
+ if logger == nil {
+ d.logger = slog.New(slog.DiscardHandler)
+ } else {
+ d.logger = logger
+ }
+}
+
+func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*core.SSLDeployResult, error) {
+ // // 如果原证书 ID 为空,则创建证书;否则更新证书。
+ if d.config.CertificateId == "" {
+ if d.config.Domain == "" {
+ return nil, errors.New("config `domain` is required")
+ }
+
+ // 遍历查询域名列表,获取域名 ID
+ // https://docs.ksyun.com/documents/198
+ var domainId string
+ getCdnDomainsPageNumber := int32(1)
+ getCdnDomainsPageSize := int32(100)
+ for {
+ select {
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ default:
+ }
+
+ getCdnDomainsInput := map[string]any{
+ "PageNumber": getCdnDomainsPageNumber,
+ "PageSize": getCdnDomainsPageSize,
+ "DomainName": d.config.Domain,
+ "FuzzyMatch": "off",
+ }
+ getCdnDomainsReq, getCdnDomainsOutput := d.sdkClient.GetCdnDomainsPostRequest(&getCdnDomainsInput)
+ getCdnDomainsErr := getCdnDomainsReq.Send()
+ d.logger.Debug("sdk request 'cdn.GetCdnDomains'", slog.Any("request", getCdnDomainsInput), slog.Any("response", getCdnDomainsOutput))
+ if getCdnDomainsErr != nil {
+ return nil, fmt.Errorf("failed to execute sdk request 'cdn.GetCdnDomains': %w", getCdnDomainsErr)
+ }
+
+ type GetCdnDomainsResponse struct {
+ PageNumber int32 `json:"PageNumber"`
+ PageSize int32 `json:"PageSize"`
+ TotalCount int32 `json:"TotalCount"`
+ Domains []*struct {
+ DomainId string `json:"DomainId"`
+ DomainName string `json:"DomainName"`
+ Cname string `json:"Cname"`
+ CdnType string `json:"CdnType"`
+ CreatedTime string `json:"CreatedTime"`
+ ModifiedTime string `json:"ModifiedTime"`
+ Region string `json:"Region"`
+ } `json:"Domains"`
+ }
+ var getCdnDomainsResp *GetCdnDomainsResponse
+ mapstructure.Decode(getCdnDomainsOutput, &getCdnDomainsResp)
+
+ if getCdnDomainsResp != nil {
+ for _, domainItem := range getCdnDomainsResp.Domains {
+ if strings.EqualFold(domainItem.DomainName, d.config.Domain) {
+ domainId = domainItem.DomainId
+ break
+ }
+ }
+
+ if domainId != "" {
+ break
+ }
+ }
+
+ if getCdnDomainsResp == nil || len(getCdnDomainsResp.Domains) < int(getCdnDomainsPageSize) {
+ break
+ } else {
+ getCdnDomainsPageNumber++
+ }
+ }
+ if domainId == "" {
+ return nil, errors.New("domain not found")
+ }
+
+ // 为加速域名配置证书接口
+ // https://docs.ksyun.com/documents/261
+ configCertificateInput := map[string]any{
+ "Enable": "on",
+ "DomainIds": domainId,
+ "CertificateName": fmt.Sprintf("certimate_%d", time.Now().UnixMilli()),
+ "ServerCertificate": certPEM,
+ "PrivateKey": privkeyPEM,
+ }
+ configCertificateReq, configCertificateOutput := d.sdkClient.ConfigCertificatePostRequest(&configCertificateInput)
+ configCertificateErr := configCertificateReq.Send()
+ d.logger.Debug("sdk request 'cdn.ConfigCertificate'", slog.Any("request", configCertificateInput), slog.Any("response", configCertificateOutput))
+ if configCertificateErr != nil {
+ return nil, fmt.Errorf("failed to execute sdk request 'cdn.ConfigCertificate': %w", configCertificateErr)
+ }
+ } else {
+ // 更新证书
+ // https://docs.ksyun.com/documents/259
+ setCertificateInput := map[string]any{
+ "CertificateId": d.config.CertificateId,
+ "CertificateName": fmt.Sprintf("certimate_%d", time.Now().UnixMilli()),
+ "ServerCertificate": certPEM,
+ "PrivateKey": privkeyPEM,
+ }
+ setCertificateReq, setCertificateOutput := d.sdkClient.SetCertificatePostRequest(&setCertificateInput)
+ setCertificateErr := setCertificateReq.Send()
+ d.logger.Debug("sdk request 'cdn.SetCertificate'", slog.Any("request", setCertificateInput), slog.Any("response", setCertificateOutput))
+ if setCertificateErr != nil {
+ return nil, fmt.Errorf("failed to execute sdk request 'cdn.SetCertificate': %w", setCertificateErr)
+ }
+ }
+
+ return &core.SSLDeployResult{}, nil
+}
+
+func createSDKClient(accessKeyId, secretAccessKey string) (*ksccdnv1.Cdnv1, error) {
+ region := "cn-beijing-6"
+ client := ksccdnv1.SdkNew(ksc.NewClient(accessKeyId, secretAccessKey), &ksc.Config{Region: ®ion})
+ return client, nil
+}
diff --git a/pkg/core/ssl-deployer/providers/ksyun-cdn/ksyun_cdn_test.go b/pkg/core/ssl-deployer/providers/ksyun-cdn/ksyun_cdn_test.go
new file mode 100644
index 00000000..e5fdb5f8
--- /dev/null
+++ b/pkg/core/ssl-deployer/providers/ksyun-cdn/ksyun_cdn_test.go
@@ -0,0 +1,80 @@
+package ksyuncdn_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/certimate-go/certimate/pkg/core/ssl-deployer/providers/ksyun-cdn"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fAccessKeyId string
+ fSecretAccessKey string
+ fDomain string
+ fCertificateId string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_SSLDEPLOYER_KSYUNCDN_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
+ flag.StringVar(&fSecretAccessKey, argsPrefix+"SECRETACCESSKEY", "", "")
+ flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
+ flag.StringVar(&fCertificateId, argsPrefix+"CERTIFICATEID", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./ksyun_cdn_test.go -args \
+ --CERTIMATE_SSLDEPLOYER_KSYUNCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_SSLDEPLOYER_KSYUNCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_SSLDEPLOYER_KSYUNCDN_ACCESSKEYID="your-access-key-id" \
+ --CERTIMATE_SSLDEPLOYER_KSYUNCDN_SECRETACCESSKEY="your-secret-access-key" \
+ --CERTIMATE_SSLDEPLOYER_KSYUNCDN_DOMAIN="example.com" \
+ --CERTIMATE_SSLDEPLOYER_KSYUNCDN_CERTIFICATEID="your-certificate-id"
+*/
+func TestDeploy(t *testing.T) {
+ flag.Parse()
+
+ t.Run("Deploy", func(t *testing.T) {
+ t.Log(strings.Join([]string{
+ "args:",
+ fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
+ fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
+ fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId),
+ fmt.Sprintf("SECRETACCESSKEY: %v", fSecretAccessKey),
+ fmt.Sprintf("DOMAIN: %v", fDomain),
+ fmt.Sprintf("CERTIFICATEID: %v", fCertificateId),
+ }, "\n"))
+
+ deployer, err := provider.NewSSLDeployerProvider(&provider.SSLDeployerProviderConfig{
+ AccessKeyId: fAccessKeyId,
+ SecretAccessKey: fSecretAccessKey,
+ Domain: fDomain,
+ CertificateId: fCertificateId,
+ })
+ if err != nil {
+ t.Errorf("err: %+v", err)
+ return
+ }
+
+ fInputCertData, _ := os.ReadFile(fInputCertPath)
+ fInputKeyData, _ := os.ReadFile(fInputKeyPath)
+ res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData))
+ if err != nil {
+ t.Errorf("err: %+v", err)
+ return
+ }
+
+ t.Logf("ok: %v", res)
+ })
+}
diff --git a/ui/public/imgs/providers/ksyun.svg b/ui/public/imgs/providers/ksyun.svg
new file mode 100644
index 00000000..424a5f12
--- /dev/null
+++ b/ui/public/imgs/providers/ksyun.svg
@@ -0,0 +1 @@
+
diff --git a/ui/src/components/access/forms/AccessConfigFieldsProvider.tsx b/ui/src/components/access/forms/AccessConfigFieldsProvider.tsx
index 135c7a80..5681b69e 100644
--- a/ui/src/components/access/forms/AccessConfigFieldsProvider.tsx
+++ b/ui/src/components/access/forms/AccessConfigFieldsProvider.tsx
@@ -54,6 +54,7 @@ import AccessConfigFieldsProviderInfomaniak from "./AccessConfigFieldsProviderIn
import AccessConfigFieldsProviderIONOS from "./AccessConfigFieldsProviderIONOS";
import AccessConfigFieldsProviderJDCloud from "./AccessConfigFieldsProviderJDCloud";
import AccessConfigFieldsProviderKong from "./AccessConfigFieldsProviderKong";
+import AccessConfigFieldsProviderKsyun from "./AccessConfigFieldsProviderKsyun";
import AccessConfigFieldsProviderKubernetes from "./AccessConfigFieldsProviderKubernetes";
import AccessConfigFieldsProviderLarkBot from "./AccessConfigFieldsProviderLarkBot";
import AccessConfigFieldsProviderLeCDN from "./AccessConfigFieldsProviderLeCDN";
@@ -151,6 +152,7 @@ const providerComponentMap: Partial {
+ const { i18n, t } = useTranslation();
+
+ const { parentNamePath } = useFormNestedFieldsContext();
+ const formSchema = z.object({
+ [parentNamePath]: getSchema({ i18n }),
+ });
+ const formRule = createSchemaFieldRule(formSchema);
+ const initialValues = getInitialValues();
+
+ return (
+ <>
+ }
+ >
+
+
+
+ }
+ >
+
+
+ >
+ );
+};
+
+const getInitialValues = (): Nullish>> => {
+ return {
+ accessKeyId: "",
+ secretAccessKey: "",
+ };
+};
+
+const getSchema = ({ i18n = getI18n() }: { i18n: ReturnType }) => {
+ const { t } = i18n;
+
+ return z.object({
+ accessKeyId: z.string().nonempty(t("access.form.ksyun_access_key_id.placeholder")),
+ secretAccessKey: z.string().nonempty(t("access.form.ksyun_secret_access_key.placeholder")),
+ });
+};
+
+const _default = Object.assign(AccessConfigFormFieldsProviderKsyun, {
+ getInitialValues,
+ getSchema,
+});
+
+export default _default;
diff --git a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider.tsx b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider.tsx
index b1278a1a..81d02b73 100644
--- a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider.tsx
+++ b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider.tsx
@@ -55,6 +55,7 @@ import BizDeployNodeConfigFieldsProviderJDCloudCDN from "./BizDeployNodeConfigFi
import BizDeployNodeConfigFieldsProviderJDCloudLive from "./BizDeployNodeConfigFieldsProviderJDCloudLive";
import BizDeployNodeConfigFieldsProviderJDCloudVOD from "./BizDeployNodeConfigFieldsProviderJDCloudVOD";
import BizDeployNodeConfigFieldsProviderKong from "./BizDeployNodeConfigFieldsProviderKong";
+import BizDeployNodeConfigFieldsProviderKsyunCDN from "./BizDeployNodeConfigFieldsProviderKsyunCDN";
import BizDeployNodeConfigFieldsProviderKubernetesSecret from "./BizDeployNodeConfigFieldsProviderKubernetesSecret";
import BizDeployNodeConfigFieldsProviderLeCDN from "./BizDeployNodeConfigFieldsProviderLeCDN";
import BizDeployNodeConfigFieldsProviderLocal from "./BizDeployNodeConfigFieldsProviderLocal";
@@ -157,6 +158,7 @@ const providerComponentMap: Partial {
+ const { i18n, t } = useTranslation();
+
+ const { parentNamePath } = useFormNestedFieldsContext();
+ const formSchema = z.object({
+ [parentNamePath]: getSchema({ i18n }),
+ });
+ const formRule = createSchemaFieldRule(formSchema);
+ const initialValues = getInitialValues();
+
+ return (
+ <>
+
+
+
+
+ }
+ >
+
+
+ >
+ );
+};
+
+const getInitialValues = (): Nullish>> => {
+ return {
+ domain: "",
+ };
+};
+
+const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType }) => {
+ const { t } = i18n;
+
+ return z.object({
+ domain: z.string().refine((v) => validDomainName(v, { allowWildcard: true }), t("common.errmsg.domain_invalid")),
+ certificateId: z.string().nullish(),
+ });
+};
+
+const _default = Object.assign(BizDeployNodeConfigFieldsProviderKsyunCDN, {
+ getInitialValues,
+ getSchema,
+});
+
+export default _default;
diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts
index ab93f557..d4ffa120 100644
--- a/ui/src/domain/provider.ts
+++ b/ui/src/domain/provider.ts
@@ -68,6 +68,7 @@ export const ACCESS_PROVIDERS = Object.freeze({
JDCLOUD: "jdcloud",
KONG: "kong",
KUBERNETES: "k8s",
+ KSYUN: "ksyun",
LARKBOT: "larkbot",
LECDN: "lecdn",
LETSENCRYPT: "letsencrypt",
@@ -158,6 +159,7 @@ export const accessProvidersMap: Maphttps://developer.konghq.com/admin-api/",
+ "access.form.ksyun_access_key_id.label": "Kingsoft Cloud AccessKeyID",
+ "access.form.ksyun_access_key_id.placeholder": "Please enter Kingsoft Cloud AccessKeyID",
+ "access.form.ksyun_access_key_id.tooltip": "For more information, see https://endocs.ksyun.com/documents/37659",
+ "access.form.ksyun_secret_access_key.label": "Kingsoft Cloud SecretAccessKey",
+ "access.form.ksyun_secret_access_key.placeholder": "Please enter Kingsoft Cloud SecretAccessKey",
+ "access.form.ksyun_secret_access_key.tooltip": "For more information, see https://endocs.ksyun.com/documents/37659",
"access.form.larkbot_webhook_url.label": "Lark bot Webhook URL",
"access.form.larkbot_webhook_url.placeholder": "Please enter Lark bot Webhook URL",
"access.form.larkbot_webhook_url.tooltip": "For more information, see https://open.larksuite.com/document/client-docs/bot-v3/add-custom-bot",
diff --git a/ui/src/i18n/locales/en/nls.provider.json b/ui/src/i18n/locales/en/nls.provider.json
index 9207ee4d..5fe77f30 100644
--- a/ui/src/i18n/locales/en/nls.provider.json
+++ b/ui/src/i18n/locales/en/nls.provider.json
@@ -117,6 +117,8 @@
"provider.kong": "Kong",
"provider.kubernetes": "Kubernetes",
"provider.kubernetes.secret": "Kubernetes - Secret",
+ "provider.ksyun": "Kingsoft Cloud",
+ "provider.ksyun.cdn": "Kingsoft Cloud - CDN (Content Delivery Network)",
"provider.larkbot": "Lark Bot",
"provider.lecdn": "LeCDN",
"provider.letsencrypt": "Let's Encrypt",
diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json
index 3da7d67b..8209bc5f 100644
--- a/ui/src/i18n/locales/en/nls.workflow.nodes.json
+++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json
@@ -618,6 +618,12 @@
"workflow_node.deploy.form.kong_certificate_id.label": "Kong certificate ID",
"workflow_node.deploy.form.kong_certificate_id.placeholder": "Please enter Kong certificate ID",
"workflow_node.deploy.form.kong_certificate_id.tooltip": "You can find it on Kong dashboard.",
+ "workflow_node.deploy.form.ksyun_cdn_domain.label": "Kingsoft Cloud CDN domain",
+ "workflow_node.deploy.form.ksyun_cdn_domain.placeholder": "Please enter Kingsoft Cloud CDN domain name",
+ "workflow_node.deploy.form.ksyun_cdn_certificate_id.label": "Kingsoft Cloud CDN certificate ID (Optional)",
+ "workflow_node.deploy.form.ksyun_cdn_certificate_id.placeholder": "Please enter Kingsoft Cloud CDN certificate ID",
+ "workflow_node.deploy.form.ksyun_cdn_certificate_id.help": "",
+ "workflow_node.deploy.form.ksyun_cdn_certificate_id.tooltip": "For more information, see https://cdn.console.ksyun.com/",
"workflow_node.deploy.form.lecdn_resource_type.label": "Resource type",
"workflow_node.deploy.form.lecdn_resource_type.placeholder": "Please select resource type",
"workflow_node.deploy.form.lecdn_resource_type.option.certificate.label": "Certificate",
diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json
index dbf7cb23..3726d063 100644
--- a/ui/src/i18n/locales/zh/nls.access.json
+++ b/ui/src/i18n/locales/zh/nls.access.json
@@ -346,6 +346,12 @@
"access.form.kong_api_token.label": "Kong Admin API Token(可选)",
"access.form.kong_api_token.placeholder": "请输入 Kong Admin API Token",
"access.form.kong_api_token.tooltip": "这是什么?请参阅 https://developer.konghq.com/admin-api/",
+ "access.form.ksyun_access_key_id.label": "金山云 AccessKeyID",
+ "access.form.ksyun_access_key_id.placeholder": "请输入金山云 AccessKeyID",
+ "access.form.ksyun_access_key_id.tooltip": "这是什么?请参阅 https://docs.ksyun.com/documents/39976",
+ "access.form.ksyun_secret_access_key.label": "金山云 SecretAccessKey",
+ "access.form.ksyun_secret_access_key.placeholder": "请输入金山云 SecretAccessKey",
+ "access.form.ksyun_secret_access_key.tooltip": "这是什么?请参阅 https://docs.ksyun.com/documents/39976",
"access.form.larkbot_webhook_url.label": "飞书群机器人 Webhook 地址",
"access.form.larkbot_webhook_url.placeholder": "请输入飞书群机器人 Webhook 地址",
"access.form.larkbot_webhook_url.tooltip": "这是什么?请参阅 https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot",
diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json
index cafb7a86..d65fab54 100644
--- a/ui/src/i18n/locales/zh/nls.provider.json
+++ b/ui/src/i18n/locales/zh/nls.provider.json
@@ -117,6 +117,8 @@
"provider.kong": "Kong",
"provider.kubernetes": "Kubernetes",
"provider.kubernetes.secret": "Kubernetes - Secret",
+ "provider.ksyun": "金山云",
+ "provider.ksyun.cdn": "金山云 - 内容分发网络 CDN",
"provider.larkbot": "飞书群机器人",
"provider.lecdn": "LeCDN",
"provider.letsencrypt": "Let's Encrypt",
diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json
index 253a629b..193fb334 100644
--- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json
+++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json
@@ -616,6 +616,12 @@
"workflow_node.deploy.form.kong_certificate_id.label": "Kong 证书 ID",
"workflow_node.deploy.form.kong_certificate_id.placeholder": "请输入 Kong 证书 ID",
"workflow_node.deploy.form.kong_certificate_id.tooltip": "请登录 Kong 控制台查看",
+ "workflow_node.deploy.form.ksyun_cdn_domain.label": "金山云 CDN 加速域名",
+ "workflow_node.deploy.form.ksyun_cdn_domain.placeholder": "请输入金山云 CDN 加速域名(支持泛域名)",
+ "workflow_node.deploy.form.ksyun_cdn_certificate_id.label": "金山云 CDN 原证书 ID(可选)",
+ "workflow_node.deploy.form.ksyun_cdn_certificate_id.placeholder": "请输入金山云 CDN 原证书 ID",
+ "workflow_node.deploy.form.ksyun_cdn_certificate_id.help": "提示:不填写时,将上传新证书;否则,将替换原证书。",
+ "workflow_node.deploy.form.ksyun_cdn_certificate_id.tooltip": "这是什么?请参阅 https://cdn.console.ksyun.com/",
"workflow_node.deploy.form.lecdn_resource_type.label": "证书部署方式",
"workflow_node.deploy.form.lecdn_resource_type.placeholder": "请选择证书部署方式",
"workflow_node.deploy.form.lecdn_resource_type.option.certificate.label": "替换指定证书",