diff --git a/automation/service/access_control.gen.go b/automation/service/access_control.gen.go index 70edbf321..7f9d65ca7 100644 --- a/automation/service/access_control.gen.go +++ b/automation/service/access_control.gen.go @@ -80,6 +80,10 @@ func (svc accessControl) Trace(ctx context.Context, userID uint64, roles []uint6 if len(rr) > 0 { resources = make([]rbac.Resource, 0, len(rr)) for _, r := range rr { + if err = rbacResourceValidator(r); err != nil { + return nil, fmt.Errorf("can not use resource %q: %w", r, err) + } + resources = append(resources, rbac.NewResource(r)) } } else { @@ -451,9 +455,9 @@ func rbacWorkflowResourceValidator(r string, oo ...string) error { // // This function is auto-generated func rbacComponentResourceValidator(r string, oo ...string) error { - if !strings.HasPrefix(r, types.ComponentResourceType) { + if r != types.ComponentResourceType+"/" { // expecting resource to always include path - return fmt.Errorf("invalid resource type") + return fmt.Errorf("invalid component resource, expecting " + types.ComponentResourceType + "/") } defOps := rbacResourceOperations(r) diff --git a/codegen/assets/templates/gocode/rbac/$component_access_control.go.tpl b/codegen/assets/templates/gocode/rbac/$component_access_control.go.tpl index c1003d15f..975d11f42 100644 --- a/codegen/assets/templates/gocode/rbac/$component_access_control.go.tpl +++ b/codegen/assets/templates/gocode/rbac/$component_access_control.go.tpl @@ -79,6 +79,10 @@ func (svc accessControl) Trace(ctx context.Context, userID uint64, roles []uint6 if len(rr) > 0 { resources = make([]rbac.Resource, 0, len(rr)) for _, r := range rr { + if err = rbacResourceValidator(r); err != nil { + return nil, fmt.Errorf("can not use resource %q: %w", r, err) + } + resources = append(resources, rbac.NewResource(r)) } } else { @@ -256,10 +260,17 @@ func rbacResourceOperations(r string) map[string]bool { // // This function is auto-generated func {{ .funcName }}(r string, oo ...string) error { + {{- if .references }} if !strings.HasPrefix(r, {{ .const }}) { // expecting resource to always include path return fmt.Errorf("invalid resource type") } + {{ else }} + if r != {{ .const }} + "/" { + // expecting resource to always include path + return fmt.Errorf("invalid component resource, expecting " + {{ .const }} + "/") + } + {{ end }} defOps := rbacResourceOperations(r) for _, o := range oo { diff --git a/compose/service/access_control.gen.go b/compose/service/access_control.gen.go index 9049f8a6d..0ea74273f 100644 --- a/compose/service/access_control.gen.go +++ b/compose/service/access_control.gen.go @@ -74,12 +74,16 @@ func (svc accessControl) Trace(ctx context.Context, userID uint64, roles []uint6 } var ( - resources = svc.Resources() + resources []rbac.Resource members systemTypes.RoleMemberSet ) if len(rr) > 0 { resources = make([]rbac.Resource, 0, len(rr)) for _, r := range rr { + if err = rbacResourceValidator(r); err != nil { + return nil, fmt.Errorf("can not use resource %q: %w", r, err) + } + resources = append(resources, rbac.NewResource(r)) } } else { @@ -981,9 +985,9 @@ func rbacRecordResourceValidator(r string, oo ...string) error { // // This function is auto-generated func rbacComponentResourceValidator(r string, oo ...string) error { - if !strings.HasPrefix(r, types.ComponentResourceType) { + if r != types.ComponentResourceType+"/" { // expecting resource to always include path - return fmt.Errorf("invalid resource type") + return fmt.Errorf("invalid component resource, expecting " + types.ComponentResourceType + "/") } defOps := rbacResourceOperations(r) diff --git a/federation/service/access_control.gen.go b/federation/service/access_control.gen.go index ac983e306..c6ea8701f 100644 --- a/federation/service/access_control.gen.go +++ b/federation/service/access_control.gen.go @@ -80,6 +80,10 @@ func (svc accessControl) Trace(ctx context.Context, userID uint64, roles []uint6 if len(rr) > 0 { resources = make([]rbac.Resource, 0, len(rr)) for _, r := range rr { + if err = rbacResourceValidator(r); err != nil { + return nil, fmt.Errorf("can not use resource %q: %w", r, err) + } + resources = append(resources, rbac.NewResource(r)) } } else { @@ -514,9 +518,9 @@ func rbacSharedModuleResourceValidator(r string, oo ...string) error { // // This function is auto-generated func rbacComponentResourceValidator(r string, oo ...string) error { - if !strings.HasPrefix(r, types.ComponentResourceType) { + if r != types.ComponentResourceType+"/" { // expecting resource to always include path - return fmt.Errorf("invalid resource type") + return fmt.Errorf("invalid component resource, expecting " + types.ComponentResourceType + "/") } defOps := rbacResourceOperations(r) diff --git a/pkg/rbac/ruleset_checks.go b/pkg/rbac/ruleset_checks.go index cf4a64038..360d13569 100644 --- a/pkg/rbac/ruleset_checks.go +++ b/pkg/rbac/ruleset_checks.go @@ -15,7 +15,7 @@ import ( // // - op and res represent operation and resource that are checked // -// - trace is optional; when not nil, function will update trace stuct +// - trace is optional; when not nil, function will update trace struct // with information as it traverses and checks the rules // func check(indexedRules OptRuleSet, rolesByKind partRoles, op, res string, trace *Trace) Access { @@ -82,7 +82,7 @@ func check(indexedRules OptRuleSet, rolesByKind partRoles, op, res string, trace } // check all rules for each role the security-context - if match = findRuleByResOp(rr, op, res); match.Access == Inherit { + if match = findRuleByResOp(rr, op, res); match == nil { // no rules match continue } @@ -136,7 +136,7 @@ func findRuleByResOp(set RuleSet, op, res string) *Rule { } } - return &Rule{Access: Inherit} + return nil } // at least one of the roles must be set to true diff --git a/pkg/rbac/ruleset_checks_test.go b/pkg/rbac/ruleset_checks_test.go index d52a7018d..944bb4a8b 100644 --- a/pkg/rbac/ruleset_checks_test.go +++ b/pkg/rbac/ruleset_checks_test.go @@ -313,6 +313,11 @@ func Test_checkRulesByResource(t *testing.T) { for _, c := range cc { t.Run(c.res, func(t *testing.T) { a := findRuleByResOp(c.set, c.op, c.res) + + if a == nil { + a = InheritRule(0, "", "") + } + require.Equal(t, c.exp.String(), a.Access.String()) }) } diff --git a/system/service/access_control.gen.go b/system/service/access_control.gen.go index 1c073fcd3..008bb73b1 100644 --- a/system/service/access_control.gen.go +++ b/system/service/access_control.gen.go @@ -10,7 +10,6 @@ import ( "context" "fmt" "github.com/cortezaproject/corteza-server/pkg/actionlog" - internalAuth "github.com/cortezaproject/corteza-server/pkg/auth" "github.com/cortezaproject/corteza-server/pkg/rbac" "github.com/cortezaproject/corteza-server/system/types" systemTypes "github.com/cortezaproject/corteza-server/system/types" @@ -81,6 +80,10 @@ func (svc accessControl) Trace(ctx context.Context, userID uint64, roles []uint6 if len(rr) > 0 { resources = make([]rbac.Resource, 0, len(rr)) for _, r := range rr { + if err = rbacResourceValidator(r); err != nil { + return nil, fmt.Errorf("can not use resource %q: %w", r, err) + } + resources = append(resources, rbac.NewResource(r)) } } else { @@ -91,7 +94,7 @@ func (svc accessControl) Trace(ctx context.Context, userID uint64, roles []uint6 if userID != 0 { if len(roles) > 0 { // should be prevented on the client - return nil, fmt.Errorf("userID and roles parameters are mutually exclusive") + return nil, fmt.Errorf("userID and roles are mutually exclusive") } members, _, err = svc.store.SearchRoleMembers(ctx, systemTypes.RoleMemberFilter{UserID: userID}) @@ -102,11 +105,6 @@ func (svc accessControl) Trace(ctx context.Context, userID uint64, roles []uint6 for _, m := range members { roles = append(roles, m.RoleID) } - - // make sure we append all "authenticated" roles - for _, r := range internalAuth.AuthenticatedRoles() { - roles = append(roles, r.ID) - } } if len(roles) == 0 { @@ -1871,9 +1869,9 @@ func rbacDalSensitivityLevelResourceValidator(r string, oo ...string) error { // // This function is auto-generated func rbacComponentResourceValidator(r string, oo ...string) error { - if !strings.HasPrefix(r, types.ComponentResourceType) { + if r != types.ComponentResourceType+"/" { // expecting resource to always include path - return fmt.Errorf("invalid resource type") + return fmt.Errorf("invalid component resource, expecting " + types.ComponentResourceType + "/") } defOps := rbacResourceOperations(r)