opencloud
opencloud copied to clipboard
every settings service start writes the role bundles to system storage
Describe the bug
Whenever we start the settings service it writes the configured role bundles to the system storage:
// we need to lazy initialize the MetadataClient because metadata service might not be ready
func (s *Store) initMetadataClient(mdc MetadataClient) error {
ctx := context.TODO()
err := mdc.Init(ctx, settingsSpaceID)
if err != nil {
return err
}
for _, p := range []string{
rootFolderLocation,
accountsFolderLocation,
bundleFolderLocation,
valuesFolderLocation,
} {
err = mdc.MakeDirIfNotExist(ctx, p)
if err != nil {
return err
}
}
for _, p := range s.cfg.Bundles {
b, err := json.Marshal(p)
if err != nil {
return err
}
err = mdc.SimpleUpload(ctx, bundlePath(p.Id), b)
if err != nil {
return err
}
}
for _, p := range defaults.DefaultRoleAssignments(s.cfg) {
accountUUID := p.AccountUuid
roleID := p.RoleId
err = mdc.MakeDirIfNotExist(ctx, accountPath(accountUUID))
if err != nil {
return err
}
assIDs, err := mdc.ReadDir(ctx, accountPath(accountUUID))
if err != nil {
return err
}
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.NewString(),
AccountUuid: accountUUID,
RoleId: roleID,
}
b, err := json.Marshal(ass)
if err != nil {
return err
}
err = mdc.SimpleUpload(ctx, assignmentPath(accountUUID, ass.Id), b)
if err != nil {
return err
}
}
s.mdc = mdc
return nil
}
The s.cfg.Bundles is filled either with the built in default or the ones configured with: SETTINGS_BUNDLES_PATH
Looking at the settings code we seem to always read the roles from the settings sevice:
// ListRoles implements the RoleServiceHandler interface
func (g Service) ListRoles(_ context.Context, req *settingssvc.ListBundlesRequest, res *settingssvc.ListBundlesResponse) error {
//accountUUID := getValidatedAccountUUID(c, "me")
if validationError := validateListRoles(req); validationError != nil {
return merrors.BadRequest(g.id, "%s", validationError)
}
r, err := g.manager.ListBundles(settingsmsg.Bundle_TYPE_ROLE, req.GetBundleIds())
if err != nil {
return merrors.NotFound(g.id, "%s", err)
}
// TODO: only allow listing roles when user has account/role/... management permissions
res.Bundles = r
return nil
}
The ListBundles the calls the system storage:
// ListBundles returns all bundles in the dataPath folder that match the given type.
func (s *Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []string) ([]*settingsmsg.Bundle, error) {
s.Init()
ctx := context.TODO()
if len(bundleIDs) == 0 {
bIDs, err := s.mdc.ReadDir(ctx, bundleFolderLocation)
switch err.(type) {
case nil:
// continue
case errtypes.NotFound:
return make([]*settingsmsg.Bundle, 0), nil
default:
return nil, err
}
bundleIDs = bIDs
}
var bundles []*settingsmsg.Bundle
for _, id := range bundleIDs {
if id == defaults.BundleUUIDServiceAccount {
bundles = append(bundles, defaults.ServiceAccountBundle())
continue
}
b, err := s.mdc.SimpleDownload(ctx, bundlePath(id))
switch err.(type) {
case nil:
// continue
case errtypes.NotFound:
continue
default:
return nil, err
}
bundle := &settingsmsg.Bundle{}
err = json.Unmarshal(b, bundle)
if err != nil {
return nil, err
}
if bundle.Type == bundleType {
bundles = append(bundles, bundle)
}
}
return bundles, nil
}
AFAICT we could just server the role bundles from the config ... no need to read from/write to systems storage.