diff --git a/internal/applicant/applicant.go b/internal/applicant/applicant.go index ecb5218e..e9ed4cb1 100644 --- a/internal/applicant/applicant.go +++ b/internal/applicant/applicant.go @@ -9,6 +9,7 @@ import ( "strconv" "strings" "sync" + "time" "github.com/go-acme/lego/v4/certcrypto" "github.com/go-acme/lego/v4/certificate" @@ -62,6 +63,7 @@ func NewWithWorkflowNode(config ApplicantWithWorkflowNodeConfig) (Applicant, err CAProviderExtendedConfig: nodeConfig.CAProviderConfig, KeyAlgorithm: nodeConfig.KeyAlgorithm, Nameservers: sliceutil.Filter(strings.Split(nodeConfig.Nameservers, ";"), func(s string) bool { return s != "" }), + DnsPropagationWait: nodeConfig.DnsPropagationWait, DnsPropagationTimeout: nodeConfig.DnsPropagationTimeout, DnsTTL: nodeConfig.DnsTTL, DisableFollowCNAME: nodeConfig.DisableFollowCNAME, @@ -189,12 +191,20 @@ func applyUseLego(legoProvider challenge.Provider, options *applicantProviderOpt } // Set the DNS01 challenge provider - challengeOptions := make([]dns01.ChallengeOption, 0) - if len(options.Nameservers) > 0 { - challengeOptions = append(challengeOptions, dns01.AddRecursiveNameservers(dns01.ParseNameservers(options.Nameservers))) - challengeOptions = append(challengeOptions, dns01.DisableAuthoritativeNssPropagationRequirement()) - } - client.Challenge.SetDNS01Provider(legoProvider, challengeOptions...) + client.Challenge.SetDNS01Provider(legoProvider, + dns01.CondOption( + len(options.Nameservers) > 0, + dns01.AddRecursiveNameservers(dns01.ParseNameservers(options.Nameservers)), + ), + dns01.CondOption( + options.DnsPropagationWait > 0, + dns01.PropagationWait(time.Duration(options.DnsPropagationWait)*time.Second, true), + ), + dns01.CondOption( + len(options.Nameservers) > 0 || options.DnsPropagationWait > 0, + dns01.DisableAuthoritativeNssPropagationRequirement(), + ), + ) // New users need to register first if !user.hasRegistration() { diff --git a/internal/applicant/providers.go b/internal/applicant/providers.go index c54d1fe2..fea6e594 100644 --- a/internal/applicant/providers.go +++ b/internal/applicant/providers.go @@ -49,6 +49,7 @@ type applicantProviderOptions struct { CAProviderExtendedConfig map[string]any KeyAlgorithm string Nameservers []string + DnsPropagationWait int32 DnsPropagationTimeout int32 DnsTTL int32 DisableFollowCNAME bool diff --git a/internal/domain/workflow.go b/internal/domain/workflow.go index 65bc35d0..6f3cccea 100644 --- a/internal/domain/workflow.go +++ b/internal/domain/workflow.go @@ -73,8 +73,9 @@ type WorkflowNodeConfigForApply struct { CAProviderConfig map[string]any `json:"caProviderConfig,omitempty"` // CA 提供商额外配置 KeyAlgorithm string `json:"keyAlgorithm"` // 证书算法 Nameservers string `json:"nameservers,omitempty"` // DNS 服务器列表,以半角分号分隔 - DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` // DNS 传播超时时间(零值取决于提供商的默认值) - DnsTTL int32 `json:"dnsTTL,omitempty"` // DNS TTL(零值取决于提供商的默认值) + DnsPropagationWait int32 `json:"dnsPropagationWait,omitempty"` // DNS 传播等待时间,等同于 lego 的 `--dns-propagation-wait` 参数 + DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` // DNS 传播检查超时时间(零值取决于提供商的默认值) + DnsTTL int32 `json:"dnsTTL,omitempty"` // DNS 解析记录 TTL(零值取决于提供商的默认值) DisableFollowCNAME bool `json:"disableFollowCNAME,omitempty"` // 是否关闭 CNAME 跟随 DisableARI bool `json:"disableARI,omitempty"` // 是否关闭 ARI SkipBeforeExpiryDays int32 `json:"skipBeforeExpiryDays,omitempty"` // 证书到期前多少天前跳过续期(零值将使用默认值 30) @@ -120,6 +121,7 @@ func (n *WorkflowNode) GetConfigForApply() WorkflowNodeConfigForApply { CAProviderConfig: maputil.GetKVMapAny(n.Config, "caProviderConfig"), KeyAlgorithm: maputil.GetString(n.Config, "keyAlgorithm"), Nameservers: maputil.GetString(n.Config, "nameservers"), + DnsPropagationWait: maputil.GetInt32(n.Config, "dnsPropagationWait"), DnsPropagationTimeout: maputil.GetInt32(n.Config, "dnsPropagationTimeout"), DnsTTL: maputil.GetInt32(n.Config, "dnsTTL"), DisableFollowCNAME: maputil.GetBool(n.Config, "disableFollowCNAME"), diff --git a/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx b/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx index 37d7c6a1..a21b7b31 100644 --- a/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx @@ -115,6 +115,14 @@ const ApplyNodeConfigForm = forwardRef validIPv4Address(e) || validIPv6Address(e) || validDomainName(e)); }, t("common.errmsg.host_invalid")), + dnsPropagationWait: z.preprocess( + (v) => (v == null || v === "" ? undefined : Number(v)), + z + .number() + .int(t("workflow_node.apply.form.dns_propagation_wait.placeholder")) + .gte(0, t("workflow_node.apply.form.dns_propagation_wait.placeholder")) + .nullish() + ), dnsPropagationTimeout: z.preprocess( (v) => (v == null || v === "" ? undefined : Number(v)), z @@ -132,7 +140,7 @@ const ApplyNodeConfigForm = forwardRef Number(v), z - .number({ message: t("workflow_node.apply.form.skip_before_expiry_days.placeholder") }) + .number() .int(t("workflow_node.apply.form.skip_before_expiry_days.placeholder")) .gte(1, t("workflow_node.apply.form.skip_before_expiry_days.placeholder")) ), @@ -390,7 +398,7 @@ const ApplyNodeConfigForm = forwardRef - {t("workflow_node.apply.form.advanced_config.label")} + {t("workflow_node.apply.form.certificate_config.label")} @@ -474,7 +482,15 @@ const ApplyNodeConfigForm = forwardRef + + + + {t("workflow_node.apply.form.advanced_config.label")} + + + +
} @@ -508,6 +524,22 @@ const ApplyNodeConfigForm = forwardRef + } + > + + + {t("workflow_node.apply.form.skip_before_expiry_days.prefix")} https://console.tencentcloud.com/edgeone", - "workflow_node.apply.form.advanced_config.label": "Advanced settings", + "workflow_node.apply.form.certificate_config.label": "Certificate settings", "workflow_node.apply.form.ca_provider.label": "Certificate authority (Optional)", "workflow_node.apply.form.ca_provider.placeholder": "Please select a certificate authority", "workflow_node.apply.form.ca_provider.tooltip": "Used to issue SSL certificates.", @@ -64,27 +64,32 @@ "workflow_node.apply.form.ca_provider_access.button": "Create", "workflow_node.apply.form.key_algorithm.label": "Certificate key algorithm", "workflow_node.apply.form.key_algorithm.placeholder": "Please select certificate key algorithm", + "workflow_node.apply.form.advanced_config.label": "Advanced settings", "workflow_node.apply.form.nameservers.label": "DNS recursive nameservers (Optional)", "workflow_node.apply.form.nameservers.placeholder": "Please enter DNS recursive nameservers (separated by semicolons)", "workflow_node.apply.form.nameservers.tooltip": "It determines whether to custom DNS recursive nameservers during ACME DNS-01 challenge. If you don't understand this option, just keep it by default. Learn more.", "workflow_node.apply.form.nameservers.multiple_input_modal.title": "Change DNS rcursive nameservers", "workflow_node.apply.form.nameservers.multiple_input_modal.placeholder": "Please enter DNS recursive nameserver", - "workflow_node.apply.form.dns_propagation_timeout.label": "DNS propagation timeout (Optional)", - "workflow_node.apply.form.dns_propagation_timeout.placeholder": "Please enter DNS propagation timeout", + "workflow_node.apply.form.dns_propagation_wait.label": "DNS propagation waiting time (Optional)", + "workflow_node.apply.form.dns_propagation_wait.placeholder": "Please enter DNS propagation waiting time", + "workflow_node.apply.form.dns_propagation_wait.unit": "seconds", + "workflow_node.apply.form.dns_propagation_wait.tooltip": "It determines the waiting time for DNS propagation during ACME DNS-01 challenge. If you don't understand this option, just keep it by default.", + "workflow_node.apply.form.dns_propagation_timeout.label": "DNS propagation checks timeout (Optional)", + "workflow_node.apply.form.dns_propagation_timeout.placeholder": "Please enter DNS propagation checks timeout", "workflow_node.apply.form.dns_propagation_timeout.unit": "seconds", - "workflow_node.apply.form.dns_propagation_timeout.tooltip": "It determines the maximum waiting time for DNS propagation checks during ACME DNS-01 challenge. If you don't understand this option, just keep it by default.

Leave it blank to use the default value provided by the provider.", + "workflow_node.apply.form.dns_propagation_timeout.tooltip": "It determines the timeout for DNS propagation checks during ACME DNS-01 challenge. If you don't understand this option, just keep it by default.

Leave it blank to use the default value provided by the provider.", "workflow_node.apply.form.dns_ttl.label": "DNS TTL (Optional)", "workflow_node.apply.form.dns_ttl.placeholder": "Please enter DNS TTL", "workflow_node.apply.form.dns_ttl.unit": "seconds", - "workflow_node.apply.form.dns_ttl.tooltip": "It determines the time to live for DNS record during ACME DNS-01 challenge. If you don't understand this option, just keep it by default.

Leave it blank to use the default value provided by the provider.", + "workflow_node.apply.form.dns_ttl.tooltip": "It determines the TTL for DNS record during ACME DNS-01 challenge. If you don't understand this option, just keep it by default.

Leave it blank to use the default value provided by the provider.", "workflow_node.apply.form.disable_follow_cname.label": "Disable CNAME following", "workflow_node.apply.form.disable_follow_cname.tooltip": "It determines whether to disable CNAME following during ACME DNS-01 challenge. If you don't understand this option, just keep it by default. Learn more.", "workflow_node.apply.form.disable_ari.label": "Disable ARI", "workflow_node.apply.form.disable_ari.tooltip": "It determines whether to disable ARI (ACME Renewal Information). If you don't understand this option, just keep it by default. Learn more.", "workflow_node.apply.form.strategy_config.label": "Strategy settings", - "workflow_node.apply.form.skip_before_expiry_days.label": "Renewal interval", + "workflow_node.apply.form.skip_before_expiry_days.label": "Repeated application", "workflow_node.apply.form.skip_before_expiry_days.placeholder": "Please enter renewal interval", - "workflow_node.apply.form.skip_before_expiry_days.prefix": "If the certificate expiration time exceeds", + "workflow_node.apply.form.skip_before_expiry_days.prefix": "If the last certificate expiration time exceeds", "workflow_node.apply.form.skip_before_expiry_days.suffix": ", skip to re-apply.", "workflow_node.apply.form.skip_before_expiry_days.unit": "days", "workflow_node.apply.form.skip_before_expiry_days.tooltip": "Be careful not to exceed the validity period limit of the issued certificate, otherwise the certificate may never be renewed.", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index d58ebe90..c35cc399 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -54,7 +54,7 @@ "workflow_node.apply.form.tencentcloud_eo_zone_id.label": "腾讯云 EdgeOne 站点 ID", "workflow_node.apply.form.tencentcloud_eo_zone_id.placeholder": "请输入腾讯云 EdgeOne 站点 ID", "workflow_node.apply.form.tencentcloud_eo_zone_id.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/edgeone", - "workflow_node.apply.form.advanced_config.label": "高级设置", + "workflow_node.apply.form.certificate_config.label": "证书设置", "workflow_node.apply.form.ca_provider.label": "证书颁发机构(可选)", "workflow_node.apply.form.ca_provider.placeholder": "请选择证书颁发机构", "workflow_node.apply.form.ca_provider.button": "设置", @@ -63,28 +63,33 @@ "workflow_node.apply.form.ca_provider_access.button": "新建", "workflow_node.apply.form.key_algorithm.label": "证书算法", "workflow_node.apply.form.key_algorithm.placeholder": "请选择证书算法", + "workflow_node.apply.form.advanced_config.label": "高级设置", "workflow_node.apply.form.nameservers.label": "DNS 递归服务器(可选)", "workflow_node.apply.form.nameservers.placeholder": "请输入 DNS 递归服务器(多个值请用半角分号隔开)", - "workflow_node.apply.form.nameservers.tooltip": "在 ACME DNS-01 质询时使用自定义的 DNS 递归服务器。如果你不了解该选项的用途,保持默认即可。点此了解更多。", + "workflow_node.apply.form.nameservers.tooltip": "表示在 ACME DNS-01 质询时使用自定义的 DNS 递归服务器。如果你不了解该选项的用途,保持默认即可。点此了解更多。", "workflow_node.apply.form.nameservers.multiple_input_modal.title": "修改 DNS 递归服务器", "workflow_node.apply.form.nameservers.multiple_input_modal.placeholder": "请输入 DNS 递归服务器", + "workflow_node.apply.form.dns_propagation_wait.label": "DNS 传播等待时间(可选)", + "workflow_node.apply.form.dns_propagation_wait.placeholder": "请输入 DNS 传播等待时间", + "workflow_node.apply.form.dns_propagation_wait.unit": "秒", + "workflow_node.apply.form.dns_propagation_wait.tooltip": "表示在 ACME DNS-01 质询时 DNS 传播的等待时间。如果你不了解此选项的用途,保持默认即可。", "workflow_node.apply.form.dns_propagation_timeout.label": "DNS 传播检查超时时间(可选)", "workflow_node.apply.form.dns_propagation_timeout.placeholder": "请输入 DNS 传播检查超时时间", "workflow_node.apply.form.dns_propagation_timeout.unit": "秒", - "workflow_node.apply.form.dns_propagation_timeout.tooltip": "在 ACME DNS-01 质询时等待 DNS 传播检查的最长时间。如果你不了解此选项的用途,保持默认即可。

不填写时,将使用提供商提供的默认值。", - "workflow_node.apply.form.dns_ttl.label": "DNS 解析 TTL(可选)", - "workflow_node.apply.form.dns_ttl.placeholder": "请输入 DNS 解析 TTL", + "workflow_node.apply.form.dns_propagation_timeout.tooltip": "表示在 ACME DNS-01 质询时 DNS 传播检查的超时时间。如果你不了解此选项的用途,保持默认即可。

不填写时,将使用提供商提供的默认值。", + "workflow_node.apply.form.dns_ttl.label": "DNS 解析记录 TTL(可选)", + "workflow_node.apply.form.dns_ttl.placeholder": "请输入 DNS 解析记录 TTL", "workflow_node.apply.form.dns_ttl.unit": "秒", - "workflow_node.apply.form.dns_ttl.tooltip": "在 ACME DNS-01 质询时 DNS 解析记录的 TTL。如果你不了解此选项的用途,保持默认即可。

不填写时,将使用提供商提供的默认值。", + "workflow_node.apply.form.dns_ttl.tooltip": "表示在 ACME DNS-01 质询时 DNS 解析记录的 TTL。如果你不了解此选项的用途,保持默认即可。

不填写时,将使用提供商提供的默认值。", "workflow_node.apply.form.disable_follow_cname.label": "阻止 CNAME 跟随", "workflow_node.apply.form.disable_follow_cname.tooltip": "在 ACME DNS-01 质询时是否阻止 CNAME 跟随。如果你不了解该选项的用途,保持默认即可。点此了解更多。", "workflow_node.apply.form.disable_ari.label": "阻止 ARI 续期", "workflow_node.apply.form.disable_ari.tooltip": "在 ACME 证书续期时是否阻止 ARI(ACME Renewal Information)。如果你不了解该选项的用途,保持默认即可。点此了解更多。", "workflow_node.apply.form.strategy_config.label": "执行策略", - "workflow_node.apply.form.skip_before_expiry_days.label": "续期间隔", + "workflow_node.apply.form.skip_before_expiry_days.label": "重复申请", "workflow_node.apply.form.skip_before_expiry_days.placeholder": "请输入续期间隔", - "workflow_node.apply.form.skip_before_expiry_days.prefix": "当上次签发的证书有效期不足", - "workflow_node.apply.form.skip_before_expiry_days.suffix": "时,重新申请证书。", + "workflow_node.apply.form.skip_before_expiry_days.prefix": "当上次签发的证书剩余有效期大于", + "workflow_node.apply.form.skip_before_expiry_days.suffix": "时,再次执行工作流时跳过此申请节点。", "workflow_node.apply.form.skip_before_expiry_days.unit": "天", "workflow_node.apply.form.skip_before_expiry_days.tooltip": "注意不要超过颁发的证书最大有效期,否则证书可能永远不会续期。", @@ -691,8 +696,8 @@ "workflow_node.deploy.form.webhook_data.errmsg.json_invalid": "请输入有效的 JSON 格式字符串", "workflow_node.deploy.form.strategy_config.label": "执行策略", "workflow_node.deploy.form.skip_on_last_succeeded.label": "重复部署", - "workflow_node.deploy.form.skip_on_last_succeeded.prefix": "当上次部署相同证书成功时,", - "workflow_node.deploy.form.skip_on_last_succeeded.suffix": "重新部署。", + "workflow_node.deploy.form.skip_on_last_succeeded.prefix": "当上次部署相同证书成功时,再次执行工作流时", + "workflow_node.deploy.form.skip_on_last_succeeded.suffix": "此部署节点。", "workflow_node.deploy.form.skip_on_last_succeeded.switch.on": "跳过", "workflow_node.deploy.form.skip_on_last_succeeded.switch.off": "不跳过",