Files
upstream-corteza/server/pkg/rbac/ruleset_checks.go
upstream-mirror 7e385fc126
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
snapshot of https://github.com/cortezaproject/corteza.git (2024.9.x, 2026-09-18; blobs > 131072B omitted)
2026-09-18 01:22:23 +05:00

117 lines
3.2 KiB
Go

package rbac
// function checks all given rules
//
// - indexRules are rules optimized for quick lookup.
// The trie data structure approach is used to optimize lookups and reduce
// memory consumption.
//
// - rolesByKind are roles optimized for quick lookup
// roles are grouped by kind and each kind contains fast-lookup (map[role-id]bool)
//
// - op and res represent operation and resource that are checked
//
// - trace is optional; when not nil, function will update trace struct
// with information as it traverses and checks the rules
func check(indexedRules *ruleIndex, rolesByKind partRoles, op, res string, trace *Trace) Access {
baseTraceInfo(trace, res, op, rolesByKind)
if member(rolesByKind, AnonymousRole) && len(rolesByKind) > 1 {
// Integrity check; when user is member of anonymous role
// should not be member of any other type of role
return resolve(trace, Deny, failedIntegrityCheck)
}
if member(rolesByKind, BypassRole) {
// if user has at least one bypass role, we allow access
return resolve(trace, Allow, bypassRoleMembership)
}
if indexedRules.empty() {
// no rules to check
return resolve(trace, Inherit, noRules)
}
var (
match *Rule
allowed bool
)
//
if trace != nil {
// from this point on, there is a chance trace (if set)
// will contain some rules.
//
// Stable order needs to be ensured: there is no production
// code that relies on that but tests might fail and API
// response would be flaky.
defer sortTraceRules(trace)
}
// Priority is important here. We want to have
// stable RBAC check behaviour and ability
// to override allow/deny depending on how niche the role (type) is:
// - context (eg owners) are more niche than common
// - rules for common roles are more important than authenticated and anonymous role types
//
// Note that bypass roles are intentionally ignored here; if user is member of
// bypass role there is no need to check any other rule
for _, kind := range []roleKind{ContextRole, CommonRole, AuthenticatedRole, AnonymousRole} {
// not a member of any role of this kind
if len(rolesByKind[kind]) == 0 {
continue
}
// reset allowed to false
// for each role kind
allowed = false
for r := range rolesByKind[kind] {
match = indexedRules.matchingRule(r, op, res)
// check all rules for each role the security-context
if match == nil {
// no rules match
continue
}
if trace != nil {
// if trace is enabled, append
// each matching rule
trace.Rules = append(trace.Rules, match)
}
if match.Access == Deny {
// if we stumble upon Deny we short-circuit the check
return resolve(trace, Deny, "")
}
if match.Access == Allow {
// allow rule found, we need to check rules on other roles
// before we allow it
allowed = true
}
}
if allowed {
// at least one of the roles (per role type) in the security context
// allows operation on a resource
return resolve(trace, Allow, "")
}
}
// No rule matched
return resolve(trace, Inherit, noMatch)
}
// at least one of the roles must be set to true
func member(r partRoles, k roleKind) bool {
for _, is := range r[k] {
if is {
return true
}
}
return false
}