From 89fb3dc99d2e3d3bb1f47bd47762e7188310963e Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Wed, 20 May 2026 17:34:16 +0800 Subject: [PATCH] feat(provider): support additional secret data keys in k8s-secret deployer --- .../deployers/sp_kubernetes_secret.go | 18 ++-- .../providers/k8s-secret/k8s_secret.go | 99 +++++++++++-------- .../designer/forms/BizApplyNodeConfigForm.tsx | 4 +- ...izDeployNodeConfigFieldsProvider1Panel.tsx | 2 +- ...deConfigFieldsProviderKubernetesSecret.tsx | 32 +++++- .../i18n/resources/en/nls.workflow.nodes.json | 50 ++++++---- ui/src/i18n/resources/zh/nls.access.json | 2 +- ui/src/i18n/resources/zh/nls.settings.json | 2 +- .../i18n/resources/zh/nls.workflow.nodes.json | 60 ++++++----- 9 files changed, 164 insertions(+), 105 deletions(-) diff --git a/internal/certmgmt/deployers/sp_kubernetes_secret.go b/internal/certmgmt/deployers/sp_kubernetes_secret.go index 1a9b2d34..d3558105 100644 --- a/internal/certmgmt/deployers/sp_kubernetes_secret.go +++ b/internal/certmgmt/deployers/sp_kubernetes_secret.go @@ -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 }) diff --git a/pkg/core/deployer/providers/k8s-secret/k8s_secret.go b/pkg/core/deployer/providers/k8s-secret/k8s_secret.go index 55755a64..b8b8d914 100644 --- a/pkg/core/deployer/providers/k8s-secret/k8s_secret.go +++ b/pkg/core/deployer/providers/k8s-secret/k8s_secret.go @@ -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 diff --git a/ui/src/components/workflow/designer/forms/BizApplyNodeConfigForm.tsx b/ui/src/components/workflow/designer/forms/BizApplyNodeConfigForm.tsx index 54e89590..81b17092 100644 --- a/ui/src/components/workflow/designer/forms/BizApplyNodeConfigForm.tsx +++ b/ui/src/components/workflow/designer/forms/BizApplyNodeConfigForm.tsx @@ -493,9 +493,9 @@ const BizApplyNodeConfigForm = ({ node, ...props }: BizApplyNodeConfigFormProps) label={t("workflow_node.apply.form.key_algorithm.label")} extra={ fieldKeySource === KEY_SOURCE_REUSE ? ( - + ) : fieldKeySource === KEY_SOURCE_CUSTOM ? ( - + ) : ( void 0 ) diff --git a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider1Panel.tsx b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider1Panel.tsx index 9a590040..475f7c17 100644 --- a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider1Panel.tsx +++ b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider1Panel.tsx @@ -62,7 +62,7 @@ const BizDeployNodeConfigFieldsProvider1Panel = () => { label={t("workflow_node.deploy.form.1panel_website_match_pattern.label")} extra={ fieldWebsiteMatchPattern === WEBSITE_MATCH_PATTERN_CERTSAN ? ( - + ) : ( void 0 ) diff --git a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderKubernetesSecret.tsx b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderKubernetesSecret.tsx index 9612e3a9..84535aa4 100644 --- a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderKubernetesSecret.tsx +++ b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderKubernetesSecret.tsx @@ -64,6 +64,16 @@ const BizDeployNodeConfigFieldsProviderKubernetesSecret = () => { + } + > + + + { } > - + + + + + }) secretType: z.string().nonempty(), secretDataKeyForCrt: z.string().nonempty(), secretDataKeyForKey: z.string().nonempty(), + secretDataKeyForCrtOnlyServer: z.string().nullish(), + secretDataKeyForCrtOnlyIntermedia: z.string().nullish(), secretAnnotations: z .string() .nullish() diff --git a/ui/src/i18n/resources/en/nls.workflow.nodes.json b/ui/src/i18n/resources/en/nls.workflow.nodes.json index 360304da..2ca52135 100644 --- a/ui/src/i18n/resources/en/nls.workflow.nodes.json +++ b/ui/src/i18n/resources/en/nls.workflow.nodes.json @@ -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 https://kubernetes.io/docs/concepts/configuration/secret/" }, + "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 https://kubernetes.io/docs/concepts/configuration/secret/" + }, "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 https://kubernetes.io/docs/concepts/configuration/secret/" }, - "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 https://kubernetes.io/docs/concepts/configuration/secret/" + "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": { diff --git a/ui/src/i18n/resources/zh/nls.access.json b/ui/src/i18n/resources/zh/nls.access.json index a20a3cba..081699b5 100644 --- a/ui/src/i18n/resources/zh/nls.access.json +++ b/ui/src/i18n/resources/zh/nls.access.json @@ -1029,7 +1029,7 @@ "s3_endpoint": { "label": "终端节点", "placeholder": "请输入终端节点", - "help": "注意:如果不指定协议,则默认使用 https://。" + "help": "提示:如果不指定协议,则默认使用 https://。" }, "s3_access_key": { "label": "AccessKey", diff --git a/ui/src/i18n/resources/zh/nls.settings.json b/ui/src/i18n/resources/zh/nls.settings.json index a75e19f3..e76d8873 100644 --- a/ui/src/i18n/resources/zh/nls.settings.json +++ b/ui/src/i18n/resources/zh/nls.settings.json @@ -104,7 +104,7 @@ "form": { "provider": { "label": "ACME 提供商", - "help": "注意:不同服务商所支持的证书有效期、私钥算法、多域名数量上限、是否允许泛域名等可能不同,切换服务商后请注意检查已有工作流的配置是否需要调整。" + "help": "提示:不同服务商所支持的证书有效期、私钥算法、多域名数量上限、是否允许泛域名等可能不同,切换服务商后请注意检查已有工作流的配置是否需要调整。" }, "letsencryptstaging_alert": "测试环境比生产环境有更宽松的速率限制,可进行测试性部署。

点击下方链接了解更多:
https://letsencrypt.org/zh-cn/docs/staging-environment/" } diff --git a/ui/src/i18n/resources/zh/nls.workflow.nodes.json b/ui/src/i18n/resources/zh/nls.workflow.nodes.json index 39001d4a..edb155a4 100644 --- a/ui/src/i18n/resources/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/resources/zh/nls.workflow.nodes.json @@ -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": "表示证书颁发时使用的首选证书链。如果你不了解该选项的用途,保持默认即可。
点此了解更多。" }, "acme_profile": { "label": "ACME 配置文件(可选)", "placeholder": "请输入 ACME 配置文件", - "help": "注意:并非所有证书颁发机构都支持此特性。", + "help": "提示:并非所有证书颁发机构都支持此特性。", "tooltip": "表示证书颁发时使用的 ACME 证书配置文件。如果你不了解该选项的用途,保持默认即可。
点此了解更多。" }, "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": "注意:对于支持泛解析的站点,精确匹配一个泛域名仅包含该站点本身、不包括相关子域名站点。" + "help.wildcard": "提示:对于支持泛解析的站点,精确匹配一个泛域名仅包含该站点本身、不包括相关子域名站点。" }, "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": "这是什么?请参阅 https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/" }, - "k8s_secret_data_key_for_crt": { - "label": "Kubernetes Secret 数据键(用于存放证书的字段)", - "placeholder": "请输入 Kubernetes Secret 中用于存放证书的数据键", - "tooltip": "这是什么?请参阅 https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/" - }, "k8s_secret_data_key_for_key": { "label": "Kubernetes Secret 数据键(用于存放私钥的字段)", "placeholder": "请输入 Kubernetes Secret 中用于存放私钥的数据键", "tooltip": "这是什么?请参阅 https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/" }, + "k8s_secret_data_key_for_crt": { + "label": "Kubernetes Secret 数据键之存放证书的字段", + "placeholder": "请输入 Kubernetes Secret 中用于存放证书的数据键", + "tooltip": "这是什么?请参阅 https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/" + }, + "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 或更高版本。"