forked from rook/rook
Merge pull request #17710 from jhoblitt/object-realm-key-urlsafe
object: generate URL-safe realm access keys
This commit is contained in:
@@ -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{
|
||||
|
||||
Reference in New Issue
Block a user