-
Notifications
You must be signed in to change notification settings - Fork 3
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
Enforcing Organization and Role API Permissions #127
base: develop
Are you sure you want to change the base?
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.
Some questions. Looks nice though.
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 love the test coverage and a lot of the additions. I have some chores and open questions that I think should be addressed before I'm ready to approve this
services/api/src/middleware.py
Outdated
logging.warning(f"User info: {user_info}") | ||
if user_info: | ||
environ[ENVIRON_USER_KEY] = EnvironWithoutOrg(user_info) | ||
# environ["user_info"] = user_info |
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: is there value in keeping this commented out code around, or can we remove it?
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.
removed
services/api/src/rsu_querycounts.py
Outdated
|
||
rsu_dict = get_organization_rsus(request.environ["organization"]) | ||
data, code = query_rsu_counts_mongo(rsu_dict, message, start, end) | ||
rsu_dict = get_organization_rsus(permission_result) |
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.
rsu_dict = get_organization_rsus(permission_result) | |
rsu_dict = get_organization_rsus(permission_result, []) |
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.
updated to pass in qualified_orgs
services/api/src/rsu_querymsgfwd.py
Outdated
@@ -96,12 +112,11 @@ def get(self): | |||
logging.debug("RsuQueryMsgFwd GET requested") | |||
# Schema check for arguments | |||
schema = RsuQueryMsgFwdSchema() | |||
user: EnvironWithOrg = request.environ[ENVIRON_USER_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.
chore: remove unused variable
user: EnvironWithOrg = request.environ[ENVIRON_USER_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.
removed, along with similar unused variables
services/api/src/rsu_ssm_srm.py
Outdated
@@ -143,6 +143,8 @@ def options(self): | |||
def get(self): | |||
logging.debug("RsuSsmSrmData GET requested") | |||
data = [] | |||
|
|||
# TODO: Filter by RSUs within authenticated organizations |
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(non-blocking): How/when do we plan to address this TODO? Is there a work item to track it so it doesn't get forgotten?
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.
went ahead and addressed this now!
services/api/src/rsuinfo.py
Outdated
logging.debug("RsuInfo GET requested") | ||
return (get_rsu_data(request.environ["organization"]), 200, self.headers) | ||
return (get_rsu_data(permission_result), 200, self.headers) |
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: I'm seeing calls to get_rsu_data
mostly without providing the positional arg of qualified_orgs
. Should we be passing an empty list in for qualified_orgs
everywhere, remove the qualified_orgs
arg, or is there another approach that makes most sense?
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.
get_rsu_info was updated to take in only what it needed, the user object and qualified organizations list
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.
A few questions so far
@@ -87,15 +109,22 @@ def modify_notification(notification_spec): | |||
failed_value = failed_value.replace(")", '"') | |||
failed_value = failed_value.replace("=", " = ") | |||
logging.error(f"Exception encountered: {failed_value}") | |||
return {"message": failed_value}, 500 | |||
raise InternalServerError(failed_value) from e | |||
except InternalServerError: |
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.
If we're not doing anything with this particular error, do we need a called out "except" for it?
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.
This is an oddity within the python try/except, while having a very broad Exception catcher at the end. Without the additional except IntersectionServerError: pass, then raise InternalServerError is caught by the last clause of the try catch. The real issue here is that the last except clause is way too broad
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 just updated all of the following cases to catch a SQLAlchemyError instead of a generic Exception. This allowed me to remove the except InternalServerError: pass cases
@@ -145,6 +168,7 @@ def options(self): | |||
# CORS support | |||
return ("", 204, self.options_headers) | |||
|
|||
@require_permission(required_role=None) |
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.
Does this just generically verify an authenticated user?
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.
Yes, this ensures a user is authorized without requiring any organization access. This is technically unnecessary since the middleware already enforces it, but this way every single method has a decorator and it's obvious that it wasn't accidentally skipped
@@ -153,15 +209,23 @@ def modify_intersection(intersection_spec): | |||
failed_value = failed_value.replace(")", '"') | |||
failed_value = failed_value.replace("=", " = ") | |||
logging.error(f"Exception encountered: {failed_value}") | |||
return {"message": failed_value}, 500 | |||
raise InternalServerError(failed_value) from e | |||
except InternalServerError: |
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.
Do we need this InternalSererError except?
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.
same as above -
@@ -126,20 +138,18 @@ def add_intersection(intersection_spec): | |||
failed_value = failed_value.replace(")", '"') | |||
failed_value = failed_value.replace("=", " = ") | |||
logging.error(f"Exception encountered: {failed_value}") | |||
return {"message": failed_value}, 500 | |||
raise InternalServerError(failed_value) from e | |||
except InternalServerError: |
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.
Is this needed?
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.
same as above -
@@ -143,6 +146,23 @@ class AdminNewUserSchema(Schema): | |||
) | |||
|
|||
|
|||
def enforce_add_user_org_permissions( |
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.
We've got pretty similary "enforce_xxx_permissions" in several of these admin file additions. Could we abstract to a shared location to reuse code?
PR Details
Description
This PR enforces organization and role permissions in the cvmanager api. This includes the following changes:
How Has This Been Tested?
This has been extensively tested by unit tests, going through the GUI, and making manual requests through postman, to test responses to malicious requests
Types of changes
Checklist: