-
-
Notifications
You must be signed in to change notification settings - Fork 57
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
feat(admin-auth): Add TTL cache for admin roles #4358
Conversation
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## master #4358 +/- ##
==========================================
- Coverage 91.05% 90.72% -0.33%
==========================================
Files 793 797 +4
Lines 38886 39254 +368
Branches 226 245 +19
==========================================
+ Hits 35408 35614 +206
- Misses 3448 3608 +160
- Partials 30 32 +2
☔ View full report in Codecov by Sentry. |
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 looks like it's caching the reading of the file (which shouldn't be that slow). Do we have evidence that this is the thing that needs to be cached? Is it caching the API calls somewhere that I don't see?
snuba/admin/auth.py
Outdated
@@ -68,7 +72,14 @@ def get_iam_roles_from_file(user: AdminUser) -> Sequence[str]: | |||
def _set_roles(user: AdminUser) -> AdminUser: | |||
# todo: depending on provider convert user email | |||
# to subset of DEFAULT_ROLES based on IAM roles | |||
iam_roles = get_iam_roles_from_file(user) | |||
key = f"roles-{user.email}" |
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.
you're caching the file reading here. Is reading from the local file really taking that much time?
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 function name is a bit misleading here, but this function reads the file and also makes a call to check whether a member is in a group and that's where the API is being called.
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 this function should be renamed get_iam_roles_for_user
.
snuba/admin/auth.py
Outdated
@@ -68,7 +72,14 @@ def get_iam_roles_from_file(user: AdminUser) -> Sequence[str]: | |||
def _set_roles(user: AdminUser) -> AdminUser: | |||
# todo: depending on provider convert user email | |||
# to subset of DEFAULT_ROLES based on IAM roles | |||
iam_roles = get_iam_roles_from_file(user) | |||
key = f"roles-{user.email}" |
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 this function should be renamed get_iam_roles_for_user
.
@@ -359,6 +364,31 @@ def test_get_iam_roles(caplog: Any) -> None: | |||
tool_role, | |||
] | |||
|
|||
iam_file.close() |
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 test is very large and should be split up into multiple tests.
You've also tested the happy path but the unhappy path is not tested. Example: what if the redis connection fails, does that mean nobody can access admin?
Also, is _set_roles
a private module function? If so, can this be tested with the public API? If not, then maybe the API is not properly thought out.
snuba/admin/auth.py
Outdated
iam_roles_str = redis_client.get(key) | ||
iam_roles = rapidjson.loads(iam_roles_str) if iam_roles_str else None | ||
if not iam_roles: | ||
iam_roles = get_iam_roles_from_file(user) | ||
redis_client.set(key, rapidjson.dumps(iam_roles)) | ||
redis_client.expire(key, settings.ADMIN_ROLES_REDIS_TTL) | ||
|
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 implementation tightly couples authentication to caching. If your cache fails to update, you'll fail the request. this should be done in such a way that:
- The distinction between cache and auth is clear
- If the caching fails the app still works
snuba/admin/auth.py
Outdated
iam_roles = rapidjson.loads(iam_roles_str) if iam_roles_str else None | ||
if not iam_roles: | ||
iam_roles = get_iam_roles_from_file(user) | ||
redis_client.set(key, rapidjson.dumps(iam_roles)) |
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.
slight performance nit: set already has an expiration parameter
Added additional tests and handling for redis failure. |
@@ -137,6 +138,9 @@ class RedisClientKey(Enum): | |||
RedisClientKey.OPTIMIZE: _initialize_specialized_redis_cluster( | |||
settings.REDIS_CLUSTERS["optimize"] | |||
), | |||
RedisClientKey.ADMIN_AUTH: _initialize_specialized_redis_cluster( | |||
settings.REDIS_CLUSTERS["admin_auth"] |
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 there a PR to add admin_auth
to the prod settings as well?
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.
not yet, I'll make a PR right now
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.
That will need to go out before this can be merged.
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 stuff is super inconvenient. I wonder if we can make it so that the prod_settings file can override individual keys of the default settings file, and does not have to redefine the entire variable
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 stuff is super inconvenient. I wonder if we can make it so that the prod_settings file can override individual keys of the default settings file, and does not have to redefine the entire variable
@untitaker I made a draft PR to do this here.
@evanh ops pr has been merged |
Suspect IssuesThis pull request has been deployed and Sentry has observed the following issues:
Have questions? Reach out to us in the #proj-github-pr-comments channel. Did you find this useful? React with a 👍 or 👎 |
PR reverted: f65f5ad |
This reverts commit a367a37. Co-authored-by: lynnagara <1779792+lynnagara@users.noreply.github.com>
Currently, we set up a user's roles every time we make a request which is inefficient as it requires reading from a file and making multiple API requests to google. In order to improve performance, I've added a TTL cache with a 10 min TTL. Since it's unlikely for roles and groups to change, we should consider increasing this TTL in the future.