-
Notifications
You must be signed in to change notification settings - Fork 46
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
Permission subset checks when creating roles #64
Conversation
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.
@billkalter added few comments.
-
spent enough time in cross checking the new overlaps() and isSubsetof() condition implementations with my own examples as well as with Subset Evaluator Visit() cases. I think your SubsetEvaluatorTest covered all the type permutations of <Condition, Condition>, and I found nothing in there to be added to disprove any case.
-
verified overlaps() and isSubsetOf() implementations for comparison, like and contains conditions.
-
verified the Subset Evaluator (and Distinct and Inverse Evaluators which are used with in it).
-
verified the tests.
Comparable rValue; | ||
|
||
if (lObject instanceof Number) { | ||
if (!(rObject instanceof Number)) { |
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.
Minor: if (lObject instance Number && rObject instanceof Number ) and leaving false case to the last else.
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.
It's a very minor efficiency gain, but if lObject
is a Number
then the next condition, which evaluates for lObject instanceof String
, is always false, so it saves the unnecessary condition check.
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 though its easy to read the code that way with only 2 if cases and one else for anything else.
@SuppressWarnings("unchecked") | ||
@Override | ||
public boolean isSubsetOf(ComparisonCondition condition) { | ||
Object lObject = getValue(); |
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.
Minor: @why not just use _value directly just to be consistent with the overlaps() implementation or the other way around.
Same with the getcomparision() usage line: 101
*/ | ||
@Override | ||
public Boolean visit(AndCondition left, Condition right) { | ||
return false; |
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 the comments are crystal clear that these methods are not called anywhere.....But I feel like it's better to throw NotImplementedException or UnsupportedOperationException instead of returning false values.
Applies to all the unused methods in DistinctEvaluator and InverseEvaluator.
"role", "any-role"), | ||
new PrintWriter(out)); | ||
|
||
assertEquals(out.toString(), "Not authorized\n"); |
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.
question here about the /role design - we are verifying that the API key created has no permission to view some random role, which is good but do you think it should have permission to view its own roles? the test gives same result even with "insufficient-role" on line 100. /api-key view is just showing the roles associated with it, (but is there any other way to see the permissions for a api-key)
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.
Interesting point.
"action", "update", | ||
"role", "new-role", | ||
"permit", "sor|update|if({..,\"foo\":\"bar\"})", | ||
"permit", "queue|post|*"), |
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.
Just a thought about the subset permission - even though A is subset of A, do we have any reason to prevent creating a new role with the different name with the same permission(s)? One advantage in preventing that is we can reuse the existing roles instead of just growing with the duplicate roles with the same permissions. Also, why would a user with ApiKey with sor|* permissions create a new role with the same sor|* to hand over to the other teams?
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 agree that it opens the door for redundant roles, but I don't think it should be prohibited. For example, it may be that the new role today shares the same permissions, but by creating the new role it can be modified in the future without needing to be concerned about either unintended consequences of modifying the existing role or hunting down all users with the reused role and re-assigning their roles in the future.
|
||
@Override | ||
public Boolean visit(EqualCondition right, Void context) { | ||
return false; |
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.
similar comment as the other one - should we throw a UnsupportedOperationException for these cases which are not implemented in the default Left Visitor? The subclasses are implementing if they are needed, otherwise its better to know I think.
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.
In this case it's not that they're unsupported, it's a convenience for sub-classes. The matrix of condition pairs which have meaningful subset evaluations is somewhat sparse, so by providing defaults of false
the subsets only need to override those subsets which could potentially return true
.
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.
yeah - agreed. I'm fine with leaving the default implementation returning false and subclasses only implementing if they want to return true, specially considering the sparseness as you mentioned.
Also we need some rebasing... |
… role grants restrict to caller's permissions
@sujithvaddi Addressed feedback and rebased |
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.
Github Issue
63
What Are We Doing Here?
This pull request contains the following overarching changes, also each of these contains several smaller details to make the overall implementation possible:
Condition
is a subset of anotherCondition
. For example,like("ge*us")
is a subset oflike("g*s")
.sor|if(in("read","update","create_table","drop_table"))|if({..,"client":+})
impliessor|if(in("read","update"))|if({..,"client":"testclient"})
, since for all permissions p if the latter implies p the former also implies p.How to Test and Verify
Risk
The main risk associated with this ticket is potentially breaking the ability to create and update roles or a regression on evaluating permissions.
Level
Somewhere between
Medium
andHigh
. This change affects core Emo functionality -- security -- but does not put data at risk.Required Testing
Manual
Risk Summary
In addition to the risks mentioned above and in the corresponding ticket, the biggest risk is in an incorrect implementation of condition subset and permission implication checks. Any issues where a user can grant wider permissions than he has is a potential security hole.
Code Review Checklist
Tests are included. If not, make sure you leave us a line or two for the reason.
Pulled down the PR and performed verification of at least being able to
build and run.
Well documented, including updates to any necessary markdown files. When
we inevitably come back to this code it will only take hours to figure out, not
days.
Consistent/Clear/Thoughtful? We are better with this code. We also aren't
a victim of rampaging consistency, and should be using this course of action.
We don't have coding standards out yet for this project, so please make sure to address any feedback regarding STYLE so the codebase remains consistent.
PR has a valid summary, and a good description.