diff --git a/server/.env.example b/server/.env.example index d34888a1a..5ac6b301c 100644 --- a/server/.env.example +++ b/server/.env.example @@ -220,6 +220,60 @@ # Default: # RBAC_LOG= +############################################################################### +# Limit the number of resources to keep in the in-memory index. +# When set to -1, max size is used. +# When set to 0, the in memory index is not used. +# Type: int +# Default: +# RBAC_MAX_INDEX_SIZE= + +############################################################################### +# Synchronous lets us make all the procedures synchronous for ease of testing +# This should always be false in production +# Type: bool +# Default: +# RBAC_SYNCHRONOUS= + +############################################################################### +# Reindex strategy defines what strategy we should use. +# The available options are: +# +# . `memory`: prioritize memory consumption which reduces performance during reindexing. +# . `speed`: prioritize speed during reindexing; memory consumption will be 2n where n is the current index size. +# +# If you wish to prioritize memory and speed, consider using `speed` with a lower max index size +# Type: string +# Default: +# RBAC_REINDEX_STRATEGY= + +############################################################################### +# Decay factor controls how long an item should be kept in the index while not in use. +# Type: float64 +# Default: +# RBAC_DECAY_FACTOR= + +############################################################################### +# Decay interval controls how fast the decay factor is applied to the index key. +# Type: time.Duration +# Default: +# RBAC_DECAY_INTERVAL= + +############################################################################### +# Cleanup interval controls when unused/low-scored index items should be yanked out of the index counter. +# Type: time.Duration +# Default: +# RBAC_CLEANUP_INTERVAL= + +############################################################################### +# [IMPORTANT] +# ==== +# Unused, will be added when state preservation is implemented. +# ==== +# Type: time.Duration +# Default: +# RBAC_INDEX_FLUSH_INTERVAL= + ############################################################################### # Type: string # Default: diff --git a/server/app/boot_levels.go b/server/app/boot_levels.go index 58f99793c..44774189b 100644 --- a/server/app/boot_levels.go +++ b/server/app/boot_levels.go @@ -1,53 +1,53 @@ package app import ( - "context" - "crypto/tls" - "fmt" - "net/url" - "os" - "regexp" - "strings" - "time" + "context" + "crypto/tls" + "fmt" + "net/url" + "os" + "regexp" + "strings" + "time" - authService "github.com/cortezaproject/corteza/server/auth" - "github.com/cortezaproject/corteza/server/auth/saml" - authSettings "github.com/cortezaproject/corteza/server/auth/settings" - autService "github.com/cortezaproject/corteza/server/automation/service" - cmpService "github.com/cortezaproject/corteza/server/compose/service" - cmpEvent "github.com/cortezaproject/corteza/server/compose/service/event" - discoveryService "github.com/cortezaproject/corteza/server/discovery/service" - fedService "github.com/cortezaproject/corteza/server/federation/service" - "github.com/cortezaproject/corteza/server/pkg/actionlog" - "github.com/cortezaproject/corteza/server/pkg/apigw" - apigwTypes "github.com/cortezaproject/corteza/server/pkg/apigw/types" - "github.com/cortezaproject/corteza/server/pkg/auth" - "github.com/cortezaproject/corteza/server/pkg/corredor" - "github.com/cortezaproject/corteza/server/pkg/eventbus" - "github.com/cortezaproject/corteza/server/pkg/healthcheck" - "github.com/cortezaproject/corteza/server/pkg/http" - "github.com/cortezaproject/corteza/server/pkg/id" - "github.com/cortezaproject/corteza/server/pkg/locale" - "github.com/cortezaproject/corteza/server/pkg/logger" - "github.com/cortezaproject/corteza/server/pkg/mail" - "github.com/cortezaproject/corteza/server/pkg/messagebus" - "github.com/cortezaproject/corteza/server/pkg/monitor" - "github.com/cortezaproject/corteza/server/pkg/options" - "github.com/cortezaproject/corteza/server/pkg/provision" - "github.com/cortezaproject/corteza/server/pkg/rbac" - "github.com/cortezaproject/corteza/server/pkg/scheduler" - "github.com/cortezaproject/corteza/server/pkg/sentry" - "github.com/cortezaproject/corteza/server/pkg/valuestore" - "github.com/cortezaproject/corteza/server/pkg/version" - "github.com/cortezaproject/corteza/server/pkg/websocket" - "github.com/cortezaproject/corteza/server/store" - "github.com/cortezaproject/corteza/server/system/service" - sysService "github.com/cortezaproject/corteza/server/system/service" - sysEvent "github.com/cortezaproject/corteza/server/system/service/event" - "github.com/cortezaproject/corteza/server/system/types" - "github.com/lestrrat-go/jwx/jwt" - "go.uber.org/zap" - gomail "gopkg.in/mail.v2" + authService "github.com/cortezaproject/corteza/server/auth" + "github.com/cortezaproject/corteza/server/auth/saml" + authSettings "github.com/cortezaproject/corteza/server/auth/settings" + autService "github.com/cortezaproject/corteza/server/automation/service" + cmpService "github.com/cortezaproject/corteza/server/compose/service" + cmpEvent "github.com/cortezaproject/corteza/server/compose/service/event" + discoveryService "github.com/cortezaproject/corteza/server/discovery/service" + fedService "github.com/cortezaproject/corteza/server/federation/service" + "github.com/cortezaproject/corteza/server/pkg/actionlog" + "github.com/cortezaproject/corteza/server/pkg/apigw" + apigwTypes "github.com/cortezaproject/corteza/server/pkg/apigw/types" + "github.com/cortezaproject/corteza/server/pkg/auth" + "github.com/cortezaproject/corteza/server/pkg/corredor" + "github.com/cortezaproject/corteza/server/pkg/eventbus" + "github.com/cortezaproject/corteza/server/pkg/healthcheck" + "github.com/cortezaproject/corteza/server/pkg/http" + "github.com/cortezaproject/corteza/server/pkg/id" + "github.com/cortezaproject/corteza/server/pkg/locale" + "github.com/cortezaproject/corteza/server/pkg/logger" + "github.com/cortezaproject/corteza/server/pkg/mail" + "github.com/cortezaproject/corteza/server/pkg/messagebus" + "github.com/cortezaproject/corteza/server/pkg/monitor" + "github.com/cortezaproject/corteza/server/pkg/options" + "github.com/cortezaproject/corteza/server/pkg/provision" + "github.com/cortezaproject/corteza/server/pkg/rbac" + "github.com/cortezaproject/corteza/server/pkg/scheduler" + "github.com/cortezaproject/corteza/server/pkg/sentry" + "github.com/cortezaproject/corteza/server/pkg/valuestore" + "github.com/cortezaproject/corteza/server/pkg/version" + "github.com/cortezaproject/corteza/server/pkg/websocket" + "github.com/cortezaproject/corteza/server/store" + "github.com/cortezaproject/corteza/server/system/service" + sysService "github.com/cortezaproject/corteza/server/system/service" + sysEvent "github.com/cortezaproject/corteza/server/system/service/event" + "github.com/cortezaproject/corteza/server/system/types" + "github.com/lestrrat-go/jwx/jwt" + "go.uber.org/zap" + gomail "gopkg.in/mail.v2" ) const ( @@ -258,15 +258,7 @@ func (app *CortezaApp) Provision(ctx context.Context) (err error) { // @todo envoy should be decoupled from RBAC and import directly into store, // w/o using any access control - var ( - ac = rbac.NewService(zap.NewNop(), app.Store) - acr = make([]*rbac.Role, 0) - ) - for _, r := range auth.ProvisionUser().Roles() { - acr = append(acr, rbac.BypassRole.Make(r, auth.BypassRoleHandle)) - } - ac.UpdateRoles(acr...) - rbac.SetGlobal(ac) + rbac.SetGlobal(rbac.NoopSvc(rbac.Allow)) defer rbac.SetGlobal(nil) } @@ -355,10 +347,29 @@ func (app *CortezaApp) InitServices(ctx context.Context) (err error) { } // Initialize RBAC subsystem - ac := rbac.NewService(log, app.Store) + // @todo add state management + // @todo potentially add .Activate like other services? + ac, err := rbac.NewService(ctx, log, app.Store, rbac.Config{ + MaxIndexSize: app.Opt.RBAC.MaxIndexSize, + Synchronous: app.Opt.RBAC.Synchronous, + ReindexStrategy: rbac.ReindexStrategy(app.Opt.RBAC.ReindexStrategy), + DecayFactor: app.Opt.RBAC.DecayFactor, + DecayInterval: app.Opt.RBAC.DecayInterval, + CleanupInterval: app.Opt.RBAC.CleanupInterval, + IndexFlushInterval: app.Opt.RBAC.IndexFlushInterval, + RuleStorage: app.Store, + RoleStorage: app.Store, - // and (re)load rules from the storage backend - ac.Reload(ctx) + PullInitialState: func(ctx context.Context, n int) ([]string, error) { + return nil, nil + }, + FlushIndexState: func(ctx context.Context, s []string) error { + return nil + }, + }) + if err != nil { + return fmt.Errorf("failed to initialize RBAC service: %w", err) + } rbac.SetGlobal(ac) } @@ -504,8 +515,6 @@ func (app *CortezaApp) Activate(ctx context.Context) (err error) { monitor.Watcher(ctx) - rbac.Global().Watch(ctx) - if err = sysService.Activate(ctx); err != nil { return fmt.Errorf("could not activate system services: %w", err) @@ -562,9 +571,9 @@ func (app *CortezaApp) Activate(ctx context.Context) (err error) { app.AuthService.Watch(ctx) - updateSassInstallSettings(ctx, sysService.DefaultStylesheet.SassInstalled(), app.Log) + updateSassInstallSettings(ctx, sysService.DefaultStylesheet.SassInstalled(), app.Log) //Generate CSS for webapps - if err = sysService.DefaultStylesheet.GenerateCSS(sysService.CurrentSettings, app.Opt.Webapp.ScssDirPath, app.Log); err != nil { + if err = sysService.DefaultStylesheet.GenerateCSS(sysService.CurrentSettings, app.Opt.Webapp.ScssDirPath, app.Log); err != nil { return fmt.Errorf("could not generate css for webapps: %w", err) } diff --git a/server/app/options/RBAC.cue b/server/app/options/RBAC.cue index b04b62dfc..d129a7edc 100644 --- a/server/app/options/RBAC.cue +++ b/server/app/options/RBAC.cue @@ -13,6 +13,75 @@ RBAC: schema.#optionsGroup & { type: "bool" description: "Log RBAC related events and actions" } + + max_index_size: { + type: "int" + defaultGoExpr: "-1" + description: """ + Limit the number of resources to keep in the in-memory index. + When set to -1, max size is used. + When set to 0, the in memory index is not used. + """ + } + + synchronous: { + type: "bool" + defaultGoExpr: "false" + description: """ + Synchronous lets us make all the procedures synchronous for ease of testing + This should always be false in production + """ + } + + reindex_strategy: { + type: "string" + defaultValue: "" + description: """ + Reindex strategy defines what strategy we should use. + The available options are: + + . `memory`: prioritize memory consumption which reduces performance during reindexing. + . `speed`: prioritize speed during reindexing; memory consumption will be 2n where n is the current index size. + + If you wish to prioritize memory and speed, consider using `speed` with a lower max index size + """ + } + + decay_factor: { + type: "float64" + defaultGoExpr: "0.9" + description: """ + Decay factor controls how long an item should be kept in the index while not in use. + """ + } + + decay_interval: { + type: "time.Duration" + defaultGoExpr: "time.Minute * 30" + description: """ + Decay interval controls how fast the decay factor is applied to the index key. + """ + } + + cleanup_interval: { + type: "time.Duration" + defaultGoExpr: "time.Minute * 31" + description: """ + Cleanup interval controls when unused/low-scored index items should be yanked out of the index counter. + """ + } + + index_flush_interval: { + type: "time.Duration" + defaultGoExpr: "time.Minute * 35" + description: """ + [IMPORTANT] + ==== + Unused, will be added when state preservation is implemented. + ==== + """ + } + service_user: {} bypass_roles: { defaultValue: "super-admin" diff --git a/server/automation/service/access_control.gen.go b/server/automation/service/access_control.gen.go index d9964efd9..41b7a011e 100644 --- a/server/automation/service/access_control.gen.go +++ b/server/automation/service/access_control.gen.go @@ -22,9 +22,9 @@ import ( type ( rbacService interface { Can(rbac.Session, string, rbac.Resource) bool - Trace(rbac.Session, string, rbac.Resource) *rbac.Trace + Trace(rbac.Session, string, rbac.Resource) (*rbac.Trace, error) Grant(context.Context, ...*rbac.Rule) error - FindRulesByRoleID(roleID uint64) (rr rbac.RuleSet) + FindRulesByRoleID(ctx context.Context, roleID uint64) (rr rbac.RuleSet, err error) } accessControl struct { @@ -120,11 +120,16 @@ func (svc accessControl) Trace(ctx context.Context, userID uint64, roles []uint6 return nil, fmt.Errorf("no roles specified") } + var auxTrace *rbac.Trace session := rbac.ParamsToSession(ctx, userID, roles...) for _, res := range resources { r := res.RbacResource() for op := range rbacResourceOperations(r) { - ee = append(ee, svc.rbac.Trace(session, op, res)) + auxTrace, err = svc.rbac.Trace(session, op, res) + if err != nil { + return + } + ee = append(ee, auxTrace) } } @@ -300,7 +305,7 @@ func (svc accessControl) FindRulesByRoleID(ctx context.Context, roleID uint64) ( return nil, AccessControlErrNotAllowedToSetPermissions() } - return svc.rbac.FindRulesByRoleID(roleID), nil + return svc.rbac.FindRulesByRoleID(ctx, roleID) } // CanReadWorkflow checks if current user can read workflow diff --git a/server/codegen/assets/templates/gocode/rbac/$component_access_control.go.tpl b/server/codegen/assets/templates/gocode/rbac/$component_access_control.go.tpl index 666ac18a2..6418d4e08 100644 --- a/server/codegen/assets/templates/gocode/rbac/$component_access_control.go.tpl +++ b/server/codegen/assets/templates/gocode/rbac/$component_access_control.go.tpl @@ -21,9 +21,9 @@ import ( type ( rbacService interface { Can(rbac.Session, string, rbac.Resource) bool - Trace(rbac.Session, string, rbac.Resource) *rbac.Trace + Trace(rbac.Session, string, rbac.Resource) (*rbac.Trace, error) Grant(context.Context, ...*rbac.Rule) error - FindRulesByRoleID(roleID uint64) (rr rbac.RuleSet) + FindRulesByRoleID(ctx context.Context, roleID uint64) (rr rbac.RuleSet, err error) } accessControl struct { @@ -119,11 +119,16 @@ func (svc accessControl) Trace(ctx context.Context, userID uint64, roles []uint6 return nil, fmt.Errorf("no roles specified") } + var auxTrace *rbac.Trace session := rbac.ParamsToSession(ctx, userID, roles...) for _, res := range resources { r := res.RbacResource() for op := range rbacResourceOperations(r) { - ee = append(ee, svc.rbac.Trace(session, op, res)) + auxTrace, err = svc.rbac.Trace(session, op, res) + if err != nil { + return + } + ee = append(ee, auxTrace) } } @@ -245,7 +250,7 @@ func (svc accessControl) FindRulesByRoleID(ctx context.Context, roleID uint64) ( return nil, AccessControlErrNotAllowedToSetPermissions() } - return svc.rbac.FindRulesByRoleID(roleID), nil + return svc.rbac.FindRulesByRoleID(ctx, roleID) } {{- range .operations }} diff --git a/server/compose/rest/namespace.go b/server/compose/rest/namespace.go index 08ce6f909..5f1423878 100644 --- a/server/compose/rest/namespace.go +++ b/server/compose/rest/namespace.go @@ -497,7 +497,10 @@ func (ctrl Namespace) exportCompose(ctx context.Context, namespaceID uint64) (re func (ctrl Namespace) exportRBAC(ctx context.Context, base envoyx.NodeSet) (resources envoyx.NodeSet, err error) { // Prepare RBAC Rules - rawRules := rbac.Global().Rules() + rawRules, err := rbac.Global().Rules(ctx) + if err != nil { + return + } resources, err = envoyx.RBACRulesForNodes(rawRules, base...) if err != nil { diff --git a/server/compose/service/access_control.gen.go b/server/compose/service/access_control.gen.go index 8513edaf1..0a0103078 100644 --- a/server/compose/service/access_control.gen.go +++ b/server/compose/service/access_control.gen.go @@ -22,9 +22,9 @@ import ( type ( rbacService interface { Can(rbac.Session, string, rbac.Resource) bool - Trace(rbac.Session, string, rbac.Resource) *rbac.Trace + Trace(rbac.Session, string, rbac.Resource) (*rbac.Trace, error) Grant(context.Context, ...*rbac.Rule) error - FindRulesByRoleID(roleID uint64) (rr rbac.RuleSet) + FindRulesByRoleID(ctx context.Context, roleID uint64) (rr rbac.RuleSet, err error) } accessControl struct { @@ -120,11 +120,16 @@ func (svc accessControl) Trace(ctx context.Context, userID uint64, roles []uint6 return nil, fmt.Errorf("no roles specified") } + var auxTrace *rbac.Trace session := rbac.ParamsToSession(ctx, userID, roles...) for _, res := range resources { r := res.RbacResource() for op := range rbacResourceOperations(r) { - ee = append(ee, svc.rbac.Trace(session, op, res)) + auxTrace, err = svc.rbac.Trace(session, op, res) + if err != nil { + return + } + ee = append(ee, auxTrace) } } @@ -446,7 +451,7 @@ func (svc accessControl) FindRulesByRoleID(ctx context.Context, roleID uint64) ( return nil, AccessControlErrNotAllowedToSetPermissions() } - return svc.rbac.FindRulesByRoleID(roleID), nil + return svc.rbac.FindRulesByRoleID(ctx, roleID) } // CanReadChart checks if current user can read diff --git a/server/compose/service/namespace.go b/server/compose/service/namespace.go index 38a8476af..6b3c1a231 100644 --- a/server/compose/service/namespace.go +++ b/server/compose/service/namespace.go @@ -850,8 +850,14 @@ func (svc namespace) reloadServices(ctx context.Context, ns *types.Namespace) (e return } - // Reload RBAC rules (in case import brought in something new) - rbac.Global().Reload(ctx) + // Reload some RBAC bits in case things changed + // + // @note no need to reload rules; just roles for now + err = rbac.Global().ReloadRoles(ctx) + if err != nil { + return + } + if err = locale.Global().ReloadResourceTranslations(ctx); err != nil { return } diff --git a/server/discovery/rest/internal/documents/compose.go b/server/discovery/rest/internal/documents/compose.go index de7843899..21406d932 100644 --- a/server/discovery/rest/internal/documents/compose.go +++ b/server/discovery/rest/internal/documents/compose.go @@ -22,7 +22,7 @@ type ( settings *sysTypes.AppSettings rbac interface { - SignificantRoles(res rbac.Resource, op string) (aRR, dRR []uint64) + SignificantRoles(ctx context.Context, res rbac.Resource, op string) (aRR, dRR []uint64, err error) } ac interface { @@ -168,7 +168,10 @@ func (d composeResources) Namespaces(ctx context.Context, limit uint, cur string }, } - doc.Security.AllowedRoles, doc.Security.DeniedRoles = d.rbac.SignificantRoles(ns, "read") + doc.Security.AllowedRoles, doc.Security.DeniedRoles, err = d.rbac.SignificantRoles(ctx, ns, "read") + if err != nil { + return + } rsp.Documents[i].Source = doc } @@ -255,7 +258,10 @@ func (d composeResources) Modules(ctx context.Context, namespaceID uint64, limit }, } - doc.Security.AllowedRoles, doc.Security.DeniedRoles = d.rbac.SignificantRoles(mod, "read") + doc.Security.AllowedRoles, doc.Security.DeniedRoles, err = d.rbac.SignificantRoles(ctx, mod, "read") + if err != nil { + return + } rsp.Documents[i].Source = doc } @@ -378,7 +384,10 @@ func (d composeResources) Records(ctx context.Context, namespaceID, moduleID uin // Values and value labels doc.Values, doc.ValueLabels = d.recordValues(ctx, rec, mod.Fields) - doc.Security.AllowedRoles, doc.Security.DeniedRoles = d.rbac.SignificantRoles(rec, "read") + doc.Security.AllowedRoles, doc.Security.DeniedRoles, err = d.rbac.SignificantRoles(ctx, rec, "read") + if err != nil { + return + } rsp.Documents[i].Source = doc } diff --git a/server/discovery/rest/internal/documents/system.go b/server/discovery/rest/internal/documents/system.go index 5b7760b93..d24b10569 100644 --- a/server/discovery/rest/internal/documents/system.go +++ b/server/discovery/rest/internal/documents/system.go @@ -21,7 +21,7 @@ type ( settings *types.AppSettings rbac interface { - SignificantRoles(res rbac.Resource, op string) (aRR, dRR []uint64) + SignificantRoles(ctx context.Context, res rbac.Resource, op string) (aRR, dRR []uint64, err error) } ac interface { @@ -92,7 +92,10 @@ func (d systemResources) Users(ctx context.Context, limit uint, cur string, user doc.Url = fmt.Sprintf("%s/admin/system/user/edit/%d", d.opt.CortezaDomain, u.ID) } - doc.Security.AllowedRoles, doc.Security.DeniedRoles = d.rbac.SignificantRoles(u, "read") + doc.Security.AllowedRoles, doc.Security.DeniedRoles, err = d.rbac.SignificantRoles(ctx, u, "read") + if err != nil { + return + } rsp.Documents[i].ID = u.ID rsp.Documents[i].Source = doc diff --git a/server/discovery/rest/internal/feed/resource.go b/server/discovery/rest/internal/feed/resource.go index a56116ca5..f0cace2f1 100644 --- a/server/discovery/rest/internal/feed/resource.go +++ b/server/discovery/rest/internal/feed/resource.go @@ -2,12 +2,13 @@ package feed import ( "context" + "time" + "github.com/cortezaproject/corteza/server/discovery/service" "github.com/cortezaproject/corteza/server/discovery/types" "github.com/cortezaproject/corteza/server/pkg/errors" "github.com/cortezaproject/corteza/server/pkg/filter" "github.com/cortezaproject/corteza/server/pkg/options" - "time" "github.com/cortezaproject/corteza/server/pkg/rbac" ) @@ -17,7 +18,7 @@ type ( opt options.DiscoveryOpt rbac interface { - SignificantRoles(res rbac.Resource, op string) (aRR, dRR []uint64) + SignificantRoles(ctx context.Context, res rbac.Resource, op string) (aRR, dRR []uint64, err error) } ac interface { diff --git a/server/federation/service/access_control.gen.go b/server/federation/service/access_control.gen.go index 7af080b2f..f752c29fd 100644 --- a/server/federation/service/access_control.gen.go +++ b/server/federation/service/access_control.gen.go @@ -22,9 +22,9 @@ import ( type ( rbacService interface { Can(rbac.Session, string, rbac.Resource) bool - Trace(rbac.Session, string, rbac.Resource) *rbac.Trace + Trace(rbac.Session, string, rbac.Resource) (*rbac.Trace, error) Grant(context.Context, ...*rbac.Rule) error - FindRulesByRoleID(roleID uint64) (rr rbac.RuleSet) + FindRulesByRoleID(ctx context.Context, roleID uint64) (rr rbac.RuleSet, err error) } accessControl struct { @@ -120,11 +120,16 @@ func (svc accessControl) Trace(ctx context.Context, userID uint64, roles []uint6 return nil, fmt.Errorf("no roles specified") } + var auxTrace *rbac.Trace session := rbac.ParamsToSession(ctx, userID, roles...) for _, res := range resources { r := res.RbacResource() for op := range rbacResourceOperations(r) { - ee = append(ee, svc.rbac.Trace(session, op, res)) + auxTrace, err = svc.rbac.Trace(session, op, res) + if err != nil { + return + } + ee = append(ee, auxTrace) } } @@ -287,7 +292,7 @@ func (svc accessControl) FindRulesByRoleID(ctx context.Context, roleID uint64) ( return nil, AccessControlErrNotAllowedToSetPermissions() } - return svc.rbac.FindRulesByRoleID(roleID), nil + return svc.rbac.FindRulesByRoleID(ctx, roleID) } // CanManageNode checks if current user can manage federation node diff --git a/server/pkg/options/options.gen.go b/server/pkg/options/options.gen.go index 9eb9c82aa..00863324f 100644 --- a/server/pkg/options/options.gen.go +++ b/server/pkg/options/options.gen.go @@ -52,11 +52,18 @@ type ( } RbacOpt struct { - Log bool `env:"RBAC_LOG"` - ServiceUser string `env:"RBAC_SERVICE_USER"` - BypassRoles string `env:"RBAC_BYPASS_ROLES"` - AuthenticatedRoles string `env:"RBAC_AUTHENTICATED_ROLES"` - AnonymousRoles string `env:"RBAC_ANONYMOUS_ROLES"` + Log bool `env:"RBAC_LOG"` + MaxIndexSize int `env:"RBAC_MAX_INDEX_SIZE"` + Synchronous bool `env:"RBAC_SYNCHRONOUS"` + ReindexStrategy string `env:"RBAC_REINDEX_STRATEGY"` + DecayFactor float64 `env:"RBAC_DECAY_FACTOR"` + DecayInterval time.Duration `env:"RBAC_DECAY_INTERVAL"` + CleanupInterval time.Duration `env:"RBAC_CLEANUP_INTERVAL"` + IndexFlushInterval time.Duration `env:"RBAC_INDEX_FLUSH_INTERVAL"` + ServiceUser string `env:"RBAC_SERVICE_USER"` + BypassRoles string `env:"RBAC_BYPASS_ROLES"` + AuthenticatedRoles string `env:"RBAC_AUTHENTICATED_ROLES"` + AnonymousRoles string `env:"RBAC_ANONYMOUS_ROLES"` } SCIMOpt struct { @@ -378,6 +385,13 @@ func HttpServer() (o *HttpServerOpt) { // This function is auto-generated func Rbac() (o *RbacOpt) { o = &RbacOpt{ + MaxIndexSize: -1, + Synchronous: false, + ReindexStrategy: "", + DecayFactor: 0.9, + DecayInterval: time.Minute * 30, + CleanupInterval: time.Minute * 31, + IndexFlushInterval: time.Minute * 35, BypassRoles: "super-admin", AuthenticatedRoles: "authenticated", AnonymousRoles: "anonymous", diff --git a/server/system/service/access_control.gen.go b/server/system/service/access_control.gen.go index c24d69cbf..023fbb9f1 100644 --- a/server/system/service/access_control.gen.go +++ b/server/system/service/access_control.gen.go @@ -22,9 +22,9 @@ import ( type ( rbacService interface { Can(rbac.Session, string, rbac.Resource) bool - Trace(rbac.Session, string, rbac.Resource) *rbac.Trace + Trace(rbac.Session, string, rbac.Resource) (*rbac.Trace, error) Grant(context.Context, ...*rbac.Rule) error - FindRulesByRoleID(roleID uint64) (rr rbac.RuleSet) + FindRulesByRoleID(ctx context.Context, roleID uint64) (rr rbac.RuleSet, err error) } accessControl struct { @@ -120,11 +120,16 @@ func (svc accessControl) Trace(ctx context.Context, userID uint64, roles []uint6 return nil, fmt.Errorf("no roles specified") } + var auxTrace *rbac.Trace session := rbac.ParamsToSession(ctx, userID, roles...) for _, res := range resources { r := res.RbacResource() for op := range rbacResourceOperations(r) { - ee = append(ee, svc.rbac.Trace(session, op, res)) + auxTrace, err = svc.rbac.Trace(session, op, res) + if err != nil { + return + } + ee = append(ee, auxTrace) } } @@ -604,7 +609,7 @@ func (svc accessControl) FindRulesByRoleID(ctx context.Context, roleID uint64) ( return nil, AccessControlErrNotAllowedToSetPermissions() } - return svc.rbac.FindRulesByRoleID(roleID), nil + return svc.rbac.FindRulesByRoleID(ctx, roleID) } // CanReadApplication checks if current user can read application