mirror of
https://github.com/certimate-go/certimate.git
synced 2026-06-22 21:05:48 +08:00
feat: support custom certificate lifetime
This commit is contained in:
parent
eee8a38a71
commit
f79b028d0b
1
go.mod
1
go.mod
@ -64,6 +64,7 @@ require (
|
||||
github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.17
|
||||
github.com/volcengine/volc-sdk-golang v1.0.212
|
||||
github.com/volcengine/volcengine-go-sdk v1.1.18
|
||||
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.39.0
|
||||
|
||||
2
go.sum
2
go.sum
@ -901,6 +901,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=
|
||||
|
||||
@ -16,6 +16,7 @@ import (
|
||||
"github.com/go-acme/lego/v4/challenge"
|
||||
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||
"github.com/go-acme/lego/v4/lego"
|
||||
"github.com/xhit/go-str2duration/v2"
|
||||
"golang.org/x/exp/slices"
|
||||
"golang.org/x/time/rate"
|
||||
|
||||
@ -64,6 +65,7 @@ func NewWithWorkflowNode(config ApplicantWithWorkflowNodeConfig) (Applicant, err
|
||||
CAProviderAccessConfig: make(map[string]any),
|
||||
CAProviderServiceConfig: nodeCfg.CAProviderConfig,
|
||||
KeyAlgorithm: nodeCfg.KeyAlgorithm,
|
||||
LifeTime: nodeCfg.LifeTime,
|
||||
ACMEProfile: nodeCfg.ACMEProfile,
|
||||
Nameservers: xslices.Filter(strings.Split(nodeCfg.Nameservers, ";"), func(s string) bool { return s != "" }),
|
||||
DnsPropagationWait: nodeCfg.DnsPropagationWait,
|
||||
@ -238,6 +240,13 @@ func applyUseLego(legoProvider challenge.Provider, options *applicantProviderOpt
|
||||
Bundle: true,
|
||||
Profile: options.ACMEProfile,
|
||||
}
|
||||
if options.LifeTime != "" {
|
||||
lifeTime, err := str2duration.ParseDuration(options.LifeTime)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid lifetime: %w", err)
|
||||
}
|
||||
certRequest.NotAfter = time.Now().Add(lifeTime)
|
||||
}
|
||||
if options.ARIReplaceAcct == user.Registration.URI {
|
||||
certRequest.ReplacesCertID = options.ARIReplaceCert
|
||||
}
|
||||
|
||||
@ -63,6 +63,7 @@ type applicantProviderOptions struct {
|
||||
DnsPropagationWait int32
|
||||
DnsPropagationTimeout int32
|
||||
DnsTTL int32
|
||||
LifeTime string
|
||||
ACMEProfile string
|
||||
DisableFollowCNAME bool
|
||||
ARIReplaceAcct string
|
||||
|
||||
@ -75,6 +75,7 @@ type WorkflowNodeConfigForApply struct {
|
||||
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` 参数
|
||||
@ -132,6 +133,7 @@ func (n *WorkflowNode) GetConfigForApply() WorkflowNodeConfigForApply {
|
||||
CAProviderAccessId: xmaps.GetString(n.Config, "caProviderAccessId"),
|
||||
CAProviderConfig: xmaps.GetKVMapAny(n.Config, "caProviderConfig"),
|
||||
KeyAlgorithm: xmaps.GetOrDefaultString(n.Config, "keyAlgorithm", string(CertificateKeyAlgorithmTypeRSA2048)),
|
||||
LifeTime: xmaps.GetString(n.Config, "lifeTime"),
|
||||
ACMEProfile: xmaps.GetString(n.Config, "acmeProfile"),
|
||||
Nameservers: xmaps.GetString(n.Config, "nameservers"),
|
||||
DnsPropagationWait: xmaps.GetInt32(n.Config, "dnsPropagationWait"),
|
||||
|
||||
@ -113,6 +113,10 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
||||
(v) => (v == null || v === "" ? undefined : 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+[ns|us|ms|s|m|h|d|w])+$/.test(v);
|
||||
}, t("workflow_node.apply.form.life_time.placeholder")),
|
||||
acmeProfile: z.string().nullish(),
|
||||
disableFollowCNAME: z.boolean().nullish(),
|
||||
disableARI: z.boolean().nullish(),
|
||||
@ -456,6 +460,19 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="lifeTime"
|
||||
label={t("workflow_node.apply.form.life_time.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.apply.form.life_time.tooltip") }}></span>}
|
||||
>
|
||||
<Input
|
||||
type="string"
|
||||
allowClear
|
||||
placeholder={t("workflow_node.apply.form.life_time.placeholder")}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="acmeProfile"
|
||||
label={t("workflow_node.apply.form.acme_profile.label")}
|
||||
|
||||
@ -151,6 +151,7 @@ export type WorkflowNodeConfigForApply = {
|
||||
caProviderAccessId?: string;
|
||||
caProviderConfig?: Record<string, unknown>;
|
||||
keyAlgorithm: string;
|
||||
lifeTime?: string;
|
||||
acmeProfile?: string;
|
||||
nameservers?: string;
|
||||
dnsPropagationTimeout?: number;
|
||||
|
||||
@ -71,6 +71,9 @@
|
||||
"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.life_time.label": "Certificate lifetime (Optional)",
|
||||
"workflow_node.apply.form.life_time.placeholder": "Please enter certificate lifetime, unit support: ns, us, ms, s, m, h, d, w. 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.<a href=\"https://letsencrypt.org/docs/profiles/\" target=\"_blank\">Learn more</a>.",
|
||||
|
||||
@ -70,6 +70,9 @@
|
||||
"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.life_time.label": "证书有效期(可选)",
|
||||
"workflow_node.apply.form.life_time.placeholder": "请输入证书有效期,单位支持:ns、us、ms、s、m、h、d、w,例如: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 证书配置。如果你不了解该选项的用途,保持默认即可。<a href=\"https://letsencrypt.org/zh-cn/docs/profiles/\" target=\"_blank\">点此了解更多</a>。",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user