1818
1919import os
2020import re
21- from typing import Any , Optional
21+ import uuid
22+ from typing import Any , Optional , Tuple
2223
2324from google .auth .exceptions import MutualTLSChannelError # type: ignore
2425from google .auth .transport import mtls # type: ignore
2526
2627_MTLS_ENDPOINT_RE = re .compile (
27- r"(?P<name>[^.]+)(?P<mtls>\.mtls)?(?P<sandbox>\.sandbox)?(?P<googledomain>\.googleapis\.com)?"
28+ r"(?P<name>[^.]+)(?P<mtls>\.mtls)?(?P<sandbox>\.sandbox)?"
29+ r"(?P<googledomain>\.googleapis\.com)?"
2830)
2931
3032
@@ -60,17 +62,20 @@ def _get_default_mtls_endpoint(api_endpoint: Optional[str]) -> Optional[str]:
6062
6163def _use_client_cert_effective () -> bool :
6264 """Returns whether client certificate should be used for mTLS if the
63- google-auth version supports should_use_client_cert automatic mTLS enablement.
65+ google-auth version supports should_use_client_cert automatic mTLS
66+ enablement.
6467
6568 Alternatively, read from the GOOGLE_API_USE_CLIENT_CERTIFICATE env var.
6669
6770 Returns:
6871 bool: whether client certificate should be used for mTLS
6972 Raises:
70- ValueError: (If using a version of google-auth without should_use_client_cert and
71- GOOGLE_API_USE_CLIENT_CERTIFICATE is set to an unexpected value.)
73+ ValueError: (If using a version of google-auth without
74+ should_use_client_cert and GOOGLE_API_USE_CLIENT_CERTIFICATE is
75+ set to an unexpected value.)
7276 """
73- # check if google-auth version supports should_use_client_cert for automatic mTLS enablement
77+ # check if google-auth version supports should_use_client_cert for
78+ # automatic mTLS enablement
7479 if hasattr (mtls , "should_use_client_cert" ): # pragma: NO COVER
7580 return mtls .should_use_client_cert ()
7681 else : # pragma: NO COVER
@@ -80,8 +85,8 @@ def _use_client_cert_effective() -> bool:
8085 ).lower ()
8186 if use_client_cert_str not in ("true" , "false" ):
8287 raise ValueError (
83- "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be "
84- " either `true` or `false`"
88+ "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` "
89+ "must be either `true` or `false`"
8590 )
8691 return use_client_cert_str == "true"
8792
@@ -116,8 +121,127 @@ def _get_api_endpoint(
116121 ):
117122 if universe_domain != default_universe :
118123 raise MutualTLSChannelError (
119- f"mTLS is not supported in any universe other than { default_universe } ."
124+ f"mTLS is not supported in any universe other than "
125+ f"{ default_universe } ."
120126 )
121127 return default_mtls_endpoint
122128 else :
123- return default_endpoint_template .format (UNIVERSE_DOMAIN = universe_domain )
129+ return default_endpoint_template .format (
130+ UNIVERSE_DOMAIN = universe_domain
131+ )
132+
133+
134+ def _read_environment_variables () -> Tuple [bool , str , Optional [str ]]:
135+ """Returns the environment variables used by the client.
136+
137+ Returns:
138+ Tuple[bool, str, Optional[str]]: returns the
139+ GOOGLE_API_USE_CLIENT_CERTIFICATE, GOOGLE_API_USE_MTLS_ENDPOINT,
140+ and GOOGLE_CLOUD_UNIVERSE_DOMAIN environment variables.
141+
142+ Raises:
143+ ValueError: If GOOGLE_API_USE_CLIENT_CERTIFICATE is not
144+ any of ["true", "false"].
145+ google.auth.exceptions.MutualTLSChannelError: If
146+ GOOGLE_API_USE_MTLS_ENDPOINT is not any of
147+ ["auto", "never", "always"].
148+ """
149+ use_client_cert = _use_client_cert_effective ()
150+ use_mtls_endpoint = os .getenv (
151+ "GOOGLE_API_USE_MTLS_ENDPOINT" , "auto"
152+ ).lower ()
153+ universe_domain_env = os .getenv ("GOOGLE_CLOUD_UNIVERSE_DOMAIN" )
154+ if use_mtls_endpoint not in ("auto" , "never" , "always" ):
155+ raise MutualTLSChannelError (
156+ "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` "
157+ "must be `never`, `auto` or `always`"
158+ )
159+ return use_client_cert , use_mtls_endpoint , universe_domain_env
160+
161+
162+ def _get_client_cert_source (
163+ provided_cert_source : Optional [Any ], use_cert_flag : bool
164+ ) -> Optional [Any ]:
165+ """Return the client cert source to be used by the client.
166+
167+ Args:
168+ provided_cert_source (bytes): The client certificate source provided.
169+ use_cert_flag (bool): A flag indicating whether to use the
170+ client certificate.
171+
172+ Returns:
173+ bytes or None: The client cert source to be used by the client.
174+ """
175+ client_cert_source = None
176+ if use_cert_flag :
177+ if provided_cert_source :
178+ client_cert_source = provided_cert_source
179+ elif (
180+ hasattr (mtls , "has_default_client_cert_source" )
181+ and mtls .has_default_client_cert_source ()
182+ ):
183+ client_cert_source = mtls .default_client_cert_source ()
184+ return client_cert_source
185+
186+
187+ def _get_universe_domain (
188+ client_universe_domain : Optional [str ],
189+ universe_domain_env : Optional [str ],
190+ default_universe : str ,
191+ ) -> str :
192+ """Return the universe domain used by the client.
193+
194+ Args:
195+ client_universe_domain (Optional[str]): The universe domain
196+ configured via the client options.
197+ universe_domain_env (Optional[str]): The universe domain
198+ configured via the "GOOGLE_CLOUD_UNIVERSE_DOMAIN" env var.
199+ default_universe (str): The default universe domain.
200+
201+ Returns:
202+ str: The universe domain to be used by the client.
203+
204+ Raises:
205+ ValueError: If the universe domain is an empty string.
206+ """
207+ universe_domain = default_universe
208+ if client_universe_domain is not None :
209+ universe_domain = client_universe_domain
210+ elif universe_domain_env is not None :
211+ universe_domain = universe_domain_env
212+ if len (universe_domain .strip ()) == 0 :
213+ raise ValueError ("Universe Domain cannot be an empty string." )
214+ return universe_domain
215+
216+
217+ def _setup_request_id (
218+ request : Any , field_name : str , is_proto3_optional : bool
219+ ) -> None :
220+ """Populate a UUID4 field in the request if it is not already set.
221+
222+ Args:
223+ request (Union[google.protobuf.message.Message, dict]): The
224+ request object.
225+ field_name (str): The name of the field to populate.
226+ is_proto3_optional (bool): Whether the field is proto3 optional.
227+ """
228+ if isinstance (request , dict ):
229+ if is_proto3_optional :
230+ if field_name not in request :
231+ request [field_name ] = str (uuid .uuid4 ())
232+ elif not request .get (field_name ):
233+ request [field_name ] = str (uuid .uuid4 ())
234+ return
235+
236+ if is_proto3_optional :
237+ try :
238+ # Pure protobuf messages
239+ if not request .HasField (field_name ):
240+ setattr (request , field_name , str (uuid .uuid4 ()))
241+ except (AttributeError , ValueError ):
242+ # Proto-plus messages or other objects
243+ if field_name not in request :
244+ setattr (request , field_name , str (uuid .uuid4 ()))
245+ else :
246+ if not getattr (request , field_name ):
247+ setattr (request , field_name , str (uuid .uuid4 ()))
0 commit comments