Repository: rook/rook (2025-08-18T10:02:45Z)

Issue:
Possible CSI priorKeyCount status calculation issue
<!-- **Are you in the right place?**
1. For issues or feature requests, please create an issue in this repository.
2. For general technical and non-technical questions, we are happy to help you on our [Rook.io Slack](https://slack.rook.io/).
3. Did you already search the existing open issues for anything similar? -->

**Is this a bug report or feature request?**
* Bug Report

**Deviation from expected behavior:**

Upon first CephCluster install, I see this tatus for CSI CephX keys:

```
    Csi:
      Key Ceph Version:  20.3.0-2332
      Key Generation:    1
      Prior Key Count:   1
```

These are the keys that are present in the fresh deploy:

```
bash-5.1$ ceph auth ls | grep csi
client.csi-cephfs-node.1
client.csi-cephfs-provisioner.1
client.csi-rbd-node.1
client.csi-rbd-provisioner.1
```

**Expected behavior:**

In this case, there are zero (0) "prior" keys. Only the single active key. I think this is probably a simple off-by-one issue with a calculation somewhere.

**How to reproduce it (minimal and precise):**
<!-- Please let us know any circumstances for reproduction of your bug. -->

**File(s) to submit**:

* Cluster CR (custom resource), typically called `cluster.yaml`, if necessary

**Logs to submit**:

* Operator's logs, if necessary
* Crashing pod(s) logs, if necessary

  To get logs, use `kubectl -n <namespace> logs <pod name>`
  When pasting logs, always surround them with backticks or use the `insert code` button from the Github UI.
  Read [GitHub documentation if you need help](https://help.github.com/en/articles/creating-and-highlighting-code-blocks).

**Cluster Status to submit**:

* Output of kubectl commands, if necessary

  To get the health of the cluster, use `kubectl rook-ceph health`
  To get the status of the cluster, use `kubectl rook-ceph ceph status`
  For more details, see the [Rook kubectl Plugin](https://rook.io/docs/rook/latest-release/Troubleshooting/kubectl-plugin)

**Environment**:
* OS (e.g. from /etc/os-release):
* Kernel (e.g. `uname -a`):
* Cloud provider or hardware configuration:
* Rook version (use `rook version` inside of a Rook Pod):
* Storage backend version (e.g. for ceph do `ceph -v`):
* Kubernetes version (use `kubectl version`):
* Kubernetes cluster type (e.g. Tectonic, GKE, OpenShift):
* Storage backend status (e.g. for Ceph use `ceph health` in the [Rook Ceph toolbox](https://rook.io/docs/rook/latest-release/Troubleshooting/ceph-toolbox/#interactive-toolbox)):



Discussion:
@parth-gr would you have any spare time to look at this before v1.18 release?
/assign
Thanks for taking this issue! Let us know if you have any questions!



Patch:
diff --git a/pkg/operator/ceph/csi/secrets.go b/pkg/operator/ceph/csi/secrets.go
index 6bec80fc1b7c..ed9f0de95549 100644
--- a/pkg/operator/ceph/csi/secrets.go
+++ b/pkg/operator/ceph/csi/secrets.go
@@ -120,6 +120,9 @@ func createCSIKeyring(
 	allKeyWithBaseName = deduplicate(allKeyWithBaseName)
 
 	currentKeyCount := len(allKeyWithBaseName) - len(keysDeleted)
+	if currentKeyCount <= 0 {
+		logger.Warningf("currentKeyCount is %d is less than or equal to 0; this could be due to an error in key generation", currentKeyCount)
+	}
 
 	return latestClientId, key, currentKeyCount, shouldRotate, nil
 }
@@ -312,7 +315,7 @@ func updateCephStatusWithCephxStatus(context *clusterd.Context, clusterInfo *cli
 			return errors.Wrapf(err, "failed to retrieve cephCluster %q to update CSICephxStatus", namespacedName.Namespace)
 		}
 		cephCluster.Status.Cephx.CSI.CephxStatus = cephxStatus
-		cephCluster.Status.Cephx.CSI.PriorKeyCount = uint8(currentKeyCount) //nolint:gosec // disable G115
+		cephCluster.Status.Cephx.CSI.PriorKeyCount = uint8(getPriorKeyCount(currentKeyCount)) //nolint:gosec // disable G115
 
 		if err := reporting.UpdateStatus(context.Client, cephCluster); err != nil {
 			return errors.Wrapf(err, "failed to update cephCluster %q to update csi cephx status to %q in namespace %q", namespacedName.Name, cephxStatus, namespacedName.Namespace)
@@ -327,6 +330,10 @@ func updateCephStatusWithCephxStatus(context *clusterd.Context, clusterInfo *cli
 	return nil
 }
 
+func getPriorKeyCount(currentKeyCount int) int {
+	return max(0, currentKeyCount-1)
+}
+
 // getCsiKeyRotationInfo runs the `ceph auth ls` command to fetch all the keys and filter out the keys with same base name. Example
 // for base name `client.csi-rbd-node`.
 // From the list of key name return from `getMatchingClient` we'll read the suffix index eg; for key `client.csi-rbd-node.3` we'll take `3` and compare with


Test patch:
diff --git a/pkg/operator/ceph/csi/secrets_test.go b/pkg/operator/ceph/csi/secrets_test.go
index d2893bd22dff..ebfe71910de8 100644
--- a/pkg/operator/ceph/csi/secrets_test.go
+++ b/pkg/operator/ceph/csi/secrets_test.go
@@ -522,3 +522,22 @@ func TestParseCsiClient(t *testing.T) {
 		})
 	}
 }
+
+func TestGetPriorKeyCount(t *testing.T) {
+	tests := []struct {
+		name     string
+		keyCount int
+		want     int
+	}{
+		{"keyGen 0", 0, 0},
+		{"keyGen 1", 1, 0},
+		{"keyGen 2", 2, 1},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got := getPriorKeyCount(tt.keyCount)
+			assert.Equal(t, tt.want, got)
+		})
+	}
+}