kubernetes/kops · error

error reading SSH public key: %v

Error message

error reading SSH public key: %v

What it means

SSHKey.Normalize runs before apply to compute the AWS key fingerprint from the user-supplied public key when KeyFingerprint isn't set. If reading the PublicKey resource fails, it errors with "error reading SSH public key". This happens on the client side, before any AWS call.

Source

Thrown at upup/pkg/fi/cloudup/awstasks/sshkey.go:123

	}
	actual.Lifecycle = e.Lifecycle
	if actual.Shared {
		// Don't report tag changes on shared keys
		actual.Tags = e.Tags
	}

	e.ID = actual.ID
	if e.IsExistingKey() && *e.Name != "" {
		e.KeyFingerprint = actual.KeyFingerprint
	}
	return actual, nil
}

func (e *SSHKey) Normalize(c *fi.CloudupContext) error {
	if e.KeyFingerprint == nil && e.PublicKey != nil {
		publicKey, err := fi.ResourceAsString(e.PublicKey)
		if err != nil {
			return fmt.Errorf("error reading SSH public key: %v", err)
		}

		keyFingerprint, err := pki.ComputeAWSKeyFingerprint(publicKey)
		if err != nil {
			return fmt.Errorf("error computing key fingerprint for SSH key: %v", err)
		}
		klog.V(2).Infof("Computed SSH key fingerprint as %q", keyFingerprint)
		e.KeyFingerprint = &keyFingerprint
	}

	return nil
}

func (e *SSHKey) Run(c *fi.CloudupContext) error {
	return fi.CloudupDefaultDeltaRunMethod(e, c)
}

func (s *SSHKey) CheckChanges(a, e, changes *SSHKey) error {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check the wrapped error: fix the file path or permissions it reports.
  2. Pass an existing file: kops create cluster --ssh-public-key ~/.ssh/id_rsa.pub.
  3. Verify the file is a readable OpenSSH public key.
  4. Ensure spec files reference absolute or workspace-relative correct paths.

Example fix

// before
kops create cluster --ssh-public-key=./keys/missing.pub
// after
kops create cluster --ssh-public-key=$HOME/.ssh/id_rsa.pub
Defensive patterns

Strategy: validation

Validate before calling

func validatePubKey(path string) error {
    fi, err := os.Stat(path)
    if err != nil { return fmt.Errorf("public key not readable: %w", err) }
    if fi.IsDir() { return fmt.Errorf("%s is a directory", path) }
    data, err := os.ReadFile(path)
    if err != nil { return err }
    if !bytes.HasPrefix(data, []byte("ssh-")) && !bytes.HasPrefix(data, []byte("ecdsa-")) {
        return fmt.Errorf("%s does not look like an OpenSSH public key", path)
    }
    return nil
}

Prevention

When it happens

Trigger: fi.ResourceAsString(e.PublicKey) fails: the --ssh-public-key path doesn't exist, isn't readable, or a resource holder was populated with nil/unresolvable data.

Common situations: kops create cluster --ssh-public-key pointing at a missing file; wrong relative path after changing working directory; permission denied on the key file; editing specs by hand with a placeholder path.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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