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

Role Manager performance / scaling issue #893

Closed
dahu33 opened this issue Sep 28, 2021 · 3 comments
Closed

Role Manager performance / scaling issue #893

dahu33 opened this issue Sep 28, 2021 · 3 comments
Assignees
Labels

Comments

@dahu33
Copy link
Contributor

dahu33 commented Sep 28, 2021

Want to prioritize this issue? Try:

issuehunt-to-marktext


Is your feature request related to a problem? Please describe.

Using the standard RBAC model:

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act

The (*RoleManager).HasLink function is called N time, where N is the the number of unique subjects found in the policies. While this may work ok if the relationships are stored in memory, it just doesn't scale at all if the relationships are stored in an external datastore.

Examples with a model containing 100 unique subjects that all have at least one policy:

  • our custom RoleManager that stores relationship in PostgreSQL would make 99 SQL queries (one per (*RoleManager).HasLink function call) for each (*Enforcer).Enforce call.
  • the https://github.com/casbin/okta-role-manager would make 99 Okta API calls (one per (*RoleManager).HasLink function call) for each (*Enforcer).Enforce call.
  • the https://github.com/casbin/auth0-role-manager would make 99 Auth0 API calls (one per (*RoleManager).HasLink function call) for each (*Enforcer).Enforce call.
  • etc...

As you can see with the examples above, this cannot really scale past a few unique subjects and I'm surprised that this issue hasn't been raised before.

Describe the solution you'd like
Ideally, when enforcing a policy, instead of calling (*RoleManager).HasLink for each unique subjects, the (*RoleManager).GetRoles function should be called to get all the relations of a subject in one shot.

@casbin-bot
Copy link
Member

@tangyang9464 @closetool @sagilio

@tangyang9464
Copy link
Member

@dahu33 I have a few opinions and questions

  1. I don't konw what means about call GetRoles to get all the relations of a subject in one shot.. Below is the code that calls HasLink each time in funtion g(r.sub, p.sub). Plz indicate how you think the code should be improved
    func GenerateGFunction(rm rbac.RoleManager) govaluate.ExpressionFunction {
    memorized := map[string]bool{}
    return func(args ...interface{}) (interface{}, error) {
    name1 := args[0].(string)
    name2 := args[1].(string)
    key := ""
    for index := 0; index < len(args); index++ {
    key += ";" + fmt.Sprintf("%v", args[index])
    }
    v, found := memorized[key]
    if found {
    return v, nil
    }
    if rm == nil {
    v = name1 == name2
    } else if len(args) == 2 {
    v, _ = rm.HasLink(name1, name2)
    } else {
    domain := args[2].(string)
    v, _ = rm.HasLink(name1, name2, domain)
    }
    memorized[key] = v
    return v, nil
    }
    }
  2. I think there are some problems in the implementation of these two manager (auth0, okta), and they cannot be used as a reference.
  3. I don't know how your custom manager is implemented. I think there is no logic problem with every enforce call to haslink. Maybe the relationship should be loaded into memory when setting up the manager?

Looking forward to your reply!

@hsluoyz hsluoyz removed the question label Sep 28, 2021
@hsluoyz
Copy link
Member

hsluoyz commented Nov 21, 2022

@dahu33 yes, the built-in role manager uses cache to achieve fast speed in HasLink(). okta-role-manager and auth0-role-manager may have a bad implementation and queries DB each time. They should be modified to cache the get roles result and serves the HasLink() query locally in memory, so they will be fast.

Actually okta-role-manager and auth0-role-manager are more of examples. If you decide to use them, we can further polish its code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants