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

  1. Generate an RSA key on the node and encode it as PKCS#1 (RSA PUBLIC KEY)
  2. Use x509.MarshalPKCS1PublicKey with Type "RSA PUBLIC KEY" when PEM-encoding
  3. Align nodeup/client key-generation code with kops-controller's expectation
  4. 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

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


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