-
Notifications
You must be signed in to change notification settings - Fork 881
feat: Add RBAC package for managing user permissions #929
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
Conversation
Just testing out some ideas. The code is far from finished, and very sloppy. Committing to share it to start conversations
Playing around with helper functions to make life easy
- Cleanup some code too
- Add some docs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should change the PR title to something like: feat: Add RBAC package for managing user permissions
. This is a big deal!
query, err := rego.New( | ||
// allowed is the `allow` field from the prepared query. This is the field to check if authorization is | ||
// granted. | ||
rego.Query("allowed = data.authz.allow"), | ||
rego.Module("policy.rego", policy), | ||
).PrepareForEval(ctx) | ||
|
||
if err != nil { | ||
return nil, xerrors.Errorf("prepare query: %w", err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we do this in init
and panic if an error occurs? Then users don't have to hold a struct, and can just call Authorize
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking about that, and I just hate init()
functions. I figure we can put the init()
anywhere if it's a pain to pass around, meaning we can put the init in coderd
somewhere too. So we can decide to init()
once we use this.
We will need more PRs for integration, and that is when I think we can make that call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough fair enough
Authorize
stub function
What this does
Authorize
is the stub function that will be called externally. This is the main entry-point for the package.#715 , #716, #718, #720, #725
Making a user with given roles
See example_test.go to see how to add multiple roles to a user.
SubjectTODO
is a placeholder, and roles can be serialized for db storage. Serialization is not implemented until required.Using
Authorize
Authorize
is a function on anauthorizer
. For now, the authorizer just precompiles a builtin rego policy.For example, to "Read all workspaces in the org
Coder
", we create aResourceWorkspace
owned by the orgCoder
To read all workspaces across the whole product, we omit the owner id since we want to include the set of all workspaces.
Making a new Role
Most roles are just
*
and easy to write. One example of enumerating certain permissions uses a helper function to keep the role as few LoC:coder/coderd/authz/role.go
Lines 40 to 47 in f5d95ef
The helper func omits negative permissions, but those can be defined explicitly. Note that no builtin roles require negative permissions, and are only needed for edge cases that we don't need to support in MVP.
Benchmarks
736 permission checks were done in <300ms. I think this is fast enough.
The rego handles role expansion, which is kinda neat.