diff --git a/go.mod b/go.mod index 23063186d..0140ddc87 100644 --- a/go.mod +++ b/go.mod @@ -35,6 +35,7 @@ require ( github.com/blinkbean/dingtalk v1.1.3 github.com/byteplus-sdk/byteplus-sdk-golang v1.0.56 github.com/go-acme/lego/v4 v4.25.2 + github.com/go-cmd/cmd v1.4.3 github.com/go-lark/lark v1.16.0 github.com/go-resty/resty/v2 v2.16.5 github.com/go-viper/mapstructure/v2 v2.4.0 @@ -65,6 +66,7 @@ require ( github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.21 github.com/volcengine/volc-sdk-golang v1.0.219 github.com/volcengine/volcengine-go-sdk v1.1.30 + github.com/xhit/go-str2duration/v2 v2.1.0 gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1 gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0 golang.org/x/crypto v0.41.0 @@ -97,7 +99,6 @@ require ( github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/go-acme/alidns-20150109/v4 v4.5.10 // indirect github.com/go-acme/tencentclouddnspod v1.0.1208 // indirect - github.com/go-cmd/cmd v1.4.3 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect @@ -127,6 +128,7 @@ require ( github.com/namedotcom/go/v4 v4.0.2 // indirect github.com/nrdcg/bunny-go v0.0.0-20250327222614-988a091fc7ea // indirect github.com/nrdcg/desec v0.11.0 // indirect + github.com/nrdcg/goacmedns v0.2.0 // indirect github.com/nrdcg/mailinabox v0.2.0 // indirect github.com/nrdcg/porkbun v0.4.0 // indirect github.com/peterhellberg/link v1.2.0 // indirect @@ -206,7 +208,7 @@ require ( github.com/nrdcg/namesilo v0.2.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/spf13/cast v1.9.2 // indirect - github.com/spf13/cobra v1.9.1 // indirect + github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.9 github.com/tjfoc/gmsm v1.4.1 // indirect golang.org/x/image v0.29.0 // indirect @@ -217,7 +219,7 @@ require ( golang.org/x/sys v0.35.0 // indirect golang.org/x/term v0.34.0 // indirect golang.org/x/text v0.28.0 // indirect - golang.org/x/time v0.12.0 + golang.org/x/time v0.12.0 // indirect golang.org/x/tools v0.36.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index e925f0e71..74227562f 100644 --- a/go.sum +++ b/go.sum @@ -404,9 +404,8 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8Wd github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= -github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= +github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= @@ -691,6 +690,8 @@ github.com/nrdcg/bunny-go v0.0.0-20250327222614-988a091fc7ea h1:OSgRS4kqOs/WuxuF github.com/nrdcg/bunny-go v0.0.0-20250327222614-988a091fc7ea/go.mod h1:IDRRngAngb2eTEaWgpO0hukQFI/vJId46fT1KErMytA= github.com/nrdcg/desec v0.11.0 h1:XZVHy07sg12y8FozMp+l7XvzPsdzog0AYXuQMaHBsfs= github.com/nrdcg/desec v0.11.0/go.mod h1:5+4vyhMRTs49V9CNoODF/HwT8Mwxv9DJ6j+7NekUnBs= +github.com/nrdcg/goacmedns v0.2.0 h1:ADMbThobzEMnr6kg2ohs4KGa3LFqmgiBA22/6jUWJR0= +github.com/nrdcg/goacmedns v0.2.0/go.mod h1:T5o6+xvSLrQpugmwHvrSNkzWht0UGAwj2ACBMhh73Cg= github.com/nrdcg/mailinabox v0.2.0 h1:IKq8mfKiVwNW2hQii/ng1dJ4yYMMv3HAP3fMFIq2CFk= github.com/nrdcg/mailinabox v0.2.0/go.mod h1:0yxqeYOiGyxAu7Sb94eMxHPIOsPYXAjTeA9ZhePhGnc= github.com/nrdcg/namesilo v0.2.1 h1:kLjCjsufdW/IlC+iSfAqj0iQGgKjlbUUeDJio5Y6eMg= @@ -893,6 +894,8 @@ github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+ github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= +github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= +github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/internal/certapply/applicators/sp_acmedns.go b/internal/certapply/applicators/sp_acmedns.go new file mode 100644 index 000000000..e0814fc9d --- /dev/null +++ b/internal/certapply/applicators/sp_acmedns.go @@ -0,0 +1,29 @@ +package applicators + +import ( + "fmt" + + "github.com/go-acme/lego/v4/challenge" + + "github.com/certimate-go/certimate/internal/domain" + "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/acmedns" + xmaps "github.com/certimate-go/certimate/pkg/utils/maps" +) + +func init() { + if err := ACMEDns01Registries.Register(domain.ACMEDns01ProviderTypeACMEDNS, func(options *ProviderFactoryOptions) (challenge.Provider, error) { + credentials := domain.AccessConfigForACMEDNS{} + if err := xmaps.Populate(options.ProviderAccessConfig, &credentials); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + provider, err := acmedns.NewChallengeProvider(&acmedns.ChallengeProviderConfig{ + ApiBase: credentials.ApiBase, + StorageBaseUrl: credentials.StorageBaseUrl, + StoragePath: credentials.StoragePath, + }) + return provider, err + }); err != nil { + panic(err) + } +} diff --git a/internal/certapply/client_certifier.go b/internal/certapply/client_certifier.go index e547aa5fb..72a601042 100644 --- a/internal/certapply/client_certifier.go +++ b/internal/certapply/client_certifier.go @@ -16,14 +16,16 @@ import ( "github.com/go-acme/lego/v4/challenge/http01" "github.com/go-acme/lego/v4/log" "github.com/samber/lo" + "github.com/xhit/go-str2duration/v2" "github.com/certimate-go/certimate/internal/certapply/applicators" "github.com/certimate-go/certimate/internal/domain" ) type ObtainCertificateRequest struct { - Domains []string - KeyType certcrypto.KeyType + Domains []string + KeyType certcrypto.KeyType + LifeTime string // 提供商相关 ChallengeType string @@ -155,6 +157,13 @@ func (c *ACMEClient) ObtainCertificate(request *ObtainCertificateRequest) (*Obta Profile: request.ACMEProfile, ReplacesCertID: lo.If(request.ARIReplacesAcctUrl == c.account.ACMEAcctUrl, request.ARIReplacesCertId).Else(""), } + if request.LifeTime != "" { + lifeTime, err := str2duration.ParseDuration(request.LifeTime) + if err != nil { + return nil, fmt.Errorf("invalid lifetime: %w", err) + } + req.NotAfter = time.Now().Add(lifeTime) + } resp, err := c.client.Certificate.Obtain(req) if err != nil { ariErr := &acme.AlreadyReplacedError{} diff --git a/internal/domain/access.go b/internal/domain/access.go index de11b2afa..4debd7f8a 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -32,6 +32,12 @@ type AccessConfigForACMECA struct { Endpoint string `json:"endpoint"` } +type AccessConfigForACMEDNS struct { + ApiBase string `json:"apiBase"` + StorageBaseUrl string `json:"storageBaseUrl,omitempty"` + StoragePath string `json:"storagePath,omitempty"` +} + type AccessConfigForACMEHttpReq struct { Endpoint string `json:"endpoint"` Mode string `json:"mode,omitempty"` diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 4da89030e..c7f32c2c9 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -11,6 +11,7 @@ NOTICE: If you add new constant, please keep ASCII order. const ( AccessProviderType1Panel = AccessProviderType("1panel") AccessProviderTypeACMECA = AccessProviderType("acmeca") + AccessProviderTypeACMEDNS = AccessProviderType("acmedns") AccessProviderTypeACMEHttpReq = AccessProviderType("acmehttpreq") AccessProviderTypeAkamai = AccessProviderType("akamai") // Akamai(预留) AccessProviderTypeAliyun = AccessProviderType("aliyun") @@ -121,6 +122,7 @@ ACME DNS-01 提供商常量值。 NOTICE: If you add new constant, please keep ASCII order. */ const ( + ACMEDns01ProviderTypeACMEDNS = ACMEDns01ProviderType(AccessProviderTypeACMEDNS) ACMEDns01ProviderTypeACMEHttpReq = ACMEDns01ProviderType(AccessProviderTypeACMEHttpReq) ACMEDns01ProviderTypeAliyun = ACMEDns01ProviderType(AccessProviderTypeAliyun) // 兼容旧值,等同于 [ACMEDns01ProviderTypeAliyunDNS] ACMEDns01ProviderTypeAliyunDNS = ACMEDns01ProviderType(AccessProviderTypeAliyun + "-dns") diff --git a/internal/domain/workflow.go b/internal/domain/workflow.go index d3b484321..1d5400793 100644 --- a/internal/domain/workflow.go +++ b/internal/domain/workflow.go @@ -150,6 +150,7 @@ func (c WorkflowNodeConfig) AsBizApply() WorkflowNodeConfigForBizApply { CAProvider: xmaps.GetString(c, "caProvider"), CAProviderAccessId: xmaps.GetString(c, "caProviderAccessId"), CAProviderConfig: xmaps.GetKVMapAny(c, "caProviderConfig"), + LifeTime: xmaps.GetString(c, "lifeTime"), ACMEProfile: xmaps.GetString(c, "acmeProfile"), Nameservers: nameservers, DnsPropagationWait: xmaps.GetInt32(c, "dnsPropagationWait"), @@ -216,10 +217,11 @@ type WorkflowNodeConfigForBizApply struct { Provider string `json:"provider"` // 质询提供商 ProviderAccessId string `json:"providerAccessId"` // 质询提供商授权记录 ID ProviderConfig map[string]any `json:"providerConfig,omitempty"` // 质询提供商额外配置 - KeyAlgorithm string `json:"keyAlgorithm,omitempty"` // 证书算法 CAProvider string `json:"caProvider,omitempty"` // CA 提供商(零值时使用全局配置) CAProviderAccessId string `json:"caProviderAccessId,omitempty"` // CA 提供商授权记录 ID CAProviderConfig map[string]any `json:"caProviderConfig,omitempty"` // CA 提供商额外配置 + KeyAlgorithm string `json:"keyAlgorithm,omitempty"` // 证书算法 + LifeTime string `json:"lifeTime,omitempty"` // 证书有效期 ACMEProfile string `json:"acmeProfile,omitempty"` // ACME Profiles Extension Nameservers []string `json:"nameservers,omitempty"` // DNS 服务器列表,以半角分号分隔 DnsPropagationWait int32 `json:"dnsPropagationWait,omitempty"` // DNS 传播等待时间,等同于 lego 的 `--dns-propagation-wait` 参数 diff --git a/internal/workflow/engine/executor_bizapply.go b/internal/workflow/engine/executor_bizapply.go index 68f107e20..547e8e4bd 100644 --- a/internal/workflow/engine/executor_bizapply.go +++ b/internal/workflow/engine/executor_bizapply.go @@ -261,6 +261,7 @@ func (ne *bizApplyNodeExecutor) executeObtain(execCtx *NodeExecutionContext, nod DnsPropagationTimeout: nodeCfg.DnsPropagationTimeout, DnsTTL: nodeCfg.DnsTTL, HttpDelayWait: nodeCfg.HttpDelayWait, + LifeTime: nodeCfg.LifeTime, ACMEProfile: nodeCfg.ACMEProfile, ARIReplacesAcctUrl: lo.If(lastCertificate == nil, ""). ElseF(func() string { diff --git a/pkg/core/ssl-applicator/acme-dns01/providers/acmedns/acmedns.go b/pkg/core/ssl-applicator/acme-dns01/providers/acmedns/acmedns.go new file mode 100644 index 000000000..992766f84 --- /dev/null +++ b/pkg/core/ssl-applicator/acme-dns01/providers/acmedns/acmedns.go @@ -0,0 +1,35 @@ +package acmedns + +import ( + "errors" + "net/url" + + "github.com/go-acme/lego/v4/providers/dns/acmedns" + + "github.com/certimate-go/certimate/pkg/core" +) + +type ChallengeProviderConfig struct { + ApiBase string `json:"apiBase,omitempty"` + StorageBaseUrl string `json:"storageBaseUrl,omitempty"` + StoragePath string `json:"storagePath,omitempty"` +} + +func NewChallengeProvider(config *ChallengeProviderConfig) (core.ACMEChallenger, error) { + if config == nil { + return nil, errors.New("the configuration of the acme challenge provider is nil") + } + + ApiBase, _ := url.Parse(config.ApiBase) + providerConfig := acmedns.NewDefaultConfig() + providerConfig.APIBase = ApiBase.String() + providerConfig.StorageBaseURL = config.StorageBaseUrl + providerConfig.StoragePath = config.StoragePath + + provider, err := acmedns.NewDNSProviderConfig(providerConfig) + if err != nil { + return nil, err + } + + return provider, nil +} diff --git a/ui/public/imgs/providers/acmedns.svg b/ui/public/imgs/providers/acmedns.svg new file mode 100644 index 000000000..936ca0771 --- /dev/null +++ b/ui/public/imgs/providers/acmedns.svg @@ -0,0 +1,2 @@ + + diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index a339ed3fd..742782a87 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -13,6 +13,7 @@ import { FormNestedFieldsContextProvider } from "./forms/_context"; import { useProviderFilterByUsage } from "./forms/_hooks"; import AccessConfigFieldsProvider1Panel from "./forms/AccessConfigFieldsProvider1Panel"; import AccessConfigFieldsProviderACMECA from "./forms/AccessConfigFieldsProviderACMECA"; +import AccessConfigFieldsProviderACMEDNS from "./forms/AccessConfigFieldsProviderACMEDNS"; import AccessConfigFieldsProviderACMEHttpReq from "./forms/AccessConfigFieldsProviderACMEHttpReq"; import AccessConfigFieldsProviderAliyun from "./forms/AccessConfigFieldsProviderAliyun"; import AccessConfigFieldsProviderAPISIX from "./forms/AccessConfigFieldsProviderAPISIX"; @@ -133,6 +134,9 @@ const AccessForm = ({ className, style, disabled, initialValues, mode, usage, .. case ACCESS_PROVIDERS.ACMECA: { return ; } + case ACCESS_PROVIDERS.ACMEDNS: { + return ; + } case ACCESS_PROVIDERS.ACMEHTTPREQ: { return ; } diff --git a/ui/src/components/access/forms/AccessConfigFieldsProviderACMEDNS.tsx b/ui/src/components/access/forms/AccessConfigFieldsProviderACMEDNS.tsx new file mode 100644 index 000000000..3a0c21a1a --- /dev/null +++ b/ui/src/components/access/forms/AccessConfigFieldsProviderACMEDNS.tsx @@ -0,0 +1,82 @@ +import { getI18n, useTranslation } from "react-i18next"; +import { Form, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod/v4"; + +import { useFormNestedFieldsContext } from "./_context"; + +const AccessConfigFieldsProviderACMEDNS = () => { + const { i18n, t } = useTranslation(); + + const { parentNamePath } = useFormNestedFieldsContext(); + const formSchema = z.object({ + [parentNamePath]: getSchema({ i18n }), + }); + const formRule = createSchemaFieldRule(formSchema); + const initialValues = getInitialValues(); + + return ( + <> + } + > + + + + } + > + + + + } + > + + + + ); +}; + +const getInitialValues = (): Nullish>> => { + return { + apiBase: "https://auth.acme-dns.io/", + storageBaseUrl: "", + storagePath: "", + }; +}; + +const getSchema = ({ i18n = getI18n() }: { i18n: ReturnType }) => { + const { t } = i18n; + + return z.object({ + apiBase: z.url(t("common.errmsg.url_invalid")), + storageBaseUrl: z + .string() + .max(256, t("common.errmsg.string_max", { max: 256 })) + .nullish(), + storagePath: z + .string() + .max(256, t("common.errmsg.string_max", { max: 256 })) + .nullish(), + }); +}; + +const _default = Object.assign(AccessConfigFieldsProviderACMEDNS, { + getInitialValues, + getSchema, +}); + +export default _default; diff --git a/ui/src/components/access/forms/AccessConfigFormProvider1Panel.tsx b/ui/src/components/access/forms/AccessConfigFormProvider1Panel.tsx deleted file mode 100644 index c2e79e451..000000000 --- a/ui/src/components/access/forms/AccessConfigFormProvider1Panel.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { getI18n, useTranslation } from "react-i18next"; -import { Form, Input, Select, Switch } from "antd"; -import { createSchemaFieldRule } from "antd-zod"; -import { z } from "zod"; - -import { useFormNestedFieldsContext } from "./_context"; - -const AccessConfigFormFieldsProvider1Panel = () => { - const { i18n, t } = useTranslation(); - - const { parentNamePath } = useFormNestedFieldsContext(); - const formSchema = z.object({ - [parentNamePath]: getSchema({ i18n }), - }); - const formRule = createSchemaFieldRule(formSchema); - const initialValues = getInitialValues(); - - return ( - <> - - - - - - + + }) (v) => (v == null || v === "" ? void 0 : Number(v)), z.number().int(t("workflow_node.apply.form.dns_ttl.placeholder")).gte(1, t("workflow_node.apply.form.dns_ttl.placeholder")).nullish() ), + lifeTime: z + .string() + .nullish() + .refine((v) => { + if (!v) return true; + return /^\d+[d|h]$/.test(v) && parseInt(v) > 0; + }, t("workflow_node.apply.form.life_time.placeholder")), acmeProfile: z.string().nullish(), disableFollowCNAME: z.boolean().nullish(), disableARI: z.boolean().nullish(), diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index ea643a754..4e2102e3d 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -6,6 +6,7 @@ export const ACCESS_PROVIDERS = Object.freeze({ ["1PANEL"]: "1panel", ACMECA: "acmeca", + ACMEDNS: "acmedns", ACMEHTTPREQ: "acmehttpreq", ALIYUN: "aliyun", APISIX: "apisix", @@ -173,6 +174,7 @@ export const accessProvidersMap: Map = new NOTICE: If you add new constant, please keep ASCII order. */ export const ACME_DNS01_PROVIDERS = Object.freeze({ + ACMEDNS: `${ACCESS_PROVIDERS.ACMEDNS}`, ACMEHTTPREQ: `${ACCESS_PROVIDERS.ACMEHTTPREQ}`, ALIYUN: `${ACCESS_PROVIDERS.ALIYUN}`, // 兼容旧值,等同于 `ALIYUN_DNS` ALIYUN_DNS: `${ACCESS_PROVIDERS.ALIYUN}-dns`, @@ -369,6 +372,7 @@ export const acmeDns01ProvidersMap: Map ).map(([type, name]) => [ diff --git a/ui/src/domain/workflow.ts b/ui/src/domain/workflow.ts index ec70fa204..7d65c1ed1 100644 --- a/ui/src/domain/workflow.ts +++ b/ui/src/domain/workflow.ts @@ -102,6 +102,7 @@ export type WorkflowNodeConfigForBizApply = { caProviderAccessId?: string; caProviderConfig?: Record; keyAlgorithm: string; + lifeTime?: string; acmeProfile?: string; nameservers?: string; dnsPropagationTimeout?: number; diff --git a/ui/src/i18n/locales/en/nls.access.json b/ui/src/i18n/locales/en/nls.access.json index 2b2dd784b..98917ac40 100644 --- a/ui/src/i18n/locales/en/nls.access.json +++ b/ui/src/i18n/locales/en/nls.access.json @@ -59,6 +59,15 @@ "access.form.acmeca_eab_kid.placeholder": "Please enter ACME EAB KID", "access.form.acmeca_eab_hmac_key.label": "ACME EAB HMAC key (Optional)", "access.form.acmeca_eab_hmac_key.placeholder": "Please enter ACME EAB HMAC key", + "access.form.acmedns_api_base.label": "ACME-DNS API URL", + "access.form.acmedns_api_base.placeholder": "Please enter ACME-DNS API URL", + "access.form.acmedns_api_base.tooltip": "For more information, see https://go-acme.github.io/lego/dns/acme-dns/", + "access.form.acmedns_storage_base_url.label": "ACME-DNS Credentials URL PATH", + "access.form.acmedns_storage_base_url.placeholder": "Enter the URL path to the ACME-DNS JSON credentials JSON file. Each credentials are stored in a separate JSON file. This file will be used for TXT record updates.", + "access.form.acmedns_storage_base_url.tooltip": "For more information, see https://go-acme.github.io/lego/dns/acme-dns/", + "access.form.acmedns_storage_path.label": "ACME-DNS Credentials Local Path", + "access.form.acmedns_storage_path.placeholder": "Please enter the ACME-DNS JSON Credentials JSON File Path. Each credentials are in a separate JSON file. It will be used for TXT record updates.", + "access.form.acmedns_storage_path.tooltip": "For more information, see https://go-acme.github.io/lego/dns/acme-dns/", "access.form.acmehttpreq_endpoint.label": "Endpoint", "access.form.acmehttpreq_endpoint.placeholder": "Please enter endpoint", "access.form.acmehttpreq_endpoint.tooltip": "For more information, see https://go-acme.github.io/lego/dns/httpreq/", diff --git a/ui/src/i18n/locales/en/nls.provider.json b/ui/src/i18n/locales/en/nls.provider.json index 27dabd463..eb0b16b69 100644 --- a/ui/src/i18n/locales/en/nls.provider.json +++ b/ui/src/i18n/locales/en/nls.provider.json @@ -3,6 +3,7 @@ "provider.1panel.console": "1Panel - Console itself", "provider.1panel.site": "1Panel - Website", "provider.acmeca": "ACME Custom CA Endpoint", + "provider.acmedns": "ACME DNS", "provider.acmehttpreq": "ACME Custom HTTP Endpoint", "provider.aliyun": "Alibaba Cloud", "provider.aliyun.alb": "Alibaba Cloud - ALB (Application Load Balancer)", diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index 0d93192cb..f5513649a 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -71,6 +71,9 @@ "workflow_node.apply.form.ca_provider_access.label": "Certificate authority credential", "workflow_node.apply.form.ca_provider_access.placeholder": "Please select an credential of the certificate authority", "workflow_node.apply.form.ca_provider_access.button": "Create", + "workflow_node.apply.form.life_time.label": "Certificate lifetime (Optional)", + "workflow_node.apply.form.life_time.placeholder": "Please enter certificate lifetime, unit support: h, d. e.g. 30d", + "workflow_node.apply.form.life_time.tooltip": "It determines the lifetime of the certificate. If you don't understand this option, just keep it by default.", "workflow_node.apply.form.acme_profile.label": "ACME certificate profile (Optional)", "workflow_node.apply.form.acme_profile.placeholder": "Please enter ACME certificate profile", "workflow_node.apply.form.acme_profile.tooltip": "It determines the ACME profile which will be used to affect issuance of the certificate requested. If you don't understand this option, just keep it by default.
Click here to learn more.", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index d8e5ad3b7..4d2329110 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -58,6 +58,15 @@ "access.form.acmeca_eab_kid.placeholder": "请输入 ACME EAB KID", "access.form.acmeca_eab_hmac_key.label": "ACME EAB HMAC Key(可选)", "access.form.acmeca_eab_hmac_key.placeholder": "请输入 ACME EAB HMAC Key", + "access.form.acmedns_api_base.label": "ACME-DNS API 地址", + "access.form.acmedns_api_base.placeholder": "请输入 ACME-DNS API 地址", + "access.form.acmedns_api_base.tooltip": "这是什么?请参阅 https://go-acme.github.io/lego/dns/acme-dns/", + "access.form.acmedns_storage_base_url.label": "ACME-DNS JSON 帐户数据服务器", + "access.form.acmedns_storage_base_url.placeholder": "请输入 ACME-DNS JSON 帐户数据服务器地址", + "access.form.acmedns_storage_base_url.tooltip": "这是什么?请参阅 https://go-acme.github.io/lego/dns/acme-dns/", + "access.form.acmedns_storage_path.label": "ACME-DNS JSON 帐户数据文件", + "access.form.acmedns_storage_path.placeholder": "ACME-DNS JSON 帐户数据文件。每个域的帐户都将注册/保存到此文件,并用于 TXT 更新。", + "access.form.acmedns_storage_path.tooltip": "这是什么?请参阅 https://go-acme.github.io/lego/dns/acme-dns/", "access.form.acmehttpreq_endpoint.label": "服务端点", "access.form.acmehttpreq_endpoint.placeholder": "请输入服务端点", "access.form.acmehttpreq_endpoint.tooltip": "这是什么?请参阅 https://go-acme.github.io/lego/dns/httpreq/", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index d58eb2727..c45922124 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -3,6 +3,7 @@ "provider.1panel.console": "1Panel - 面板自身", "provider.1panel.site": "1Panel - 网站", "provider.acmeca": "ACME 自定义 CA 端点", + "provider.acmedns": "ACME DNS", "provider.acmehttpreq": "ACME 自定义 HTTP 端点", "provider.aliyun": "阿里云", "provider.aliyun.alb": "阿里云 - 应用型负载均衡 ALB", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index 0398cef57..0a1bcd352 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -70,6 +70,9 @@ "workflow_node.apply.form.ca_provider_access.label": "证书颁发机构授权", "workflow_node.apply.form.ca_provider_access.placeholder": "请选择证书颁发机构授权", "workflow_node.apply.form.ca_provider_access.button": "新建", + "workflow_node.apply.form.life_time.label": "证书有效期(可选)", + "workflow_node.apply.form.life_time.placeholder": "请输入证书有效期,单位支持:h、d,例如:30d", + "workflow_node.apply.form.life_time.tooltip": "表示证书的有效期。如果你不了解该选项的用途,保持默认即可。", "workflow_node.apply.form.acme_profile.label": "ACME 证书配置(可选)", "workflow_node.apply.form.acme_profile.placeholder": "请输入 ACME 证书配置", "workflow_node.apply.form.acme_profile.tooltip": "表示证书颁发时使用的 ACME 证书配置。如果你不了解该选项的用途,保持默认即可。
点此了解更多。",