Skip to content

Commit

Permalink
Merge pull request #8897 from owncloud/fix-role-assignments
Browse files Browse the repository at this point in the history
fix: always assign the admin role to the default admin
  • Loading branch information
micbar committed Apr 19, 2024
2 parents e861512 + 4960f8c commit 648a3fc
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 1 deletion.
6 changes: 6 additions & 0 deletions changelog/unreleased/fix-admin-role-assignment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Bugfix: Update the admin user role assignment to enforce the config

The admin user role assigment was not updated after the first assignment. We now read the assigned role during init and update the admin user ID accordingly if the role is not assigned.
This is especially needed when the OCIS_ADMIN_USER_ID is set after the autoprovisioning of the admin user when it originates from an external Identity Provider.

https://github.com/owncloud/ocis/pull/8897
71 changes: 70 additions & 1 deletion services/settings/pkg/store/metadata/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"log"
"sync"

"github.com/cs3org/reva/v2/pkg/errtypes"
"github.com/cs3org/reva/v2/pkg/storage/utils/metadata"
"github.com/gofrs/uuid"
olog "github.com/owncloud/ocis/v2/ocis-pkg/log"
Expand Down Expand Up @@ -139,10 +140,20 @@ func (s *Store) initMetadataClient(mdc MetadataClient) error {
if err != nil {
return err
}
if len(assIDs) > 0 {

adminUserID := accountUUID == s.cfg.AdminUserID
if len(assIDs) > 0 && !adminUserID {
// There is already a role assignment for this ID, skip to the next
continue
}
// for the adminUserID we need to check if the user has the admin role every time
if adminUserID {
err = s.userMustHaveAdminRole(accountUUID, assIDs, mdc)
if err != nil {
return err
}
continue
}

ass := &settingsmsg.UserRoleAssignment{
Id: uuid.Must(uuid.NewV4()).String(),
Expand All @@ -164,6 +175,64 @@ func (s *Store) initMetadataClient(mdc MetadataClient) error {
return nil
}

func (s *Store) userMustHaveAdminRole(accountUUID string, assIDs []string, mdc MetadataClient) error {
ctx := context.TODO()
var hasAdminRole bool

// load the assignments from the store and check if the admin role is already assigned
for _, assID := range assIDs {
b, err := mdc.SimpleDownload(ctx, assignmentPath(accountUUID, assID))
switch err.(type) {
case nil:
// continue
case errtypes.NotFound:
continue
default:
return err
}

a := &settingsmsg.UserRoleAssignment{}
err = json.Unmarshal(b, a)
if err != nil {
return err
}

if a.RoleId == defaults.BundleUUIDRoleAdmin {
hasAdminRole = true
}
}

// delete old role assignment and set admin role
if !hasAdminRole {
err := mdc.Delete(ctx, accountPath(accountUUID))
switch err.(type) {
case nil:
// continue
case errtypes.NotFound:
// already gone, continue
default:
return err
}

err = mdc.MakeDirIfNotExist(ctx, accountPath(accountUUID))
if err != nil {
return err
}

ass := &settingsmsg.UserRoleAssignment{
Id: uuid.Must(uuid.NewV4()).String(),
AccountUuid: accountUUID,
RoleId: defaults.BundleUUIDRoleAdmin,
}
b, err := json.Marshal(ass)
if err != nil {
return err
}
return mdc.SimpleUpload(ctx, assignmentPath(accountUUID, ass.Id), b)
}
return nil
}

func init() {
settings.Registry[managerName] = New
}
76 changes: 76 additions & 0 deletions services/settings/pkg/store/metadata/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@ package store

import (
"context"
"encoding/json"
"strings"
"testing"

"github.com/cs3org/reva/v2/pkg/errtypes"
. "github.com/onsi/gomega"
settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0"
"github.com/owncloud/ocis/v2/services/settings/pkg/config/defaults"
rdefaults "github.com/owncloud/ocis/v2/services/settings/pkg/store/defaults"
)

const (
Expand Down Expand Up @@ -112,3 +117,74 @@ func (m *MockedMetadataClient) IDExists(id string) bool {
func (m *MockedMetadataClient) IDHasContent(id string, content []byte) bool {
return string(m.data[id]) == string(content)
}

// TestAdminUserIDInit test the happy path during initialization
func TestAdminUserIDInit(t *testing.T) {
RegisterTestingT(t)
s := &Store{
cfg: defaults.DefaultConfig(),
}
s.cfg.Bundles = rdefaults.GenerateBundlesDefaultRoles()
s.cfg.AdminUserID = "admin"

// the first assignment is always happening during the initialisation of the metadata client
err := NewMDC(s)
Expect(err).To(BeNil())

assID, err := s.mdc.ReadDir(context.TODO(), accountPath(s.cfg.AdminUserID))
Expect(len(assID)).To(Equal(1))
ass, err := s.mdc.SimpleDownload(context.TODO(), assignmentPath(s.cfg.AdminUserID, assID[0]))
Expect(ass).ToNot(BeNil())

assignment := &settingsmsg.UserRoleAssignment{}
err = json.Unmarshal(ass, assignment)
Expect(err).To(BeNil())
Expect(assignment.RoleId).To(Equal(rdefaults.BundleUUIDRoleAdmin))
}

// TestAdminUserIDUpdate test the update on following initialisations
func TestAdminUserIDUpdate(t *testing.T) {
RegisterTestingT(t)
s := &Store{
cfg: defaults.DefaultConfig(),
}
s.cfg.Bundles = rdefaults.GenerateBundlesDefaultRoles()
s.cfg.AdminUserID = "admin"

// the first assignment is always happening during the initialisation of the metadata client
err := NewMDC(s)
Expect(err).To(BeNil())

// read assignment
assID, err := s.mdc.ReadDir(context.TODO(), accountPath(s.cfg.AdminUserID))
Expect(len(assID)).To(Equal(1))

// set assignment to user role
userRoleAssignment := &settingsmsg.UserRoleAssignment{
AccountUuid: s.cfg.AdminUserID,
RoleId: rdefaults.BundleUUIDRoleUser,
}
b, err := json.Marshal(userRoleAssignment)
err = s.mdc.Delete(context.TODO(), assignmentPath(s.cfg.AdminUserID, assID[0]))
Expect(err).To(BeNil())
err = s.mdc.SimpleUpload(context.TODO(), assignmentPath(s.cfg.AdminUserID, assID[0]), b)
Expect(err).To(BeNil())

// this happens on every Read / Write on the store
// the actual init is only done if the metadata client has not been initialized before
// this normally needs a restart of the service
err = s.initMetadataClient(s.mdc)
Expect(err).To(BeNil())

// read assignment id, changes every time the assignment is written
assID, err = s.mdc.ReadDir(context.TODO(), accountPath(s.cfg.AdminUserID))
Expect(len(assID)).To(Equal(1))

// check if the assignment is the admin role again
ass, err := s.mdc.SimpleDownload(context.TODO(), assignmentPath(s.cfg.AdminUserID, assID[0]))
Expect(ass).ToNot(BeNil())
assignment := &settingsmsg.UserRoleAssignment{}
err = json.Unmarshal(ass, assignment)
Expect(err).To(BeNil())
Expect(assignment.RoleId).To(Equal(rdefaults.BundleUUIDRoleAdmin))
}

0 comments on commit 648a3fc

Please sign in to comment.