kubernetes/kops · error

Forbidden: cannot register node name '%s' with client cert '

Error message

Forbidden: cannot register node name '%s' with client cert '%s'

What it means

handleCreateDiscoveryEndpoint enforces that a supplied metadata.name matches the ClientID extracted from the client's mTLS certificate. If the body sets a name different from the certificate identity, the server refuses the registration with 403. Sending no name (empty) is allowed and gets the cert identity.

Source

Thrown at discovery/pkg/discovery/server.go:162

		}
	}

	s.writeJSON(w, http.StatusOK, resp)
}

func (s *Server) handleCreateDiscoveryEndpoint(w http.ResponseWriter, r *http.Request, userInfo *UserInfo) {
	universeID := r.PathValue("universe")
	ns := r.PathValue("namespace")

	var input api.DiscoveryEndpoint
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		http.Error(w, "Invalid request body", http.StatusBadRequest)
		return
	}

	// Validation: ensure the name matches the clientID from the cert
	if input.ObjectMeta.Name != "" && input.ObjectMeta.Name != userInfo.ClientID {
		http.Error(w, fmt.Sprintf("Forbidden: cannot register node name '%s' with client cert '%s'", input.ObjectMeta.Name, userInfo.ClientID), http.StatusForbidden)
		return
	}

	// Validation: ensure the namespace in body matches the URL
	if input.ObjectMeta.Namespace != ns {
		http.Error(w, "Forbidden: namespace does not match", http.StatusForbidden)
		return
	}

	if err := s.Store.UpsertDiscoveryEndpoint(r.Context(), universeID, &input); err != nil {
		http.Error(w, fmt.Sprintf("Error creating endpoint: %v", err), http.StatusInternalServerError)
		return
	}

	// Return the created object
	s.writeJSON(w, http.StatusCreated, input)
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Omit metadata.name in the POST body and let the server use the cert's ClientID.
  2. Set metadata.name exactly equal to the CN/ClientID of the presented client certificate.
  3. Issue/use a certificate whose CN matches the desired endpoint name.
  4. Check for stale hardcoded names in your manifests/templates.

Example fix

// before
body := []byte(`{"metadata":{"name":"wrong-node"}}`)
// after: name matches cert CN
body := []byte(`{"metadata":{"name":"ip-10-0-0-5"}}`)
Defensive patterns

Strategy: validation

Validate before calling

if body.Name != "" && body.Name != certClientID {
    return fmt.Errorf("body name %q does not match cert ClientID %q", body.Name, certClientID)
}

Prevention

When it happens

Trigger: POST create where body's metadata.name is non-empty and != the cert CN/ClientID, e.g. a node trying to register under another node's name or a copied manifest retaining an old name.

Common situations: Reusing a manifest from another node without clearing metadata.name; renaming nodes while reusing certs; automation that templates the wrong name; attempting to impersonate another endpoint (correctly blocked).

Understand the failure class

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/5fd03b6bc1a2d757. Report an issue: GitHub.