Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[full-ci] Service Account Roles #8051

Merged
merged 2 commits into from
Dec 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions changelog/unreleased/service-account-roles.md
Original file line number Diff line number Diff line change
@@ -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
7 changes: 3 additions & 4 deletions services/settings/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion services/settings/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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. Note: When using 'OCIS_SERVICE_ACCOUNT_ID' this will contain only one value while 'SETTINGS_SERVICE_ACCOUNT_IDS' can have multiple. 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."`

Expand Down
6 changes: 3 additions & 3 deletions services/settings/pkg/config/defaults/defaultconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"},
}
}

Expand Down
1 change: 1 addition & 0 deletions services/settings/pkg/service/v0/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

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()
Expand Down
47 changes: 39 additions & 8 deletions services/settings/pkg/store/defaults/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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
}
13 changes: 13 additions & 0 deletions services/settings/pkg/store/metadata/assignments.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
6 changes: 6 additions & 0 deletions services/settings/pkg/store/metadata/bundles.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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))
Expand Down