1# -*- coding: utf-8 -*-
2# Copyright 2023 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#
16from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union
17import warnings
18
19from google.api_core import gapic_v1, grpc_helpers_async
20from google.auth import credentials as ga_credentials # type: ignore
21from google.auth.transport.grpc import SslCredentials # type: ignore
22import grpc # type: ignore
23from grpc.experimental import aio # type: ignore
24
25from google.cloud.iam_credentials_v1.types import common
26
27from .base import DEFAULT_CLIENT_INFO, IAMCredentialsTransport
28from .grpc import IAMCredentialsGrpcTransport
29
30
31class IAMCredentialsGrpcAsyncIOTransport(IAMCredentialsTransport):
32 """gRPC AsyncIO backend transport for IAMCredentials.
33
34 A service account is a special type of Google account that
35 belongs to your application or a virtual machine (VM), instead
36 of to an individual end user. Your application assumes the
37 identity of the service account to call Google APIs, so that the
38 users aren't directly involved.
39
40 Service account credentials are used to temporarily assume the
41 identity of the service account. Supported credential types
42 include OAuth 2.0 access tokens, OpenID Connect ID tokens,
43 self-signed JSON Web Tokens (JWTs), and more.
44
45 This class defines the same methods as the primary client, so the
46 primary client can load the underlying transport implementation
47 and call it.
48
49 It sends protocol buffers over the wire using gRPC (which is built on
50 top of HTTP/2); the ``grpcio`` package must be installed.
51 """
52
53 _grpc_channel: aio.Channel
54 _stubs: Dict[str, Callable] = {}
55
56 @classmethod
57 def create_channel(
58 cls,
59 host: str = "iamcredentials.googleapis.com",
60 credentials: Optional[ga_credentials.Credentials] = None,
61 credentials_file: Optional[str] = None,
62 scopes: Optional[Sequence[str]] = None,
63 quota_project_id: Optional[str] = None,
64 **kwargs,
65 ) -> aio.Channel:
66 """Create and return a gRPC AsyncIO channel object.
67 Args:
68 host (Optional[str]): The host for the channel to use.
69 credentials (Optional[~.Credentials]): The
70 authorization credentials to attach to requests. These
71 credentials identify this application to the service. If
72 none are specified, the client will attempt to ascertain
73 the credentials from the environment.
74 credentials_file (Optional[str]): A file with credentials that can
75 be loaded with :func:`google.auth.load_credentials_from_file`.
76 This argument is ignored if ``channel`` is provided.
77 scopes (Optional[Sequence[str]]): A optional list of scopes needed for this
78 service. These are only used when credentials are not specified and
79 are passed to :func:`google.auth.default`.
80 quota_project_id (Optional[str]): An optional project to use for billing
81 and quota.
82 kwargs (Optional[dict]): Keyword arguments, which are passed to the
83 channel creation.
84 Returns:
85 aio.Channel: A gRPC AsyncIO channel object.
86 """
87
88 return grpc_helpers_async.create_channel(
89 host,
90 credentials=credentials,
91 credentials_file=credentials_file,
92 quota_project_id=quota_project_id,
93 default_scopes=cls.AUTH_SCOPES,
94 scopes=scopes,
95 default_host=cls.DEFAULT_HOST,
96 **kwargs,
97 )
98
99 def __init__(
100 self,
101 *,
102 host: str = "iamcredentials.googleapis.com",
103 credentials: Optional[ga_credentials.Credentials] = None,
104 credentials_file: Optional[str] = None,
105 scopes: Optional[Sequence[str]] = None,
106 channel: Optional[aio.Channel] = None,
107 api_mtls_endpoint: Optional[str] = None,
108 client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None,
109 ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None,
110 client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None,
111 quota_project_id: Optional[str] = None,
112 client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
113 always_use_jwt_access: Optional[bool] = False,
114 api_audience: Optional[str] = None,
115 ) -> None:
116 """Instantiate the transport.
117
118 Args:
119 host (Optional[str]):
120 The hostname to connect to.
121 credentials (Optional[google.auth.credentials.Credentials]): The
122 authorization credentials to attach to requests. These
123 credentials identify the application to the service; if none
124 are specified, the client will attempt to ascertain the
125 credentials from the environment.
126 This argument is ignored if ``channel`` is provided.
127 credentials_file (Optional[str]): A file with credentials that can
128 be loaded with :func:`google.auth.load_credentials_from_file`.
129 This argument is ignored if ``channel`` is provided.
130 scopes (Optional[Sequence[str]]): A optional list of scopes needed for this
131 service. These are only used when credentials are not specified and
132 are passed to :func:`google.auth.default`.
133 channel (Optional[aio.Channel]): A ``Channel`` instance through
134 which to make calls.
135 api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint.
136 If provided, it overrides the ``host`` argument and tries to create
137 a mutual TLS channel with client SSL credentials from
138 ``client_cert_source`` or application default SSL credentials.
139 client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]):
140 Deprecated. A callback to provide client SSL certificate bytes and
141 private key bytes, both in PEM format. It is ignored if
142 ``api_mtls_endpoint`` is None.
143 ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials
144 for the grpc channel. It is ignored if ``channel`` is provided.
145 client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]):
146 A callback to provide client certificate bytes and private key bytes,
147 both in PEM format. It is used to configure a mutual TLS channel. It is
148 ignored if ``channel`` or ``ssl_channel_credentials`` is provided.
149 quota_project_id (Optional[str]): An optional project to use for billing
150 and quota.
151 client_info (google.api_core.gapic_v1.client_info.ClientInfo):
152 The client info used to send a user-agent string along with
153 API requests. If ``None``, then default info will be used.
154 Generally, you only need to set this if you're developing
155 your own client library.
156 always_use_jwt_access (Optional[bool]): Whether self signed JWT should
157 be used for service account credentials.
158
159 Raises:
160 google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
161 creation failed for any reason.
162 google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials``
163 and ``credentials_file`` are passed.
164 """
165 self._grpc_channel = None
166 self._ssl_channel_credentials = ssl_channel_credentials
167 self._stubs: Dict[str, Callable] = {}
168
169 if api_mtls_endpoint:
170 warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning)
171 if client_cert_source:
172 warnings.warn("client_cert_source is deprecated", DeprecationWarning)
173
174 if channel:
175 # Ignore credentials if a channel was passed.
176 credentials = False
177 # If a channel was explicitly provided, set it.
178 self._grpc_channel = channel
179 self._ssl_channel_credentials = None
180 else:
181 if api_mtls_endpoint:
182 host = api_mtls_endpoint
183
184 # Create SSL credentials with client_cert_source or application
185 # default SSL credentials.
186 if client_cert_source:
187 cert, key = client_cert_source()
188 self._ssl_channel_credentials = grpc.ssl_channel_credentials(
189 certificate_chain=cert, private_key=key
190 )
191 else:
192 self._ssl_channel_credentials = SslCredentials().ssl_credentials
193
194 else:
195 if client_cert_source_for_mtls and not ssl_channel_credentials:
196 cert, key = client_cert_source_for_mtls()
197 self._ssl_channel_credentials = grpc.ssl_channel_credentials(
198 certificate_chain=cert, private_key=key
199 )
200
201 # The base transport sets the host, credentials and scopes
202 super().__init__(
203 host=host,
204 credentials=credentials,
205 credentials_file=credentials_file,
206 scopes=scopes,
207 quota_project_id=quota_project_id,
208 client_info=client_info,
209 always_use_jwt_access=always_use_jwt_access,
210 api_audience=api_audience,
211 )
212
213 if not self._grpc_channel:
214 self._grpc_channel = type(self).create_channel(
215 self._host,
216 # use the credentials which are saved
217 credentials=self._credentials,
218 # Set ``credentials_file`` to ``None`` here as
219 # the credentials that we saved earlier should be used.
220 credentials_file=None,
221 scopes=self._scopes,
222 ssl_credentials=self._ssl_channel_credentials,
223 quota_project_id=quota_project_id,
224 options=[
225 ("grpc.max_send_message_length", -1),
226 ("grpc.max_receive_message_length", -1),
227 ],
228 )
229
230 # Wrap messages. This must be done after self._grpc_channel exists
231 self._prep_wrapped_messages(client_info)
232
233 @property
234 def grpc_channel(self) -> aio.Channel:
235 """Create the channel designed to connect to this service.
236
237 This property caches on the instance; repeated calls return
238 the same channel.
239 """
240 # Return the channel from cache.
241 return self._grpc_channel
242
243 @property
244 def generate_access_token(
245 self,
246 ) -> Callable[
247 [common.GenerateAccessTokenRequest],
248 Awaitable[common.GenerateAccessTokenResponse],
249 ]:
250 r"""Return a callable for the generate access token method over gRPC.
251
252 Generates an OAuth 2.0 access token for a service
253 account.
254
255 Returns:
256 Callable[[~.GenerateAccessTokenRequest],
257 Awaitable[~.GenerateAccessTokenResponse]]:
258 A function that, when called, will call the underlying RPC
259 on the server.
260 """
261 # Generate a "stub function" on-the-fly which will actually make
262 # the request.
263 # gRPC handles serialization and deserialization, so we just need
264 # to pass in the functions for each.
265 if "generate_access_token" not in self._stubs:
266 self._stubs["generate_access_token"] = self.grpc_channel.unary_unary(
267 "/google.iam.credentials.v1.IAMCredentials/GenerateAccessToken",
268 request_serializer=common.GenerateAccessTokenRequest.serialize,
269 response_deserializer=common.GenerateAccessTokenResponse.deserialize,
270 )
271 return self._stubs["generate_access_token"]
272
273 @property
274 def generate_id_token(
275 self,
276 ) -> Callable[
277 [common.GenerateIdTokenRequest], Awaitable[common.GenerateIdTokenResponse]
278 ]:
279 r"""Return a callable for the generate id token method over gRPC.
280
281 Generates an OpenID Connect ID token for a service
282 account.
283
284 Returns:
285 Callable[[~.GenerateIdTokenRequest],
286 Awaitable[~.GenerateIdTokenResponse]]:
287 A function that, when called, will call the underlying RPC
288 on the server.
289 """
290 # Generate a "stub function" on-the-fly which will actually make
291 # the request.
292 # gRPC handles serialization and deserialization, so we just need
293 # to pass in the functions for each.
294 if "generate_id_token" not in self._stubs:
295 self._stubs["generate_id_token"] = self.grpc_channel.unary_unary(
296 "/google.iam.credentials.v1.IAMCredentials/GenerateIdToken",
297 request_serializer=common.GenerateIdTokenRequest.serialize,
298 response_deserializer=common.GenerateIdTokenResponse.deserialize,
299 )
300 return self._stubs["generate_id_token"]
301
302 @property
303 def sign_blob(
304 self,
305 ) -> Callable[[common.SignBlobRequest], Awaitable[common.SignBlobResponse]]:
306 r"""Return a callable for the sign blob method over gRPC.
307
308 Signs a blob using a service account's system-managed
309 private key.
310
311 Returns:
312 Callable[[~.SignBlobRequest],
313 Awaitable[~.SignBlobResponse]]:
314 A function that, when called, will call the underlying RPC
315 on the server.
316 """
317 # Generate a "stub function" on-the-fly which will actually make
318 # the request.
319 # gRPC handles serialization and deserialization, so we just need
320 # to pass in the functions for each.
321 if "sign_blob" not in self._stubs:
322 self._stubs["sign_blob"] = self.grpc_channel.unary_unary(
323 "/google.iam.credentials.v1.IAMCredentials/SignBlob",
324 request_serializer=common.SignBlobRequest.serialize,
325 response_deserializer=common.SignBlobResponse.deserialize,
326 )
327 return self._stubs["sign_blob"]
328
329 @property
330 def sign_jwt(
331 self,
332 ) -> Callable[[common.SignJwtRequest], Awaitable[common.SignJwtResponse]]:
333 r"""Return a callable for the sign jwt method over gRPC.
334
335 Signs a JWT using a service account's system-managed
336 private key.
337
338 Returns:
339 Callable[[~.SignJwtRequest],
340 Awaitable[~.SignJwtResponse]]:
341 A function that, when called, will call the underlying RPC
342 on the server.
343 """
344 # Generate a "stub function" on-the-fly which will actually make
345 # the request.
346 # gRPC handles serialization and deserialization, so we just need
347 # to pass in the functions for each.
348 if "sign_jwt" not in self._stubs:
349 self._stubs["sign_jwt"] = self.grpc_channel.unary_unary(
350 "/google.iam.credentials.v1.IAMCredentials/SignJwt",
351 request_serializer=common.SignJwtRequest.serialize,
352 response_deserializer=common.SignJwtResponse.deserialize,
353 )
354 return self._stubs["sign_jwt"]
355
356 def close(self):
357 return self.grpc_channel.close()
358
359
360__all__ = ("IAMCredentialsGrpcAsyncIOTransport",)