mirror of
https://github.com/certimate-go/certimate.git
synced 2026-06-13 21:01:32 +08:00
feat(provider): support additional secret data keys in k8s-secret deployer
This commit is contained in:
parent
e460bb6fc7
commit
89fb3dc99d
@ -62,14 +62,16 @@ func init() {
|
||||
}
|
||||
|
||||
provider, err := k8ssecret.NewDeployer(&k8ssecret.DeployerConfig{
|
||||
KubeConfig: credentials.KubeConfig,
|
||||
Namespace: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "namespace", "default"),
|
||||
SecretName: xmaps.GetString(options.ProviderExtendedConfig, "secretName"),
|
||||
SecretType: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "secretType", "kubernetes.io/tls"),
|
||||
SecretDataKeyForKey: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "secretDataKeyForKey", "tls.key"),
|
||||
SecretDataKeyForCrt: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "secretDataKeyForCrt", "tls.crt"),
|
||||
SecretAnnotations: secretAnnotations,
|
||||
SecretLabels: secretLabels,
|
||||
KubeConfig: credentials.KubeConfig,
|
||||
Namespace: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "namespace", "default"),
|
||||
SecretName: xmaps.GetString(options.ProviderExtendedConfig, "secretName"),
|
||||
SecretType: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "secretType", "kubernetes.io/tls"),
|
||||
SecretDataKeyForKey: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "secretDataKeyForKey", "tls.key"),
|
||||
SecretDataKeyForCrt: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "secretDataKeyForCrt", "tls.crt"),
|
||||
SecretDataKeyForCrtOnlyServer: xmaps.GetString(options.ProviderExtendedConfig, "secretDataKeyForCrtOnlyServer"),
|
||||
SecretDataKeyForCrtOnlyIntermedia: xmaps.GetString(options.ProviderExtendedConfig, "secretDataKeyForCrtOnlyIntermedia"),
|
||||
SecretAnnotations: secretAnnotations,
|
||||
SecretLabels: secretLabels,
|
||||
})
|
||||
return provider, err
|
||||
})
|
||||
|
||||
@ -30,6 +30,12 @@ type DeployerConfig struct {
|
||||
SecretDataKeyForKey string `json:"secretDataKeyForKey,omitempty"`
|
||||
// Kubernetes Secret 中用于存放证书的键。
|
||||
SecretDataKeyForCrt string `json:"secretDataKeyForCrt,omitempty"`
|
||||
// Kubernetes Secret 中用于存放证书(仅含服务器证书)的键。
|
||||
// 选填。
|
||||
SecretDataKeyForCrtOnlyServer string `json:"secretDataKeyForCrtOnlyServer,omitempty"`
|
||||
// Kubernetes Secret 中用于存放证书(仅含中间证书)的键。
|
||||
// 选填。
|
||||
SecretDataKeyForCrtOnlyIntermedia string `json:"secretDataKeyForCrtOnlyIntermedia,omitempty"`
|
||||
// Kubernetes Secret 注解。
|
||||
SecretAnnotations map[string]string `json:"secretAnnotations,omitempty"`
|
||||
// Kubernetes Secret 标签。
|
||||
@ -73,18 +79,47 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
|
||||
return nil, fmt.Errorf("config `secretType` is required")
|
||||
}
|
||||
|
||||
// 解析证书内容
|
||||
certX509, err := xcert.ParseCertificateFromPEM(certPEM)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 连接
|
||||
// 提取服务器证书和中间证书
|
||||
serverCertPEM, intermediaCertPEM, err := xcert.ExtractCertificatesFromPEM(certPEM)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to extract certs: %w", err)
|
||||
}
|
||||
|
||||
// 连接到 Kubernetes
|
||||
client, err := createK8sClient(d.config.KubeConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create kubernetes client: %w", err)
|
||||
}
|
||||
|
||||
// 获取 Secret 实例
|
||||
var secretPayload *k8score.Secret
|
||||
var secretIsNew bool
|
||||
secretPayload, err = client.Secrets(d.config.Namespace).Get(ctx, d.config.SecretName, meta.GetOptions{})
|
||||
if err != nil {
|
||||
if !k8serrs.IsNotFound(err) {
|
||||
return nil, fmt.Errorf("failed to get kubernetes secret: %w", err)
|
||||
}
|
||||
|
||||
secretPayload = &k8score.Secret{
|
||||
Type: k8score.SecretType(d.config.SecretType),
|
||||
TypeMeta: meta.TypeMeta{
|
||||
Kind: "Secret",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ObjectMeta: meta.ObjectMeta{
|
||||
Name: d.config.SecretName,
|
||||
},
|
||||
}
|
||||
secretIsNew = true
|
||||
}
|
||||
|
||||
// 生成 Secret 注解和标签
|
||||
secretAnnotations := map[string]string{
|
||||
"certimate/common-name": certX509.Subject.CommonName,
|
||||
"certimate/subject-sn": certX509.Subject.SerialNumber,
|
||||
@ -104,43 +139,7 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
|
||||
}
|
||||
}
|
||||
|
||||
// 获取 Secret 实例,如果不存在则创建
|
||||
secretPayload, err = client.Secrets(d.config.Namespace).Get(ctx, d.config.SecretName, meta.GetOptions{})
|
||||
if err != nil {
|
||||
if !k8serrs.IsNotFound(err) {
|
||||
return nil, fmt.Errorf("failed to get kubernetes secret: %w", err)
|
||||
}
|
||||
|
||||
secretPayload = &k8score.Secret{
|
||||
TypeMeta: meta.TypeMeta{
|
||||
Kind: "Secret",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ObjectMeta: meta.ObjectMeta{
|
||||
Name: d.config.SecretName,
|
||||
Annotations: secretAnnotations,
|
||||
Labels: secretLabels,
|
||||
},
|
||||
Type: k8score.SecretType(d.config.SecretType),
|
||||
}
|
||||
secretPayload.Data = make(map[string][]byte)
|
||||
if d.config.SecretDataKeyForKey != "" {
|
||||
secretPayload.Data[d.config.SecretDataKeyForKey] = []byte(privkeyPEM)
|
||||
}
|
||||
if d.config.SecretDataKeyForCrt != "" {
|
||||
secretPayload.Data[d.config.SecretDataKeyForCrt] = []byte(certPEM)
|
||||
}
|
||||
|
||||
secretPayload, err = client.Secrets(d.config.Namespace).Create(ctx, secretPayload, meta.CreateOptions{})
|
||||
d.logger.Debug("kubernetes operate 'Secrets.Create'", slog.String("namespace", d.config.Namespace), slog.Any("secret", secretPayload))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create kubernetes secret: %w", err)
|
||||
} else {
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// 更新 Secret 实例
|
||||
// 赋值 Secret 实例
|
||||
secretPayload.Type = k8score.SecretType(d.config.SecretType)
|
||||
if secretPayload.ObjectMeta.Annotations == nil {
|
||||
secretPayload.ObjectMeta.Annotations = secretAnnotations
|
||||
@ -165,10 +164,26 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
|
||||
if d.config.SecretDataKeyForCrt != "" {
|
||||
secretPayload.Data[d.config.SecretDataKeyForCrt] = []byte(certPEM)
|
||||
}
|
||||
secretPayload, err = client.Secrets(d.config.Namespace).Update(ctx, secretPayload, meta.UpdateOptions{})
|
||||
d.logger.Debug("kubernetes operate 'Secrets.Update'", slog.String("namespace", d.config.Namespace), slog.Any("secret", secretPayload))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to update kubernetes secret: %w", err)
|
||||
if d.config.SecretDataKeyForCrtOnlyServer != "" {
|
||||
secretPayload.Data[d.config.SecretDataKeyForCrtOnlyServer] = []byte(serverCertPEM)
|
||||
}
|
||||
if d.config.SecretDataKeyForCrtOnlyIntermedia != "" {
|
||||
secretPayload.Data[d.config.SecretDataKeyForCrtOnlyIntermedia] = []byte(intermediaCertPEM)
|
||||
}
|
||||
|
||||
// 创建或更新 Secret 实例
|
||||
if secretIsNew {
|
||||
secretPayload, err = client.Secrets(d.config.Namespace).Create(ctx, secretPayload, meta.CreateOptions{})
|
||||
d.logger.Debug("kubernetes operate 'Secrets.Create'", slog.String("namespace", d.config.Namespace), slog.Any("secret", secretPayload))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create kubernetes secret: %w", err)
|
||||
}
|
||||
} else {
|
||||
secretPayload, err = client.Secrets(d.config.Namespace).Update(ctx, secretPayload, meta.UpdateOptions{})
|
||||
d.logger.Debug("kubernetes operate 'Secrets.Update'", slog.String("namespace", d.config.Namespace), slog.Any("secret", secretPayload))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to update kubernetes secret: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return &deployer.DeployResult{}, nil
|
||||
|
||||
@ -493,9 +493,9 @@ const BizApplyNodeConfigForm = ({ node, ...props }: BizApplyNodeConfigFormProps)
|
||||
label={t("workflow_node.apply.form.key_algorithm.label")}
|
||||
extra={
|
||||
fieldKeySource === KEY_SOURCE_REUSE ? (
|
||||
<span dangerouslySetInnerHTML={{ __html: t("workflow_node.apply.form.key_algorithm.help_reuse") }}></span>
|
||||
<span dangerouslySetInnerHTML={{ __html: t("workflow_node.apply.form.key_source.option.reuse.help") }}></span>
|
||||
) : fieldKeySource === KEY_SOURCE_CUSTOM ? (
|
||||
<span dangerouslySetInnerHTML={{ __html: t("workflow_node.apply.form.key_algorithm.help_custom") }}></span>
|
||||
<span dangerouslySetInnerHTML={{ __html: t("workflow_node.apply.form.key_source.option.custom.help") }}></span>
|
||||
) : (
|
||||
void 0
|
||||
)
|
||||
|
||||
@ -62,7 +62,7 @@ const BizDeployNodeConfigFieldsProvider1Panel = () => {
|
||||
label={t("workflow_node.deploy.form.1panel_website_match_pattern.label")}
|
||||
extra={
|
||||
fieldWebsiteMatchPattern === WEBSITE_MATCH_PATTERN_CERTSAN ? (
|
||||
<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.1panel_website_match_pattern.help_certsan") }}></span>
|
||||
<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.1panel_website_match_pattern.option.certsan.help") }}></span>
|
||||
) : (
|
||||
void 0
|
||||
)
|
||||
|
||||
@ -64,6 +64,16 @@ const BizDeployNodeConfigFieldsProviderKubernetesSecret = () => {
|
||||
<Input placeholder={t("workflow_node.deploy.form.k8s_secret_type.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "secretDataKeyForKey"]}
|
||||
initialValue={initialValues.secretDataKeyForKey}
|
||||
label={t("workflow_node.deploy.form.k8s_secret_data_key_for_key.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.k8s_secret_data_key_for_key.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.k8s_secret_data_key_for_key.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "secretDataKeyForCrt"]}
|
||||
initialValue={initialValues.secretDataKeyForCrt}
|
||||
@ -75,13 +85,23 @@ const BizDeployNodeConfigFieldsProviderKubernetesSecret = () => {
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "secretDataKeyForKey"]}
|
||||
initialValue={initialValues.secretDataKeyForKey}
|
||||
label={t("workflow_node.deploy.form.k8s_secret_data_key_for_key.label")}
|
||||
name={[parentNamePath, "secretDataKeyForCrtOnlyServer"]}
|
||||
initialValue={initialValues.secretDataKeyForCrtOnlyServer}
|
||||
label={t("workflow_node.deploy.form.k8s_secret_data_key_for_servercrt.label")}
|
||||
extra={t("workflow_node.deploy.form.k8s_secret_data_key_for_servercrt.help")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.k8s_secret_data_key_for_key.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.k8s_secret_data_key_for_key.placeholder")} />
|
||||
<Input allowClear placeholder={t("workflow_node.deploy.form.k8s_secret_data_key_for_servercrt.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "secretDataKeyForCrtOnlyIntermedia"]}
|
||||
initialValue={initialValues.secretDataKeyForCrtOnlyIntermedia}
|
||||
label={t("workflow_node.deploy.form.k8s_secret_data_key_for_intermediacrt.label")}
|
||||
extra={t("workflow_node.deploy.form.k8s_secret_data_key_for_intermediacrt.help")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Input allowClear placeholder={t("workflow_node.deploy.form.k8s_secret_data_key_for_intermediacrt.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
@ -141,6 +161,8 @@ const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> })
|
||||
secretType: z.string().nonempty(),
|
||||
secretDataKeyForCrt: z.string().nonempty(),
|
||||
secretDataKeyForKey: z.string().nonempty(),
|
||||
secretDataKeyForCrtOnlyServer: z.string().nullish(),
|
||||
secretDataKeyForCrtOnlyIntermedia: z.string().nullish(),
|
||||
secretAnnotations: z
|
||||
.string()
|
||||
.nullish()
|
||||
|
||||
@ -168,18 +168,18 @@
|
||||
"label": "Auto"
|
||||
},
|
||||
"reuse": {
|
||||
"label": "Reuse"
|
||||
"label": "Reuse",
|
||||
"help": "Notes: If there is an existing certificate, the original key algorithm will be used."
|
||||
},
|
||||
"custom": {
|
||||
"label": "Custom"
|
||||
"label": "Custom",
|
||||
"help": "Notes: Please ensure that the algorithm matches the private key."
|
||||
}
|
||||
}
|
||||
},
|
||||
"key_algorithm": {
|
||||
"label": "Key algorithm",
|
||||
"placeholder": "Please select key algorithm",
|
||||
"help_reuse": "Notes: If there is an existing certificate, the original key algorithm will be used.",
|
||||
"help_custom": "Notes: Please ensure that the algorithm matches the private key."
|
||||
"placeholder": "Please select key algorithm"
|
||||
},
|
||||
"key_content": {
|
||||
"label": "Private key (PEM format)",
|
||||
@ -514,22 +514,22 @@
|
||||
},
|
||||
"shared_file_path_for_key": {
|
||||
"label": "Private key file path",
|
||||
"placeholder": "Please enter the output file path for private key file",
|
||||
"placeholder": "Please enter output file path for private key file",
|
||||
"help": "Notes: It should include the full file path, not just the directory."
|
||||
},
|
||||
"shared_file_path_for_crt": {
|
||||
"label": "Certificate file path",
|
||||
"placeholder": "Please enter the output file path for certificate",
|
||||
"placeholder": "Please enter output file path for certificate",
|
||||
"help": "Notes: It should include the full file path, not just the directory."
|
||||
},
|
||||
"shared_file_path_for_servercrt": {
|
||||
"label": "Certificate file (includes the end-entity parts only) path (Optional)",
|
||||
"placeholder": "Please enter the output file path for server certificate file",
|
||||
"placeholder": "Please enter output file path for server certificate file",
|
||||
"help": "Notes: It should include the full file path, not just the directory."
|
||||
},
|
||||
"shared_file_path_for_intermediacrt": {
|
||||
"label": "Certificate file (includes the CA parts only) path (Optional)",
|
||||
"placeholder": "Please enter the output file path for intermediate certificate file",
|
||||
"placeholder": "Please enter output file path for intermediate certificate file",
|
||||
"help": "Notes: It should include the full file path, not just the directory."
|
||||
},
|
||||
"shared_pfx_password": {
|
||||
@ -577,10 +577,10 @@
|
||||
"label": "Specified ID"
|
||||
},
|
||||
"certsan": {
|
||||
"label": "via Certificate"
|
||||
"label": "via Certificate",
|
||||
"help": "Notes: The website name should be a domain name and include SSL configurations."
|
||||
}
|
||||
},
|
||||
"help_certsan": "Notes: The website name should be a domain name and include SSL configurations."
|
||||
}
|
||||
},
|
||||
"1panel_website_id": {
|
||||
"label": "1Panel website ID",
|
||||
@ -1516,15 +1516,25 @@
|
||||
"placeholder": "Please enter Kubernetes Secret type",
|
||||
"tooltip": "For more information, see <a href=\"https://kubernetes.io/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/docs/concepts/configuration/secret/</a>"
|
||||
},
|
||||
"k8s_secret_data_key_for_key": {
|
||||
"label": "Kubernetes Secret data key for private key",
|
||||
"placeholder": "Please enter Kubernetes Secret data key for private key",
|
||||
"tooltip": "For more information, see <a href=\"https://kubernetes.io/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/docs/concepts/configuration/secret/</a>"
|
||||
},
|
||||
"k8s_secret_data_key_for_crt": {
|
||||
"label": "Kubernetes Secret data key for certificate",
|
||||
"placeholder": "Please enter Kubernetes Secret data key for certificate",
|
||||
"tooltip": "For more information, see <a href=\"https://kubernetes.io/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/docs/concepts/configuration/secret/</a>"
|
||||
},
|
||||
"k8s_secret_data_key_for_key": {
|
||||
"label": "Kubernetes Secret data key for private key",
|
||||
"placeholder": "Please enter Kubernetes Secret data key for private key",
|
||||
"tooltip": "For more information, see <a href=\"https://kubernetes.io/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/docs/concepts/configuration/secret/</a>"
|
||||
"k8s_secret_data_key_for_servercrt": {
|
||||
"label": "Kubernetes Secret data key for certificate (includes the end-entity parts only) (Optional)",
|
||||
"placeholder": "Please enter Kubernetes Secret data key for server certificate",
|
||||
"help": ""
|
||||
},
|
||||
"k8s_secret_data_key_for_intermediacrt": {
|
||||
"label": "Kubernetes Secret data key for certificate (includes the CA parts only) (Optional)",
|
||||
"placeholder": "Please enter Kubernetes Secret data key for intermediate certificate",
|
||||
"help": ""
|
||||
},
|
||||
"k8s_secret_annotations": {
|
||||
"label": "Kubernetes Secret annotations (Optional)",
|
||||
@ -1805,20 +1815,20 @@
|
||||
},
|
||||
"s3_object_key_for_key": {
|
||||
"label": "Private key file object key",
|
||||
"placeholder": "Please enter the object key for private key file"
|
||||
"placeholder": "Please enter object key for private key file"
|
||||
},
|
||||
"s3_object_key_for_crt": {
|
||||
"label": "Certificate file object key",
|
||||
"placeholder": "Please enter the object key for certificate"
|
||||
"placeholder": "Please enter object key for certificate"
|
||||
},
|
||||
"s3_object_key_for_servercrt": {
|
||||
"label": "Certificate file (includes the end-entity parts only) object key (Optional)",
|
||||
"placeholder": "Please enter the object key for server certificate file",
|
||||
"placeholder": "Please enter object key for server certificate file",
|
||||
"help": ""
|
||||
},
|
||||
"s3_object_key_for_intermediacrt": {
|
||||
"label": "Certificate file (includes the CA parts only) object key (Optional)",
|
||||
"placeholder": "Please enter the object key for intermediate certificate file",
|
||||
"placeholder": "Please enter object key for intermediate certificate file",
|
||||
"help": ""
|
||||
},
|
||||
"safeline": {
|
||||
|
||||
@ -1029,7 +1029,7 @@
|
||||
"s3_endpoint": {
|
||||
"label": "终端节点",
|
||||
"placeholder": "请输入终端节点",
|
||||
"help": "注意:如果不指定协议,则默认使用 <em>https://</em>。"
|
||||
"help": "提示:如果不指定协议,则默认使用 <em>https://</em>。"
|
||||
},
|
||||
"s3_access_key": {
|
||||
"label": "AccessKey",
|
||||
|
||||
@ -104,7 +104,7 @@
|
||||
"form": {
|
||||
"provider": {
|
||||
"label": "ACME 提供商",
|
||||
"help": "注意:不同服务商所支持的证书有效期、私钥算法、多域名数量上限、是否允许泛域名等可能不同,切换服务商后请注意检查已有工作流的配置是否需要调整。"
|
||||
"help": "提示:不同服务商所支持的证书有效期、私钥算法、多域名数量上限、是否允许泛域名等可能不同,切换服务商后请注意检查已有工作流的配置是否需要调整。"
|
||||
},
|
||||
"letsencryptstaging_alert": "测试环境比生产环境有更宽松的速率限制,可进行测试性部署。<br><br>点击下方链接了解更多:<br><a href=\"https://letsencrypt.org/zh-cn/docs/staging-environment/\" target=\"_blank\">https://letsencrypt.org/zh-cn/docs/staging-environment/</a>"
|
||||
}
|
||||
|
||||
@ -168,18 +168,18 @@
|
||||
"label": "随机生成"
|
||||
},
|
||||
"reuse": {
|
||||
"label": "复用私钥"
|
||||
"label": "复用私钥",
|
||||
"help": "提示:如果存在之前申请的证书,将以原私钥算法为准;否则才使用此选项。"
|
||||
},
|
||||
"custom": {
|
||||
"label": "自定义"
|
||||
"label": "自定义",
|
||||
"help": "提示:请确保算法与私钥相匹配。"
|
||||
}
|
||||
}
|
||||
},
|
||||
"key_algorithm": {
|
||||
"label": "私钥算法",
|
||||
"placeholder": "请选择证书的私钥算法",
|
||||
"help_reuse": "提示:如果存在之前申请的证书,将以原私钥算法为准;否则才使用此选项。",
|
||||
"help_custom": "注意:请确保算法与私钥相匹配。"
|
||||
"placeholder": "请选择证书的私钥算法"
|
||||
},
|
||||
"key_content": {
|
||||
"label": "私钥文件(PEM 格式)",
|
||||
@ -202,7 +202,7 @@
|
||||
"validity_lifetime": {
|
||||
"label": "有效期(可选)",
|
||||
"placeholder": "请输入证书的有效期",
|
||||
"help": "注意:并非所有证书颁发机构都支持此特性。",
|
||||
"help": "提示:并非所有证书颁发机构都支持此特性。",
|
||||
"tooltip": "表示证书的有效期。如果你不了解该选项的用途,保持默认即可。",
|
||||
"units": {
|
||||
"h": "小时",
|
||||
@ -212,13 +212,13 @@
|
||||
"preferred_chain": {
|
||||
"label": "首选链(可选)",
|
||||
"placeholder": "请输入证书首选链",
|
||||
"help": "注意:并非所有证书颁发机构都支持此特性。",
|
||||
"help": "提示:并非所有证书颁发机构都支持此特性。",
|
||||
"tooltip": "表示证书颁发时使用的首选证书链。如果你不了解该选项的用途,保持默认即可。<br><a href=\"https://letsencrypt.org/zh-cn/certificates/\" target=\"_blank\">点此了解更多</a>。"
|
||||
},
|
||||
"acme_profile": {
|
||||
"label": "ACME 配置文件(可选)",
|
||||
"placeholder": "请输入 ACME 配置文件",
|
||||
"help": "注意:并非所有证书颁发机构都支持此特性。",
|
||||
"help": "提示:并非所有证书颁发机构都支持此特性。",
|
||||
"tooltip": "表示证书颁发时使用的 ACME 证书配置文件。如果你不了解该选项的用途,保持默认即可。<br><a href=\"https://letsencrypt.org/zh-cn/docs/profiles/#%E6%88%91%E4%BB%AC%E6%8F%90%E4%BE%9B%E7%9A%84%E9%85%8D%E7%BD%AE\" target=\"_blank\">点此了解更多</a>。"
|
||||
},
|
||||
"disable_cn": {
|
||||
@ -273,7 +273,7 @@
|
||||
"prefix": "当上次申请的证书剩余时长大于",
|
||||
"suffix": ",再次运行工作流时跳过此节点。",
|
||||
"unit": "天",
|
||||
"help": "注意:证书实际续期间隔还取决于触发运行的 CRON 表达式。"
|
||||
"help": "提示:证书实际续期间隔还取决于触发运行的 CRON 表达式。"
|
||||
},
|
||||
|
||||
"aliyun_esa_region": {
|
||||
@ -483,7 +483,7 @@
|
||||
"option": {
|
||||
"exact": {
|
||||
"label": "精确匹配",
|
||||
"help.wildcard": "注意:对于支持泛解析的站点,<strong>精确匹配</strong>一个泛域名仅包含该站点本身、不包括相关子域名站点。"
|
||||
"help.wildcard": "提示:对于支持泛解析的站点,<strong>精确匹配</strong>一个泛域名仅包含该站点本身、不包括相关子域名站点。"
|
||||
},
|
||||
"wildcard": {
|
||||
"label": "通配符匹配(泛域名)"
|
||||
@ -514,22 +514,22 @@
|
||||
"shared_file_path_for_key": {
|
||||
"label": "私钥文件输出路径",
|
||||
"placeholder": "请输入私钥文件输出路径",
|
||||
"help": "注意:路径需包含完整的文件名,而不是只有目录。"
|
||||
"help": "提示:路径需包含完整的文件名,而不是只有目录。"
|
||||
},
|
||||
"shared_file_path_for_crt": {
|
||||
"label": "证书文件输出路径",
|
||||
"placeholder": "请输入证书文件输出路径",
|
||||
"help": "注意:路径需包含完整的文件名,而不是只有目录。"
|
||||
"help": "提示:路径需包含完整的文件名,而不是只有目录。"
|
||||
},
|
||||
"shared_file_path_for_servercrt": {
|
||||
"label": "证书文件(仅含服务器证书)输出路径(可选)",
|
||||
"placeholder": "请输入服务器证书文件输出路径",
|
||||
"help": "注意:路径需包含完整的文件名,而不是只有目录。不填写时将不输出服务器证书。"
|
||||
"help": "提示:路径需包含完整的文件名,而不是只有目录。不填写时将不会保存服务器证书。"
|
||||
},
|
||||
"shared_file_path_for_intermediacrt": {
|
||||
"label": "证书文件(仅含中间证书)输出路径(可选)",
|
||||
"placeholder": "请输入中间证书文件输出路径",
|
||||
"help": "注意:路径需包含完整的文件名,而不是只有目录。不填写时将不输出中间证书。"
|
||||
"help": "提示:路径需包含完整的文件名,而不是只有目录。不填写时将不会保存中间证书。"
|
||||
},
|
||||
"shared_pfx_password": {
|
||||
"label": "PFX 导出密码",
|
||||
@ -576,10 +576,10 @@
|
||||
"label": "指定 ID"
|
||||
},
|
||||
"certsan": {
|
||||
"label": "根据证书自动匹配"
|
||||
"label": "根据证书自动匹配",
|
||||
"help": "提示:网站名称需要是域名、且包含开启了 SSL 的域名配置。"
|
||||
}
|
||||
},
|
||||
"help_certsan": "注意:网站名称需要为域名、且包含开启了 SSL 的域名配置。"
|
||||
}
|
||||
},
|
||||
"1panel_website_id": {
|
||||
"label": "1Panel 网站 ID",
|
||||
@ -1299,7 +1299,7 @@
|
||||
"flyio_domain": {
|
||||
"label": "Fly.io 自定义域名",
|
||||
"placeholder": "请输入 Fly.io 自定义域名",
|
||||
"help": "注意:首次导入自定义证书后,请登录 Fly.io 控制台完成域名所有权验证。"
|
||||
"help": "提示:首次导入自定义证书后,请登录 Fly.io 控制台完成域名所有权验证。"
|
||||
},
|
||||
"gcore_cdn_resource_id": {
|
||||
"label": "G-Core CDN 资源 ID",
|
||||
@ -1512,16 +1512,26 @@
|
||||
"placeholder": "请输入 Kubernetes Secret 类型",
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/</a>"
|
||||
},
|
||||
"k8s_secret_data_key_for_crt": {
|
||||
"label": "Kubernetes Secret 数据键(用于存放证书的字段)",
|
||||
"placeholder": "请输入 Kubernetes Secret 中用于存放证书的数据键",
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/</a>"
|
||||
},
|
||||
"k8s_secret_data_key_for_key": {
|
||||
"label": "Kubernetes Secret 数据键(用于存放私钥的字段)",
|
||||
"placeholder": "请输入 Kubernetes Secret 中用于存放私钥的数据键",
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/</a>"
|
||||
},
|
||||
"k8s_secret_data_key_for_crt": {
|
||||
"label": "Kubernetes Secret 数据键之存放证书的字段",
|
||||
"placeholder": "请输入 Kubernetes Secret 中用于存放证书的数据键",
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/</a>"
|
||||
},
|
||||
"k8s_secret_data_key_for_servercrt": {
|
||||
"label": "Kubernetes Secret 数据键之存放仅服务器证书的字段(可选)",
|
||||
"placeholder": "请输入 Kubernetes Secret 中用于存放服务器证书的数据键",
|
||||
"help": "提示:不填写时将不会保存服务器证书。"
|
||||
},
|
||||
"k8s_secret_data_key_for_intermediacrt": {
|
||||
"label": "Kubernetes Secret 数据键之存放仅中间证书的字段(可选)",
|
||||
"placeholder": "请输入 Kubernetes Secret 中用于存放中间证书的数据键",
|
||||
"help": "提示:不填写时将不会保存中间证书。"
|
||||
},
|
||||
"k8s_secret_annotations": {
|
||||
"label": "Kubernetes Secret 注解(可选)",
|
||||
"placeholder": "请输入 Kubernetes Secret 注解",
|
||||
@ -1810,12 +1820,12 @@
|
||||
"s3_object_key_for_servercrt": {
|
||||
"label": "证书文件(仅含服务器证书)对象键(可选)",
|
||||
"placeholder": "请输入服务器证书文件对象键",
|
||||
"help": "注意:不填写时将不会上传服务器证书。"
|
||||
"help": "提示:不填写时将不会保存服务器证书。"
|
||||
},
|
||||
"s3_object_key_for_intermediacrt": {
|
||||
"label": "证书文件(仅含中间证书)对象键(可选)",
|
||||
"placeholder": "请输入中间证书文件对象键",
|
||||
"help": "注意:不填写时将不会上传中间证书。"
|
||||
"help": "提示:不填写时将不会保存中间证书。"
|
||||
},
|
||||
"safeline": {
|
||||
"guide": "需要雷池 v6.6 或更高版本。"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user