kubernetes/kops · error
unexpected key type %q
Error message
unexpected key type %q
What it means
issueCert only accepts PEM blocks of type "RSA PUBLIC KEY". This error is thrown when the decoded block has a different type (e.g. PUBLIC KEY, EC PUBLIC KEY), meaning the client submitted a key type this endpoint does not accept.
Source
Thrown at cmd/kops-controller/pkg/server/server.go:296
w.WriteHeader(http.StatusBadRequest)
_, _ = fmt.Fprintf(w, "failed to issue %q: %v", name, err)
return
}
resp.Certs[name] = cert
}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(resp)
klog.Infof("bootstrap %s (req.includeNodeConfig: %t, req.certs.#: %d, req.keypairs.#: %d) success", r.RemoteAddr, req.IncludeNodeConfig, len(req.Certs), len(req.KeypairIDs))
}
func (s *Server) issueCert(ctx context.Context, name string, pubKey string, id *bootstrap.VerifyResult, validHours uint32, keypairIDs map[string]string) (string, error) {
block, _ := pem.Decode([]byte(pubKey))
if block == nil {
return "", fmt.Errorf("decoding pem public key")
}
if block.Type != "RSA PUBLIC KEY" {
return "", fmt.Errorf("unexpected key type %q", block.Type)
}
key, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return "", fmt.Errorf("parsing key: %v", err)
}
issueReq := &pki.IssueCertRequest{
Signer: fi.CertificateIDCA,
Type: "client",
PublicKey: key,
Validity: time.Hour * time.Duration(validHours),
}
if !s.certNames.Has(name) {
return "", fmt.Errorf("key name not enabled")
}
switch name {
case "etcd-client-cilium":View on GitHub (pinned to 4c8573c808)
Solutions
- Generate an RSA key on the node and encode it as PKCS#1 (RSA PUBLIC KEY)
- Use x509.MarshalPKCS1PublicKey with Type "RSA PUBLIC KEY" when PEM-encoding
- Align nodeup/client key-generation code with kops-controller's expectation
- Verify no custom patches switched the key algorithm
Example fix
// before
block := &pem.Block{Type: "PUBLIC KEY", Bytes: derBytes}
// after
block := &pem.Block{Type: "RSA PUBLIC KEY", Bytes: x509.MarshalPKCS1PublicKey(rsaKey)} Defensive patterns
Strategy: type-guard
Validate before calling
if block.Type != "RSA PUBLIC KEY" {
return fmt.Errorf("expected RSA PUBLIC KEY, got %q", block.Type)
} Type guard
func isRSAPublicKeyPEM(pub string) bool {
b, _ := pem.Decode([]byte(pub))
return b != nil && b.Type == "RSA PUBLIC KEY"
} Try / catch
if block.Type != "RSA PUBLIC KEY" {
return "", fmt.Errorf("unexpected key type %q", block.Type)
} Prevention
- Generate RSA keys on nodes; do not switch to ECDSA/Ed25519
- Encode with x509.MarshalPKCS1PublicKey under Type "RSA PUBLIC KEY"
- Document the accepted key format for custom bootstrap clients
When it happens
Trigger: Bootstrap request pubKey decodes to a PEM block whose Type is not exactly "RSA PUBLIC KEY" — e.g. a PKIX "PUBLIC KEY" block, an EC/Ed25519 key, or a private key.
Common situations: Node generating an ECDSA or ED25519 key instead of RSA; sending a public key in SPKI ("PUBLIC KEY") format rather than PKCS#1; template or nodeup script customized to use different key algorithms.
Related errors
- decoding pem public key
- building nodeConfig for instanceGroup: %w
- error loading secret %q: %w
- CAPI Machine is missing cluster.x-k8s.io/deployment-name lab
- CAPI Machine is missing spec.failureDomain
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/14aea26cd44e01df.
Report an issue: GitHub.