-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Factor common IAM policy bits into 'google.cloud.iam'. #3188
Factor common IAM policy bits into 'google.cloud.iam'. #3188
Conversation
/cc @elibixby |
core/google/cloud/iam.py
Outdated
@@ -0,0 +1,217 @@ | |||
# Copyright 2016 Google Inc. |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
I had a previous proposal to do this which got abandoned due to slow review cycle, but it's here: See #2031 The key takeaway: the API representation of bindings is really gross to interact with. Client side it would be much nicer if bindings were a dict with roles as keys, and member sets as values. So instead of code like:
We had code like:
|
core/google/cloud/iam.py
Outdated
""" | ||
return 'allAuthenticatedUsers' | ||
|
||
def _bind_custom_role(self, role, members): |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
core/google/cloud/iam.py
Outdated
self.viewers = set() | ||
|
||
@staticmethod | ||
def user(email): |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
core/google/cloud/iam.py
Outdated
def __init__(self, etag=None, version=None): | ||
self.etag = etag | ||
self.version = version | ||
self.owners = set() |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Additionally note that Roles are an API resource, and should be represented with an object. What does the Both Role resources will be user managed with the addition of custom roles (currently in alpha), and will have a list of iam permissions that they grant, which will be important for user protection of custom methods, and for identifying the necessary roles that a member needs to be granted. (combining Further explanation of suggestions like these can be found in comment threads in #2031 EDIT: Slight correction: EDIT2: This can probably be tackled in a followup PR, but should be considered when defining the interface? Do we want to make |
pubsub/google/cloud/pubsub/iam.py
Outdated
@staticmethod | ||
def user(email): | ||
"""Factory method for a user member. | ||
def _bind_custom_role(self, role, members): |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
@elibixby I think I have addressed your concerns about supporting user-defined roles in b625017. re: |
@tseaver But I agree that this can be tackled in a follow-up PR. Long term I still believe a common implementatoin for One Platform APIs will save you the most heartache. Storage is an oddball because it is so old (i.e. not a One Platform API) and IAM support was "backported" in a slightly weird way. But going forward all OP APIs will share a common IAM signature, and a Mixin could provide drop in support for that. |
core/google/cloud/iam.py
Outdated
policy.viewers |= members | ||
else: | ||
policy._bind_custom_role(role, members) | ||
members = sorted(binding['members']) |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
core/google/cloud/iam.py
Outdated
resource['bindings'] = bindings | ||
if len(self.bindings) > 0: | ||
resource['bindings'] = [ | ||
{'role': role, 'members': members} |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
core/google/cloud/iam.py
Outdated
for role in self._OWNER_ROLES: | ||
for member in self.bindings.get(role, ()): | ||
result.add(member) | ||
return result |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This is fine with me also. |
@tseaver Checking on the status of this. :-) |
Pubsub-specific roles, permissions left behind in 'google.cloud.pubsub.iam'. 'google.cloud.pubsub.iam.Policy' subclasses the core one, extending it to deal with the pubsub-specific roles.
- google.cloud.iam.Policy holds a 'bindings' mapping, which doesn't enforce using known roles. - Its 'owners', 'editors', and 'viewers' are now properties which indirect over that 'bindings' attribute. Note that this is a breaking change, as users who relied on mutating one of those sets (rather than re-assigning it) will need to update.
- Don't pass roles w/ empty members to back-end. - De-duplicate role members when passing to back-end.
- Re-assign 'policy.viewers'/'policy.editors', rather than mutating them in place.
@lukesneeringer I'm back at this, but can't figure out what the desired resolution would be. Here is a sketch at a way forward:
Then, the question is what the desired surface would be: I'm really leery of exposing the mutable
|
Updating them in place never actually worked (they were sets created on the fly), but at least we give an appropriate error now if the user tries.
My personal preference is the first option (making |
@lukesneeringer That is my preference as well. Update on the way. |
Keys are roles, values are lists of principals.
@lukesneeringer OK, I've updated |
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.
Approved, but giving @elibixby a chance to weigh in before merge.
core/google/cloud/iam.py
Outdated
return self._bindings[key] | ||
|
||
def __setitem__(self, key, value): | ||
self._bindings[key] = value |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Merging this when CI goes green. |
…b-iam-for-storage Factor common IAM policy bits into 'google.cloud.iam'.
Toward #1679.
Pubsub-specific roles, permissions left behind in
google.cloud.pubsub.iam
.google.cloud.pubsub.iam.Policy
subclasses the core one, extending it to deal with the pubsub-specific roles.