mirror of
https://github.com/certimate-go/certimate.git
synced 2026-06-22 21:05:48 +08:00
feat(provider): supoprt cloud product access type in deployment to aliyun waf
This commit is contained in:
parent
664d8b9434
commit
ec91575fef
@ -22,7 +22,11 @@ func init() {
|
||||
ResourceGroupId: credentials.ResourceGroupId,
|
||||
Region: xmaps.GetString(options.ProviderExtendedConfig, "region"),
|
||||
ServiceVersion: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "serviceVersion", "3.0"),
|
||||
ServiceType: xmaps.GetString(options.ProviderExtendedConfig, "serviceType"),
|
||||
InstanceId: xmaps.GetString(options.ProviderExtendedConfig, "instanceId"),
|
||||
ResourceProduct: xmaps.GetString(options.ProviderExtendedConfig, "resourceProduct"),
|
||||
ResourceId: xmaps.GetString(options.ProviderExtendedConfig, "resourceId"),
|
||||
ResourcePort: xmaps.GetOrDefaultInt32(options.ProviderExtendedConfig, "resourcePort", 443),
|
||||
Domain: xmaps.GetString(options.ProviderExtendedConfig, "domain"),
|
||||
})
|
||||
return provider, err
|
||||
|
||||
@ -20,12 +20,12 @@ func init() {
|
||||
}
|
||||
|
||||
provider, err := tencentcloudssldeploy.NewSSLDeployerProvider(&tencentcloudssldeploy.SSLDeployerProviderConfig{
|
||||
SecretId: credentials.SecretId,
|
||||
SecretKey: credentials.SecretKey,
|
||||
Endpoint: xmaps.GetString(options.ProviderExtendedConfig, "endpoint"),
|
||||
Region: xmaps.GetString(options.ProviderExtendedConfig, "region"),
|
||||
ResourceType: xmaps.GetString(options.ProviderExtendedConfig, "resourceType"),
|
||||
ResourceIds: lo.Filter(strings.Split(xmaps.GetString(options.ProviderExtendedConfig, "resourceIds"), ";"), func(s string, _ int) bool { return s != "" }),
|
||||
SecretId: credentials.SecretId,
|
||||
SecretKey: credentials.SecretKey,
|
||||
Endpoint: xmaps.GetString(options.ProviderExtendedConfig, "endpoint"),
|
||||
Region: xmaps.GetString(options.ProviderExtendedConfig, "region"),
|
||||
ResourceProduct: xmaps.GetString(options.ProviderExtendedConfig, "resourceProduct"),
|
||||
ResourceIds: lo.Filter(strings.Split(xmaps.GetString(options.ProviderExtendedConfig, "resourceIds"), ";"), func(s string, _ int) bool { return s != "" }),
|
||||
})
|
||||
return provider, err
|
||||
})
|
||||
|
||||
@ -20,13 +20,13 @@ func init() {
|
||||
}
|
||||
|
||||
provider, err := tencentcloudsslupdate.NewSSLDeployerProvider(&tencentcloudsslupdate.SSLDeployerProviderConfig{
|
||||
SecretId: credentials.SecretId,
|
||||
SecretKey: credentials.SecretKey,
|
||||
Endpoint: xmaps.GetString(options.ProviderExtendedConfig, "endpoint"),
|
||||
CertificateId: xmaps.GetString(options.ProviderExtendedConfig, "certificateId"),
|
||||
IsReplaced: xmaps.GetBool(options.ProviderExtendedConfig, "isReplaced"),
|
||||
ResourceTypes: lo.Filter(strings.Split(xmaps.GetString(options.ProviderExtendedConfig, "resourceTypes"), ";"), func(s string, _ int) bool { return s != "" }),
|
||||
ResourceRegions: lo.Filter(strings.Split(xmaps.GetString(options.ProviderExtendedConfig, "resourceRegions"), ";"), func(s string, _ int) bool { return s != "" }),
|
||||
SecretId: credentials.SecretId,
|
||||
SecretKey: credentials.SecretKey,
|
||||
Endpoint: xmaps.GetString(options.ProviderExtendedConfig, "endpoint"),
|
||||
CertificateId: xmaps.GetString(options.ProviderExtendedConfig, "certificateId"),
|
||||
IsReplaced: xmaps.GetBool(options.ProviderExtendedConfig, "isReplaced"),
|
||||
ResourceProducts: lo.Filter(strings.Split(xmaps.GetString(options.ProviderExtendedConfig, "resourceProducts"), ";"), func(s string, _ int) bool { return s != "" }),
|
||||
ResourceRegions: lo.Filter(strings.Split(xmaps.GetString(options.ProviderExtendedConfig, "resourceRegions"), ";"), func(s string, _ int) bool { return s != "" }),
|
||||
})
|
||||
return provider, err
|
||||
})
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(app core.App) error {
|
||||
tracer := NewTracer("v0.4.5")
|
||||
tracer.Printf("go ...")
|
||||
|
||||
// adapt to new workflow data structure
|
||||
{
|
||||
if _, err := app.DB().NewQuery("UPDATE workflow SET graphDraft = REPLACE(graphDraft, '\"matchPattern\"', '\"domainMatchPattern\"')").Execute(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := app.DB().NewQuery("UPDATE workflow SET graphContent = REPLACE(graphContent, '\"matchPattern\"', '\"domainMatchPattern\"')").Execute(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := app.DB().NewQuery("UPDATE workflow_run SET graph = REPLACE(graph, '\"matchPattern\"', '\"domainMatchPattern\"')").Execute(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := app.DB().NewQuery("UPDATE workflow_output SET nodeConfig = REPLACE(nodeConfig, '\"matchPattern\"', '\"domainMatchPattern\"')").Execute(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
tracer.Printf("done")
|
||||
return nil
|
||||
}, func(app core.App) error {
|
||||
return nil
|
||||
})
|
||||
}
|
||||
218
migrations/1763092800_m0.4.5.go
Normal file
218
migrations/1763092800_m0.4.5.go
Normal file
@ -0,0 +1,218 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/go-viper/mapstructure/v2"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(app core.App) error {
|
||||
tracer := NewTracer("v0.4.5")
|
||||
tracer.Printf("go ...")
|
||||
|
||||
// adapt to new workflow data structure
|
||||
{
|
||||
type dWorkflowNode struct {
|
||||
Id string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Data map[string]any `json:"data"`
|
||||
Blocks []*dWorkflowNode `json:"blocks,omitempty,omitzero"`
|
||||
}
|
||||
|
||||
var deepMigrateNode func(node *dWorkflowNode) (_node *dWorkflowNode, _migrated bool)
|
||||
var deepMigrateNodes func(nodes []*dWorkflowNode) (_nodes []*dWorkflowNode, _migrated bool)
|
||||
deepMigrateNode = func(node *dWorkflowNode) (*dWorkflowNode, bool) {
|
||||
migrated := false
|
||||
|
||||
if node.Type == "bizDeploy" {
|
||||
if node.Data != nil {
|
||||
if _, ok := node.Data["config"]; ok {
|
||||
nodeCfg := node.Data["config"].(map[string]any)
|
||||
if nodeCfg["provider"] == "tencentcloud-ssldeploy" {
|
||||
if nodeCfg["providerConfig"] != nil {
|
||||
providerCfg := nodeCfg["providerConfig"].(map[string]any)
|
||||
providerCfg["resourceProduct"] = providerCfg["resourceType"]
|
||||
delete(providerCfg, "resourceType")
|
||||
nodeCfg["providerConfig"] = providerCfg
|
||||
|
||||
node.Data["config"] = nodeCfg
|
||||
migrated = true
|
||||
}
|
||||
} else if nodeCfg["provider"] == "tencentcloud-sslupdate" {
|
||||
if nodeCfg["providerConfig"] != nil {
|
||||
providerCfg := nodeCfg["providerConfig"].(map[string]any)
|
||||
providerCfg["resourceProducts"] = providerCfg["resourceTypes"]
|
||||
delete(providerCfg, "resourceTypes")
|
||||
nodeCfg["providerConfig"] = providerCfg
|
||||
|
||||
node.Data["config"] = nodeCfg
|
||||
migrated = true
|
||||
}
|
||||
} else if nodeCfg["provider"] == "aliyun-waf" {
|
||||
if nodeCfg["providerConfig"] != nil {
|
||||
providerCfg := nodeCfg["providerConfig"].(map[string]any)
|
||||
providerCfg["serviceType"] = "cname"
|
||||
nodeCfg["providerConfig"] = providerCfg
|
||||
|
||||
node.Data["config"] = nodeCfg
|
||||
migrated = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(node.Blocks) > 0 {
|
||||
if newBlocks, changed := deepMigrateNodes(node.Blocks); changed {
|
||||
node.Blocks = newBlocks
|
||||
migrated = true
|
||||
}
|
||||
}
|
||||
|
||||
return node, migrated
|
||||
}
|
||||
deepMigrateNodes = func(nodes []*dWorkflowNode) ([]*dWorkflowNode, bool) {
|
||||
migrated := false
|
||||
|
||||
for i, node := range nodes {
|
||||
if newNode, changed := deepMigrateNode(node); changed {
|
||||
nodes[i] = newNode
|
||||
migrated = true
|
||||
}
|
||||
}
|
||||
|
||||
return nodes, migrated
|
||||
}
|
||||
|
||||
// update collection `workflow`
|
||||
// - migrate field `graphDraft` / `graphContent`
|
||||
{
|
||||
collection, err := app.FindCollectionByNameOrId("tovyif5ax6j62ur")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
records, err := app.FindAllRecords(collection)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, record := range records {
|
||||
changed := false
|
||||
|
||||
graphDraft := make(map[string]any)
|
||||
if err := record.UnmarshalJSONField("graphDraft", &graphDraft); err == nil {
|
||||
if _, ok := graphDraft["nodes"]; ok {
|
||||
nodes := make([]*dWorkflowNode, 0)
|
||||
if err := mapstructure.Decode(graphDraft["nodes"], &nodes); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if newNodes, migrated := deepMigrateNodes(nodes); migrated {
|
||||
graphDraft["nodes"] = newNodes
|
||||
record.Set("graphDraft", graphDraft)
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
graphContent := make(map[string]any)
|
||||
if err := record.UnmarshalJSONField("graphContent", &graphContent); err == nil {
|
||||
if _, ok := graphContent["nodes"]; ok {
|
||||
nodes := make([]*dWorkflowNode, 0)
|
||||
if err := mapstructure.Decode(graphContent["nodes"], &nodes); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if newNodes, migrated := deepMigrateNodes(nodes); migrated {
|
||||
graphContent["nodes"] = newNodes
|
||||
record.Set("graphContent", graphContent)
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if changed {
|
||||
if err := app.Save(record); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tracer.Printf("record #%s in collection '%s' updated", record.Id, collection.Name)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := app.DB().NewQuery("UPDATE workflow SET graphDraft = REPLACE(graphDraft, '\"matchPattern\"', '\"domainMatchPattern\"')").Execute(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := app.DB().NewQuery("UPDATE workflow SET graphContent = REPLACE(graphContent, '\"matchPattern\"', '\"domainMatchPattern\"')").Execute(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// update collection `workflow_run`
|
||||
// - migrate field `graph`
|
||||
{
|
||||
collection, err := app.FindCollectionByNameOrId("qjp8lygssgwyqyz")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
records, err := app.FindAllRecords(collection)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, record := range records {
|
||||
changed := false
|
||||
|
||||
graph := make(map[string]any)
|
||||
if err := record.UnmarshalJSONField("graph", &graph); err == nil {
|
||||
if _, ok := graph["nodes"]; ok {
|
||||
nodes := make([]*dWorkflowNode, 0)
|
||||
if err := mapstructure.Decode(graph["nodes"], &nodes); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if newNodes, migrated := deepMigrateNodes(nodes); migrated {
|
||||
graph["nodes"] = newNodes
|
||||
record.Set("graph", graph)
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if changed {
|
||||
if err := app.Save(record); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tracer.Printf("record #%s in collection '%s' updated", record.Id, collection.Name)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := app.DB().NewQuery("UPDATE workflow_run SET graph = REPLACE(graph, '\"matchPattern\"', '\"domainMatchPattern\"')").Execute(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// update collection `workflow_output`
|
||||
// - migrate field `nodeConfig`
|
||||
{
|
||||
if _, err := app.DB().NewQuery("UPDATE workflow_output SET nodeConfig = REPLACE(nodeConfig, '\"matchPattern\"', '\"domainMatchPattern\"')").Execute(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := app.DB().NewQuery("UPDATE workflow_output SET nodeConfig = REPLACE(nodeConfig, '\"resourceType\"', '\"resourceProduct\"') WHERE nodeConfig LIKE '%\"provider\":\"tencentcloud-ssldeploy\"%' OR nodeConfig LIKE '%\"provider\":\"tencentcloud-sslupdate\"%'").Execute(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tracer.Printf("done")
|
||||
return nil
|
||||
}, func(app core.App) error {
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@ -46,9 +46,9 @@ Shell command to run this test:
|
||||
--CERTIMATE_SSLDEPLOYER_ALIYUNAPIGW_ACCESSKEYID="your-access-key-id" \
|
||||
--CERTIMATE_SSLDEPLOYER_ALIYUNAPIGW_ACCESSKEYSECRET="your-access-key-secret" \
|
||||
--CERTIMATE_SSLDEPLOYER_ALIYUNAPIGW_REGION="cn-hangzhou" \
|
||||
--CERTIMATE_SSLDEPLOYER_ALIYUNAPIGW_SERVICETYPE="cloudnative" \
|
||||
--CERTIMATE_SSLDEPLOYER_ALIYUNAPIGW_GATEWAYID="your-api-gateway-id" \
|
||||
--CERTIMATE_SSLDEPLOYER_ALIYUNAPIGW_GROUPID="your-api-group-id" \
|
||||
--CERTIMATE_SSLDEPLOYER_ALIYUNAPIGW_SERVICETYPE="cloudnative" \
|
||||
--CERTIMATE_SSLDEPLOYER_ALIYUNAPIGW_DOMAIN="example.com"
|
||||
*/
|
||||
func TestDeploy(t *testing.T) {
|
||||
@ -62,9 +62,9 @@ func TestDeploy(t *testing.T) {
|
||||
fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId),
|
||||
fmt.Sprintf("ACCESSKEYSECRET: %v", fAccessKeySecret),
|
||||
fmt.Sprintf("REGION: %v", fRegion),
|
||||
fmt.Sprintf("SERVICETYPE: %v", fServiceType),
|
||||
fmt.Sprintf("GATEWAYID: %v", fGatewayId),
|
||||
fmt.Sprintf("GROUPID: %v", fGroupId),
|
||||
fmt.Sprintf("SERVICETYPE: %v", fServiceType),
|
||||
fmt.Sprintf("DOMAIN: %v", fDomain),
|
||||
}, "\n"))
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client"
|
||||
"github.com/alibabacloud-go/tea/dara"
|
||||
@ -28,10 +29,22 @@ type SSLDeployerProviderConfig struct {
|
||||
// 阿里云地域。
|
||||
Region string `json:"region"`
|
||||
// 服务版本。
|
||||
// 可取值 "3.0"。
|
||||
ServiceVersion string `json:"serviceVersion"`
|
||||
// 服务类型。
|
||||
ServiceType string `json:"serviceType"`
|
||||
// WAF 实例 ID。
|
||||
InstanceId string `json:"instanceId"`
|
||||
// 接入域名(支持泛域名)。
|
||||
// 云产品类型。
|
||||
// 服务类型为 [SERVICE_TYPE_CLOUDRESOURCE] 时必填。
|
||||
ResourceProduct string `json:"resourceProduct,omitempty"`
|
||||
// 云产品资源 ID。
|
||||
// 服务类型为 [SERVICE_TYPE_CLOUDRESOURCE] 时必填。
|
||||
ResourceId string `json:"resourceId,omitempty"`
|
||||
// 云产品资源端口。
|
||||
// 服务类型为 [SERVICE_TYPE_CLOUDRESOURCE] 时必填。
|
||||
ResourcePort int32 `json:"resourcePort,omitempty"`
|
||||
// 扩展域名(支持泛域名)。
|
||||
Domain string `json:"domain,omitempty"`
|
||||
}
|
||||
|
||||
@ -85,10 +98,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.InstanceId == "" {
|
||||
return nil, errors.New("config `instanceId` is required")
|
||||
}
|
||||
|
||||
switch d.config.ServiceVersion {
|
||||
case "3", "3.0":
|
||||
if err := d.deployToWAF3(ctx, certPEM, privkeyPEM); err != nil {
|
||||
@ -103,6 +112,10 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
|
||||
}
|
||||
|
||||
func (d *SSLDeployerProvider) deployToWAF3(ctx context.Context, certPEM string, privkeyPEM string) error {
|
||||
if d.config.InstanceId == "" {
|
||||
return errors.New("config `instanceId` is required")
|
||||
}
|
||||
|
||||
// 上传证书
|
||||
upres, err := d.sslManager.Upload(ctx, certPEM, privkeyPEM)
|
||||
if err != nil {
|
||||
@ -111,8 +124,180 @@ func (d *SSLDeployerProvider) deployToWAF3(ctx context.Context, certPEM string,
|
||||
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
|
||||
}
|
||||
|
||||
// 根据接入方式决定部署方式
|
||||
switch d.config.ServiceType {
|
||||
case SERVICE_TYPE_CLOUDRESOURCE:
|
||||
certId := upres.ExtendedData["CertIdentifier"].(string)
|
||||
if err := d.deployToWAF3WithCloudResource(ctx, certId); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case SERVICE_TYPE_CNAME:
|
||||
certId := upres.ExtendedData["CertIdentifier"].(string)
|
||||
if err := d.deployToWAF3WithCNAME(ctx, certId); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unsupported service version '%s'", d.config.ServiceVersion)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *SSLDeployerProvider) deployToWAF3WithCloudResource(ctx context.Context, cloudCertId string) error {
|
||||
if d.config.ResourceProduct == "" {
|
||||
return errors.New("config `resourceProduct` is required")
|
||||
}
|
||||
if d.config.ResourceId == "" {
|
||||
return errors.New("config `resourceId` is required")
|
||||
}
|
||||
if d.config.ResourcePort == 0 {
|
||||
d.config.ResourcePort = 443
|
||||
}
|
||||
|
||||
// 查询已同步的云产品资产
|
||||
// REF: https://www.alibabacloud.com/help/zh/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-describeproductinstances
|
||||
var resourceInstance *aliwaf.DescribeProductInstancesResponseBodyProductInstances
|
||||
var resourceInstancePort *aliwaf.DescribeProductInstancesResponseBodyProductInstancesResourcePorts
|
||||
describeProductInstancesReq := &aliwaf.DescribeProductInstancesRequest{
|
||||
ResourceManagerResourceGroupId: lo.EmptyableToPtr(d.config.ResourceGroupId),
|
||||
RegionId: tea.String(d.config.Region),
|
||||
InstanceId: tea.String(d.config.InstanceId),
|
||||
ResourceProduct: tea.String(d.config.ResourceProduct),
|
||||
ResourceInstanceId: tea.String(d.config.ResourceId),
|
||||
}
|
||||
describeProductInstancesResp, err := d.sdkClient.DescribeProductInstancesWithContext(ctx, describeProductInstancesReq, &dara.RuntimeOptions{})
|
||||
d.logger.Debug("sdk request 'waf.DescribeProductInstances'", slog.Any("request", describeProductInstancesReq), slog.Any("response", describeProductInstancesResp))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute sdk request 'waf.DescribeProductInstances': %w", err)
|
||||
} else if len(describeProductInstancesResp.Body.ProductInstances) == 0 {
|
||||
return fmt.Errorf("cloud not find waf '%s' cloud resource '%s %s'", d.config.InstanceId, d.config.ResourceProduct, d.config.ResourceId)
|
||||
} else {
|
||||
resourceInstance = describeProductInstancesResp.Body.ProductInstances[0]
|
||||
|
||||
resourceInstancePort, _ = lo.Find(resourceInstance.ResourcePorts, func(p *aliwaf.DescribeProductInstancesResponseBodyProductInstancesResourcePorts) bool {
|
||||
return tea.Int32Value(p.Port) == d.config.ResourcePort
|
||||
})
|
||||
if resourceInstancePort == nil {
|
||||
return fmt.Errorf("could not find waf '%s' cloud resource '%s %s:%d'", d.config.InstanceId, d.config.ResourceProduct, d.config.ResourceId, d.config.ResourcePort)
|
||||
}
|
||||
}
|
||||
|
||||
// 查询云产品实例的证书列表
|
||||
var resourceInstanceCertificates []*aliwaf.DescribeResourceInstanceCertsResponseBodyCerts = make([]*aliwaf.DescribeResourceInstanceCertsResponseBodyCerts, 0)
|
||||
describeResourceInstanceCertsPageNumber := 1
|
||||
describeResourceInstanceCertsPageSize := 10
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
describeResourceInstanceCertsReq := &aliwaf.DescribeResourceInstanceCertsRequest{
|
||||
ResourceManagerResourceGroupId: lo.EmptyableToPtr(d.config.ResourceGroupId),
|
||||
InstanceId: tea.String(d.config.InstanceId),
|
||||
ResourceInstanceId: tea.String(d.config.ResourceId),
|
||||
PageNumber: tea.Int64(int64(describeResourceInstanceCertsPageNumber)),
|
||||
PageSize: tea.Int64(int64(describeResourceInstanceCertsPageSize)),
|
||||
}
|
||||
describeResourceInstanceCertsResp, err := d.sdkClient.DescribeResourceInstanceCertsWithContext(ctx, describeResourceInstanceCertsReq, &dara.RuntimeOptions{})
|
||||
d.logger.Debug("sdk request 'waf.DescribeResourceInstanceCerts'", slog.Any("request", describeResourceInstanceCertsReq), slog.Any("response", describeResourceInstanceCertsResp))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute sdk request 'wafw.DescribeResourceInstanceCerts': %w", err)
|
||||
}
|
||||
|
||||
if describeResourceInstanceCertsResp.Body == nil {
|
||||
break
|
||||
}
|
||||
|
||||
resourceInstanceCertificates = append(resourceInstanceCertificates, describeResourceInstanceCertsResp.Body.Certs...)
|
||||
|
||||
if len(describeResourceInstanceCertsResp.Body.Certs) < describeResourceInstanceCertsPageSize {
|
||||
break
|
||||
}
|
||||
|
||||
describeResourceInstanceCertsPageNumber++
|
||||
}
|
||||
|
||||
// 生成请求参数
|
||||
modifyCloudResourceReq := &aliwaf.ModifyCloudResourceRequest{
|
||||
ResourceManagerResourceGroupId: lo.EmptyableToPtr(d.config.ResourceGroupId),
|
||||
RegionId: tea.String(d.config.Region),
|
||||
Listen: &aliwaf.ModifyCloudResourceRequestListen{
|
||||
ResourceProduct: resourceInstance.ResourceProduct,
|
||||
ResourceInstanceId: resourceInstance.ResourceInstanceId,
|
||||
Protocol: tea.String("https"),
|
||||
Port: resourceInstancePort.Port,
|
||||
Certificates: lo.Map(resourceInstancePort.Certificates, func(c *aliwaf.DescribeProductInstancesResponseBodyProductInstancesResourcePortsCertificates, _ int) *aliwaf.ModifyCloudResourceRequestListenCertificates {
|
||||
return &aliwaf.ModifyCloudResourceRequestListenCertificates{
|
||||
CertificateId: c.CertificateId,
|
||||
AppliedType: c.AppliedType,
|
||||
}
|
||||
}),
|
||||
},
|
||||
}
|
||||
if d.config.Domain == "" {
|
||||
// 未指定接入域名,只需替换默认证书即可
|
||||
// 未指定扩展域名,只需替换默认证书
|
||||
const certAppliedTypeDefault = "default"
|
||||
for _, certItem := range modifyCloudResourceReq.Listen.Certificates {
|
||||
if tea.StringValue(certItem.AppliedType) == certAppliedTypeDefault &&
|
||||
tea.StringValue(certItem.CertificateId) == cloudCertId {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
modifyCloudResourceReq.Listen.Certificates = lo.Filter(modifyCloudResourceReq.Listen.Certificates, func(c *aliwaf.ModifyCloudResourceRequestListenCertificates, _ int) bool {
|
||||
return tea.StringValue(c.AppliedType) != certAppliedTypeDefault
|
||||
})
|
||||
modifyCloudResourceReq.Listen.Certificates = append(modifyCloudResourceReq.Listen.Certificates, &aliwaf.ModifyCloudResourceRequestListenCertificates{
|
||||
CertificateId: tea.String(cloudCertId),
|
||||
AppliedType: tea.String(certAppliedTypeDefault),
|
||||
})
|
||||
} else {
|
||||
// 指定扩展域名,需替换扩展证书
|
||||
const certAppliedTypeExtension = "extension"
|
||||
|
||||
modifyCloudResourceReq.Listen.Certificates = append(modifyCloudResourceReq.Listen.Certificates, &aliwaf.ModifyCloudResourceRequestListenCertificates{
|
||||
CertificateId: tea.String(cloudCertId),
|
||||
AppliedType: tea.String(certAppliedTypeExtension),
|
||||
})
|
||||
}
|
||||
|
||||
// 过滤掉不存在或已过期的证书,防止接口报错
|
||||
modifyCloudResourceReq.Listen.Certificates = lo.Filter(modifyCloudResourceReq.Listen.Certificates, func(c *aliwaf.ModifyCloudResourceRequestListenCertificates, _ int) bool {
|
||||
if tea.StringValue(c.CertificateId) == cloudCertId {
|
||||
return true
|
||||
}
|
||||
|
||||
resourceInstanceCert, _ := lo.Find(resourceInstanceCertificates, func(r *aliwaf.DescribeResourceInstanceCertsResponseBodyCerts) bool {
|
||||
cId := tea.StringValue(c.CertificateId)
|
||||
rId := tea.StringValue(r.CertIdentifier)
|
||||
return cId == rId || strings.Split(cId, "-")[0] == strings.Split(rId, "-")[0]
|
||||
})
|
||||
if resourceInstanceCert != nil {
|
||||
certNotAfter := time.Unix(tea.Int64Value(resourceInstanceCert.AfterDate)/1000, 0)
|
||||
return certNotAfter.After(time.Now())
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
// 修改云产品接入的配置
|
||||
// REF: https://www.alibabacloud.com/help/zh/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-modifycloudresource
|
||||
modifyCloudResourceResp, err := d.sdkClient.ModifyCloudResourceWithContext(ctx, modifyCloudResourceReq, &dara.RuntimeOptions{})
|
||||
d.logger.Debug("sdk request 'waf.ModifyCloudResource'", slog.Any("request", modifyCloudResourceReq), slog.Any("response", modifyCloudResourceResp))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute sdk request 'waf.ModifyCloudResource': %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *SSLDeployerProvider) deployToWAF3WithCNAME(ctx context.Context, cloudCertId string) error {
|
||||
if d.config.Domain == "" {
|
||||
// 未指定扩展域名,只需替换默认证书
|
||||
|
||||
// 查询默认 SSL/TLS 设置
|
||||
// REF: https://help.aliyun.com/zh/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-describedefaulthttps
|
||||
@ -133,7 +318,7 @@ func (d *SSLDeployerProvider) deployToWAF3(ctx context.Context, certPEM string,
|
||||
ResourceManagerResourceGroupId: lo.EmptyableToPtr(d.config.ResourceGroupId),
|
||||
RegionId: tea.String(d.config.Region),
|
||||
InstanceId: tea.String(d.config.InstanceId),
|
||||
CertId: tea.String(upres.ExtendedData["CertIdentifier"].(string)),
|
||||
CertId: tea.String(cloudCertId),
|
||||
TLSVersion: tea.String("tlsv1"),
|
||||
EnableTLSv3: tea.Bool(true),
|
||||
}
|
||||
@ -151,7 +336,7 @@ func (d *SSLDeployerProvider) deployToWAF3(ctx context.Context, certPEM string,
|
||||
return fmt.Errorf("failed to execute sdk request 'waf.ModifyDefaultHttps': %w", err)
|
||||
}
|
||||
} else {
|
||||
// 指定接入域名
|
||||
// 指定扩展域名,需替换扩展证书
|
||||
|
||||
// 查询 CNAME 接入详情
|
||||
// REF: https://help.aliyun.com/zh/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-describedomaindetail
|
||||
@ -172,7 +357,7 @@ func (d *SSLDeployerProvider) deployToWAF3(ctx context.Context, certPEM string,
|
||||
RegionId: tea.String(d.config.Region),
|
||||
InstanceId: tea.String(d.config.InstanceId),
|
||||
Domain: tea.String(d.config.Domain),
|
||||
Listen: &aliwaf.ModifyDomainRequestListen{CertId: tea.String(upres.ExtendedData["CertIdentifier"].(string))},
|
||||
Listen: &aliwaf.ModifyDomainRequestListen{CertId: tea.String(cloudCertId)},
|
||||
Redirect: &aliwaf.ModifyDomainRequestRedirect{Loadbalance: tea.String("iphash")},
|
||||
}
|
||||
modifyDomainReq = _assign(modifyDomainReq, describeDomainDetailResp.Body)
|
||||
|
||||
8
pkg/core/ssl-deployer/providers/aliyun-waf/consts.go
Normal file
8
pkg/core/ssl-deployer/providers/aliyun-waf/consts.go
Normal file
@ -0,0 +1,8 @@
|
||||
package aliyunwaf
|
||||
|
||||
const (
|
||||
// 服务类型:云产品接入。
|
||||
SERVICE_TYPE_CLOUDRESOURCE = "cloudresource"
|
||||
// 服务类型:CNAME 接入。
|
||||
SERVICE_TYPE_CNAME = "cname"
|
||||
)
|
||||
@ -123,6 +123,208 @@ func (client *WafClient) DescribeDomainDetailWithContext(ctx context.Context, re
|
||||
return _result, _err
|
||||
}
|
||||
|
||||
func (client *WafClient) DescribeProductInstancesWithContext(ctx context.Context, request *aliwaf.DescribeProductInstancesRequest, runtime *dara.RuntimeOptions) (_result *aliwaf.DescribeProductInstancesResponse, _err error) {
|
||||
_err = request.Validate()
|
||||
if _err != nil {
|
||||
return _result, _err
|
||||
}
|
||||
query := map[string]interface{}{}
|
||||
|
||||
if !dara.IsNil(request.InstanceId) {
|
||||
query["InstanceId"] = request.InstanceId
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.OwnerUserId) {
|
||||
query["OwnerUserId"] = request.OwnerUserId
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.PageNumber) {
|
||||
query["PageNumber"] = request.PageNumber
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.PageSize) {
|
||||
query["PageSize"] = request.PageSize
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.RegionId) {
|
||||
query["RegionId"] = request.RegionId
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.ResourceInstanceAccessStatus) {
|
||||
query["ResourceInstanceAccessStatus"] = request.ResourceInstanceAccessStatus
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.ResourceInstanceId) {
|
||||
query["ResourceInstanceId"] = request.ResourceInstanceId
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.ResourceInstanceIp) {
|
||||
query["ResourceInstanceIp"] = request.ResourceInstanceIp
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.ResourceInstanceName) {
|
||||
query["ResourceInstanceName"] = request.ResourceInstanceName
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.ResourceIp) {
|
||||
query["ResourceIp"] = request.ResourceIp
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.ResourceManagerResourceGroupId) {
|
||||
query["ResourceManagerResourceGroupId"] = request.ResourceManagerResourceGroupId
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.ResourceName) {
|
||||
query["ResourceName"] = request.ResourceName
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.ResourceProduct) {
|
||||
query["ResourceProduct"] = request.ResourceProduct
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.ResourceRegionId) {
|
||||
query["ResourceRegionId"] = request.ResourceRegionId
|
||||
}
|
||||
|
||||
req := &openapiutil.OpenApiRequest{
|
||||
Query: openapiutil.Query(query),
|
||||
}
|
||||
params := &openapiutil.Params{
|
||||
Action: dara.String("DescribeProductInstances"),
|
||||
Version: dara.String("2021-10-01"),
|
||||
Protocol: dara.String("HTTPS"),
|
||||
Pathname: dara.String("/"),
|
||||
Method: dara.String("POST"),
|
||||
AuthType: dara.String("AK"),
|
||||
Style: dara.String("RPC"),
|
||||
ReqBodyType: dara.String("formData"),
|
||||
BodyType: dara.String("json"),
|
||||
}
|
||||
_result = &aliwaf.DescribeProductInstancesResponse{}
|
||||
_body, _err := client.CallApiWithCtx(ctx, params, req, runtime)
|
||||
if _err != nil {
|
||||
return _result, _err
|
||||
}
|
||||
_err = dara.Convert(_body, &_result)
|
||||
return _result, _err
|
||||
}
|
||||
|
||||
func (client *WafClient) DescribeResourceInstanceCertsWithContext(ctx context.Context, request *aliwaf.DescribeResourceInstanceCertsRequest, runtime *dara.RuntimeOptions) (_result *aliwaf.DescribeResourceInstanceCertsResponse, _err error) {
|
||||
_err = request.Validate()
|
||||
if _err != nil {
|
||||
return _result, _err
|
||||
}
|
||||
query := map[string]interface{}{}
|
||||
|
||||
if !dara.IsNil(request.InstanceId) {
|
||||
query["InstanceId"] = request.InstanceId
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.PageNumber) {
|
||||
query["PageNumber"] = request.PageNumber
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.PageSize) {
|
||||
query["PageSize"] = request.PageSize
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.RegionId) {
|
||||
query["RegionId"] = request.RegionId
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.ResourceInstanceId) {
|
||||
query["ResourceInstanceId"] = request.ResourceInstanceId
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.ResourceManagerResourceGroupId) {
|
||||
query["ResourceManagerResourceGroupId"] = request.ResourceManagerResourceGroupId
|
||||
}
|
||||
|
||||
req := &openapiutil.OpenApiRequest{
|
||||
Query: openapiutil.Query(query),
|
||||
}
|
||||
params := &openapiutil.Params{
|
||||
Action: dara.String("DescribeResourceInstanceCerts"),
|
||||
Version: dara.String("2021-10-01"),
|
||||
Protocol: dara.String("HTTPS"),
|
||||
Pathname: dara.String("/"),
|
||||
Method: dara.String("POST"),
|
||||
AuthType: dara.String("AK"),
|
||||
Style: dara.String("RPC"),
|
||||
ReqBodyType: dara.String("formData"),
|
||||
BodyType: dara.String("json"),
|
||||
}
|
||||
_result = &aliwaf.DescribeResourceInstanceCertsResponse{}
|
||||
_body, _err := client.CallApiWithCtx(ctx, params, req, runtime)
|
||||
if _err != nil {
|
||||
return _result, _err
|
||||
}
|
||||
_err = dara.Convert(_body, &_result)
|
||||
return _result, _err
|
||||
}
|
||||
|
||||
func (client *WafClient) ModifyCloudResourceWithContext(ctx context.Context, tmpReq *aliwaf.ModifyCloudResourceRequest, runtime *dara.RuntimeOptions) (_result *aliwaf.ModifyCloudResourceResponse, _err error) {
|
||||
_err = tmpReq.Validate()
|
||||
if _err != nil {
|
||||
return _result, _err
|
||||
}
|
||||
|
||||
request := &aliwaf.ModifyCloudResourceShrinkRequest{}
|
||||
openapiutil.Convert(tmpReq, request)
|
||||
|
||||
if !dara.IsNil(tmpReq.Listen) {
|
||||
request.ListenShrink = openapiutil.ArrayToStringWithSpecifiedStyle(tmpReq.Listen, dara.String("Listen"), dara.String("json"))
|
||||
}
|
||||
|
||||
if !dara.IsNil(tmpReq.Redirect) {
|
||||
request.RedirectShrink = openapiutil.ArrayToStringWithSpecifiedStyle(tmpReq.Redirect, dara.String("Redirect"), dara.String("json"))
|
||||
}
|
||||
|
||||
query := map[string]interface{}{}
|
||||
|
||||
if !dara.IsNil(request.InstanceId) {
|
||||
query["InstanceId"] = request.InstanceId
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.ListenShrink) {
|
||||
query["Listen"] = request.ListenShrink
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.RedirectShrink) {
|
||||
query["Redirect"] = request.RedirectShrink
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.RegionId) {
|
||||
query["RegionId"] = request.RegionId
|
||||
}
|
||||
|
||||
if !dara.IsNil(request.ResourceManagerResourceGroupId) {
|
||||
query["ResourceManagerResourceGroupId"] = request.ResourceManagerResourceGroupId
|
||||
}
|
||||
|
||||
req := &openapiutil.OpenApiRequest{
|
||||
Query: openapiutil.Query(query),
|
||||
}
|
||||
params := &openapiutil.Params{
|
||||
Action: dara.String("ModifyCloudResource"),
|
||||
Version: dara.String("2021-10-01"),
|
||||
Protocol: dara.String("HTTPS"),
|
||||
Pathname: dara.String("/"),
|
||||
Method: dara.String("POST"),
|
||||
AuthType: dara.String("AK"),
|
||||
Style: dara.String("RPC"),
|
||||
ReqBodyType: dara.String("formData"),
|
||||
BodyType: dara.String("json"),
|
||||
}
|
||||
_result = &aliwaf.ModifyCloudResourceResponse{}
|
||||
_body, _err := client.CallApiWithCtx(ctx, params, req, runtime)
|
||||
if _err != nil {
|
||||
return _result, _err
|
||||
}
|
||||
_err = dara.Convert(_body, &_result)
|
||||
return _result, _err
|
||||
}
|
||||
|
||||
func (client *WafClient) ModifyDefaultHttpsWithContext(ctx context.Context, request *aliwaf.ModifyDefaultHttpsRequest, runtime *dara.RuntimeOptions) (_result *aliwaf.ModifyDefaultHttpsResponse, _err error) {
|
||||
_err = request.Validate()
|
||||
if _err != nil {
|
||||
|
||||
@ -26,9 +26,9 @@ type SSLDeployerProviderConfig struct {
|
||||
Endpoint string `json:"endpoint,omitempty"`
|
||||
// 腾讯云地域。
|
||||
Region string `json:"region"`
|
||||
// 云资源类型。
|
||||
ResourceType string `json:"resourceType"`
|
||||
// 云资源 ID 数组。
|
||||
// 云产品类型。
|
||||
ResourceProduct string `json:"resourceProduct"`
|
||||
// 云产品资源 ID 数组。
|
||||
ResourceIds []string `json:"resourceIds,omitempty"`
|
||||
}
|
||||
|
||||
@ -79,8 +79,8 @@ func (d *SSLDeployerProvider) SetLogger(logger *slog.Logger) {
|
||||
}
|
||||
|
||||
func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*core.SSLDeployResult, error) {
|
||||
if d.config.ResourceType == "" {
|
||||
return nil, errors.New("config `resourceType` is required")
|
||||
if d.config.ResourceProduct == "" {
|
||||
return nil, errors.New("config `resourceProduct` is required")
|
||||
}
|
||||
if len(d.config.ResourceIds) == 0 {
|
||||
return nil, errors.New("config `resourceIds` is required")
|
||||
@ -98,7 +98,7 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
|
||||
// REF: https://cloud.tencent.com/document/api/400/91667
|
||||
deployCertificateInstanceReq := tcssl.NewDeployCertificateInstanceRequest()
|
||||
deployCertificateInstanceReq.CertificateId = common.StringPtr(upres.CertId)
|
||||
deployCertificateInstanceReq.ResourceType = common.StringPtr(d.config.ResourceType)
|
||||
deployCertificateInstanceReq.ResourceType = common.StringPtr(d.config.ResourceProduct)
|
||||
deployCertificateInstanceReq.InstanceIdList = common.StringPtrs(d.config.ResourceIds)
|
||||
deployCertificateInstanceReq.Status = common.Int64Ptr(1)
|
||||
deployCertificateInstanceResp, err := d.sdkClient.DeployCertificateInstance(deployCertificateInstanceReq)
|
||||
|
||||
@ -29,9 +29,9 @@ type SSLDeployerProviderConfig struct {
|
||||
CertificateId string `json:"certificateId"`
|
||||
// 是否替换原有证书(即保持原证书 ID 不变)。
|
||||
IsReplaced bool `json:"isReplaced,omitempty"`
|
||||
// 云资源类型数组。
|
||||
ResourceTypes []string `json:"resourceTypes"`
|
||||
// 云资源地域数组。
|
||||
// 云产品类型数组。
|
||||
ResourceProducts []string `json:"resourceProducts"`
|
||||
// 云产品地域数组。
|
||||
ResourceRegions []string `json:"resourceRegions"`
|
||||
}
|
||||
|
||||
@ -85,8 +85,8 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
|
||||
if d.config.CertificateId == "" {
|
||||
return nil, errors.New("config `certificateId` is required")
|
||||
}
|
||||
if len(d.config.ResourceTypes) == 0 {
|
||||
return nil, errors.New("config `resourceTypes` is required")
|
||||
if len(d.config.ResourceProducts) == 0 {
|
||||
return nil, errors.New("config `resourceProducts` is required")
|
||||
}
|
||||
|
||||
if d.config.IsReplaced {
|
||||
@ -124,8 +124,8 @@ func (d *SSLDeployerProvider) executeUpdateCertificateInstance(ctx context.Conte
|
||||
updateCertificateInstanceReq := tcssl.NewUpdateCertificateInstanceRequest()
|
||||
updateCertificateInstanceReq.OldCertificateId = common.StringPtr(d.config.CertificateId)
|
||||
updateCertificateInstanceReq.CertificateId = common.StringPtr(upres.CertId)
|
||||
updateCertificateInstanceReq.ResourceTypes = common.StringPtrs(d.config.ResourceTypes)
|
||||
updateCertificateInstanceReq.ResourceTypesRegions = wrapResourceTypeRegions(d.config.ResourceTypes, d.config.ResourceRegions)
|
||||
updateCertificateInstanceReq.ResourceTypes = common.StringPtrs(d.config.ResourceProducts)
|
||||
updateCertificateInstanceReq.ResourceTypesRegions = wrapResourceProductRegions(d.config.ResourceProducts, d.config.ResourceRegions)
|
||||
updateCertificateInstanceResp, err := d.sdkClient.UpdateCertificateInstance(updateCertificateInstanceReq)
|
||||
d.logger.Debug("sdk request 'ssl.UpdateCertificateInstance'", slog.Any("request", updateCertificateInstanceReq), slog.Any("response", updateCertificateInstanceResp))
|
||||
if err != nil {
|
||||
@ -200,8 +200,8 @@ func (d *SSLDeployerProvider) executeUploadUpdateCertificateInstance(ctx context
|
||||
uploadUpdateCertificateInstanceReq.OldCertificateId = common.StringPtr(d.config.CertificateId)
|
||||
uploadUpdateCertificateInstanceReq.CertificatePublicKey = common.StringPtr(certPEM)
|
||||
uploadUpdateCertificateInstanceReq.CertificatePrivateKey = common.StringPtr(privkeyPEM)
|
||||
uploadUpdateCertificateInstanceReq.ResourceTypes = common.StringPtrs(d.config.ResourceTypes)
|
||||
uploadUpdateCertificateInstanceReq.ResourceTypesRegions = wrapResourceTypeRegions(d.config.ResourceTypes, d.config.ResourceRegions)
|
||||
uploadUpdateCertificateInstanceReq.ResourceTypes = common.StringPtrs(d.config.ResourceProducts)
|
||||
uploadUpdateCertificateInstanceReq.ResourceTypesRegions = wrapResourceProductRegions(d.config.ResourceProducts, d.config.ResourceRegions)
|
||||
uploadUpdateCertificateInstanceResp, err := d.sdkClient.UploadUpdateCertificateInstance(uploadUpdateCertificateInstanceReq)
|
||||
d.logger.Debug("sdk request 'ssl.UploadUpdateCertificateInstance'", slog.Any("request", uploadUpdateCertificateInstanceReq), slog.Any("response", uploadUpdateCertificateInstanceResp))
|
||||
if err != nil {
|
||||
@ -278,19 +278,19 @@ func createSDKClient(secretId, secretKey, endpoint string) (*internal.SslClient,
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func wrapResourceTypeRegions(resourceTypes, resourceRegions []string) []*tcssl.ResourceTypeRegions {
|
||||
if len(resourceTypes) == 0 || len(resourceRegions) == 0 {
|
||||
func wrapResourceProductRegions(resourceProducts, resourceRegions []string) []*tcssl.ResourceTypeRegions {
|
||||
if len(resourceProducts) == 0 || len(resourceRegions) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 仅以下云资源类型支持地域
|
||||
resourceTypesRequireRegion := []string{"apigateway", "clb", "cos", "tcb", "tke", "tse", "waf"}
|
||||
// 仅以下云产品类型支持地域
|
||||
resourceProductsRequireRegion := []string{"apigateway", "clb", "cos", "tcb", "tke", "tse", "waf"}
|
||||
|
||||
temp := make([]*tcssl.ResourceTypeRegions, 0)
|
||||
for _, resourceType := range resourceTypes {
|
||||
if slices.Contains(resourceTypesRequireRegion, resourceType) {
|
||||
for _, resourceProduct := range resourceProducts {
|
||||
if slices.Contains(resourceProductsRequireRegion, resourceProduct) {
|
||||
temp = append(temp, &tcssl.ResourceTypeRegions{
|
||||
ResourceType: common.StringPtr(resourceType),
|
||||
ResourceType: common.StringPtr(resourceProduct),
|
||||
Regions: common.StringPtrs(resourceRegions),
|
||||
})
|
||||
}
|
||||
|
||||
@ -31,6 +31,16 @@ const BizDeployNodeConfigFieldsProviderAliyunAPIGW = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name={[parentNamePath, "region"]}
|
||||
initialValue={initialValues.region}
|
||||
label={t("workflow_node.deploy.form.aliyun_apigw_region.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_apigw_region.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_apigw_region.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "serviceType"]}
|
||||
initialValue={initialValues.serviceType}
|
||||
@ -47,16 +57,6 @@ const BizDeployNodeConfigFieldsProviderAliyunAPIGW = () => {
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "region"]}
|
||||
initialValue={initialValues.region}
|
||||
label={t("workflow_node.deploy.form.aliyun_apigw_region.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_apigw_region.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_apigw_region.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Show when={fieldServiceType === SERVICE_TYPE_CLOUDNATIVE}>
|
||||
<Form.Item
|
||||
name={[parentNamePath, "gatewayId"]}
|
||||
|
||||
@ -1,12 +1,16 @@
|
||||
import { getI18n, useTranslation } from "react-i18next";
|
||||
import { Form, Input, Select } from "antd";
|
||||
import { AutoComplete, Form, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
import Show from "@/components/Show";
|
||||
import { validDomainName, validPortNumber } from "@/utils/validators";
|
||||
|
||||
import { useFormNestedFieldsContext } from "./_context";
|
||||
|
||||
const SERVICE_TYPE_CLOUDRESOURCE = "cloudresource" as const;
|
||||
const SERVICE_TYPE_CNAME = "cname" as const;
|
||||
|
||||
const BizDeployNodeConfigFieldsProviderAliyunWAF = () => {
|
||||
const { i18n, t } = useTranslation();
|
||||
|
||||
@ -15,8 +19,11 @@ const BizDeployNodeConfigFieldsProviderAliyunWAF = () => {
|
||||
[parentNamePath]: getSchema({ i18n }),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const formInst = Form.useFormInstance();
|
||||
const initialValues = getInitialValues();
|
||||
|
||||
const fieldServiceType = Form.useWatch([parentNamePath, "serviceType"], formInst);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
@ -42,6 +49,22 @@ const BizDeployNodeConfigFieldsProviderAliyunWAF = () => {
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "serviceType"]}
|
||||
initialValue={initialValues.serviceType}
|
||||
label={t("workflow_node.deploy.form.aliyun_waf_service_type.label")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Select placeholder={t("workflow_node.deploy.form.aliyun_waf_service_type.placeholder")}>
|
||||
<Select.Option key={SERVICE_TYPE_CLOUDRESOURCE} value={SERVICE_TYPE_CLOUDRESOURCE}>
|
||||
{t("workflow_node.deploy.form.aliyun_waf_service_type.option.cloudresource.label")}
|
||||
</Select.Option>
|
||||
<Select.Option key={SERVICE_TYPE_CNAME} value={SERVICE_TYPE_CNAME}>
|
||||
{t("workflow_node.deploy.form.aliyun_waf_service_type.option.cname.label")}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "instanceId"]}
|
||||
initialValue={initialValues.instanceId}
|
||||
@ -52,6 +75,39 @@ const BizDeployNodeConfigFieldsProviderAliyunWAF = () => {
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_waf_instance_id.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Show when={fieldServiceType === SERVICE_TYPE_CLOUDRESOURCE}>
|
||||
<Form.Item
|
||||
name={[parentNamePath, "resourceProduct"]}
|
||||
initialValue={initialValues.resourceProduct}
|
||||
label={t("workflow_node.deploy.form.aliyun_waf_resource_product.label")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<AutoComplete
|
||||
options={["ecs", "clb4", "clb7", "nlb"].map((value) => ({ value }))}
|
||||
placeholder={t("workflow_node.deploy.form.aliyun_waf_resource_product.placeholder")}
|
||||
filterOption={(inputValue, option) => option!.value.toLowerCase().includes(inputValue.toLowerCase())}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "resourceId"]}
|
||||
initialValue={initialValues.resourceId}
|
||||
label={t("workflow_node.deploy.form.aliyun_waf_resource_id.label")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_waf_resource_id.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "resourcePort"]}
|
||||
initialValue={initialValues.resourcePort}
|
||||
label={t("workflow_node.deploy.form.aliyun_waf_resource_port.label")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Input type="number" min={1} max={65535} placeholder={t("workflow_node.deploy.form.aliyun_waf_resource_port.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "domain"]}
|
||||
initialValue={initialValues.domain}
|
||||
@ -70,23 +126,62 @@ const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
|
||||
region: "",
|
||||
serviceVersion: "3.0",
|
||||
instanceId: "",
|
||||
resourceProduct: "",
|
||||
resourceId: "",
|
||||
resourcePort: 443,
|
||||
};
|
||||
};
|
||||
|
||||
const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> }) => {
|
||||
const { t } = i18n;
|
||||
|
||||
return z.object({
|
||||
region: z.string().nonempty(t("workflow_node.deploy.form.aliyun_waf_region.placeholder")),
|
||||
serviceVersion: z.literal("3.0", t("workflow_node.deploy.form.aliyun_waf_service_version.placeholder")),
|
||||
instanceId: z.string().nonempty(t("workflow_node.deploy.form.aliyun_waf_instance_id.placeholder")),
|
||||
domain: z
|
||||
.string()
|
||||
.nullish()
|
||||
.refine((v) => {
|
||||
return !v || validDomainName(v!, { allowWildcard: true });
|
||||
}, t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
return z
|
||||
.object({
|
||||
region: z.string().nonempty(t("workflow_node.deploy.form.aliyun_waf_region.placeholder")),
|
||||
serviceVersion: z.literal("3.0", t("workflow_node.deploy.form.aliyun_waf_service_version.placeholder")),
|
||||
serviceType: z.literal([SERVICE_TYPE_CLOUDRESOURCE, SERVICE_TYPE_CNAME], t("workflow_node.deploy.form.aliyun_waf_service_type.placeholder")),
|
||||
instanceId: z.string().nonempty(t("workflow_node.deploy.form.aliyun_waf_instance_id.placeholder")),
|
||||
resourceProduct: z.string().nullish(),
|
||||
resourceId: z.string().nullish(),
|
||||
resourcePort: z.preprocess((v) => (v == null || v === "" ? void 0 : Number(v)), z.number().nullish()),
|
||||
domain: z
|
||||
.string()
|
||||
.nullish()
|
||||
.refine((v) => {
|
||||
return !v || validDomainName(v!, { allowWildcard: true });
|
||||
}, t("common.errmsg.domain_invalid")),
|
||||
})
|
||||
.superRefine((values, ctx) => {
|
||||
switch (values.serviceType) {
|
||||
case SERVICE_TYPE_CLOUDRESOURCE:
|
||||
{
|
||||
if (!values.resourceProduct) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: t("workflow_node.deploy.form.aliyun_waf_resource_product.placeholder"),
|
||||
path: ["resourceProduct"],
|
||||
});
|
||||
}
|
||||
|
||||
if (!values.resourceId) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: t("workflow_node.deploy.form.aliyun_waf_resource_id.placeholder"),
|
||||
path: ["resourceId"],
|
||||
});
|
||||
}
|
||||
|
||||
if (!validPortNumber(values.resourcePort!)) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: t("workflow_node.deploy.form.aliyun_waf_resource_port.placeholder"),
|
||||
path: ["resourcePort"],
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const _default = Object.assign(BizDeployNodeConfigFieldsProviderAliyunWAF, {
|
||||
|
||||
@ -47,15 +47,15 @@ const BizDeployNodeConfigFieldsProviderTencentCloudSSLDeploy = () => {
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "resourceType"]}
|
||||
initialValue={initialValues.resourceType}
|
||||
label={t("workflow_node.deploy.form.tencentcloud_ssldeploy_resource_type.label")}
|
||||
name={[parentNamePath, "resourceProduct"]}
|
||||
initialValue={initialValues.resourceProduct}
|
||||
label={t("workflow_node.deploy.form.tencentcloud_ssldeploy_resource_product.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_ssldeploy_resource_type.tooltip") }}></span>}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_ssldeploy_resource_product.tooltip") }}></span>}
|
||||
>
|
||||
<AutoComplete
|
||||
options={["apigateway", "cdn", "clb", "cos", "ddos", "lighthouse", "live", "tcb", "teo", "tke", "tse", "vod", "waf"].map((value) => ({ value }))}
|
||||
placeholder={t("workflow_node.deploy.form.tencentcloud_ssldeploy_resource_type.placeholder")}
|
||||
placeholder={t("workflow_node.deploy.form.tencentcloud_ssldeploy_resource_product.placeholder")}
|
||||
filterOption={(inputValue, option) => option!.value.toLowerCase().includes(inputValue.toLowerCase())}
|
||||
/>
|
||||
</Form.Item>
|
||||
@ -83,7 +83,7 @@ const BizDeployNodeConfigFieldsProviderTencentCloudSSLDeploy = () => {
|
||||
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
|
||||
return {
|
||||
region: "",
|
||||
resourceType: "",
|
||||
resourceProduct: "",
|
||||
resourceIds: "",
|
||||
};
|
||||
};
|
||||
@ -94,7 +94,7 @@ const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> })
|
||||
return z.object({
|
||||
endpoint: z.string().nullish(),
|
||||
region: z.string().nonempty(t("workflow_node.deploy.form.tencentcloud_ssldeploy_region.placeholder")),
|
||||
resourceType: z.string().nonempty(t("workflow_node.deploy.form.tencentcloud_ssldeploy_resource_type.placeholder")),
|
||||
resourceProduct: z.string().nonempty(t("workflow_node.deploy.form.tencentcloud_ssldeploy_resource_product.placeholder")),
|
||||
resourceIds: z.string().refine((v) => {
|
||||
if (!v) return false;
|
||||
return String(v)
|
||||
|
||||
@ -47,17 +47,17 @@ const BizDeployNodeConfigFieldsProviderTencentCloudSSLUpdate = () => {
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "resourceTypes"]}
|
||||
initialValue={initialValues.resourceTypes}
|
||||
label={t("workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.label")}
|
||||
extra={t("workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.help")}
|
||||
name={[parentNamePath, "resourceProducts"]}
|
||||
initialValue={initialValues.resourceProducts}
|
||||
label={t("workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.label")}
|
||||
extra={t("workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.help")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.tooltip") }}></span>}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.tooltip") }}></span>}
|
||||
>
|
||||
<MultipleSplitValueInput
|
||||
modalTitle={t("workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.multiple_input_modal.title")}
|
||||
placeholder={t("workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.placeholder")}
|
||||
placeholderInModal={t("workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.multiple_input_modal.placeholder")}
|
||||
modalTitle={t("workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.multiple_input_modal.title")}
|
||||
placeholder={t("workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.placeholder")}
|
||||
placeholderInModal={t("workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.multiple_input_modal.placeholder")}
|
||||
separator={MULTIPLE_INPUT_SEPARATOR}
|
||||
splitOptions={{ removeEmpty: true, trimSpace: true }}
|
||||
/>
|
||||
@ -96,7 +96,7 @@ const BizDeployNodeConfigFieldsProviderTencentCloudSSLUpdate = () => {
|
||||
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
|
||||
return {
|
||||
certificateId: "",
|
||||
resourceTypes: "",
|
||||
resourceProducts: "",
|
||||
};
|
||||
};
|
||||
|
||||
@ -106,12 +106,12 @@ const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> })
|
||||
return z.object({
|
||||
endpoint: z.string().nullish(),
|
||||
certificateId: z.string().nonempty(t("workflow_node.deploy.form.tencentcloud_sslupdate_certificate_id.placeholder")),
|
||||
resourceTypes: z.string().refine((v) => {
|
||||
resourceProducts: z.string().refine((v) => {
|
||||
if (!v) return false;
|
||||
return String(v)
|
||||
.split(MULTIPLE_INPUT_SEPARATOR)
|
||||
.every((e) => !!e.trim());
|
||||
}, t("workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.placeholder")),
|
||||
}, t("workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.placeholder")),
|
||||
resourceRegions: z
|
||||
.string()
|
||||
.nullish()
|
||||
|
||||
@ -230,13 +230,13 @@
|
||||
"workflow_node.deploy.form.aliyun_alb_snidomain.label": "Alibaba Cloud ALB SNI domain (Optional)",
|
||||
"workflow_node.deploy.form.aliyun_alb_snidomain.placeholder": "Please enter Alibaba Cloud ALB SNI domain name",
|
||||
"workflow_node.deploy.form.aliyun_alb_snidomain.help": "",
|
||||
"workflow_node.deploy.form.aliyun_apigw_region.label": "Alibaba Cloud region",
|
||||
"workflow_node.deploy.form.aliyun_apigw_region.placeholder": "Please enter Alibaba Cloud API gateway region (e.g. cn-hangzhou)",
|
||||
"workflow_node.deploy.form.aliyun_apigw_region.tooltip": "For more information, see <a href=\"https://www.alibabacloud.com/help/en/api-gateway/cloud-native-api-gateway/product-overview/regions\" target=\"_blank\">https://www.alibabacloud.com/help/en/api-gateway/cloud-native-api-gateway/product-overview/regions</a>",
|
||||
"workflow_node.deploy.form.aliyun_apigw_service_type.label": "Alibaba Cloud API gateway type",
|
||||
"workflow_node.deploy.form.aliyun_apigw_service_type.placeholder": "Please select Alibaba Cloud API gateway type",
|
||||
"workflow_node.deploy.form.aliyun_apigw_service_type.option.cloudnative.label": "Cloud-native API gateway",
|
||||
"workflow_node.deploy.form.aliyun_apigw_service_type.option.traditional.label": "Traditional API gateway",
|
||||
"workflow_node.deploy.form.aliyun_apigw_region.label": "Alibaba Cloud region",
|
||||
"workflow_node.deploy.form.aliyun_apigw_region.placeholder": "Please enter Alibaba Cloud API gateway region (e.g. cn-hangzhou)",
|
||||
"workflow_node.deploy.form.aliyun_apigw_region.tooltip": "For more information, see <a href=\"https://www.alibabacloud.com/help/en/api-gateway/cloud-native-api-gateway/product-overview/regions\" target=\"_blank\">https://www.alibabacloud.com/help/en/api-gateway/cloud-native-api-gateway/product-overview/regions</a>",
|
||||
"workflow_node.deploy.form.aliyun_apigw_gateway_id.label": "Alibaba Cloud API gateway ID",
|
||||
"workflow_node.deploy.form.aliyun_apigw_gateway_id.placeholder": "Please enter Alibaba Cloud API gateway ID",
|
||||
"workflow_node.deploy.form.aliyun_apigw_gateway_id.tooltip": "For more information, see <a href=\"https://apigw.console.aliyun.com\" target=\"_blank\">https://apigw.console.aliyun.com</a>",
|
||||
@ -358,11 +358,21 @@
|
||||
"workflow_node.deploy.form.aliyun_waf_region.tooltip": "For more information, see <a href=\"https://www.alibabacloud.com/help/en/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-endpoint\" target=\"_blank\">https://www.alibabacloud.com/help/en/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-endpoint</a>",
|
||||
"workflow_node.deploy.form.aliyun_waf_service_version.label": "Alibaba Cloud WAF version",
|
||||
"workflow_node.deploy.form.aliyun_waf_service_version.placeholder": "Please select Alibaba Cloud WAF version",
|
||||
"workflow_node.deploy.form.aliyun_waf_service_type.label": "Alibaba Cloud WAF access type",
|
||||
"workflow_node.deploy.form.aliyun_waf_service_type.placeholder": "Please select Alibaba Cloud WAF access type",
|
||||
"workflow_node.deploy.form.aliyun_waf_service_type.option.cloudresource.label": "Cloud product access",
|
||||
"workflow_node.deploy.form.aliyun_waf_service_type.option.cname.label": "CNAME access",
|
||||
"workflow_node.deploy.form.aliyun_waf_instance_id.label": "Alibaba Cloud WAF instance ID",
|
||||
"workflow_node.deploy.form.aliyun_waf_instance_id.placeholder": "Please enter Alibaba Cloud WAF instance ID",
|
||||
"workflow_node.deploy.form.aliyun_waf_instance_id.tooltip": "For more information, see <a href=\"https://waf.console.aliyun.com\" target=\"_blank\">https://waf.console.aliyun.com</a>",
|
||||
"workflow_node.deploy.form.aliyun_waf_domain.label": "Alibaba Cloud WAF domain (Optional)",
|
||||
"workflow_node.deploy.form.aliyun_waf_domain.placeholder": "Please enter Alibaba Cloud WAF domain name",
|
||||
"workflow_node.deploy.form.aliyun_waf_resource_product.label": "Alibaba Cloud WAF accessed resource product",
|
||||
"workflow_node.deploy.form.aliyun_waf_resource_product.placeholder": "Please enter Alibaba Cloud WAF accessed resource product",
|
||||
"workflow_node.deploy.form.aliyun_waf_resource_id.label": "Alibaba Cloud WAF accessed resource ID",
|
||||
"workflow_node.deploy.form.aliyun_waf_resource_id.placeholder": "Please enter Alibaba Cloud WAF accessed resource ID",
|
||||
"workflow_node.deploy.form.aliyun_waf_resource_port.label": "Alibaba Cloud WAF accessed resource port",
|
||||
"workflow_node.deploy.form.aliyun_waf_resource_port.placeholder": "Please enter Alibaba Cloud WAF accessed resource port",
|
||||
"workflow_node.deploy.form.aliyun_waf_domain.label": "Alibaba Cloud WAF SNI domain (Optional)",
|
||||
"workflow_node.deploy.form.aliyun_waf_domain.placeholder": "Please enter Alibaba Cloud WAF SNI domain name",
|
||||
"workflow_node.deploy.form.aliyun_waf_domain.help": "",
|
||||
"workflow_node.deploy.form.apisix_resource_type.label": "Resource type",
|
||||
"workflow_node.deploy.form.apisix_resource_type.placeholder": "Please select resource type",
|
||||
@ -845,9 +855,9 @@
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_region.label": "Tencent Cloud region",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_region.placeholder": "Please enter Tencent Cloud service region (e.g. ap-guangzhou)",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_region.tooltip": "For more information, see <a href=\"https://www.tencentcloud.com/document/product/1007/36573\" target=\"_blank\">https://www.tencentcloud.com/document/product/1007/36573</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_resource_type.label": "Tencent Cloud resource type",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_resource_type.placeholder": "Please enter Tencent Cloud resource type",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_resource_type.tooltip": "For more information, see <a href=\"https://cloud.tencent.com/document/product/400/91667\" target=\"_blank\">https://cloud.tencent.com/document/product/400/91667</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_resource_product.label": "Tencent Cloud resource product",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_resource_product.placeholder": "Please enter Tencent Cloud resource product",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_resource_product.tooltip": "For more information, see <a href=\"https://cloud.tencent.com/document/product/400/91667\" target=\"_blank\">https://cloud.tencent.com/document/product/400/91667</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_resource_ids.label": "Tencent Cloud resource IDs",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_resource_ids.placeholder": "Please enter Tencent Cloud resource IDs (separated by semicolons)",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_resource_ids.errmsg.invalid": "Please enter a valid Tencent Cloud resource ID",
|
||||
@ -862,12 +872,12 @@
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_certificate_id.label": "Tencent Cloud SSL certificate ID",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_certificate_id.placeholder": "Please enter Tencent Cloud SSL certificate ID",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_certificate_id.tooltip": "For more information, see <a href=\"https://console.cloud.tencent.com/certoverview\" target=\"_blank\">https://console.cloud.tencent.com/certoverview</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.label": "Tencent Cloud resource types",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.placeholder": "Please enter Tencent Cloud resource types (separated by semicolons)",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.help": "Notes: Multi-values should be separated by semicolons.",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.tooltip": "For more information, see <a href=\"https://www.tencentcloud.com/document/product/1007/57981\" target=\"_blank\">https://www.tencentcloud.com/document/product/1007/57981</a> or <a href=\"https://www.tencentcloud.com/document/product/1007/70503\" target=\"_blank\">https://www.tencentcloud.com/document/product/1007/70503</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.multiple_input_modal.title": "Change Tencent Cloud resource types",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.multiple_input_modal.placeholder": "Please enter Tencent Cloud resource type",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.label": "Tencent Cloud resource products",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.placeholder": "Please enter Tencent Cloud resource products (separated by semicolons)",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.help": "Notes: Multi-values should be separated by semicolons.",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.tooltip": "For more information, see <a href=\"https://www.tencentcloud.com/document/product/1007/57981\" target=\"_blank\">https://www.tencentcloud.com/document/product/1007/57981</a> or <a href=\"https://www.tencentcloud.com/document/product/1007/70503\" target=\"_blank\">https://www.tencentcloud.com/document/product/1007/70503</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.multiple_input_modal.title": "Change Tencent Cloud resource products",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.multiple_input_modal.placeholder": "Please enter Tencent Cloud resource product",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_regions.label": "Tencent Cloud resource regions (Optional)",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_regions.placeholder": "Please enter Tencent Cloud resource regions (separated by semicolons)",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_regions.help": "Notes: Multi-values should be separated by semicolons.",
|
||||
|
||||
@ -229,13 +229,13 @@
|
||||
"workflow_node.deploy.form.aliyun_alb_snidomain.label": "阿里云 ALB 扩展域名(可选)",
|
||||
"workflow_node.deploy.form.aliyun_alb_snidomain.placeholder": "请输入阿里云 ALB 扩展域名",
|
||||
"workflow_node.deploy.form.aliyun_alb_snidomain.help": "提示:不填写时,将替换监听器的默认证书;否则,将替换扩展域名证书。",
|
||||
"workflow_node.deploy.form.aliyun_apigw_region.label": "阿里云服务地域",
|
||||
"workflow_node.deploy.form.aliyun_apigw_region.placeholder": "请输入阿里云 API 网关地域(例如:cn-hangzhou)",
|
||||
"workflow_node.deploy.form.aliyun_apigw_region.tooltip": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/api-gateway/cloud-native-api-gateway/product-overview/regions\" target=\"_blank\">https://help.aliyun.com/zh/api-gateway/cloud-native-api-gateway/product-overview/regions</a>",
|
||||
"workflow_node.deploy.form.aliyun_apigw_service_type.label": "阿里云 API 网关服务类型",
|
||||
"workflow_node.deploy.form.aliyun_apigw_service_type.placeholder": "请选择阿里云 API 网关服务类型",
|
||||
"workflow_node.deploy.form.aliyun_apigw_service_type.option.cloudnative.label": "云原生 API 网关",
|
||||
"workflow_node.deploy.form.aliyun_apigw_service_type.option.traditional.label": "原 API 网关",
|
||||
"workflow_node.deploy.form.aliyun_apigw_region.label": "阿里云服务地域",
|
||||
"workflow_node.deploy.form.aliyun_apigw_region.placeholder": "请输入阿里云 API 网关地域(例如:cn-hangzhou)",
|
||||
"workflow_node.deploy.form.aliyun_apigw_region.tooltip": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/api-gateway/cloud-native-api-gateway/product-overview/regions\" target=\"_blank\">https://help.aliyun.com/zh/api-gateway/cloud-native-api-gateway/product-overview/regions</a>",
|
||||
"workflow_node.deploy.form.aliyun_apigw_gateway_id.label": "阿里云 API 网关 ID",
|
||||
"workflow_node.deploy.form.aliyun_apigw_gateway_id.placeholder": "请输入阿里云 API 网关 ID",
|
||||
"workflow_node.deploy.form.aliyun_apigw_gateway_id.tooltip": "这是什么?请参阅 <a href=\"https://apigw.console.aliyun.com\" target=\"_blank\">https://apigw.console.aliyun.com</a>",
|
||||
@ -357,11 +357,21 @@
|
||||
"workflow_node.deploy.form.aliyun_waf_region.tooltip": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-endpoint\" target=\"_blank\">https://help.aliyun.com/zh/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-endpoint</a>",
|
||||
"workflow_node.deploy.form.aliyun_waf_service_version.label": "阿里云 WAF 服务版本",
|
||||
"workflow_node.deploy.form.aliyun_waf_service_version.placeholder": "请选择阿里云 WAF 服务版本",
|
||||
"workflow_node.deploy.form.aliyun_waf_service_type.label": "阿里云 WAF 服务接入方式",
|
||||
"workflow_node.deploy.form.aliyun_waf_service_type.placeholder": "请选择阿里云 WAF 服务接入方式",
|
||||
"workflow_node.deploy.form.aliyun_waf_service_type.option.cloudresource.label": "云产品接入",
|
||||
"workflow_node.deploy.form.aliyun_waf_service_type.option.cname.label": "CNAME 接入",
|
||||
"workflow_node.deploy.form.aliyun_waf_instance_id.label": "阿里云 WAF 实例 ID",
|
||||
"workflow_node.deploy.form.aliyun_waf_instance_id.placeholder": "请输入阿里云 WAF 实例 ID",
|
||||
"workflow_node.deploy.form.aliyun_waf_instance_id.tooltip": "这是什么?请参阅 <a href=\"https://waf.console.aliyun.com\" target=\"_blank\">https://waf.console.aliyun.com</a><br>仅支持 CNAME 接入。",
|
||||
"workflow_node.deploy.form.aliyun_waf_domain.label": "阿里云 WAF 接入域名(可选)",
|
||||
"workflow_node.deploy.form.aliyun_waf_domain.placeholder": "请输入阿里云 WAF 接入域名",
|
||||
"workflow_node.deploy.form.aliyun_waf_instance_id.tooltip": "这是什么?请参阅 <a href=\"https://waf.console.aliyun.com\" target=\"_blank\">https://waf.console.aliyun.com</a>",
|
||||
"workflow_node.deploy.form.aliyun_waf_resource_product.label": "阿里云 WAF 云产品接入资源类型",
|
||||
"workflow_node.deploy.form.aliyun_waf_resource_product.placeholder": "请选择 WAF 云产品接入资源类型",
|
||||
"workflow_node.deploy.form.aliyun_waf_resource_id.label": "阿里云 WAF 云产品接入资源 ID",
|
||||
"workflow_node.deploy.form.aliyun_waf_resource_id.placeholder": "请选择阿里云 WAF 云产品接入资源 ID",
|
||||
"workflow_node.deploy.form.aliyun_waf_resource_port.label": "阿里云 WAF 云产品接入端口",
|
||||
"workflow_node.deploy.form.aliyun_waf_resource_port.placeholder": "请选择阿里云 WAF 云产品接入端口",
|
||||
"workflow_node.deploy.form.aliyun_waf_domain.label": "阿里云 WAF 扩展域名(可选)",
|
||||
"workflow_node.deploy.form.aliyun_waf_domain.placeholder": "请输入阿里云 WAF 扩展域名",
|
||||
"workflow_node.deploy.form.aliyun_waf_domain.help": "提示:不填写时,将替换实例的默认证书;否则,将替换扩展域名证书。",
|
||||
"workflow_node.deploy.form.apisix_resource_type.label": "证书部署方式",
|
||||
"workflow_node.deploy.form.apisix_resource_type.placeholder": "请选择证书部署方式",
|
||||
@ -843,9 +853,9 @@
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_region.label": "腾讯云服务地域",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_region.placeholder": "请输入腾讯云云产品服务地域(例如:ap-guangzhou)",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_region.tooltip": "这是什么?请参阅 <a href=\"https://cloud.tencent.com/document/product/400/41659\" target=\"_blank\">https://cloud.tencent.com/document/product/400/41659</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_resource_type.label": "腾讯云云产品资源类型",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_resource_type.placeholder": "请输入腾讯云产品资源类型",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_resource_type.tooltip": "这是什么?请参阅 <a href=\"https://cloud.tencent.com/document/product/400/91667\" target=\"_blank\">https://cloud.tencent.com/document/product/400/91667</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_resource_product.label": "腾讯云云产品资源类型",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_resource_product.placeholder": "请输入腾讯云产品资源类型",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_resource_product.tooltip": "这是什么?请参阅 <a href=\"https://cloud.tencent.com/document/product/400/91667\" target=\"_blank\">https://cloud.tencent.com/document/product/400/91667</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_resource_ids.label": "腾讯云云产品资源 ID",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_resource_ids.placeholder": "请输入腾讯云云产品资源 ID(多个值请用半角分号隔开)",
|
||||
"workflow_node.deploy.form.tencentcloud_ssldeploy_resource_ids.errmsg.invalid": "请输入正确的腾讯云云产品资源 ID",
|
||||
@ -860,12 +870,12 @@
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_certificate_id.label": "腾讯云原证书 ID",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_certificate_id.placeholder": "请输入腾讯云原证书 ID",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_certificate_id.tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/certoverview\" target=\"_blank\">https://console.cloud.tencent.com/certoverview</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.label": "腾讯云云产品资源类型",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.placeholder": "请输入腾讯云云产品资源类型(多个值请用半角分号隔开)",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.help": "提示:多个类型请用半角分号隔开。",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.tooltip": "这是什么?请参阅 <a href=\"https://cloud.tencent.com/document/product/400/91649\" target=\"_blank\">https://cloud.tencent.com/document/product/400/91649</a> 或 <a href=\"https://cloud.tencent.com/document/product/400/119791\" target=\"_blank\">https://cloud.tencent.com/document/product/400/119791</a><br>注意,这两个接口的所支持的云产品资源类型有所不同,具体请查看腾讯云官方文档。",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.multiple_input_modal.title": "修改腾讯云云产品资源类型",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_types.multiple_input_modal.placeholder": "请输入腾讯云云产品资源类型",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.label": "腾讯云云产品资源类型",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.placeholder": "请输入腾讯云云产品资源类型(多个值请用半角分号隔开)",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.help": "提示:多个类型请用半角分号隔开。",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.tooltip": "这是什么?请参阅 <a href=\"https://cloud.tencent.com/document/product/400/91649\" target=\"_blank\">https://cloud.tencent.com/document/product/400/91649</a> 或 <a href=\"https://cloud.tencent.com/document/product/400/119791\" target=\"_blank\">https://cloud.tencent.com/document/product/400/119791</a><br>注意,这两个接口的所支持的云产品资源类型有所不同,具体请查看腾讯云官方文档。",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.multiple_input_modal.title": "修改腾讯云云产品资源类型",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_products.multiple_input_modal.placeholder": "请输入腾讯云云产品资源类型",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_regions.label": "腾讯云云产品部署地域(可选)",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_regions.placeholder": "请输入腾讯云云产品部署地域(多个值请用半角分号隔开)",
|
||||
"workflow_node.deploy.form.tencentcloud_sslupdate_resource_regions.help": "提示:多个地域请用半角分号隔开。",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user