@@ -273,6 +273,73 @@ def parse_common_location_path(path: str) -> Dict[str, str]:
273273 m = re .match (r"^projects/(?P<project>.+?)/locations/(?P<location>.+?)$" , path )
274274 return m .groupdict () if m else {}
275275
276+ @classmethod
277+ def get_mtls_endpoint_and_cert_source (
278+ cls , client_options : Optional [client_options_lib .ClientOptions ] = None
279+ ):
280+ """Return the API endpoint and client cert source for mutual TLS.
281+
282+ The client cert source is determined in the following order:
283+ (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the
284+ client cert source is None.
285+ (2) if `client_options.client_cert_source` is provided, use the provided one; if the
286+ default client cert source exists, use the default one; otherwise the client cert
287+ source is None.
288+
289+ The API endpoint is determined in the following order:
290+ (1) if `client_options.api_endpoint` if provided, use the provided one.
291+ (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the
292+ default mTLS endpoint; if the environment variabel is "never", use the default API
293+ endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise
294+ use the default API endpoint.
295+
296+ More details can be found at https://google.aip.dev/auth/4114.
297+
298+ Args:
299+ client_options (google.api_core.client_options.ClientOptions): Custom options for the
300+ client. Only the `api_endpoint` and `client_cert_source` properties may be used
301+ in this method.
302+
303+ Returns:
304+ Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the
305+ client cert source to use.
306+
307+ Raises:
308+ google.auth.exceptions.MutualTLSChannelError: If any errors happen.
309+ """
310+ if client_options is None :
311+ client_options = client_options_lib .ClientOptions ()
312+ use_client_cert = os .getenv ("GOOGLE_API_USE_CLIENT_CERTIFICATE" , "false" )
313+ use_mtls_endpoint = os .getenv ("GOOGLE_API_USE_MTLS_ENDPOINT" , "auto" )
314+ if use_client_cert not in ("true" , "false" ):
315+ raise ValueError (
316+ "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
317+ )
318+ if use_mtls_endpoint not in ("auto" , "never" , "always" ):
319+ raise MutualTLSChannelError (
320+ "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
321+ )
322+
323+ # Figure out the client cert source to use.
324+ client_cert_source = None
325+ if use_client_cert == "true" :
326+ if client_options .client_cert_source :
327+ client_cert_source = client_options .client_cert_source
328+ elif mtls .has_default_client_cert_source ():
329+ client_cert_source = mtls .default_client_cert_source ()
330+
331+ # Figure out which api endpoint to use.
332+ if client_options .api_endpoint is not None :
333+ api_endpoint = client_options .api_endpoint
334+ elif use_mtls_endpoint == "always" or (
335+ use_mtls_endpoint == "auto" and client_cert_source
336+ ):
337+ api_endpoint = cls .DEFAULT_MTLS_ENDPOINT
338+ else :
339+ api_endpoint = cls .DEFAULT_ENDPOINT
340+
341+ return api_endpoint , client_cert_source
342+
276343 def __init__ (
277344 self ,
278345 * ,
@@ -323,57 +390,22 @@ def __init__(
323390 if client_options is None :
324391 client_options = client_options_lib .ClientOptions ()
325392
326- # Create SSL credentials for mutual TLS if needed.
327- if os .getenv ("GOOGLE_API_USE_CLIENT_CERTIFICATE" , "false" ) not in (
328- "true" ,
329- "false" ,
330- ):
331- raise ValueError (
332- "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
333- )
334- use_client_cert = (
335- os .getenv ("GOOGLE_API_USE_CLIENT_CERTIFICATE" , "false" ) == "true"
393+ api_endpoint , client_cert_source_func = self .get_mtls_endpoint_and_cert_source (
394+ client_options
336395 )
337396
338- client_cert_source_func = None
339- is_mtls = False
340- if use_client_cert :
341- if client_options .client_cert_source :
342- is_mtls = True
343- client_cert_source_func = client_options .client_cert_source
344- else :
345- is_mtls = mtls .has_default_client_cert_source ()
346- if is_mtls :
347- client_cert_source_func = mtls .default_client_cert_source ()
348- else :
349- client_cert_source_func = None
350-
351- # Figure out which api endpoint to use.
352- if client_options .api_endpoint is not None :
353- api_endpoint = client_options .api_endpoint
354- else :
355- use_mtls_env = os .getenv ("GOOGLE_API_USE_MTLS_ENDPOINT" , "auto" )
356- if use_mtls_env == "never" :
357- api_endpoint = self .DEFAULT_ENDPOINT
358- elif use_mtls_env == "always" :
359- api_endpoint = self .DEFAULT_MTLS_ENDPOINT
360- elif use_mtls_env == "auto" :
361- if is_mtls :
362- api_endpoint = self .DEFAULT_MTLS_ENDPOINT
363- else :
364- api_endpoint = self .DEFAULT_ENDPOINT
365- else :
366- raise MutualTLSChannelError (
367- "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted "
368- "values: never, auto, always"
369- )
397+ api_key_value = getattr (client_options , "api_key" , None )
398+ if api_key_value and credentials :
399+ raise ValueError (
400+ "client_options.api_key and credentials are mutually exclusive"
401+ )
370402
371403 # Save or instantiate the transport.
372404 # Ordinarily, we provide the transport, but allowing a custom transport
373405 # instance provides an extensibility point for unusual situations.
374406 if isinstance (transport , TpuTransport ):
375407 # transport is a TpuTransport instance.
376- if credentials or client_options .credentials_file :
408+ if credentials or client_options .credentials_file or api_key_value :
377409 raise ValueError (
378410 "When providing a transport instance, "
379411 "provide its credentials directly."
@@ -385,6 +417,15 @@ def __init__(
385417 )
386418 self ._transport = transport
387419 else :
420+ import google .auth ._default # type: ignore
421+
422+ if api_key_value and hasattr (
423+ google .auth ._default , "get_api_key_credentials"
424+ ):
425+ credentials = google .auth ._default .get_api_key_credentials (
426+ api_key_value
427+ )
428+
388429 Transport = type (self ).get_transport_class (transport )
389430 self ._transport = Transport (
390431 credentials = credentials ,
0 commit comments