Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[Question] Optimization for IAM-like policies #1688

Open

Description

Hello,
I'm trying to design an AWS IAM like system where we have a set of resources which you can "allow" or "deny" for certain roles and users.

My Initial was this:

Initial Option: Model
[request_definition]
r = sub, dom, obj, act
[policy_definition]
p = sub, obj, act, eft
[role_definition]
g = _, _, _ # Roles permission
g2 = _, _ # Data group
g3 = _, _ # Action group
[policy_effect]
# Allow as soon as there one rule allowing
#e = some(where (p.eft == allow))
#Deny as soon as there is one rule denying
e = some(where (p.eft == allow)) && !some(where (p.eft == deny))
[matchers]
m = g3(r.act, p.act) && g(r.sub, p.sub, r.dom) && keyMatch5(r.obj, p.obj)
Initial Option: Policy
# sub/perm, resource, action
p, perm:instance:list, /instance, READ, allow
p, perm:instance:delete, /instance/{name}, DELETE, allow
p, perm:instance:describe, /instance/{name}, READ, allow
p, perm:instance:create, /instance/{name}, POST, allow
p, perm:service:list, /service, READ, allow
p, perm:proxy:read, /proxy/{name}/*, READ, allow
p, perm:proxy:write, /proxy/{name}/*, WRITE, allow
p, perm:proxy:crashes, /proxy/{name}/crashes, READ, allow
p, block:proxy:crashes, /proxy/{name}/crashes, READ, deny
# Adding wild cards in the group does seem to add a lot of time when users grow
#
#g, role:instance:admin, perm:instance:*, *
#g, role:service:admin, perm:service:*, *
#g, role:proxy:admin, perm:proxy:*, *
#
g, role:instance:admin, perm:instance:list, *
g, role:instance:admin, perm:instance:delete, *
g, role:instance:admin, perm:instance:describe, *
g, role:instance:admin, perm:instance:create, *
g, role:service:admin, perm:service:list, *
g, role:proxy:admin, perm:proxy:read, *
g, role:proxy:admin, perm:proxy:write, *
g, role:instance:viewer, perm:instance:list, *
g, role:instance:viewer, perm:instance:describe, *
g, role:service:viewer, perm:service:list, *
g, role:proxy:viewer, perm:proxy:read, *
g, role:proxy:viewer, block:proxy:crashes, *
g, user:admin, role:instance:admin, *
g, user:admin, role:service:admin, *
g, user:admin, role:proxy:admin, *
g, user:alice, role:instance:admin, orgA
g, user:alice, role:service:admin, orgA
g, user:alice, role:proxy:admin, orgA
g, user:alice, role:instance:viewer, orgB
g, user:alice, role:service:viewer, orgB
g, user:alice, role:proxy:viewer, orgB
g, user:bob, role:instance:viewer, orgB
g, user:bob, role:service:viewer, orgB
g, user:bob, role:proxy:viewer, orgB
g, user:nancy, role:proxy:admin, orgA
g3, POST, WRITE
g3, PUT, WRITE
g3, PATCH, WRITE
g3, DELETE, WRITE
g3, OPTIONS, READ
g3, HEAD, READ
g3, GET, READ
g3, READ, ANY
g3, WRITE, ANY

I find it's not ideal because I would need to duplicate every p to have one for deny and one for allow.

So My second option is this:

Tentative Option; Model
[request_definition]
r = sub, dom, obj, act
[policy_definition]
p = sub, obj, eft, dom
[role_definition]
g = _, _, _ # Roles permission
g2 = _, _, _ # Data group
g3 = _, _ # Action group
[policy_effect]
# Allow as soon as there one rule allowing
#e = some(where (p.eft == allow))
#Deny as soon as there is one rule denying
e = some(where (p.eft == allow)) && !some(where (p.eft == deny))
[matchers]
m = globMatch(r.dom, p.dom) && g(r.sub, p.sub, r.dom) && g2(r.obj, p.obj, r.act)
Tentative Option; Policy
#
p, role:instance:admin, perm:instance:list, allow, *
p, role:instance:admin, perm:instance:delete, allow, *
p, role:instance:admin, perm:instance:describe, allow, *
p, role:instance:admin, perm:instance:create, allow, *
p, role:service:admin, perm:service:list, allow, *
p, role:proxy:admin, perm:proxy:read, allow, *
p, role:proxy:admin, perm:proxy:write, allow, *
p, role:instance:viewer, perm:instance:list, allow, *
p, role:instance:viewer, perm:instance:describe, allow, *
p, role:service:viewer, perm:service:list, allow, *
p, role:proxy:viewer, perm:proxy:read, allow, *
p, role:proxy:viewer, perm:proxy:crashes, deny, *
# sub/perm, resource, action
g2, /instance, perm:instance:list, GET
g2, /instance/{name}, perm:instance:delete, DELETE
g2, /instance/{name}, perm:instance:describe, GET
g2, /instance/{name}, perm:instance:create, POST
g2, /service, perm:service:list, GET
g2, /proxy/{name}/*, perm:proxy:read, GET
g2, /proxy/{name}/*, perm:proxy:write, POST
g2, /proxy/{name}/crashes, perm:proxy:crashes, GET
g, user:admin, role:instance:admin, *
g, user:admin, role:service:admin, *
g, user:admin, role:proxy:admin, *
g, user:alice, role:instance:admin, orgA
g, user:alice, role:service:admin, orgA
g, user:alice, role:proxy:admin, orgA
g, user:alice, role:instance:viewer, orgB
g, user:alice, role:service:viewer, orgB
g, user:alice, role:proxy:viewer, orgB
g, user:bob, role:instance:viewer, orgB
g, user:bob, role:service:viewer, orgB
g, user:bob, role:proxy:viewer, orgB
g, user:nancy, role:proxy:admin, orgA

Both work, but the first one is significantly (at least 8 times) faster for a few thousand checks. Is there a way for me to optimize option 2 or am I better off going with my initial design?

Metadata

Metadata

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      AltStyle によって変換されたページ (->オリジナル) /