1# -*- coding: utf-8 -*-
2# Copyright 2022 Google LLC
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17import dataclasses
18import json # type: ignore
19import re
20from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
21import warnings
22
23from google.api_core import gapic_v1, path_template, rest_helpers, rest_streaming
24from google.api_core import exceptions as core_exceptions
25from google.api_core import retry as retries
26from google.auth import credentials as ga_credentials # type: ignore
27from google.auth.transport.grpc import SslCredentials # type: ignore
28from google.auth.transport.requests import AuthorizedSession # type: ignore
29from google.longrunning import operations_pb2
30from google.protobuf import json_format
31import grpc # type: ignore
32from requests import __version__ as requests_version
33
34try:
35 OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault]
36except AttributeError: # pragma: NO COVER
37 OptionalRetry = Union[retries.Retry, object] # type: ignore
38
39
40from google.iam.v1 import iam_policy_pb2 # type: ignore
41from google.iam.v1 import policy_pb2 # type: ignore
42
43from google.cloud.resourcemanager_v3.types import organizations
44
45from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO
46from .base import OrganizationsTransport
47
48DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
49 gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version,
50 grpc_version=None,
51 rest_version=requests_version,
52)
53
54
55class OrganizationsRestInterceptor:
56 """Interceptor for Organizations.
57
58 Interceptors are used to manipulate requests, request metadata, and responses
59 in arbitrary ways.
60 Example use cases include:
61 * Logging
62 * Verifying requests according to service or custom semantics
63 * Stripping extraneous information from responses
64
65 These use cases and more can be enabled by injecting an
66 instance of a custom subclass when constructing the OrganizationsRestTransport.
67
68 .. code-block:: python
69 class MyCustomOrganizationsInterceptor(OrganizationsRestInterceptor):
70 def pre_get_iam_policy(self, request, metadata):
71 logging.log(f"Received request: {request}")
72 return request, metadata
73
74 def post_get_iam_policy(self, response):
75 logging.log(f"Received response: {response}")
76 return response
77
78 def pre_get_organization(self, request, metadata):
79 logging.log(f"Received request: {request}")
80 return request, metadata
81
82 def post_get_organization(self, response):
83 logging.log(f"Received response: {response}")
84 return response
85
86 def pre_search_organizations(self, request, metadata):
87 logging.log(f"Received request: {request}")
88 return request, metadata
89
90 def post_search_organizations(self, response):
91 logging.log(f"Received response: {response}")
92 return response
93
94 def pre_set_iam_policy(self, request, metadata):
95 logging.log(f"Received request: {request}")
96 return request, metadata
97
98 def post_set_iam_policy(self, response):
99 logging.log(f"Received response: {response}")
100 return response
101
102 def pre_test_iam_permissions(self, request, metadata):
103 logging.log(f"Received request: {request}")
104 return request, metadata
105
106 def post_test_iam_permissions(self, response):
107 logging.log(f"Received response: {response}")
108 return response
109
110 transport = OrganizationsRestTransport(interceptor=MyCustomOrganizationsInterceptor())
111 client = OrganizationsClient(transport=transport)
112
113
114 """
115
116 def pre_get_iam_policy(
117 self,
118 request: iam_policy_pb2.GetIamPolicyRequest,
119 metadata: Sequence[Tuple[str, str]],
120 ) -> Tuple[iam_policy_pb2.GetIamPolicyRequest, Sequence[Tuple[str, str]]]:
121 """Pre-rpc interceptor for get_iam_policy
122
123 Override in a subclass to manipulate the request or metadata
124 before they are sent to the Organizations server.
125 """
126 return request, metadata
127
128 def post_get_iam_policy(self, response: policy_pb2.Policy) -> policy_pb2.Policy:
129 """Post-rpc interceptor for get_iam_policy
130
131 Override in a subclass to manipulate the response
132 after it is returned by the Organizations server but before
133 it is returned to user code.
134 """
135 return response
136
137 def pre_get_organization(
138 self,
139 request: organizations.GetOrganizationRequest,
140 metadata: Sequence[Tuple[str, str]],
141 ) -> Tuple[organizations.GetOrganizationRequest, Sequence[Tuple[str, str]]]:
142 """Pre-rpc interceptor for get_organization
143
144 Override in a subclass to manipulate the request or metadata
145 before they are sent to the Organizations server.
146 """
147 return request, metadata
148
149 def post_get_organization(
150 self, response: organizations.Organization
151 ) -> organizations.Organization:
152 """Post-rpc interceptor for get_organization
153
154 Override in a subclass to manipulate the response
155 after it is returned by the Organizations server but before
156 it is returned to user code.
157 """
158 return response
159
160 def pre_search_organizations(
161 self,
162 request: organizations.SearchOrganizationsRequest,
163 metadata: Sequence[Tuple[str, str]],
164 ) -> Tuple[organizations.SearchOrganizationsRequest, Sequence[Tuple[str, str]]]:
165 """Pre-rpc interceptor for search_organizations
166
167 Override in a subclass to manipulate the request or metadata
168 before they are sent to the Organizations server.
169 """
170 return request, metadata
171
172 def post_search_organizations(
173 self, response: organizations.SearchOrganizationsResponse
174 ) -> organizations.SearchOrganizationsResponse:
175 """Post-rpc interceptor for search_organizations
176
177 Override in a subclass to manipulate the response
178 after it is returned by the Organizations server but before
179 it is returned to user code.
180 """
181 return response
182
183 def pre_set_iam_policy(
184 self,
185 request: iam_policy_pb2.SetIamPolicyRequest,
186 metadata: Sequence[Tuple[str, str]],
187 ) -> Tuple[iam_policy_pb2.SetIamPolicyRequest, Sequence[Tuple[str, str]]]:
188 """Pre-rpc interceptor for set_iam_policy
189
190 Override in a subclass to manipulate the request or metadata
191 before they are sent to the Organizations server.
192 """
193 return request, metadata
194
195 def post_set_iam_policy(self, response: policy_pb2.Policy) -> policy_pb2.Policy:
196 """Post-rpc interceptor for set_iam_policy
197
198 Override in a subclass to manipulate the response
199 after it is returned by the Organizations server but before
200 it is returned to user code.
201 """
202 return response
203
204 def pre_test_iam_permissions(
205 self,
206 request: iam_policy_pb2.TestIamPermissionsRequest,
207 metadata: Sequence[Tuple[str, str]],
208 ) -> Tuple[iam_policy_pb2.TestIamPermissionsRequest, Sequence[Tuple[str, str]]]:
209 """Pre-rpc interceptor for test_iam_permissions
210
211 Override in a subclass to manipulate the request or metadata
212 before they are sent to the Organizations server.
213 """
214 return request, metadata
215
216 def post_test_iam_permissions(
217 self, response: iam_policy_pb2.TestIamPermissionsResponse
218 ) -> iam_policy_pb2.TestIamPermissionsResponse:
219 """Post-rpc interceptor for test_iam_permissions
220
221 Override in a subclass to manipulate the response
222 after it is returned by the Organizations server but before
223 it is returned to user code.
224 """
225 return response
226
227 def pre_get_operation(
228 self,
229 request: operations_pb2.GetOperationRequest,
230 metadata: Sequence[Tuple[str, str]],
231 ) -> Tuple[operations_pb2.GetOperationRequest, Sequence[Tuple[str, str]]]:
232 """Pre-rpc interceptor for get_operation
233
234 Override in a subclass to manipulate the request or metadata
235 before they are sent to the Organizations server.
236 """
237 return request, metadata
238
239 def post_get_operation(
240 self, response: operations_pb2.Operation
241 ) -> operations_pb2.Operation:
242 """Post-rpc interceptor for get_operation
243
244 Override in a subclass to manipulate the response
245 after it is returned by the Organizations server but before
246 it is returned to user code.
247 """
248 return response
249
250
251@dataclasses.dataclass
252class OrganizationsRestStub:
253 _session: AuthorizedSession
254 _host: str
255 _interceptor: OrganizationsRestInterceptor
256
257
258class OrganizationsRestTransport(OrganizationsTransport):
259 """REST backend transport for Organizations.
260
261 Allows users to manage their organization resources.
262
263 This class defines the same methods as the primary client, so the
264 primary client can load the underlying transport implementation
265 and call it.
266
267 It sends JSON representations of protocol buffers over HTTP/1.1
268
269 """
270
271 def __init__(
272 self,
273 *,
274 host: str = "cloudresourcemanager.googleapis.com",
275 credentials: Optional[ga_credentials.Credentials] = None,
276 credentials_file: Optional[str] = None,
277 scopes: Optional[Sequence[str]] = None,
278 client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None,
279 quota_project_id: Optional[str] = None,
280 client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
281 always_use_jwt_access: Optional[bool] = False,
282 url_scheme: str = "https",
283 interceptor: Optional[OrganizationsRestInterceptor] = None,
284 api_audience: Optional[str] = None,
285 ) -> None:
286 """Instantiate the transport.
287
288 Args:
289 host (Optional[str]):
290 The hostname to connect to.
291 credentials (Optional[google.auth.credentials.Credentials]): The
292 authorization credentials to attach to requests. These
293 credentials identify the application to the service; if none
294 are specified, the client will attempt to ascertain the
295 credentials from the environment.
296
297 credentials_file (Optional[str]): A file with credentials that can
298 be loaded with :func:`google.auth.load_credentials_from_file`.
299 This argument is ignored if ``channel`` is provided.
300 scopes (Optional(Sequence[str])): A list of scopes. This argument is
301 ignored if ``channel`` is provided.
302 client_cert_source_for_mtls (Callable[[], Tuple[bytes, bytes]]): Client
303 certificate to configure mutual TLS HTTP channel. It is ignored
304 if ``channel`` is provided.
305 quota_project_id (Optional[str]): An optional project to use for billing
306 and quota.
307 client_info (google.api_core.gapic_v1.client_info.ClientInfo):
308 The client info used to send a user-agent string along with
309 API requests. If ``None``, then default info will be used.
310 Generally, you only need to set this if you are developing
311 your own client library.
312 always_use_jwt_access (Optional[bool]): Whether self signed JWT should
313 be used for service account credentials.
314 url_scheme: the protocol scheme for the API endpoint. Normally
315 "https", but for testing or local servers,
316 "http" can be specified.
317 """
318 # Run the base constructor
319 # TODO(yon-mg): resolve other ctor params i.e. scopes, quota, etc.
320 # TODO: When custom host (api_endpoint) is set, `scopes` must *also* be set on the
321 # credentials object
322 maybe_url_match = re.match("^(?P<scheme>http(?:s)?://)?(?P<host>.*)$", host)
323 if maybe_url_match is None:
324 raise ValueError(
325 f"Unexpected hostname structure: {host}"
326 ) # pragma: NO COVER
327
328 url_match_items = maybe_url_match.groupdict()
329
330 host = f"{url_scheme}://{host}" if not url_match_items["scheme"] else host
331
332 super().__init__(
333 host=host,
334 credentials=credentials,
335 client_info=client_info,
336 always_use_jwt_access=always_use_jwt_access,
337 api_audience=api_audience,
338 )
339 self._session = AuthorizedSession(
340 self._credentials, default_host=self.DEFAULT_HOST
341 )
342 if client_cert_source_for_mtls:
343 self._session.configure_mtls_channel(client_cert_source_for_mtls)
344 self._interceptor = interceptor or OrganizationsRestInterceptor()
345 self._prep_wrapped_messages(client_info)
346
347 class _GetIamPolicy(OrganizationsRestStub):
348 def __hash__(self):
349 return hash("GetIamPolicy")
350
351 __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {}
352
353 @classmethod
354 def _get_unset_required_fields(cls, message_dict):
355 return {
356 k: v
357 for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items()
358 if k not in message_dict
359 }
360
361 def __call__(
362 self,
363 request: iam_policy_pb2.GetIamPolicyRequest,
364 *,
365 retry: OptionalRetry = gapic_v1.method.DEFAULT,
366 timeout: Optional[float] = None,
367 metadata: Sequence[Tuple[str, str]] = (),
368 ) -> policy_pb2.Policy:
369 r"""Call the get iam policy method over HTTP.
370
371 Args:
372 request (~.iam_policy_pb2.GetIamPolicyRequest):
373 The request object. Request message for ``GetIamPolicy`` method.
374 retry (google.api_core.retry.Retry): Designation of what errors, if any,
375 should be retried.
376 timeout (float): The timeout for this request.
377 metadata (Sequence[Tuple[str, str]]): Strings which should be
378 sent along with the request as metadata.
379
380 Returns:
381 ~.policy_pb2.Policy:
382 An Identity and Access Management (IAM) policy, which
383 specifies access controls for Google Cloud resources.
384
385 A ``Policy`` is a collection of ``bindings``. A
386 ``binding`` binds one or more ``members``, or
387 principals, to a single ``role``. Principals can be user
388 accounts, service accounts, Google groups, and domains
389 (such as G Suite). A ``role`` is a named list of
390 permissions; each ``role`` can be an IAM predefined role
391 or a user-created custom role.
392
393 For some types of Google Cloud resources, a ``binding``
394 can also specify a ``condition``, which is a logical
395 expression that allows access to a resource only if the
396 expression evaluates to ``true``. A condition can add
397 constraints based on attributes of the request, the
398 resource, or both. To learn which resources support
399 conditions in their IAM policies, see the `IAM
400 documentation <https://cloud.google.com/iam/help/conditions/resource-policies>`__.
401
402 **JSON example:**
403
404 ::
405
406 {
407 "bindings": [
408 {
409 "role": "roles/resourcemanager.organizationAdmin",
410 "members": [
411 "user:mike@example.com",
412 "group:admins@example.com",
413 "domain:google.com",
414 "serviceAccount:my-project-id@appspot.gserviceaccount.com"
415 ]
416 },
417 {
418 "role": "roles/resourcemanager.organizationViewer",
419 "members": [
420 "user:eve@example.com"
421 ],
422 "condition": {
423 "title": "expirable access",
424 "description": "Does not grant access after Sep 2020",
425 "expression": "request.time <
426 timestamp('2020-10-01T00:00:00.000Z')",
427 }
428 }
429 ],
430 "etag": "BwWWja0YfJA=",
431 "version": 3
432 }
433
434 **YAML example:**
435
436 ::
437
438 bindings:
439 - members:
440 - user:mike@example.com
441 - group:admins@example.com
442 - domain:google.com
443 - serviceAccount:my-project-id@appspot.gserviceaccount.com
444 role: roles/resourcemanager.organizationAdmin
445 - members:
446 - user:eve@example.com
447 role: roles/resourcemanager.organizationViewer
448 condition:
449 title: expirable access
450 description: Does not grant access after Sep 2020
451 expression: request.time < timestamp('2020-10-01T00:00:00.000Z')
452 etag: BwWWja0YfJA=
453 version: 3
454
455 For a description of IAM and its features, see the `IAM
456 documentation <https://cloud.google.com/iam/docs/>`__.
457
458 """
459
460 http_options: List[Dict[str, str]] = [
461 {
462 "method": "post",
463 "uri": "/v3/{resource=organizations/*}:getIamPolicy",
464 "body": "*",
465 },
466 ]
467 request, metadata = self._interceptor.pre_get_iam_policy(request, metadata)
468 pb_request = request
469 transcoded_request = path_template.transcode(http_options, pb_request)
470
471 # Jsonify the request body
472
473 body = json_format.MessageToJson(
474 transcoded_request["body"],
475 including_default_value_fields=False,
476 use_integers_for_enums=True,
477 )
478 uri = transcoded_request["uri"]
479 method = transcoded_request["method"]
480
481 # Jsonify the query params
482 query_params = json.loads(
483 json_format.MessageToJson(
484 transcoded_request["query_params"],
485 including_default_value_fields=False,
486 use_integers_for_enums=True,
487 )
488 )
489 query_params.update(self._get_unset_required_fields(query_params))
490
491 query_params["$alt"] = "json;enum-encoding=int"
492
493 # Send the request
494 headers = dict(metadata)
495 headers["Content-Type"] = "application/json"
496 response = getattr(self._session, method)(
497 "{host}{uri}".format(host=self._host, uri=uri),
498 timeout=timeout,
499 headers=headers,
500 params=rest_helpers.flatten_query_params(query_params, strict=True),
501 data=body,
502 )
503
504 # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception
505 # subclass.
506 if response.status_code >= 400:
507 raise core_exceptions.from_http_response(response)
508
509 # Return the response
510 resp = policy_pb2.Policy()
511 pb_resp = resp
512
513 json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True)
514 resp = self._interceptor.post_get_iam_policy(resp)
515 return resp
516
517 class _GetOrganization(OrganizationsRestStub):
518 def __hash__(self):
519 return hash("GetOrganization")
520
521 __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {}
522
523 @classmethod
524 def _get_unset_required_fields(cls, message_dict):
525 return {
526 k: v
527 for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items()
528 if k not in message_dict
529 }
530
531 def __call__(
532 self,
533 request: organizations.GetOrganizationRequest,
534 *,
535 retry: OptionalRetry = gapic_v1.method.DEFAULT,
536 timeout: Optional[float] = None,
537 metadata: Sequence[Tuple[str, str]] = (),
538 ) -> organizations.Organization:
539 r"""Call the get organization method over HTTP.
540
541 Args:
542 request (~.organizations.GetOrganizationRequest):
543 The request object. The request sent to the ``GetOrganization`` method. The
544 ``name`` field is required. ``organization_id`` is no
545 longer accepted.
546 retry (google.api_core.retry.Retry): Designation of what errors, if any,
547 should be retried.
548 timeout (float): The timeout for this request.
549 metadata (Sequence[Tuple[str, str]]): Strings which should be
550 sent along with the request as metadata.
551
552 Returns:
553 ~.organizations.Organization:
554 The root node in the resource
555 hierarchy to which a particular entity's
556 (a company, for example) resources
557 belong.
558
559 """
560
561 http_options: List[Dict[str, str]] = [
562 {
563 "method": "get",
564 "uri": "/v3/{name=organizations/*}",
565 },
566 ]
567 request, metadata = self._interceptor.pre_get_organization(
568 request, metadata
569 )
570 pb_request = organizations.GetOrganizationRequest.pb(request)
571 transcoded_request = path_template.transcode(http_options, pb_request)
572
573 uri = transcoded_request["uri"]
574 method = transcoded_request["method"]
575
576 # Jsonify the query params
577 query_params = json.loads(
578 json_format.MessageToJson(
579 transcoded_request["query_params"],
580 including_default_value_fields=False,
581 use_integers_for_enums=True,
582 )
583 )
584 query_params.update(self._get_unset_required_fields(query_params))
585
586 query_params["$alt"] = "json;enum-encoding=int"
587
588 # Send the request
589 headers = dict(metadata)
590 headers["Content-Type"] = "application/json"
591 response = getattr(self._session, method)(
592 "{host}{uri}".format(host=self._host, uri=uri),
593 timeout=timeout,
594 headers=headers,
595 params=rest_helpers.flatten_query_params(query_params, strict=True),
596 )
597
598 # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception
599 # subclass.
600 if response.status_code >= 400:
601 raise core_exceptions.from_http_response(response)
602
603 # Return the response
604 resp = organizations.Organization()
605 pb_resp = organizations.Organization.pb(resp)
606
607 json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True)
608 resp = self._interceptor.post_get_organization(resp)
609 return resp
610
611 class _SearchOrganizations(OrganizationsRestStub):
612 def __hash__(self):
613 return hash("SearchOrganizations")
614
615 def __call__(
616 self,
617 request: organizations.SearchOrganizationsRequest,
618 *,
619 retry: OptionalRetry = gapic_v1.method.DEFAULT,
620 timeout: Optional[float] = None,
621 metadata: Sequence[Tuple[str, str]] = (),
622 ) -> organizations.SearchOrganizationsResponse:
623 r"""Call the search organizations method over HTTP.
624
625 Args:
626 request (~.organizations.SearchOrganizationsRequest):
627 The request object. The request sent to the ``SearchOrganizations`` method.
628 retry (google.api_core.retry.Retry): Designation of what errors, if any,
629 should be retried.
630 timeout (float): The timeout for this request.
631 metadata (Sequence[Tuple[str, str]]): Strings which should be
632 sent along with the request as metadata.
633
634 Returns:
635 ~.organizations.SearchOrganizationsResponse:
636 The response returned from the ``SearchOrganizations``
637 method.
638
639 """
640
641 http_options: List[Dict[str, str]] = [
642 {
643 "method": "get",
644 "uri": "/v3/organizations:search",
645 },
646 ]
647 request, metadata = self._interceptor.pre_search_organizations(
648 request, metadata
649 )
650 pb_request = organizations.SearchOrganizationsRequest.pb(request)
651 transcoded_request = path_template.transcode(http_options, pb_request)
652
653 uri = transcoded_request["uri"]
654 method = transcoded_request["method"]
655
656 # Jsonify the query params
657 query_params = json.loads(
658 json_format.MessageToJson(
659 transcoded_request["query_params"],
660 including_default_value_fields=False,
661 use_integers_for_enums=True,
662 )
663 )
664
665 query_params["$alt"] = "json;enum-encoding=int"
666
667 # Send the request
668 headers = dict(metadata)
669 headers["Content-Type"] = "application/json"
670 response = getattr(self._session, method)(
671 "{host}{uri}".format(host=self._host, uri=uri),
672 timeout=timeout,
673 headers=headers,
674 params=rest_helpers.flatten_query_params(query_params, strict=True),
675 )
676
677 # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception
678 # subclass.
679 if response.status_code >= 400:
680 raise core_exceptions.from_http_response(response)
681
682 # Return the response
683 resp = organizations.SearchOrganizationsResponse()
684 pb_resp = organizations.SearchOrganizationsResponse.pb(resp)
685
686 json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True)
687 resp = self._interceptor.post_search_organizations(resp)
688 return resp
689
690 class _SetIamPolicy(OrganizationsRestStub):
691 def __hash__(self):
692 return hash("SetIamPolicy")
693
694 __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {}
695
696 @classmethod
697 def _get_unset_required_fields(cls, message_dict):
698 return {
699 k: v
700 for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items()
701 if k not in message_dict
702 }
703
704 def __call__(
705 self,
706 request: iam_policy_pb2.SetIamPolicyRequest,
707 *,
708 retry: OptionalRetry = gapic_v1.method.DEFAULT,
709 timeout: Optional[float] = None,
710 metadata: Sequence[Tuple[str, str]] = (),
711 ) -> policy_pb2.Policy:
712 r"""Call the set iam policy method over HTTP.
713
714 Args:
715 request (~.iam_policy_pb2.SetIamPolicyRequest):
716 The request object. Request message for ``SetIamPolicy`` method.
717 retry (google.api_core.retry.Retry): Designation of what errors, if any,
718 should be retried.
719 timeout (float): The timeout for this request.
720 metadata (Sequence[Tuple[str, str]]): Strings which should be
721 sent along with the request as metadata.
722
723 Returns:
724 ~.policy_pb2.Policy:
725 An Identity and Access Management (IAM) policy, which
726 specifies access controls for Google Cloud resources.
727
728 A ``Policy`` is a collection of ``bindings``. A
729 ``binding`` binds one or more ``members``, or
730 principals, to a single ``role``. Principals can be user
731 accounts, service accounts, Google groups, and domains
732 (such as G Suite). A ``role`` is a named list of
733 permissions; each ``role`` can be an IAM predefined role
734 or a user-created custom role.
735
736 For some types of Google Cloud resources, a ``binding``
737 can also specify a ``condition``, which is a logical
738 expression that allows access to a resource only if the
739 expression evaluates to ``true``. A condition can add
740 constraints based on attributes of the request, the
741 resource, or both. To learn which resources support
742 conditions in their IAM policies, see the `IAM
743 documentation <https://cloud.google.com/iam/help/conditions/resource-policies>`__.
744
745 **JSON example:**
746
747 ::
748
749 {
750 "bindings": [
751 {
752 "role": "roles/resourcemanager.organizationAdmin",
753 "members": [
754 "user:mike@example.com",
755 "group:admins@example.com",
756 "domain:google.com",
757 "serviceAccount:my-project-id@appspot.gserviceaccount.com"
758 ]
759 },
760 {
761 "role": "roles/resourcemanager.organizationViewer",
762 "members": [
763 "user:eve@example.com"
764 ],
765 "condition": {
766 "title": "expirable access",
767 "description": "Does not grant access after Sep 2020",
768 "expression": "request.time <
769 timestamp('2020-10-01T00:00:00.000Z')",
770 }
771 }
772 ],
773 "etag": "BwWWja0YfJA=",
774 "version": 3
775 }
776
777 **YAML example:**
778
779 ::
780
781 bindings:
782 - members:
783 - user:mike@example.com
784 - group:admins@example.com
785 - domain:google.com
786 - serviceAccount:my-project-id@appspot.gserviceaccount.com
787 role: roles/resourcemanager.organizationAdmin
788 - members:
789 - user:eve@example.com
790 role: roles/resourcemanager.organizationViewer
791 condition:
792 title: expirable access
793 description: Does not grant access after Sep 2020
794 expression: request.time < timestamp('2020-10-01T00:00:00.000Z')
795 etag: BwWWja0YfJA=
796 version: 3
797
798 For a description of IAM and its features, see the `IAM
799 documentation <https://cloud.google.com/iam/docs/>`__.
800
801 """
802
803 http_options: List[Dict[str, str]] = [
804 {
805 "method": "post",
806 "uri": "/v3/{resource=organizations/*}:setIamPolicy",
807 "body": "*",
808 },
809 ]
810 request, metadata = self._interceptor.pre_set_iam_policy(request, metadata)
811 pb_request = request
812 transcoded_request = path_template.transcode(http_options, pb_request)
813
814 # Jsonify the request body
815
816 body = json_format.MessageToJson(
817 transcoded_request["body"],
818 including_default_value_fields=False,
819 use_integers_for_enums=True,
820 )
821 uri = transcoded_request["uri"]
822 method = transcoded_request["method"]
823
824 # Jsonify the query params
825 query_params = json.loads(
826 json_format.MessageToJson(
827 transcoded_request["query_params"],
828 including_default_value_fields=False,
829 use_integers_for_enums=True,
830 )
831 )
832 query_params.update(self._get_unset_required_fields(query_params))
833
834 query_params["$alt"] = "json;enum-encoding=int"
835
836 # Send the request
837 headers = dict(metadata)
838 headers["Content-Type"] = "application/json"
839 response = getattr(self._session, method)(
840 "{host}{uri}".format(host=self._host, uri=uri),
841 timeout=timeout,
842 headers=headers,
843 params=rest_helpers.flatten_query_params(query_params, strict=True),
844 data=body,
845 )
846
847 # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception
848 # subclass.
849 if response.status_code >= 400:
850 raise core_exceptions.from_http_response(response)
851
852 # Return the response
853 resp = policy_pb2.Policy()
854 pb_resp = resp
855
856 json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True)
857 resp = self._interceptor.post_set_iam_policy(resp)
858 return resp
859
860 class _TestIamPermissions(OrganizationsRestStub):
861 def __hash__(self):
862 return hash("TestIamPermissions")
863
864 __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {}
865
866 @classmethod
867 def _get_unset_required_fields(cls, message_dict):
868 return {
869 k: v
870 for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items()
871 if k not in message_dict
872 }
873
874 def __call__(
875 self,
876 request: iam_policy_pb2.TestIamPermissionsRequest,
877 *,
878 retry: OptionalRetry = gapic_v1.method.DEFAULT,
879 timeout: Optional[float] = None,
880 metadata: Sequence[Tuple[str, str]] = (),
881 ) -> iam_policy_pb2.TestIamPermissionsResponse:
882 r"""Call the test iam permissions method over HTTP.
883
884 Args:
885 request (~.iam_policy_pb2.TestIamPermissionsRequest):
886 The request object. Request message for ``TestIamPermissions`` method.
887 retry (google.api_core.retry.Retry): Designation of what errors, if any,
888 should be retried.
889 timeout (float): The timeout for this request.
890 metadata (Sequence[Tuple[str, str]]): Strings which should be
891 sent along with the request as metadata.
892
893 Returns:
894 ~.iam_policy_pb2.TestIamPermissionsResponse:
895 Response message for ``TestIamPermissions`` method.
896 """
897
898 http_options: List[Dict[str, str]] = [
899 {
900 "method": "post",
901 "uri": "/v3/{resource=organizations/*}:testIamPermissions",
902 "body": "*",
903 },
904 ]
905 request, metadata = self._interceptor.pre_test_iam_permissions(
906 request, metadata
907 )
908 pb_request = request
909 transcoded_request = path_template.transcode(http_options, pb_request)
910
911 # Jsonify the request body
912
913 body = json_format.MessageToJson(
914 transcoded_request["body"],
915 including_default_value_fields=False,
916 use_integers_for_enums=True,
917 )
918 uri = transcoded_request["uri"]
919 method = transcoded_request["method"]
920
921 # Jsonify the query params
922 query_params = json.loads(
923 json_format.MessageToJson(
924 transcoded_request["query_params"],
925 including_default_value_fields=False,
926 use_integers_for_enums=True,
927 )
928 )
929 query_params.update(self._get_unset_required_fields(query_params))
930
931 query_params["$alt"] = "json;enum-encoding=int"
932
933 # Send the request
934 headers = dict(metadata)
935 headers["Content-Type"] = "application/json"
936 response = getattr(self._session, method)(
937 "{host}{uri}".format(host=self._host, uri=uri),
938 timeout=timeout,
939 headers=headers,
940 params=rest_helpers.flatten_query_params(query_params, strict=True),
941 data=body,
942 )
943
944 # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception
945 # subclass.
946 if response.status_code >= 400:
947 raise core_exceptions.from_http_response(response)
948
949 # Return the response
950 resp = iam_policy_pb2.TestIamPermissionsResponse()
951 pb_resp = resp
952
953 json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True)
954 resp = self._interceptor.post_test_iam_permissions(resp)
955 return resp
956
957 @property
958 def get_iam_policy(
959 self,
960 ) -> Callable[[iam_policy_pb2.GetIamPolicyRequest], policy_pb2.Policy]:
961 # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here.
962 # In C++ this would require a dynamic_cast
963 return self._GetIamPolicy(self._session, self._host, self._interceptor) # type: ignore
964
965 @property
966 def get_organization(
967 self,
968 ) -> Callable[[organizations.GetOrganizationRequest], organizations.Organization]:
969 # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here.
970 # In C++ this would require a dynamic_cast
971 return self._GetOrganization(self._session, self._host, self._interceptor) # type: ignore
972
973 @property
974 def search_organizations(
975 self,
976 ) -> Callable[
977 [organizations.SearchOrganizationsRequest],
978 organizations.SearchOrganizationsResponse,
979 ]:
980 # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here.
981 # In C++ this would require a dynamic_cast
982 return self._SearchOrganizations(self._session, self._host, self._interceptor) # type: ignore
983
984 @property
985 def set_iam_policy(
986 self,
987 ) -> Callable[[iam_policy_pb2.SetIamPolicyRequest], policy_pb2.Policy]:
988 # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here.
989 # In C++ this would require a dynamic_cast
990 return self._SetIamPolicy(self._session, self._host, self._interceptor) # type: ignore
991
992 @property
993 def test_iam_permissions(
994 self,
995 ) -> Callable[
996 [iam_policy_pb2.TestIamPermissionsRequest],
997 iam_policy_pb2.TestIamPermissionsResponse,
998 ]:
999 # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here.
1000 # In C++ this would require a dynamic_cast
1001 return self._TestIamPermissions(self._session, self._host, self._interceptor) # type: ignore
1002
1003 @property
1004 def get_operation(self):
1005 return self._GetOperation(self._session, self._host, self._interceptor) # type: ignore
1006
1007 class _GetOperation(OrganizationsRestStub):
1008 def __call__(
1009 self,
1010 request: operations_pb2.GetOperationRequest,
1011 *,
1012 retry: OptionalRetry = gapic_v1.method.DEFAULT,
1013 timeout: Optional[float] = None,
1014 metadata: Sequence[Tuple[str, str]] = (),
1015 ) -> operations_pb2.Operation:
1016
1017 r"""Call the get operation method over HTTP.
1018
1019 Args:
1020 request (operations_pb2.GetOperationRequest):
1021 The request object for GetOperation method.
1022 retry (google.api_core.retry.Retry): Designation of what errors, if any,
1023 should be retried.
1024 timeout (float): The timeout for this request.
1025 metadata (Sequence[Tuple[str, str]]): Strings which should be
1026 sent along with the request as metadata.
1027
1028 Returns:
1029 operations_pb2.Operation: Response from GetOperation method.
1030 """
1031
1032 http_options: List[Dict[str, str]] = [
1033 {
1034 "method": "get",
1035 "uri": "/v3/{name=operations/**}",
1036 },
1037 ]
1038
1039 request, metadata = self._interceptor.pre_get_operation(request, metadata)
1040 request_kwargs = json_format.MessageToDict(request)
1041 transcoded_request = path_template.transcode(http_options, **request_kwargs)
1042
1043 uri = transcoded_request["uri"]
1044 method = transcoded_request["method"]
1045
1046 # Jsonify the query params
1047 query_params = json.loads(json.dumps(transcoded_request["query_params"]))
1048
1049 # Send the request
1050 headers = dict(metadata)
1051 headers["Content-Type"] = "application/json"
1052
1053 response = getattr(self._session, method)(
1054 "{host}{uri}".format(host=self._host, uri=uri),
1055 timeout=timeout,
1056 headers=headers,
1057 params=rest_helpers.flatten_query_params(query_params),
1058 )
1059
1060 # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception
1061 # subclass.
1062 if response.status_code >= 400:
1063 raise core_exceptions.from_http_response(response)
1064
1065 resp = operations_pb2.Operation()
1066 resp = json_format.Parse(response.content.decode("utf-8"), resp)
1067 resp = self._interceptor.post_get_operation(resp)
1068 return resp
1069
1070 @property
1071 def kind(self) -> str:
1072 return "rest"
1073
1074 def close(self):
1075 self._session.close()
1076
1077
1078__all__ = ("OrganizationsRestTransport",)