3
0

Hook up reworked rbac svc

This commit is contained in:
Tomaž Jerman
2024-11-26 12:50:24 +01:00
parent 7e2ba8c08f
commit 3fdaafd8a1
14 changed files with 291 additions and 98 deletions

View File

@@ -220,6 +220,60 @@
# Default: <no value>
# RBAC_LOG=<no value>
###############################################################################
# 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: <no value>
# RBAC_MAX_INDEX_SIZE=<no value>
###############################################################################
# Synchronous lets us make all the procedures synchronous for ease of testing
# This should always be false in production
# Type: bool
# Default: <no value>
# RBAC_SYNCHRONOUS=<no value>
###############################################################################
# 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: <no value>
# RBAC_DECAY_FACTOR=<no value>
###############################################################################
# Decay interval controls how fast the decay factor is applied to the index key.
# Type: time.Duration
# Default: <no value>
# RBAC_DECAY_INTERVAL=<no value>
###############################################################################
# Cleanup interval controls when unused/low-scored index items should be yanked out of the index counter.
# Type: time.Duration
# Default: <no value>
# RBAC_CLEANUP_INTERVAL=<no value>
###############################################################################
# [IMPORTANT]
# ====
# Unused, will be added when state preservation is implemented.
# ====
# Type: time.Duration
# Default: <no value>
# RBAC_INDEX_FLUSH_INTERVAL=<no value>
###############################################################################
# Type: string
# Default: <no value>

View File

@@ -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)
}

View File

@@ -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"

View File

@@ -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

View File

@@ -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 }}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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 {

View File

@@ -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

View File

@@ -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",

View File

@@ -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