Merge pull request #17710 from jhoblitt/object-realm-key-urlsafe

object: generate URL-safe realm access keys
This commit is contained in:
Travis Nielsen
2026-06-16 15:16:22 -06:00
committed by GitHub
2 changed files with 33 additions and 3 deletions
+7 -3
View File
@@ -291,18 +291,22 @@ func (r *ReconcileObjectRealm) createRealmKeys(realm *cephv1.CephObjectRealm) (r
return reconcile.Result{}, nil
}
// the realm's secret key and access key are randomly generated and then encoded to base64
// The realm's secret key and access key are randomly generated and then encoded to base64.
// The encoded values are used verbatim as the S3 keys of the realm's system user, so the
// encoding alphabet must be URL-safe: an access key containing '/' breaks AWS SigV4
// credential scope parsing ("<access-key>/<date>/<region>/...") and makes
// "radosgw-admin realm pull" against this realm fail with "(22) Invalid argument".
accessKey, err := mgr.GeneratePassword(accessKeyLength, mgr.AccessKey)
if err != nil {
return reconcile.Result{}, errors.Wrapf(err, "access key failed to generate")
}
accessKey = base64.StdEncoding.EncodeToString([]byte(accessKey))
accessKey = base64.RawURLEncoding.EncodeToString([]byte(accessKey))
secretKey, err := mgr.GeneratePassword(secretKeyLength, mgr.DefaultKey)
if err != nil {
return reconcile.Result{}, errors.Wrapf(err, "failed to generate secret key")
}
secretKey = base64.StdEncoding.EncodeToString([]byte(secretKey))
secretKey = base64.RawURLEncoding.EncodeToString([]byte(secretKey))
log.NamedDebug(nsName, logger, "creating secrets for new realm %q", realm.Name)
@@ -19,6 +19,7 @@ package realm
import (
"context"
"regexp"
"testing"
"time"
@@ -30,6 +31,7 @@ import (
"github.com/rook/rook/pkg/operator/test"
exectest "github.com/rook/rook/pkg/util/exec/test"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
@@ -304,6 +306,30 @@ func TestReconcileObjectRealm_createRealmKeys(t *testing.T) {
}
})
t.Run("generated keys are URL-safe", func(t *testing.T) {
// the access key is embedded in the '/'-delimited SigV4 credential scope, so a '/'
// anywhere in it makes "radosgw-admin realm pull" fail with "(22) Invalid argument"
urlSafe := regexp.MustCompile(`^[A-Za-z0-9_-]+$`)
for i := 0; i < 100; i++ {
r := ReconcileObjectRealm{
context: &clusterd.Context{
Clientset: k8sfake.NewClientset(),
},
scheme: scheme,
recorder: events.NewFakeRecorder(50),
}
res, err := r.createRealmKeys(realm)
require.NoError(t, err)
assert.True(t, res.IsZero())
secret, err := r.context.Clientset.CoreV1().Secrets(ns).Get(ctx, realmName+"-keys", metav1.GetOptions{})
require.NoError(t, err)
assert.Regexp(t, urlSafe, string(secret.Data["access-key"]))
assert.Regexp(t, urlSafe, string(secret.Data["secret-key"]))
}
})
t.Run("should fail if the secret doesn't have the necessary keys", func(t *testing.T) {
secret := &v1.Secret{
TypeMeta: metav1.TypeMeta{