kubernetes/kubernetes · error

subject organization is not system:nodes

Error message

subject organization is not system:nodes

What it means

Returned by ValidateKubeletServingCSR / ValidateKubeletClientCSR when the CSR's Subject.Organization is not exactly the single-element slice ["system:nodes"]. Kubelet-serving and kubelet-client CSRs are strictly scoped to the system:nodes group; any other (or missing) organization is rejected.

Source

Thrown at pkg/apis/certificates/helpers.go:44

	"k8s.io/apimachinery/pkg/util/sets"
)

// ParseCSR extracts the CSR from the bytes and decodes it.
func ParseCSR(pemBytes []byte) (*x509.CertificateRequest, error) {
	block, _ := pem.Decode(pemBytes)
	if block == nil || block.Type != "CERTIFICATE REQUEST" {
		return nil, errors.New("PEM block type must be CERTIFICATE REQUEST")
	}
	csr, err := x509.ParseCertificateRequest(block.Bytes)
	if err != nil {
		return nil, err
	}
	return csr, nil
}

var (
	organizationNotSystemNodesErr = fmt.Errorf("subject organization is not system:nodes")
	commonNameNotSystemNode       = fmt.Errorf("subject common name does not begin with system:node:")
	dnsOrIPSANRequiredErr         = fmt.Errorf("DNS or IP subjectAltName is required")
	dnsSANNotAllowedErr           = fmt.Errorf("DNS subjectAltNames are not allowed")
	emailSANNotAllowedErr         = fmt.Errorf("Email subjectAltNames are not allowed")
	ipSANNotAllowedErr            = fmt.Errorf("IP subjectAltNames are not allowed")
	uriSANNotAllowedErr           = fmt.Errorf("URI subjectAltNames are not allowed")
)

var (
	kubeletServingRequiredUsages = sets.NewString(
		string(UsageDigitalSignature),
		string(UsageKeyEncipherment),
		string(UsageServerAuth),
	)
	kubeletServingRequiredUsagesNoRSA = sets.NewString(
		string(UsageDigitalSignature),
		string(UsageServerAuth),
	)

View on GitHub (pinned to b882c60b40)

Solutions

  1. Set the CSR Subject.Organization to exactly []string{"system:nodes"}.
  2. Verify the kubelet's --bootstrap-kubeconfig and node registration config produce the correct Subject.
  3. Regenerate the CSR after fixing the Subject.

Example fix

// before
template := x509.CertificateRequest{
    Subject: pkix.Name{CommonName: "system:node:node1", Organization: []string{"kube-system"}},
}
// after
template := x509.CertificateRequest{
    Subject: pkix.Name{CommonName: "system:node:node1", Organization: []string{"system:nodes"}},
}
Defensive patterns

Strategy: validation

Validate before calling

func hasSystemNodesOrg(req *x509.CertificateRequest) bool {
    return reflect.DeepEqual(req.Subject.Organization, []string{"system:nodes"})
}

Type guard

func isKubeletCSRSubject(req *x509.CertificateRequest) bool {
    return reflect.DeepEqual(req.Subject.Organization, []string{"system:nodes"}) &&
        strings.HasPrefix(req.Subject.CommonName, "system:node:")
}

Try / catch

if err := certificates.ValidateKubeletServingCSR(csr, usages); err != nil {
    if errors.Is(err, certificates.ErrOrgNotSystemNodes) { /* fix Subject */ }
    return err
}

Prevention

When it happens

Trigger: Calling certificates.ValidateKubeletServingCSR or ValidateKubeletClientCSR with an x509.CertificateRequest whose Subject.Organization differs from ["system:nodes"] (empty, multi-element, or a different value).

Common situations: A kubelet bootstrapping with a wrong/missing org in its CSR config; a custom CSR generator that sets O to the node's cloud group; TLS bootstrap misconfiguration in kubelet flags.

Related errors


AI-assisted analysis of kubernetes/kubernetes@b882c60b40 (2026-08-07). Data as JSON: /api/errors/c2a9d95305f60a31. Report an issue: GitHub.