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
- Omit metadata.name in the POST body and let the server use the cert's ClientID.
- Set metadata.name exactly equal to the CN/ClientID of the presented client certificate.
- Issue/use a certificate whose CN matches the desired endpoint name.
- 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
- Omit metadata.name on create and let the server derive it from the cert
- Extract the cert CN at bootstrap and template manifests from it
- Never copy manifests between nodes without clearing metadata.name
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
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- no TLS connection
- Unauthorized
- Forbidden: namespace does not match
- Forbidden: name does not match
- ErrAlreadyExists
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/5fd03b6bc1a2d757.
Report an issue: GitHub.