@@ -287,6 +287,73 @@ def parse_common_location_path(path: str) -> Dict[str, str]:
287287 m = re .match (r"^projects/(?P<project>.+?)/locations/(?P<location>.+?)$" , path )
288288 return m .groupdict () if m else {}
289289
290+ @classmethod
291+ def get_mtls_endpoint_and_cert_source (
292+ cls , client_options : Optional [client_options_lib .ClientOptions ] = None
293+ ):
294+ """Return the API endpoint and client cert source for mutual TLS.
295+
296+ The client cert source is determined in the following order:
297+ (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the
298+ client cert source is None.
299+ (2) if `client_options.client_cert_source` is provided, use the provided one; if the
300+ default client cert source exists, use the default one; otherwise the client cert
301+ source is None.
302+
303+ The API endpoint is determined in the following order:
304+ (1) if `client_options.api_endpoint` if provided, use the provided one.
305+ (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the
306+ default mTLS endpoint; if the environment variabel is "never", use the default API
307+ endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise
308+ use the default API endpoint.
309+
310+ More details can be found at https://google.aip.dev/auth/4114.
311+
312+ Args:
313+ client_options (google.api_core.client_options.ClientOptions): Custom options for the
314+ client. Only the `api_endpoint` and `client_cert_source` properties may be used
315+ in this method.
316+
317+ Returns:
318+ Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the
319+ client cert source to use.
320+
321+ Raises:
322+ google.auth.exceptions.MutualTLSChannelError: If any errors happen.
323+ """
324+ if client_options is None :
325+ client_options = client_options_lib .ClientOptions ()
326+ use_client_cert = os .getenv ("GOOGLE_API_USE_CLIENT_CERTIFICATE" , "false" )
327+ use_mtls_endpoint = os .getenv ("GOOGLE_API_USE_MTLS_ENDPOINT" , "auto" )
328+ if use_client_cert not in ("true" , "false" ):
329+ raise ValueError (
330+ "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
331+ )
332+ if use_mtls_endpoint not in ("auto" , "never" , "always" ):
333+ raise MutualTLSChannelError (
334+ "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
335+ )
336+
337+ # Figure out the client cert source to use.
338+ client_cert_source = None
339+ if use_client_cert == "true" :
340+ if client_options .client_cert_source :
341+ client_cert_source = client_options .client_cert_source
342+ elif mtls .has_default_client_cert_source ():
343+ client_cert_source = mtls .default_client_cert_source ()
344+
345+ # Figure out which api endpoint to use.
346+ if client_options .api_endpoint is not None :
347+ api_endpoint = client_options .api_endpoint
348+ elif use_mtls_endpoint == "always" or (
349+ use_mtls_endpoint == "auto" and client_cert_source
350+ ):
351+ api_endpoint = cls .DEFAULT_MTLS_ENDPOINT
352+ else :
353+ api_endpoint = cls .DEFAULT_ENDPOINT
354+
355+ return api_endpoint , client_cert_source
356+
290357 def __init__ (
291358 self ,
292359 * ,
@@ -337,57 +404,22 @@ def __init__(
337404 if client_options is None :
338405 client_options = client_options_lib .ClientOptions ()
339406
340- # Create SSL credentials for mutual TLS if needed.
341- if os .getenv ("GOOGLE_API_USE_CLIENT_CERTIFICATE" , "false" ) not in (
342- "true" ,
343- "false" ,
344- ):
345- raise ValueError (
346- "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
347- )
348- use_client_cert = (
349- os .getenv ("GOOGLE_API_USE_CLIENT_CERTIFICATE" , "false" ) == "true"
407+ api_endpoint , client_cert_source_func = self .get_mtls_endpoint_and_cert_source (
408+ client_options
350409 )
351410
352- client_cert_source_func = None
353- is_mtls = False
354- if use_client_cert :
355- if client_options .client_cert_source :
356- is_mtls = True
357- client_cert_source_func = client_options .client_cert_source
358- else :
359- is_mtls = mtls .has_default_client_cert_source ()
360- if is_mtls :
361- client_cert_source_func = mtls .default_client_cert_source ()
362- else :
363- client_cert_source_func = None
364-
365- # Figure out which api endpoint to use.
366- if client_options .api_endpoint is not None :
367- api_endpoint = client_options .api_endpoint
368- else :
369- use_mtls_env = os .getenv ("GOOGLE_API_USE_MTLS_ENDPOINT" , "auto" )
370- if use_mtls_env == "never" :
371- api_endpoint = self .DEFAULT_ENDPOINT
372- elif use_mtls_env == "always" :
373- api_endpoint = self .DEFAULT_MTLS_ENDPOINT
374- elif use_mtls_env == "auto" :
375- if is_mtls :
376- api_endpoint = self .DEFAULT_MTLS_ENDPOINT
377- else :
378- api_endpoint = self .DEFAULT_ENDPOINT
379- else :
380- raise MutualTLSChannelError (
381- "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted "
382- "values: never, auto, always"
383- )
411+ api_key_value = getattr (client_options , "api_key" , None )
412+ if api_key_value and credentials :
413+ raise ValueError (
414+ "client_options.api_key and credentials are mutually exclusive"
415+ )
384416
385417 # Save or instantiate the transport.
386418 # Ordinarily, we provide the transport, but allowing a custom transport
387419 # instance provides an extensibility point for unusual situations.
388420 if isinstance (transport , ConfigServiceV2Transport ):
389421 # transport is a ConfigServiceV2Transport instance.
390- if credentials or client_options .credentials_file :
422+ if credentials or client_options .credentials_file or api_key_value :
391423 raise ValueError (
392424 "When providing a transport instance, "
393425 "provide its credentials directly."
@@ -399,6 +431,15 @@ def __init__(
399431 )
400432 self ._transport = transport
401433 else :
434+ import google .auth ._default # type: ignore
435+
436+ if api_key_value and hasattr (
437+ google .auth ._default , "get_api_key_credentials"
438+ ):
439+ credentials = google .auth ._default .get_api_key_credentials (
440+ api_key_value
441+ )
442+
402443 Transport = type (self ).get_transport_class (transport )
403444 self ._transport = Transport (
404445 credentials = credentials ,
0 commit comments