{"record":{"id":"d4bf9cc68ace9433","repo":"kubernetes/kops","slug":"method-deletesshcredential-not-supported-in-server","errorCode":null,"errorMessage":"method DeleteSSHCredential not supported in server-side client","messagePattern":"method DeleteSSHCredential not supported in server-side client","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/kops-controller/pkg/controllerclientset/sshcredentialstore.go","lineNumber":52,"sourceCode":"\nvar _ fi.SSHCredentialStore = &sshCredentialStore{}\n\nfunc newSSHCredentialStore(clusterBasePath vfs.Path, cluster *kops.Cluster) *sshCredentialStore {\n\tif cluster == nil || cluster.Name == \"\" {\n\t\tklog.Fatalf(\"cluster / cluster.Name is required\")\n\t}\n\n\ts := &sshCredentialStore{\n\t\tclusterBasePath: clusterBasePath,\n\t\tcluster:         cluster,\n\t}\n\n\treturn s\n}\n\n// DeleteSSHCredential deletes the specified SSH credential.\nfunc (s *sshCredentialStore) DeleteSSHCredential() error {\n\treturn fmt.Errorf(\"method DeleteSSHCredential not supported in server-side client\")\n}\n\n// AddSSHPublicKey adds an SSH public key.\nfunc (s *sshCredentialStore) AddSSHPublicKey(ctx context.Context, data []byte) error {\n\treturn fmt.Errorf(\"method AddSSHPublicKey not supported in server-side client\")\n}\n\n// FindSSHPublicKeys retrieves the SSH public keys.\nfunc (s *sshCredentialStore) FindSSHPublicKeys() ([]*kops.SSHCredential, error) {\n\tklog.Warningf(\"method FindSSHPublicKeys is stub-implemented supported in server-side client\")\n\treturn nil, nil\n}\n","sourceCodeStart":34,"sourceCodeEnd":65,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/cmd/kops-controller/pkg/controllerclientset/sshcredentialstore.go#L34-L65","documentation":"The server-side sshCredentialStore does not support deleting SSH credentials; DeleteSSHCredential unconditionally returns this sentinel error. The kops-controller clientset implements only read-oriented credential operations, so any deletion attempt fails immediately without contacting the API server. Callers such as the `kops delete sshpublickey` command path (RunDeleteSSHPublicKey) will surface this error to the user.","triggerScenarios":"Running `kops delete sshpublickey` (or programmatic calls to DeleteSSHCredential) against a cluster whose registry is backed by the server-side controller clientset, e.g. when the kops binary is configured to talk to the kops-controller-managed API surface.","commonSituations":"Operators rotating or revoking SSH access by deleting the sshpublickey secret through the kops CLI while using a server-side registry configuration; automation scripts that clean up old SSH keys; environments migrated from the legacy (S3/state-store) registry to server-side mode.","solutions":["Delete the SSH credential secret directly with kubectl (the sshpublickeys.kops.k8s.io secret in the cluster), e.g. `kubectl -n kube-system delete secret sshpublickey.<name>`","Use the standard kops registry (state store) client for credential deletion, which implements DeleteSSHCredential","Rotate keys by adding a new key with the desired name rather than deleting via this client","Contribute a DeleteSSHCredential implementation backed by the Kubernetes secret API in cmd/kops-controller/pkg/controllerclientset/sshcredentialstore.go"],"exampleFix":"// before\nstore, err := serverSideRegistry.SSHCredentialStore(clusterName)\nif err != nil { return err }\nif err := store.DeleteSSHCredential(); err != nil { return err } // always fails\n// after\nerr = kubectlDelete(ctx, \"-n\", \"kube-system\", \"secret\", \"sshpublickey.admin\")","handlingStrategy":"try-catch","validationCode":"// Detect server-side registry before attempting deletion:\nif registry, ok := reg.(*controllerclientset.Registry); ok {\n\treturn fmt.Errorf(\"SSH credential deletion must go through kubectl or the state-store registry\")\n}\n","typeGuard":"func isServerSideStore(v interface{}) bool {\n\t_, ok := v.(*controllerclientset.SSHCredentialStoreProxy)\n\treturn ok\n}","tryCatchPattern":"if err := store.DeleteSSHCredential(); err != nil {\n\tif strings.Contains(err.Error(), \"not supported in server-side client\") {\n\t\treturn kubectl.Delete(ctx, \"kube-system\", \"secret\", sshCredentialSecretName)\n\t}\n\treturn err\n}","preventionTips":["Delete SSH credential secrets via kubectl directly when operating in server-side mode","Gate SSH key management code on the registry mode (state store vs server-side)","Document that server-side mode supports read-only SSH credential operations","Test key-rotation runbooks against a server-side-mode cluster"],"tags":["kubernetes","kops-controller","ssh","credentials","unsupported-method"],"backgroundTag":"unsupported-clientset-method","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}