add a hidden role for service accounts

Signed-off-by: jkoberg <jkoberg@owncloud.com>
This commit is contained in:
jkoberg
2023-12-21 12:37:46 +01:00
parent e76f2eaf8c
commit 20f77d4b5b
8 changed files with 72 additions and 16 deletions

View File

@@ -0,0 +1,6 @@
Enhancement: Service Account roles
Use a hidden role for service accounts. It will not appear in ListRoles calls but internally handled
by settings service
https://github.com/owncloud/ocis/pull/8051

View File

@@ -15,10 +15,9 @@ As an example, user profile settings that can be changed in the Web UI must be p
The settings service supports two different backends for persisting the data. The backend can be set via the `SETTINGS_STORE_TYPE` environment variable. Supported values are:
* `metadata`: The default. This backend persists the settings data via the `storage-system` service.
* `filesystem`: This backend persists the settings data in a directory on the local filesystem.
* `filesystem`: (deprecated) This backend persists the settings data in a directory on the local filesystem.
The directory can be configured with `SETTINGS_DATA_PATH`. This backend is **not** suitable for running
multiple intances of the `settings` service in a scale-out deployment and should be therefore considered
deprecated.
multiple intances of the `settings` service in a scale-out deployment and was therefore deprecated.
<!--- Note: The diagramm is outdate, leaving it here for a future rework
The diagram shows how the settings service integrates into oCIS:
@@ -72,7 +71,7 @@ Services can set or query Infinite Scale *setting values* of a user from setting
## Service Accounts
The settings service needs to know the ID's of service accounts but it doesn't need their secrets. Currently only one service account can be configured which has the admin role. This can be set with the `SETTINGS_SERVICE_ACCOUNT_ID_ADMIN` envvar, but it will also pick up the global `OCIS_SERVICE_ACCOUNT_ID` environment variable. Also see the 'auth-service' service description for additional details.
The settings service needs to know the IDs of service accounts but it doesn't need their secrets. They can be configured using the `SETTINGS_SERVICE_ACCOUNTS_IDS` envvar. When only using one service account `OCIS_SERVICE_ACCOUNT_ID` can also be used. All configured service accounts will get a hidden 'service-account' role. This role contains all permissions the service account needs but will not appear calls to the list roles endpoint. It is not possible to assign the 'service-account' role to a normal user.
## Default Language

View File

@@ -37,7 +37,7 @@ type Config struct {
SetupDefaultAssignments bool `yaml:"set_default_assignments" env:"SETTINGS_SETUP_DEFAULT_ASSIGNMENTS;IDM_CREATE_DEMO_USERS" desc:"The default role assignments the demo users should be setup."`
ServiceAccountIDAdmin string `yaml:"service_account_id_admin" env:"OCIS_SERVICE_ACCOUNT_ID;SETTINGS_SERVICE_ACCOUNT_ID_ADMIN" desc:"The ID of the service account having the admin role. See the 'auth-service' service description for more details."`
ServiceAccountIDs []string `yaml:"service_account_ids" env:"SETTINGS_SERVICE_ACCOUNT_IDS;OCIS_SERVICE_ACCOUNT_ID" desc:"The list of all service account IDs. These will be assigned the hidden 'service-account' role See the 'auth-service' service description for more details about service accounts."`
DefaultLanguage string `yaml:"default_language" env:"OCIS_DEFAULT_LANGUAGE" desc:"The default language used by services and the WebUI. If not defined, English will be used as default. See the documentation for more details."`

View File

@@ -65,9 +65,9 @@ func DefaultConfig() *config.Config {
TTL: time.Minute * 10,
},
},
BundlesPath: "",
Bundles: nil,
ServiceAccountIDAdmin: "service-user-id",
BundlesPath: "",
Bundles: nil,
ServiceAccountIDs: []string{"service-user-id"},
}
}

View File

@@ -46,6 +46,7 @@ func NewService(cfg *config.Config, logger log.Logger) settings.ServiceHandler {
case "metadata":
service.manager = metastore.New(cfg)
case "filesystem":
fmt.Println("WARNING: filesystem store is deprecated and will be removed in the future. Please use metadata store instead.")
service.manager = filestore.New(cfg)
// TODO: if we want to further support filesystem store it should use default permissions from store/defaults/defaults.go instead using this duplicate
service.RegisterDefaultRoles()

View File

@@ -14,8 +14,10 @@ const (
BundleUUIDRoleUser = "d7beeea8-8ff4-406b-8fb6-ab2dd81e6b11"
// BundleUUIDRoleUserLight represents the user light role.
BundleUUIDRoleUserLight = "38071a68-456a-4553-846a-fa67bf5596cc"
// BundleUUIDProfile represents the user profile
// BundleUUIDProfile represents the user profile.
BundleUUIDProfile = "2a506de7-99bd-4f0d-994e-c38e72c28fd9"
// BundleUUIDServiceAccount represents the service account role.
BundleUUIDServiceAccount = "bcceed81-c610-49cc-ab77-39a024e8da12"
// SettingUUIDProfileLanguage is the hardcoded setting UUID for the user profile language
SettingUUIDProfileLanguage = "aa8cfbe5-95d4-4f7e-a032-c3c01f5f062f"
// SettingUUIDProfileDisableNotifications is the hardcoded setting UUID for the disable notifications setting
@@ -35,6 +37,42 @@ func GenerateBundlesDefaultRoles() []*settingsmsg.Bundle {
}
}
// ServiceAccountBundle returns the service account bundle
func ServiceAccountBundle() *settingsmsg.Bundle {
return &settingsmsg.Bundle{
Id: BundleUUIDServiceAccount,
Name: "service-account",
Type: settingsmsg.Bundle_TYPE_ROLE,
Extension: "ocis-roles",
DisplayName: "Service Account",
Resource: &settingsmsg.Resource{
Type: settingsmsg.Resource_TYPE_SYSTEM,
},
Settings: []*settingsmsg.Setting{
AccountManagementPermission(All),
ChangeLogoPermission(All),
CreatePublicLinkPermission(All),
CreateSharePermission(All),
CreateSpacesPermission(All),
DeletePersonalSpacesPermission(All),
DeleteProjectSpacesPermission(All),
DeleteReadOnlyPublicLinkPasswordPermission(All),
GroupManagementPermission(All),
LanguageManagementPermission(All),
ListFavoritesPermission(All),
ListSpacesPermission(All),
ManageSpacePropertiesPermission(All),
RoleManagementPermission(All),
SetPersonalSpaceQuotaPermission(All),
SetProjectSpaceQuotaPermission(All),
SettingsManagementPermission(All),
SpaceAbilityPermission(All),
WriteFavoritesPermission(All),
// TODO: add more permissions? remove some?
},
}
}
func generateBundleAdminRole() *settingsmsg.Bundle {
return &settingsmsg.Bundle{
Id: BundleUUIDRoleAdmin,
@@ -353,12 +391,5 @@ func DefaultRoleAssignments(cfg *config.Config) []*settingsmsg.UserRoleAssignmen
})
}
if cfg.ServiceAccountIDAdmin != "" {
assignments = append(assignments, &settingsmsg.UserRoleAssignment{
AccountUuid: cfg.ServiceAccountIDAdmin,
RoleId: BundleUUIDRoleAdmin,
})
}
return assignments
}

View File

@@ -10,10 +10,23 @@ import (
"github.com/gofrs/uuid"
settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0"
"github.com/owncloud/ocis/v2/services/settings/pkg/settings"
"github.com/owncloud/ocis/v2/services/settings/pkg/store/defaults"
)
// ListRoleAssignments loads and returns all role assignments matching the given assignment identifier.
func (s *Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRoleAssignment, error) {
// shortcut for service accounts
for _, serviceAccountID := range s.cfg.ServiceAccountIDs {
if accountUUID == serviceAccountID {
return []*settingsmsg.UserRoleAssignment{
{
Id: uuid.Must(uuid.NewV4()).String(), // should we hardcode this id too?
AccountUuid: accountUUID,
RoleId: defaults.BundleUUIDServiceAccount,
},
}, nil
}
}
s.Init()
ctx := context.TODO()
assIDs, err := s.mdc.ReadDir(ctx, accountPath(accountUUID))

View File

@@ -11,6 +11,7 @@ import (
"github.com/gofrs/uuid"
settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0"
"github.com/owncloud/ocis/v2/services/settings/pkg/settings"
"github.com/owncloud/ocis/v2/services/settings/pkg/store/defaults"
)
// ListBundles returns all bundles in the dataPath folder that match the given type.
@@ -59,6 +60,11 @@ func (s *Store) ListBundles(bundleType settingsmsg.Bundle_Type, bundleIDs []stri
// ReadBundle tries to find a bundle by the given id from the metadata service
func (s *Store) ReadBundle(bundleID string) (*settingsmsg.Bundle, error) {
// shortcut for service accounts
if bundleID == defaults.BundleUUIDServiceAccount {
return defaults.ServiceAccountBundle(), nil
}
s.Init()
ctx := context.TODO()
b, err := s.mdc.SimpleDownload(ctx, bundlePath(bundleID))