kubernetes/kops · error
error parsing SSH public key: %v
Error message
error parsing SSH public key: %v
What it means
AddSSHPublicKey validates the supplied key with golang.org/x/crypto/ssh.ParseAuthorizedKey before storing it. If the bytes are not a valid OpenSSH authorized_keys entry, it returns 'error parsing SSH public key: %v'. kOps never persists unparseable keys.
Source
Thrown at upup/pkg/fi/clientset_castore.go:301
}
return nil
}
// deleteSSHCredential deletes the SSHCredential from the registry.
func (c *ClientsetCAStore) deleteSSHCredential(ctx context.Context) error {
client := c.clientset.SSHCredentials(c.namespace)
err := client.Delete(ctx, "admin", metav1.DeleteOptions{})
if err != nil {
return fmt.Errorf("error deleting SSHCredential: %v", err)
}
return nil
}
// AddSSHPublicKey implements CAStore::AddSSHPublicKey
func (c *ClientsetCAStore) AddSSHPublicKey(ctx context.Context, pubkey []byte) error {
_, _, _, _, err := ssh.ParseAuthorizedKey(pubkey)
if err != nil {
return fmt.Errorf("error parsing SSH public key: %v", err)
}
return c.addSSHCredential(ctx, strings.TrimSpace(string(pubkey)))
}
// FindSSHPublicKeys implements CAStore::FindSSHPublicKeys
func (c *ClientsetCAStore) FindSSHPublicKeys() ([]*kops.SSHCredential, error) {
ctx := context.TODO()
o, err := c.clientset.SSHCredentials(c.namespace).Get(ctx, "admin", metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
return nil, nil
}
return nil, fmt.Errorf("error reading SSHCredential: %v", err)
}
o.Spec.PublicKey = strings.TrimSpace(o.Spec.PublicKey)
View on GitHub (pinned to 4c8573c808)
Solutions
- Pass the contents of the .pub file (e.g. ~/.ssh/id_rsa.pub), never the private key
- Validate locally: `ssh-keygen -l -f mykey.pub` must succeed
- Ensure the file has no CRLF line endings and is a single authorized_keys line
- Regenerate the key with `ssh-keygen -t ed25519` if the format is non-standard
Example fix
// before
pub, _ := os.ReadFile("~/.ssh/id_rsa") // private key — parse fails
store.AddSSHPublicKey(ctx, pub)
// after
pub, _ := os.ReadFile("~/.ssh/id_rsa.pub")
if _, _, _, _, err := ssh.ParseAuthorizedKey(pub); err != nil {
return fmt.Errorf("invalid public key: %w", err)
}
store.AddSSHPublicKey(ctx, pub) Defensive patterns
Strategy: validation
Validate before calling
func validPublicKey(pub []byte) error {
if len(pub) == 0 { return errors.New("empty key") }
if _, _, _, _, err := ssh.ParseAuthorizedKey(pub); err != nil { return err }
return nil
}
// call before AddSSHPublicKey
if err := validPublicKey(pub); err != nil { return err } Type guard
func isParsedAuthorizedKey(b []byte) bool {
_, _, _, _, err := ssh.ParseAuthorizedKey(b)
return err == nil
} Try / catch
if err := store.AddSSHPublicKey(ctx, pub); err != nil {
if strings.Contains(err.Error(), "error parsing SSH public key") {
return fmt.Errorf("not an authorized_keys-format public key: %w", err)
}
return err
} Prevention
- Always pass the .pub file contents, never the private key
- Validate with `ssh-keygen -l -f key.pub` before uploading
- Convert non-OpenSSH formats (PuTTY PPK) to OpenSSH first
- Strip CRLF and keep the key on a single line
When it happens
Trigger: Passing a private key file, a certificate, an empty/truncated buffer, or text with a broken base64 field to AddSSHPublicKey; also caused by reading the wrong file (e.g. id_rsa instead of id_rsa.pub) or Windows line endings/CRLF in the key file.
Common situations: `kops create sshpublickey` pointed at a private key instead of the .pub file; copy-pasted key losing characters; key generated by a tool producing non-standard formats (e.g. PuTTY PPK not exported to OpenSSH).
Related errors
- error computing key fingerprint for SSH key: %v
- spec.PublicKey is required
- error adding SSH public key: %v
- host is required
- hostname was empty
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/9494c35dd904a9b6.
Report an issue: GitHub.