Skip to content

Commit 9017661

Browse files
authored
Move google.cloud.iam (core) to google.api_core.iam (#6740)
* move google.cloud.iam (core) to google.api.core.iam
1 parent 6f4070d commit 9017661

File tree

2 files changed

+523
-0
lines changed

2 files changed

+523
-0
lines changed

google/api_core/iam.py

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
# Copyright 2017 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
"""Non-API-specific IAM policy definitions
15+
16+
For allowed roles / permissions, see:
17+
https://cloud.google.com/iam/docs/understanding-roles
18+
"""
19+
20+
import collections
21+
try:
22+
from collections import abc as collections_abc
23+
except ImportError: # Python 2.7
24+
import collections as collections_abc
25+
import warnings
26+
27+
# Generic IAM roles
28+
29+
OWNER_ROLE = "roles/owner"
30+
"""Generic role implying all rights to an object."""
31+
32+
EDITOR_ROLE = "roles/editor"
33+
"""Generic role implying rights to modify an object."""
34+
35+
VIEWER_ROLE = "roles/viewer"
36+
"""Generic role implying rights to access an object."""
37+
38+
_ASSIGNMENT_DEPRECATED_MSG = """\
39+
Assigning to '{}' is deprecated. Replace with 'policy[{}] = members."""
40+
41+
42+
class Policy(collections_abc.MutableMapping):
43+
"""IAM Policy
44+
45+
See
46+
https://cloud.google.com/iam/reference/rest/v1/Policy
47+
48+
:type etag: str
49+
:param etag: ETag used to identify a unique of the policy
50+
51+
:type version: int
52+
:param version: unique version of the policy
53+
"""
54+
55+
_OWNER_ROLES = (OWNER_ROLE,)
56+
"""Roles mapped onto our ``owners`` attribute."""
57+
58+
_EDITOR_ROLES = (EDITOR_ROLE,)
59+
"""Roles mapped onto our ``editors`` attribute."""
60+
61+
_VIEWER_ROLES = (VIEWER_ROLE,)
62+
"""Roles mapped onto our ``viewers`` attribute."""
63+
64+
def __init__(self, etag=None, version=None):
65+
self.etag = etag
66+
self.version = version
67+
self._bindings = collections.defaultdict(set)
68+
69+
def __iter__(self):
70+
return iter(self._bindings)
71+
72+
def __len__(self):
73+
return len(self._bindings)
74+
75+
def __getitem__(self, key):
76+
return self._bindings[key]
77+
78+
def __setitem__(self, key, value):
79+
self._bindings[key] = set(value)
80+
81+
def __delitem__(self, key):
82+
del self._bindings[key]
83+
84+
@property
85+
def owners(self):
86+
"""Legacy access to owner role."""
87+
result = set()
88+
for role in self._OWNER_ROLES:
89+
for member in self._bindings.get(role, ()):
90+
result.add(member)
91+
return frozenset(result)
92+
93+
@owners.setter
94+
def owners(self, value):
95+
"""Update owners."""
96+
warnings.warn(
97+
_ASSIGNMENT_DEPRECATED_MSG.format("owners", OWNER_ROLE), DeprecationWarning
98+
)
99+
self[OWNER_ROLE] = value
100+
101+
@property
102+
def editors(self):
103+
"""Legacy access to editor role."""
104+
result = set()
105+
for role in self._EDITOR_ROLES:
106+
for member in self._bindings.get(role, ()):
107+
result.add(member)
108+
return frozenset(result)
109+
110+
@editors.setter
111+
def editors(self, value):
112+
"""Update editors."""
113+
warnings.warn(
114+
_ASSIGNMENT_DEPRECATED_MSG.format("editors", EDITOR_ROLE),
115+
DeprecationWarning,
116+
)
117+
self[EDITOR_ROLE] = value
118+
119+
@property
120+
def viewers(self):
121+
"""Legacy access to viewer role."""
122+
result = set()
123+
for role in self._VIEWER_ROLES:
124+
for member in self._bindings.get(role, ()):
125+
result.add(member)
126+
return frozenset(result)
127+
128+
@viewers.setter
129+
def viewers(self, value):
130+
"""Update viewers."""
131+
warnings.warn(
132+
_ASSIGNMENT_DEPRECATED_MSG.format("viewers", VIEWER_ROLE),
133+
DeprecationWarning,
134+
)
135+
self[VIEWER_ROLE] = value
136+
137+
@staticmethod
138+
def user(email):
139+
"""Factory method for a user member.
140+
141+
:type email: str
142+
:param email: E-mail for this particular user.
143+
144+
:rtype: str
145+
:returns: A member string corresponding to the given user.
146+
"""
147+
return "user:%s" % (email,)
148+
149+
@staticmethod
150+
def service_account(email):
151+
"""Factory method for a service account member.
152+
153+
:type email: str
154+
:param email: E-mail for this particular service account.
155+
156+
:rtype: str
157+
:returns: A member string corresponding to the given service account.
158+
"""
159+
return "serviceAccount:%s" % (email,)
160+
161+
@staticmethod
162+
def group(email):
163+
"""Factory method for a group member.
164+
165+
:type email: str
166+
:param email: An id or e-mail for this particular group.
167+
168+
:rtype: str
169+
:returns: A member string corresponding to the given group.
170+
"""
171+
return "group:%s" % (email,)
172+
173+
@staticmethod
174+
def domain(domain):
175+
"""Factory method for a domain member.
176+
177+
:type domain: str
178+
:param domain: The domain for this member.
179+
180+
:rtype: str
181+
:returns: A member string corresponding to the given domain.
182+
"""
183+
return "domain:%s" % (domain,)
184+
185+
@staticmethod
186+
def all_users():
187+
"""Factory method for a member representing all users.
188+
189+
:rtype: str
190+
:returns: A member string representing all users.
191+
"""
192+
return "allUsers"
193+
194+
@staticmethod
195+
def authenticated_users():
196+
"""Factory method for a member representing all authenticated users.
197+
198+
:rtype: str
199+
:returns: A member string representing all authenticated users.
200+
"""
201+
return "allAuthenticatedUsers"
202+
203+
@classmethod
204+
def from_api_repr(cls, resource):
205+
"""Create a policy from the resource returned from the API.
206+
207+
:type resource: dict
208+
:param resource: resource returned from the ``getIamPolicy`` API.
209+
210+
:rtype: :class:`Policy`
211+
:returns: the parsed policy
212+
"""
213+
version = resource.get("version")
214+
etag = resource.get("etag")
215+
policy = cls(etag, version)
216+
for binding in resource.get("bindings", ()):
217+
role = binding["role"]
218+
members = sorted(binding["members"])
219+
policy[role] = members
220+
return policy
221+
222+
def to_api_repr(self):
223+
"""Construct a Policy resource.
224+
225+
:rtype: dict
226+
:returns: a resource to be passed to the ``setIamPolicy`` API.
227+
"""
228+
resource = {}
229+
230+
if self.etag is not None:
231+
resource["etag"] = self.etag
232+
233+
if self.version is not None:
234+
resource["version"] = self.version
235+
236+
if self._bindings:
237+
bindings = resource["bindings"] = []
238+
for role, members in sorted(self._bindings.items()):
239+
if members:
240+
bindings.append({"role": role, "members": sorted(set(members))})
241+
242+
if not bindings:
243+
del resource["bindings"]
244+
245+
return resource
246+
247+
248+
collections_abc.MutableMapping.register(Policy)

0 commit comments

Comments
 (0)