Skip to content

Commit 2fc5ca1

Browse files
feat: add support for mtls env variables (#1008)
1 parent 1026375 commit 2fc5ca1

File tree

2 files changed

+207
-93
lines changed

2 files changed

+207
-93
lines changed

googleapiclient/discovery.py

Lines changed: 63 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@
117117
}
118118
_PAGE_TOKEN_NAMES = ("pageToken", "nextPageToken")
119119

120+
# Parameters controlling mTLS behavior. See https://google.aip.dev/auth/4114.
121+
GOOGLE_API_USE_CLIENT_CERTIFICATE = "GOOGLE_API_USE_CLIENT_CERTIFICATE"
122+
GOOGLE_API_USE_MTLS_ENDPOINT = "GOOGLE_API_USE_MTLS_ENDPOINT"
123+
120124
# Parameters accepted by the stack, but not visible via discovery.
121125
# TODO(dhermes): Remove 'userip' in 'v2'.
122126
STACK_QUERY_PARAMETERS = frozenset(["trace", "pp", "userip", "strict"])
@@ -215,15 +219,30 @@ def build(
215219
cache: googleapiclient.discovery_cache.base.CacheBase, an optional
216220
cache object for the discovery documents.
217221
client_options: Mapping object or google.api_core.client_options, client
218-
options to set user options on the client. The API endpoint should be set
219-
through client_options. client_cert_source is not supported, client cert
220-
should be provided using client_encrypted_cert_source instead.
222+
options to set user options on the client.
223+
(1) The API endpoint should be set through client_options. If API endpoint
224+
is not set, `GOOGLE_API_USE_MTLS_ENDPOINT` environment variable can be used
225+
to control which endpoint to use.
226+
(2) client_cert_source is not supported, client cert should be provided using
227+
client_encrypted_cert_source instead. In order to use the provided client
228+
cert, `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable must be
229+
set to `true`.
230+
More details on the environment variables are here:
231+
https://google.aip.dev/auth/4114
221232
adc_cert_path: str, client certificate file path to save the application
222233
default client certificate for mTLS. This field is required if you want to
223-
use the default client certificate.
234+
use the default client certificate. `GOOGLE_API_USE_CLIENT_CERTIFICATE`
235+
environment variable must be set to `true` in order to use this field,
236+
otherwise this field doesn't nothing.
237+
More details on the environment variables are here:
238+
https://google.aip.dev/auth/4114
224239
adc_key_path: str, client encrypted private key file path to save the
225240
application default client encrypted private key for mTLS. This field is
226241
required if you want to use the default client certificate.
242+
`GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable must be set to
243+
`true` in order to use this field, otherwise this field doesn't nothing.
244+
More details on the environment variables are here:
245+
https://google.aip.dev/auth/4114
227246
num_retries: Integer, number of times to retry discovery with
228247
randomized exponential backoff in case of intermittent/connection issues.
229248
@@ -392,15 +411,30 @@ def build_from_document(
392411
google.auth.credentials.Credentials, credentials to be used for
393412
authentication.
394413
client_options: Mapping object or google.api_core.client_options, client
395-
options to set user options on the client. The API endpoint should be set
396-
through client_options. client_cert_source is not supported, client cert
397-
should be provided using client_encrypted_cert_source instead.
414+
options to set user options on the client.
415+
(1) The API endpoint should be set through client_options. If API endpoint
416+
is not set, `GOOGLE_API_USE_MTLS_ENDPOINT` environment variable can be used
417+
to control which endpoint to use.
418+
(2) client_cert_source is not supported, client cert should be provided using
419+
client_encrypted_cert_source instead. In order to use the provided client
420+
cert, `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable must be
421+
set to `true`.
422+
More details on the environment variables are here:
423+
https://google.aip.dev/auth/4114
398424
adc_cert_path: str, client certificate file path to save the application
399425
default client certificate for mTLS. This field is required if you want to
400-
use the default client certificate.
426+
use the default client certificate. `GOOGLE_API_USE_CLIENT_CERTIFICATE`
427+
environment variable must be set to `true` in order to use this field,
428+
otherwise this field doesn't nothing.
429+
More details on the environment variables are here:
430+
https://google.aip.dev/auth/4114
401431
adc_key_path: str, client encrypted private key file path to save the
402432
application default client encrypted private key for mTLS. This field is
403433
required if you want to use the default client certificate.
434+
`GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable must be set to
435+
`true` in order to use this field, otherwise this field doesn't nothing.
436+
More details on the environment variables are here:
437+
https://google.aip.dev/auth/4114
404438
405439
Returns:
406440
A Resource object with methods for interacting with the service.
@@ -469,20 +503,26 @@ def build_from_document(
469503

470504
# Obtain client cert and create mTLS http channel if cert exists.
471505
client_cert_to_use = None
506+
use_client_cert = os.getenv(GOOGLE_API_USE_CLIENT_CERTIFICATE, "false")
507+
if not use_client_cert in ("true", "false"):
508+
raise MutualTLSChannelError(
509+
"Unsupported GOOGLE_API_USE_CLIENT_CERTIFICATE value. Accepted values: true, false"
510+
)
472511
if client_options and client_options.client_cert_source:
473512
raise MutualTLSChannelError(
474513
"ClientOptions.client_cert_source is not supported, please use ClientOptions.client_encrypted_cert_source."
475514
)
476-
if (
477-
client_options
478-
and hasattr(client_options, "client_encrypted_cert_source")
479-
and client_options.client_encrypted_cert_source
480-
):
481-
client_cert_to_use = client_options.client_encrypted_cert_source
482-
elif adc_cert_path and adc_key_path and mtls.has_default_client_cert_source():
483-
client_cert_to_use = mtls.default_client_encrypted_cert_source(
484-
adc_cert_path, adc_key_path
485-
)
515+
if use_client_cert == "true":
516+
if (
517+
client_options
518+
and hasattr(client_options, "client_encrypted_cert_source")
519+
and client_options.client_encrypted_cert_source
520+
):
521+
client_cert_to_use = client_options.client_encrypted_cert_source
522+
elif adc_cert_path and adc_key_path and mtls.has_default_client_cert_source():
523+
client_cert_to_use = mtls.default_client_encrypted_cert_source(
524+
adc_cert_path, adc_key_path
525+
)
486526
if client_cert_to_use:
487527
cert_path, key_path, passphrase = client_cert_to_use()
488528

@@ -503,17 +543,17 @@ def build_from_document(
503543
not client_options or not client_options.api_endpoint
504544
):
505545
mtls_endpoint = urljoin(service["mtlsRootUrl"], service["servicePath"])
506-
use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS", "never")
546+
use_mtls_endpoint = os.getenv(GOOGLE_API_USE_MTLS_ENDPOINT, "auto")
507547

508-
if not use_mtls_env in ("never", "auto", "always"):
548+
if not use_mtls_endpoint in ("never", "auto", "always"):
509549
raise MutualTLSChannelError(
510-
"Unsupported GOOGLE_API_USE_MTLS value. Accepted values: never, auto, always"
550+
"Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always"
511551
)
512552

513553
# Switch to mTLS endpoint, if environment variable is "always", or
514554
# environment varibable is "auto" and client cert exists.
515-
if use_mtls_env == "always" or (
516-
use_mtls_env == "auto" and client_cert_to_use
555+
if use_mtls_endpoint == "always" or (
556+
use_mtls_endpoint == "auto" and client_cert_to_use
517557
):
518558
base = mtls_endpoint
519559

0 commit comments

Comments
 (0)