From 245c45d536adf6a9febccc3137c80d22f72ad056 Mon Sep 17 00:00:00 2001 From: Anas Khan <83116240+anxkhn@users.noreply.github.com> Date: Mon, 6 Jul 2026 16:50:56 +0530 Subject: [PATCH] csi: do not log peer bootstrap token secret decodePeerToken logged the whole decoded PeerToken with "%+v" at debug level. PeerToken embeds Key, the peer cluster's cephx auth secret, so running the operator with ROOK_LOG_LEVEL=DEBUG wrote that credential to the operator logs in plaintext (CWE-532). Log only the non-sensitive fields (fsid, client id, mon host, namespace), which keep the message useful for diagnostics, and drop Key. Add a regression test that captures the debug output and asserts the key is never present. Signed-off-by: Anas Khan <83116240+anxkhn@users.noreply.github.com> (cherry picked from commit 1013a8effc1cbbc564ccc61bfcbe9596c0bc03f4) --- pkg/operator/ceph/csi/peermap/config.go | 5 ++++- pkg/operator/ceph/csi/peermap/config_test.go | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/pkg/operator/ceph/csi/peermap/config.go b/pkg/operator/ceph/csi/peermap/config.go index cf9b17f82..610fdee15 100644 --- a/pkg/operator/ceph/csi/peermap/config.go +++ b/pkg/operator/ceph/csi/peermap/config.go @@ -348,7 +348,10 @@ func decodePeerToken(token string) (*cephclient.PeerToken, error) { return nil, errors.Wrap(err, "failed to unmarshal decoded token") } - logger.Debugf("peer cluster info %+v", decodedTokenToGo) + // Log only the non-sensitive fields; the token embeds the peer cluster's + // cephx auth key (decodedTokenToGo.Key), which must never be logged. + logger.Debugf("decoded peer cluster info fsid=%q clientID=%q monHost=%q namespace=%q", + decodedTokenToGo.ClusterFSID, decodedTokenToGo.ClientID, decodedTokenToGo.MonHost, decodedTokenToGo.Namespace) return &decodedTokenToGo, nil } diff --git a/pkg/operator/ceph/csi/peermap/config_test.go b/pkg/operator/ceph/csi/peermap/config_test.go index 2b9c9bdf0..63d7ff687 100644 --- a/pkg/operator/ceph/csi/peermap/config_test.go +++ b/pkg/operator/ceph/csi/peermap/config_test.go @@ -17,6 +17,7 @@ limitations under the License. package peermap import ( + "bytes" "context" "fmt" "os" @@ -26,6 +27,7 @@ import ( "testing" "time" + "github.com/coreos/pkg/capnslog" cephv1 "github.com/rook/rook/pkg/apis/ceph.rook.io/v1" "github.com/rook/rook/pkg/client/clientset/versioned/scheme" "github.com/rook/rook/pkg/clusterd" @@ -406,6 +408,23 @@ func TestDecodePeerToken(t *testing.T) { assert.Error(t, err) } +func TestDecodePeerTokenDoesNotLogSecret(t *testing.T) { + // The peer token embeds the peer cluster's cephx auth key, which must never + // be written to the operator logs, even at debug level. + logBuf := bytes.NewBuffer([]byte{}) + capnslog.SetFormatter(capnslog.NewLogFormatter(logBuf, "", 0)) + capnslog.SetGlobalLogLevel(capnslog.DEBUG) + + decodedToken, err := decodePeerToken(fakeTokenPeer1) + assert.NoError(t, err) + + logOutput := logBuf.String() + assert.NotEmpty(t, decodedToken.Key) + assert.NotContains(t, logOutput, decodedToken.Key) + // The non-sensitive fields are still useful for diagnostics. + assert.Contains(t, logOutput, decodedToken.Namespace) +} + func TestCreateOrUpdateConfig(t *testing.T) { t.Setenv("POD_NAME", "rook-ceph-operator") t.Setenv("POD_NAMESPACE", ns)