kubernetes/kops · error

decoding pem public key

Error message

decoding pem public key

What it means

issueCert receives a PEM-encoded public key from the bootstrap request. This error is thrown when pem.Decode cannot parse any PEM block from the submitted key material, i.e. the payload is not valid PEM.

Source

Thrown at cmd/kops-controller/pkg/server/server.go:293

		cert, err := s.issueCert(ctx, name, pubKey, id, validHours, req.KeypairIDs)
		if err != nil {
			klog.Infof("bootstrap %s cert %q issue err: %v", r.RemoteAddr, name, err)
			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")

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Log the offending request source and regenerate the key on the node
  2. Confirm nodeup and kops-controller versions match
  3. Ensure the client sends the PEM text (with BEGIN/END headers) not raw DER
  4. Check any proxies/mutating layers for truncation

Example fix

// before
payload["publicKey"] = string(derBytes)
// after
payload["publicKey"] = string(pem.EncodeToMemory(&pem.Block{Type: "RSA PUBLIC KEY", Bytes: derBytes}))
Defensive patterns

Strategy: validation

Validate before calling

if !strings.HasPrefix(pubKey, "-----BEGIN ") {
    return fmt.Errorf("public key is not PEM-encoded")
}

Type guard

func isPEMBlock(s string) bool {
    b, _ := pem.Decode([]byte(s))
    return b != nil
}

Try / catch

block, _ := pem.Decode([]byte(pubKey))
if block == nil {
    return "", fmt.Errorf("decoding pem public key")
}

Prevention

When it happens

Trigger: A bootstrap client posts a cert request whose pubKey field is empty, base64-corrupted, or otherwise not PEM-encoded, so pem.Decode returns block == nil.

Common situations: Node-side nodeup version mismatch producing non-PEM key format; key truncated or double-encoded in transit; malicious/garbage requests against the bootstrap endpoint.

Related errors


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