From c81aa7f8566bee247f9de11b0ae22adb6c5f82f1 Mon Sep 17 00:00:00 2001 From: Liang Zheng Date: Sun, 19 Feb 2023 21:07:12 +0800 Subject: [PATCH] object: update os user caps Removing user caps will be skipped as the UserCaps is empty, which will cause updating user caps to not take effect. Signed-off-by: Liang Zheng --- pkg/operator/ceph/object/user/controller.go | 21 ++++++++++++++++--- .../ceph/object/user/controller_test.go | 14 ++++++++++++- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/pkg/operator/ceph/object/user/controller.go b/pkg/operator/ceph/object/user/controller.go index 44b314057..352162f4c 100644 --- a/pkg/operator/ceph/object/user/controller.go +++ b/pkg/operator/ceph/object/user/controller.go @@ -296,6 +296,8 @@ func (r *ReconcileObjectStoreUser) createOrUpdateCephUser(u *cephv1.CephObjectSt } // Update max bucket if necessary + logger.Tracef("user capabilities(id: %s, caps: %#v, user caps: %s, op mask: %s)", + user.ID, user.Caps, user.UserCaps, user.OpMask) if *user.MaxBuckets != *r.userConfig.MaxBuckets { user, err = r.objContext.AdminOpsClient.ModifyUser(r.opManagerContext, *r.userConfig) if err != nil { @@ -305,17 +307,22 @@ func (r *ReconcileObjectStoreUser) createOrUpdateCephUser(u *cephv1.CephObjectSt } // Update caps if necessary + user.UserCaps = generateUserCaps(user) if user.UserCaps != r.userConfig.UserCaps { // If they are no caps to be removed, the API will return an error "missing user capabilities" if user.UserCaps != "" { + logger.Tracef("remove capabilities %s from user %s", user.UserCaps, r.userConfig.ID) _, err = r.objContext.AdminOpsClient.RemoveUserCap(r.opManagerContext, r.userConfig.ID, user.UserCaps) if err != nil { return errors.Wrapf(err, "failed to remove current ceph object user %q capabilities", r.userConfig.ID) } } - _, err = r.objContext.AdminOpsClient.AddUserCap(r.opManagerContext, r.userConfig.ID, r.userConfig.UserCaps) - if err != nil { - return errors.Wrapf(err, "failed to update ceph object user %q capabilities", r.userConfig.ID) + if r.userConfig.UserCaps != "" { + logger.Tracef("set capabilities %s for user %s", r.userConfig.UserCaps, r.userConfig.ID) + _, err = r.objContext.AdminOpsClient.AddUserCap(r.opManagerContext, r.userConfig.ID, r.userConfig.UserCaps) + if err != nil { + return errors.Wrapf(err, "failed to update ceph object user %q capabilities", r.userConfig.ID) + } } logCreateOrUpdate = fmt.Sprintf("updated ceph object user %q", u.Name) } @@ -384,6 +391,14 @@ func (r *ReconcileObjectStoreUser) initializeObjectStoreContext(u *cephv1.CephOb return nil } +func generateUserCaps(user admin.User) string { + var caps string + for _, c := range user.Caps { + caps += fmt.Sprintf("%s=%s;", c.Type, c.Perm) + } + return caps +} + func generateUserConfig(user *cephv1.CephObjectStoreUser) admin.User { // Set DisplayName to match Name if DisplayName is not set displayName := user.Spec.DisplayName diff --git a/pkg/operator/ceph/object/user/controller_test.go b/pkg/operator/ceph/object/user/controller_test.go index 4c660d85c..c27df6bfb 100644 --- a/pkg/operator/ceph/object/user/controller_test.go +++ b/pkg/operator/ceph/object/user/controller_test.go @@ -67,7 +67,7 @@ const ( "caps": [ { "type": "users", - "perms": "*" + "perm": "*" } ], "op_mask": "read, write, delete", @@ -298,6 +298,12 @@ func TestCephObjectStoreUserController(t *testing.T) { Body: io.NopCloser(bytes.NewReader([]byte(userCreateJSON))), }, nil } + if req.Method == http.MethodDelete && req.URL.RawQuery == "caps=&format=json&uid=my-user&user-caps=users%3D%2A%3B" { + return &http.Response{ + StatusCode: 200, + Body: io.NopCloser(bytes.NewReader([]byte(`[]`))), + }, nil + } return nil, fmt.Errorf("unexpected request: %q. method %q. path %q", req.URL.RawQuery, req.Method, req.URL.Path) }, } @@ -390,6 +396,12 @@ func TestCreateOrUpdateCephUser(t *testing.T) { Body: io.NopCloser(bytes.NewReader([]byte(`[]`))), }, nil } + if req.URL.RawQuery == "caps=&format=json&uid=my-user&user-caps=users%3D%2A%3B" { + return &http.Response{ + StatusCode: 200, + Body: io.NopCloser(bytes.NewReader([]byte(`[]`))), + }, nil + } } if req.Method == http.MethodPut { if req.URL.RawQuery == "enabled=false&format=json&max-objects=-1&max-size=-1"a="a-type=user&uid=my-user" ||