You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Kubernetes Go-Client审批证书签名请求(CSR)

问题分析与解决方案

核心问题总结

  1. 创建CSR时直接设置Status字段无效:Kubernetes的Status字段由集群控制器维护,客户端创建资源时传入的Status会被API Server忽略,因此CSR始终处于Pending状态。
  2. 审批函数的错误根源:
    • 未使用官方枚举值设置Condition的Status字段,直接用字符串"True"会触发API字段验证错误。
    • 使用创建时的旧CSR对象更新,未获取集群中最新的CSR状态,导致字段缺失。
    • 缺少LastTransitionTime这个必填的Condition字段。

修正后的代码实现

1. 修正CSR构造函数(移除无效的Status字段)

func PopulateCSR(UserName string, csrPemBlock []byte) corev1.CertificateSigningRequest {
    var seconds int32 = 315569260
    // 使用官方KeyUsage枚举值,避免字符串拼写错误
    usages := []corev1.KeyUsage{
        corev1.UsageDigitalSignature,
        corev1.UsageKeyEncipherment,
        corev1.UsageClientAuth,
    }

    csr := corev1.CertificateSigningRequest{
        TypeMeta: v1.TypeMeta{
            Kind:       "CertificateSigningRequest",
            APIVersion: "certificates.k8s.io/v1",
        },
        ObjectMeta: v1.ObjectMeta{
            Name: UserName + "-csr",
        },
        Spec: corev1.CertificateSigningRequestSpec{
            Request:           csrPemBlock,
            SignerName:        "kubernetes.io/kube-apiserver-client",
            ExpirationSeconds: &seconds,
            Usages:            usages,
        },
        // 移除Status字段,创建时集群会忽略该字段
    }
    return csr
}

2. 修正CSR审批函数(获取最新对象+规范设置Condition)

func approveCSR(csrName string, clientSet *kubernetes.Clientset) {
    // 先获取集群中最新的CSR对象,避免使用旧对象导致字段缺失
    csr, err := clientSet.CertificatesV1().CertificateSigningRequests().Get(context.Background(), csrName, v1.GetOptions{})
    if err != nil {
        fmt.Printf("failed to fetch CSR: %v\n", err)
        os.Exit(1)
    }

    // 检查是否已存在审批条件,避免重复添加
    hasApproved := false
    for _, cond := range csr.Status.Conditions {
        if cond.Type == corev1.CertificateApproved {
            hasApproved = true
            break
        }
    }
    if hasApproved {
        fmt.Println("CSR is already approved")
        return
    }

    // 使用官方枚举值构建审批条件,确保所有必填字段齐全
    approvalCondition := corev1.CertificateSigningRequestCondition{
        Type:               corev1.CertificateApproved,
        Status:             corev1.ConditionTrue, // 必须用官方枚举,不能直接用字符串"True"
        Reason:             "UserActivation",
        Message:            "CSR approved for client authentication",
        LastUpdateTime:     v1.Now(),
        LastTransitionTime: v1.Now(), // 该字段为必填项,之前缺失会触发验证错误
    }

    csr.Status.Conditions = append(csr.Status.Conditions, approvalCondition)

    // 调用UpdateApproval API更新审批状态
    _, err = clientSet.CertificatesV1().CertificateSigningRequests().UpdateApproval(context.Background(), csrName, csr, v1.UpdateOptions{})
    if err != nil {
        fmt.Printf("failed to approve CSR: %v\n", err)
        os.Exit(1)
    }
    fmt.Println("CSR approved successfully")
}

关键说明

  • Status字段的只读特性:Kubernetes资源的Status字段仅由集群内部控制器更新,客户端创建/更新资源时传入的Status会被直接忽略,因此创建CSR时无需设置该字段。
  • 枚举值的必要性:corev1.ConditionStatus是强类型枚举,直接使用字符串可能触发API的字段验证逻辑,导致status.conditions[0].status: Required value错误。
  • 获取最新对象:使用创建时的旧CSR对象更新审批,会丢失集群中已生成的状态元数据,必须先通过Get接口获取最新的CSR对象再进行修改。
  • 证书签署延迟:审批完成后,需要等待kube-controller-manager中的CSR签署控制器完成证书生成,此时CSR的Status.Certificate字段才会被填充,可通过轮询该字段获取最终证书。

内容的提问来源于stack exchange,提问作者Maximilian Koch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 15:30:03