diff --git a/internal/certdeploy/deployers/sp_rainyun_rcdn.go b/internal/certdeploy/deployers/sp_rainyun_rcdn.go index 27d3c5330..6ae3bfbb1 100644 --- a/internal/certdeploy/deployers/sp_rainyun_rcdn.go +++ b/internal/certdeploy/deployers/sp_rainyun_rcdn.go @@ -17,9 +17,10 @@ func init() { } provider, err := rainyunrcdn.NewSSLDeployerProvider(&rainyunrcdn.SSLDeployerProviderConfig{ - ApiKey: credentials.ApiKey, - InstanceId: xmaps.GetInt64(options.ProviderExtendedConfig, "instanceId"), - Domain: xmaps.GetString(options.ProviderExtendedConfig, "domain"), + ApiKey: credentials.ApiKey, + InstanceId: xmaps.GetInt64(options.ProviderExtendedConfig, "instanceId"), + DomainMatchPattern: xmaps.GetString(options.ProviderExtendedConfig, "domainMatchPattern"), + Domain: xmaps.GetString(options.ProviderExtendedConfig, "domain"), }) return provider, err }) diff --git a/pkg/core/ssl-deployer/providers/aliyun-apigw/aliyun_apigw.go b/pkg/core/ssl-deployer/providers/aliyun-apigw/aliyun_apigw.go index 06a31052e..1415953f7 100644 --- a/pkg/core/ssl-deployer/providers/aliyun-apigw/aliyun_apigw.go +++ b/pkg/core/ssl-deployer/providers/aliyun-apigw/aliyun_apigw.go @@ -205,7 +205,7 @@ func (d *SSLDeployerProvider) findCloudNativeDomainIdByDomain(ctx context.Contex listDomainsReq := &aliapig.ListDomainsRequest{ ResourceGroupId: lo.EmptyableToPtr(d.config.ResourceGroupId), GatewayId: tea.String(d.config.GatewayId), - NameLike: tea.String(d.config.Domain), + NameLike: tea.String(domain), PageNumber: tea.Int32(int32(listDomainsPageNumber)), PageSize: tea.Int32(int32(listDomainsPageSize)), } @@ -220,7 +220,7 @@ func (d *SSLDeployerProvider) findCloudNativeDomainIdByDomain(ctx context.Contex } for _, domainItem := range listDomainsResp.Body.Data.Items { - if strings.EqualFold(tea.StringValue(domainItem.Name), d.config.Domain) { + if strings.EqualFold(tea.StringValue(domainItem.Name), domain) { return tea.StringValue(domainItem.DomainId), nil } } diff --git a/pkg/core/ssl-deployer/providers/aliyun-cdn/aliyun_cdn.go b/pkg/core/ssl-deployer/providers/aliyun-cdn/aliyun_cdn.go index 74a0366c0..decda89be 100644 --- a/pkg/core/ssl-deployer/providers/aliyun-cdn/aliyun_cdn.go +++ b/pkg/core/ssl-deployer/providers/aliyun-cdn/aliyun_cdn.go @@ -144,7 +144,8 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke } domains = lo.Filter(domainCandidates, func(domain string, _ int) bool { - return certX509.VerifyHostname(domain) == nil + return certX509.VerifyHostname(domain) == nil || + strings.TrimPrefix(d.config.Domain, "*") == strings.TrimPrefix(domain, "*") }) if len(domains) == 0 { return nil, errors.New("could not find any domains matched by certificate") diff --git a/pkg/core/ssl-deployer/providers/aliyun-dcdn/aliyun_dcdn.go b/pkg/core/ssl-deployer/providers/aliyun-dcdn/aliyun_dcdn.go index 4a22b6112..dac0877a5 100644 --- a/pkg/core/ssl-deployer/providers/aliyun-dcdn/aliyun_dcdn.go +++ b/pkg/core/ssl-deployer/providers/aliyun-dcdn/aliyun_dcdn.go @@ -144,7 +144,8 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke } domains = lo.Filter(domainCandidates, func(domain string, _ int) bool { - return certX509.VerifyHostname(domain) == nil + return certX509.VerifyHostname(domain) == nil || + strings.TrimPrefix(d.config.Domain, "*") == strings.TrimPrefix(domain, "*") }) if len(domains) == 0 { return nil, errors.New("could not find any domains matched by certificate") diff --git a/pkg/core/ssl-deployer/providers/jdcloud-cdn/jdcloud_cdn.go b/pkg/core/ssl-deployer/providers/jdcloud-cdn/jdcloud_cdn.go index 6c6facb26..541d46f2c 100644 --- a/pkg/core/ssl-deployer/providers/jdcloud-cdn/jdcloud_cdn.go +++ b/pkg/core/ssl-deployer/providers/jdcloud-cdn/jdcloud_cdn.go @@ -215,7 +215,7 @@ func (d *SSLDeployerProvider) updateDomainCertificate(ctx context.Context, domai // 查询域名配置信息 // REF: https://docs.jdcloud.com/cn/cdn/api/querydomainconfig queryDomainConfigReq := jdcdn.NewQueryDomainConfigRequestWithoutParam() - queryDomainConfigReq.SetDomain(d.config.Domain) + queryDomainConfigReq.SetDomain(domain) queryDomainConfigResp, err := d.sdkClient.QueryDomainConfig(queryDomainConfigReq) d.logger.Debug("sdk request 'cdn.QueryDomainConfig'", slog.Any("request", queryDomainConfigReq), slog.Any("response", queryDomainConfigResp)) if err != nil { @@ -225,7 +225,7 @@ func (d *SSLDeployerProvider) updateDomainCertificate(ctx context.Context, domai // 设置通讯协议 // REF: https://docs.jdcloud.com/cn/cdn/api/sethttptype setHttpTypeReq := jdcdn.NewSetHttpTypeRequestWithoutParam() - setHttpTypeReq.SetDomain(d.config.Domain) + setHttpTypeReq.SetDomain(domain) setHttpTypeReq.SetHttpType("https") setHttpTypeReq.SetCertFrom("ssl") setHttpTypeReq.SetSslCertId(cloudCertId) diff --git a/pkg/core/ssl-deployer/providers/qiniu-cdn/qiniu_cdn.go b/pkg/core/ssl-deployer/providers/qiniu-cdn/qiniu_cdn.go index c97917b21..739948bed 100644 --- a/pkg/core/ssl-deployer/providers/qiniu-cdn/qiniu_cdn.go +++ b/pkg/core/ssl-deployer/providers/qiniu-cdn/qiniu_cdn.go @@ -131,7 +131,8 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke } domains = lo.Filter(domainCandidates, func(domain string, _ int) bool { - return certX509.VerifyHostname(domain) == nil + return certX509.VerifyHostname(domain) == nil || + strings.TrimPrefix(d.config.Domain, "*") == strings.TrimPrefix(domain, "*") }) if len(domains) == 0 { return nil, errors.New("could not find any domains matched by certificate") diff --git a/pkg/core/ssl-deployer/providers/rainyun-rcdn/consts.go b/pkg/core/ssl-deployer/providers/rainyun-rcdn/consts.go new file mode 100644 index 000000000..5b3b3eefa --- /dev/null +++ b/pkg/core/ssl-deployer/providers/rainyun-rcdn/consts.go @@ -0,0 +1,6 @@ +package rainyunrcdn + +const ( + // 匹配模式:精确匹配。 + DOMAIN_MATCH_PATTERN_EXACT = "exact" +) diff --git a/pkg/core/ssl-deployer/providers/rainyun-rcdn/rainyun_rcdn.go b/pkg/core/ssl-deployer/providers/rainyun-rcdn/rainyun_rcdn.go index 853b3cf53..4e4a726b9 100644 --- a/pkg/core/ssl-deployer/providers/rainyun-rcdn/rainyun_rcdn.go +++ b/pkg/core/ssl-deployer/providers/rainyun-rcdn/rainyun_rcdn.go @@ -17,6 +17,9 @@ type SSLDeployerProviderConfig struct { ApiKey string `json:"apiKey"` // RCDN 实例 ID。 InstanceId int64 `json:"instanceId"` + // 域名匹配模式。暂时只支持精确匹配。 + // 零值时默认值 [DOMAIN_MATCH_PATTERN_EXACT]。 + DomainMatchPattern string `json:"domainMatchPattern,omitempty"` // 加速域名(支持泛域名)。 Domain string `json:"domain"` } diff --git a/pkg/core/ssl-deployer/providers/rainyun-rcdn/rainyun_rcdn_test.go b/pkg/core/ssl-deployer/providers/rainyun-rcdn/rainyun_rcdn_test.go index e9838ed30..07508f2d8 100644 --- a/pkg/core/ssl-deployer/providers/rainyun-rcdn/rainyun_rcdn_test.go +++ b/pkg/core/ssl-deployer/providers/rainyun-rcdn/rainyun_rcdn_test.go @@ -53,9 +53,10 @@ func TestDeploy(t *testing.T) { }, "\n")) deployer, err := provider.NewSSLDeployerProvider(&provider.SSLDeployerProviderConfig{ - ApiKey: fApiKey, - InstanceId: fInstanceId, - Domain: fDomain, + ApiKey: fApiKey, + InstanceId: fInstanceId, + DomainMatchPattern: provider.DOMAIN_MATCH_PATTERN_EXACT, + Domain: fDomain, }) if err != nil { t.Errorf("err: %+v", err) diff --git a/pkg/core/ssl-deployer/providers/upyun-cdn/consts.go b/pkg/core/ssl-deployer/providers/upyun-cdn/consts.go new file mode 100644 index 000000000..6a119706b --- /dev/null +++ b/pkg/core/ssl-deployer/providers/upyun-cdn/consts.go @@ -0,0 +1,10 @@ +package upyuncdn + +const ( + // 匹配模式:精确匹配。 + DOMAIN_MATCH_PATTERN_EXACT = "exact" + // 匹配模式:通配符匹配。 + DOMAIN_MATCH_PATTERN_WILDCARD = "wildcard" + // 匹配模式:证书 SAN 匹配。 + DOMAIN_MATCH_PATTERN_CERTSAN = "certsan" +) diff --git a/pkg/core/ssl-deployer/providers/upyun-cdn/upyun_cdn.go b/pkg/core/ssl-deployer/providers/upyun-cdn/upyun_cdn.go index 9d83508d3..69941c329 100644 --- a/pkg/core/ssl-deployer/providers/upyun-cdn/upyun_cdn.go +++ b/pkg/core/ssl-deployer/providers/upyun-cdn/upyun_cdn.go @@ -5,12 +5,15 @@ import ( "errors" "fmt" "log/slog" + "strings" "github.com/samber/lo" "github.com/certimate-go/certimate/pkg/core" sslmgrsp "github.com/certimate-go/certimate/pkg/core/ssl-manager/providers/upyun-ssl" upyunsdk "github.com/certimate-go/certimate/pkg/sdk3rd/upyun/console" + xcert "github.com/certimate-go/certimate/pkg/utils/cert" + xcerthostname "github.com/certimate-go/certimate/pkg/utils/cert/hostname" ) type SSLDeployerProviderConfig struct { @@ -18,6 +21,9 @@ type SSLDeployerProviderConfig struct { Username string `json:"username"` // 又拍云账号密码。 Password string `json:"password"` + // 域名匹配模式。 + // 零值时默认值 [DOMAIN_MATCH_PATTERN_EXACT]。 + DomainMatchPattern string `json:"domainMatchPattern,omitempty"` // 加速域名(支持泛域名)。 Domain string `json:"domain"` } @@ -68,10 +74,6 @@ func (d *SSLDeployerProvider) SetLogger(logger *slog.Logger) { } func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*core.SSLDeployResult, error) { - if d.config.Domain == "" { - return nil, errors.New("config `domain` is required") - } - // 上传证书 upres, err := d.sslManager.Upload(ctx, certPEM, privkeyPEM) if err != nil { @@ -80,44 +82,185 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } - // 获取域名证书配置 - getHttpsServiceManagerResp, err := d.sdkClient.GetHttpsServiceManager(d.config.Domain) - d.logger.Debug("sdk request 'console.GetHttpsServiceManager'", slog.String("request.domain", d.config.Domain), slog.Any("response", getHttpsServiceManagerResp)) - if err != nil { - return nil, fmt.Errorf("failed to execute sdk request 'console.GetHttpsServiceManager': %w", err) + // 获取待部署的域名列表 + var domains []string + switch d.config.DomainMatchPattern { + case "", DOMAIN_MATCH_PATTERN_EXACT: + { + if d.config.Domain == "" { + return nil, errors.New("config `domain` is required") + } + + domains = []string{d.config.Domain} + } + + case DOMAIN_MATCH_PATTERN_WILDCARD: + { + if d.config.Domain == "" { + return nil, errors.New("config `domain` is required") + } + + if strings.HasPrefix(d.config.Domain, "*.") { + domainCandidates, err := d.getAllDomains(ctx) + if err != nil { + return nil, err + } + + domains = lo.Filter(domainCandidates, func(domain string, _ int) bool { + return xcerthostname.IsMatch(d.config.Domain, domain) + }) + if len(domains) == 0 { + return nil, errors.New("could not find any domains matched by wildcard") + } + } else { + domains = []string{d.config.Domain} + } + } + + case DOMAIN_MATCH_PATTERN_CERTSAN: + { + certX509, err := xcert.ParseCertificateFromPEM(certPEM) + if err != nil { + return nil, err + } + + domainCandidates, err := d.getAllDomains(ctx) + if err != nil { + return nil, err + } + + domains = lo.Filter(domainCandidates, func(domain string, _ int) bool { + return certX509.VerifyHostname(domain) == nil + }) + if len(domains) == 0 { + return nil, errors.New("could not find any domains matched by certificate") + } + } + + default: + return nil, fmt.Errorf("unsupported domain match pattern: '%s'", d.config.DomainMatchPattern) } - // 判断域名是否已启用 HTTPS。如果已启用,迁移域名证书;否则,设置新证书 - _, lastCertIndex, _ := lo.FindIndexOf(getHttpsServiceManagerResp.Data.Domains, func(item upyunsdk.HttpsServiceManagerDomain) bool { - return item.Https - }) - if lastCertIndex == -1 { - updateHttpsCertificateManagerReq := &upyunsdk.UpdateHttpsCertificateManagerRequest{ - CertificateId: upres.CertId, - Domain: d.config.Domain, - Https: true, - ForceHttps: true, + // 遍历更新域名证书 + if len(domains) == 0 { + d.logger.Info("no cdn domains to deploy") + } else { + d.logger.Info("found cdn domains to deploy", slog.Any("domains", domains)) + var errs []error + + for _, domain := range domains { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + if err := d.updateDomainCertificate(ctx, domain, upres.CertId); err != nil { + errs = append(errs, err) + } + } } - updateHttpsCertificateManagerResp, err := d.sdkClient.UpdateHttpsCertificateManager(updateHttpsCertificateManagerReq) - d.logger.Debug("sdk request 'console.EnableDomainHttps'", slog.Any("request", updateHttpsCertificateManagerReq), slog.Any("response", updateHttpsCertificateManagerResp)) - if err != nil { - return nil, fmt.Errorf("failed to execute sdk request 'console.UpdateHttpsCertificateManager': %w", err) - } - } else if getHttpsServiceManagerResp.Data.Domains[lastCertIndex].CertificateId != upres.CertId { - migrateHttpsDomainReq := &upyunsdk.MigrateHttpsDomainRequest{ - CertificateId: upres.CertId, - Domain: d.config.Domain, - } - migrateHttpsDomainResp, err := d.sdkClient.MigrateHttpsDomain(migrateHttpsDomainReq) - d.logger.Debug("sdk request 'console.MigrateHttpsDomain'", slog.Any("request", migrateHttpsDomainReq), slog.Any("response", migrateHttpsDomainResp)) - if err != nil { - return nil, fmt.Errorf("failed to execute sdk request 'console.MigrateHttpsDomain': %w", err) + + if len(errs) > 0 { + return nil, errors.Join(errs...) } } return &core.SSLDeployResult{}, nil } +func (d *SSLDeployerProvider) getAllDomains(ctx context.Context) ([]string, error) { + domains := make([]string, 0) + + // 获取服务列表 + getBucketsPage := 1 + getBucketsPerPage := 10 + for { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + + getBucketsReq := &upyunsdk.GetBucketsRequest{ + Type: "ucdn", + Tag: "all", + Status: "all", + IsSecurityCDN: false, + WithDomains: true, + Page: int32(getBucketsPage), + PerPage: int32(getBucketsPerPage), + } + getBucketsResp, err := d.sdkClient.GetBuckets(getBucketsReq) + d.logger.Debug("sdk request 'console.GetBuckets'", slog.Any("request", getBucketsReq), slog.Any("response", getBucketsResp)) + if err != nil { + return nil, fmt.Errorf("failed to execute sdk request 'console.GetBuckets': %w", err) + } + + if getBucketsResp.Data == nil { + break + } + + for _, bucketItem := range getBucketsResp.Data.Buckets { + if !bucketItem.Visible { + continue + } + + for _, domainItem := range bucketItem.Domains { + if strings.EqualFold(domainItem.Status, "NORMAL") && !strings.HasSuffix(domainItem.Domain, ".test.upcdn.net") { + domains = append(domains, domainItem.Domain) + } + } + } + + if len(getBucketsResp.Data.Buckets) < getBucketsPerPage { + break + } + + getBucketsPage++ + } + + return domains, nil +} + +func (d *SSLDeployerProvider) updateDomainCertificate(ctx context.Context, domain string, cloudCertId string) error { + // 获取域名证书配置 + getHttpsServiceManagerResp, err := d.sdkClient.GetHttpsServiceManager(domain) + d.logger.Debug("sdk request 'console.GetHttpsServiceManager'", slog.String("request.domain", domain), slog.Any("response", getHttpsServiceManagerResp)) + if err != nil { + return fmt.Errorf("failed to execute sdk request 'console.GetHttpsServiceManager': %w", err) + } + + // 判断域名是否已启用 HTTPS + // 如果已启用,迁移域名证书;否则,设置新证书 + _, lastCertIndex, _ := lo.FindIndexOf(getHttpsServiceManagerResp.Data.Domains, func(item upyunsdk.HttpsServiceManagerDomain) bool { + return item.Https + }) + if lastCertIndex == -1 { + updateHttpsCertificateManagerReq := &upyunsdk.UpdateHttpsCertificateManagerRequest{ + CertificateId: cloudCertId, + Domain: domain, + Https: true, + ForceHttps: true, + } + updateHttpsCertificateManagerResp, err := d.sdkClient.UpdateHttpsCertificateManager(updateHttpsCertificateManagerReq) + d.logger.Debug("sdk request 'console.EnableDomainHttps'", slog.Any("request", updateHttpsCertificateManagerReq), slog.Any("response", updateHttpsCertificateManagerResp)) + if err != nil { + return fmt.Errorf("failed to execute sdk request 'console.UpdateHttpsCertificateManager': %w", err) + } + } else if getHttpsServiceManagerResp.Data.Domains[lastCertIndex].CertificateId != cloudCertId { + migrateHttpsDomainReq := &upyunsdk.MigrateHttpsDomainRequest{ + CertificateId: cloudCertId, + Domain: domain, + } + migrateHttpsDomainResp, err := d.sdkClient.MigrateHttpsDomain(migrateHttpsDomainReq) + d.logger.Debug("sdk request 'console.MigrateHttpsDomain'", slog.Any("request", migrateHttpsDomainReq), slog.Any("response", migrateHttpsDomainResp)) + if err != nil { + return fmt.Errorf("failed to execute sdk request 'console.MigrateHttpsDomain': %w", err) + } + } + + return nil +} + func createSDKClient(username, password string) (*upyunsdk.Client, error) { return upyunsdk.NewClient(username, password) } diff --git a/pkg/core/ssl-deployer/providers/wangsu-cdn/wangsu_cdn.go b/pkg/core/ssl-deployer/providers/wangsu-cdn/wangsu_cdn.go index 7f1b6ade5..768626829 100644 --- a/pkg/core/ssl-deployer/providers/wangsu-cdn/wangsu_cdn.go +++ b/pkg/core/ssl-deployer/providers/wangsu-cdn/wangsu_cdn.go @@ -71,10 +71,6 @@ func (d *SSLDeployerProvider) SetLogger(logger *slog.Logger) { } func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*core.SSLDeployResult, error) { - if len(d.config.Domains) == 0 { - return nil, errors.New("config `domains` is required") - } - // 上传证书 upres, err := d.sslManager.Upload(ctx, certPEM, privkeyPEM) if err != nil { @@ -83,15 +79,31 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } + // 获取待部署的域名列表 + domains := make([]string, 0) + switch d.config.DomainMatchPattern { + case "", DOMAIN_MATCH_PATTERN_EXACT: + { + if len(d.config.Domains) == 0 { + return nil, errors.New("config `domains` is required") + } + + // "*.example.com" → ".example.com",适配网宿云 CDN 要求的泛域名格式 + domains = lo.Map(d.config.Domains, func(domain string, _ int) string { + return strings.TrimPrefix(domain, "*") + }) + } + + default: + return nil, fmt.Errorf("unsupported domain match pattern: '%s'", d.config.DomainMatchPattern) + } + // 批量修改域名证书配置 // REF: https://www.wangsu.com/document/api-doc/37447 certId, _ := strconv.ParseInt(upres.CertId, 10, 64) batchUpdateCertificateConfigReq := &wangsusdk.BatchUpdateCertificateConfigRequest{ CertificateId: certId, - DomainNames: lo.Map(d.config.Domains, func(domain string, _ int) string { - // "*.example.com" → ".example.com",适配网宿云 CDN 要求的泛域名格式 - return strings.TrimPrefix(domain, "*") - }), + DomainNames: domains, } batchUpdateCertificateConfigResp, err := d.sdkClient.BatchUpdateCertificateConfig(batchUpdateCertificateConfigReq) d.logger.Debug("sdk request 'cdn.BatchUpdateCertificateConfig'", slog.Any("request", batchUpdateCertificateConfigReq), slog.Any("response", batchUpdateCertificateConfigResp)) diff --git a/pkg/sdk3rd/upyun/console/api_get_buckets.go b/pkg/sdk3rd/upyun/console/api_get_buckets.go new file mode 100644 index 000000000..8ddccc80e --- /dev/null +++ b/pkg/sdk3rd/upyun/console/api_get_buckets.go @@ -0,0 +1,85 @@ +package console + +import ( + "context" + "fmt" + "net/http" +) + +type GetBucketsRequest struct { + BucketName string `json:"status"` + BusinessType string `json:"business_type"` + Type string `json:"type"` + Status string `json:"state"` + Tag string `json:"tag"` + IsSecurityCDN bool `json:"security_cdn"` + WithDomains bool `json:"with_domains"` + Page int32 `json:"page"` + PerPage int32 `json:"perPage"` +} + +type GetBucketsResponse struct { + apiResponseBase + Data *struct { + apiResponseBaseData + Buckets []*BucketInfo `json:"buckets"` + Pager BucketPager `json:"pager"` + } `json:"data,omitempty"` +} + +type BucketInfo struct { + BucketName string `json:"bucket_name"` + BusinessType string `json:"business_type"` + Type string `json:"type"` + Status string `json:"status"` + Tag string `json:"tag"` + IsFusionCDN bool `json:"fusion_cdn"` + IsSecurityCDN bool `json:"security_cdn"` + Domains []*BucketDomain `json:"domains"` + Visible bool `json:"visible"` + CreatedAt string `json:"created_at"` +} + +type BucketDomain struct { + Domain string `json:"domain"` + Status string `json:"status"` +} + +type BucketPager struct { + Page int32 `json:"page"` + Pages int64 `json:"pages"` + Total int64 `json:"total"` +} + +func (c *Client) GetBuckets(req *GetBucketsRequest) (*GetBucketsResponse, error) { + return c.GetBucketsWithContext(context.Background(), req) +} + +func (c *Client) GetBucketsWithContext(ctx context.Context, req *GetBucketsRequest) (*GetBucketsResponse, error) { + if err := c.ensureCookieExists(); err != nil { + return nil, err + } + + httpreq, err := c.newRequest(http.MethodGet, "/api/v2/buckets") + if err != nil { + return nil, err + } else { + httpreq.SetQueryParam("bucket_name", req.BucketName) + httpreq.SetQueryParam("business_type", req.BusinessType) + httpreq.SetQueryParam("type", req.Type) + httpreq.SetQueryParam("state", req.Status) + httpreq.SetQueryParam("tag", req.Tag) + httpreq.SetQueryParam("security_cdn", fmt.Sprintf("%v", req.IsSecurityCDN)) + httpreq.SetQueryParam("with_domains", fmt.Sprintf("%v", req.WithDomains)) + httpreq.SetQueryParam("page", fmt.Sprintf("%d", req.Page)) + httpreq.SetQueryParam("perPage", fmt.Sprintf("%d", req.PerPage)) + httpreq.SetContext(ctx) + } + + result := &GetBucketsResponse{} + if _, err := c.doRequestWithResult(httpreq, result); err != nil { + return result, err + } + + return result, nil +} diff --git a/pkg/utils/cert/hostname/hostname.go b/pkg/utils/cert/hostname/hostname.go index 69ddf4bbd..00d76996b 100644 --- a/pkg/utils/cert/hostname/hostname.go +++ b/pkg/utils/cert/hostname/hostname.go @@ -19,14 +19,13 @@ func IsMatch(match, candidate string) bool { return false } - if strings.EqualFold(match, candidate) { - return true - } - mockCert := &x509.Certificate{} if ip := net.ParseIP(match); ip != nil { mockCert.IPAddresses = []net.IP{ip} } else { + if strings.EqualFold(match, candidate) { + return true + } mockCert.DNSNames = []string{match} } return mockCert.VerifyHostname(candidate) == nil diff --git a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderRainYunRCDN.tsx b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderRainYunRCDN.tsx index 705dd617a..9854a990f 100644 --- a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderRainYunRCDN.tsx +++ b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderRainYunRCDN.tsx @@ -1,5 +1,5 @@ import { getI18n, useTranslation } from "react-i18next"; -import { Form, Input } from "antd"; +import { Form, Input, Radio } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; @@ -7,6 +7,8 @@ import { validDomainName } from "@/utils/validators"; import { useFormNestedFieldsContext } from "./_context"; +const DOMAIN_MATCH_PATTERN_EXACT = "exact" as const; + const BizDeployNodeConfigFieldsProviderRainYunRCDN = () => { const { i18n, t } = useTranslation(); @@ -15,8 +17,11 @@ const BizDeployNodeConfigFieldsProviderRainYunRCDN = () => { [parentNamePath]: getSchema({ i18n }), }); const formRule = createSchemaFieldRule(formSchema); + const formInst = Form.useFormInstance(); const initialValues = getInitialValues(); + const fieldDomainMatchPattern = Form.useWatch([parentNamePath, "domainMatchPattern"], { form: formInst, preserve: true }); + return ( <>