feat: add support for mtls env variables (#1008)

diff --git a/googleapiclient/discovery.py b/googleapiclient/discovery.py
index 7244c5b..13bdf96 100644
--- a/googleapiclient/discovery.py
+++ b/googleapiclient/discovery.py
@@ -117,6 +117,10 @@
 }
 _PAGE_TOKEN_NAMES = ("pageToken", "nextPageToken")
 
+# Parameters controlling mTLS behavior. See https://google.aip.dev/auth/4114.
+GOOGLE_API_USE_CLIENT_CERTIFICATE = "GOOGLE_API_USE_CLIENT_CERTIFICATE"
+GOOGLE_API_USE_MTLS_ENDPOINT = "GOOGLE_API_USE_MTLS_ENDPOINT"
+
 # Parameters accepted by the stack, but not visible via discovery.
 # TODO(dhermes): Remove 'userip' in 'v2'.
 STACK_QUERY_PARAMETERS = frozenset(["trace", "pp", "userip", "strict"])
@@ -215,15 +219,30 @@
     cache: googleapiclient.discovery_cache.base.CacheBase, an optional
       cache object for the discovery documents.
     client_options: Mapping object or google.api_core.client_options, client
-      options to set user options on the client. The API endpoint should be set
-      through client_options. client_cert_source is not supported, client cert
-      should be provided using client_encrypted_cert_source instead.
+      options to set user options on the client.
+      (1) The API endpoint should be set through client_options. If API endpoint
+      is not set, `GOOGLE_API_USE_MTLS_ENDPOINT` environment variable can be used
+      to control which endpoint to use.
+      (2) client_cert_source is not supported, client cert should be provided using
+      client_encrypted_cert_source instead. In order to use the provided client
+      cert, `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable must be
+      set to `true`.
+      More details on the environment variables are here:
+      https://google.aip.dev/auth/4114
     adc_cert_path: str, client certificate file path to save the application
       default client certificate for mTLS. This field is required if you want to
-      use the default client certificate.
+      use the default client certificate. `GOOGLE_API_USE_CLIENT_CERTIFICATE`
+      environment variable must be set to `true` in order to use this field,
+      otherwise this field doesn't nothing.
+      More details on the environment variables are here:
+      https://google.aip.dev/auth/4114
     adc_key_path: str, client encrypted private key file path to save the
       application default client encrypted private key for mTLS. This field is
       required if you want to use the default client certificate.
+      `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable must be set to
+      `true` in order to use this field, otherwise this field doesn't nothing.
+      More details on the environment variables are here:
+      https://google.aip.dev/auth/4114
     num_retries: Integer, number of times to retry discovery with
       randomized exponential backoff in case of intermittent/connection issues.
 
@@ -392,15 +411,30 @@
       google.auth.credentials.Credentials, credentials to be used for
       authentication.
     client_options: Mapping object or google.api_core.client_options, client
-      options to set user options on the client. The API endpoint should be set
-      through client_options. client_cert_source is not supported, client cert
-      should be provided using client_encrypted_cert_source instead.
+      options to set user options on the client.
+      (1) The API endpoint should be set through client_options. If API endpoint
+      is not set, `GOOGLE_API_USE_MTLS_ENDPOINT` environment variable can be used
+      to control which endpoint to use.
+      (2) client_cert_source is not supported, client cert should be provided using
+      client_encrypted_cert_source instead. In order to use the provided client
+      cert, `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable must be
+      set to `true`.
+      More details on the environment variables are here:
+      https://google.aip.dev/auth/4114
     adc_cert_path: str, client certificate file path to save the application
       default client certificate for mTLS. This field is required if you want to
-      use the default client certificate.
+      use the default client certificate. `GOOGLE_API_USE_CLIENT_CERTIFICATE`
+      environment variable must be set to `true` in order to use this field,
+      otherwise this field doesn't nothing.
+      More details on the environment variables are here:
+      https://google.aip.dev/auth/4114
     adc_key_path: str, client encrypted private key file path to save the
       application default client encrypted private key for mTLS. This field is
       required if you want to use the default client certificate.
+      `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable must be set to
+      `true` in order to use this field, otherwise this field doesn't nothing.
+      More details on the environment variables are here:
+      https://google.aip.dev/auth/4114
 
   Returns:
     A Resource object with methods for interacting with the service.
@@ -469,20 +503,26 @@
 
         # Obtain client cert and create mTLS http channel if cert exists.
         client_cert_to_use = None
+        use_client_cert = os.getenv(GOOGLE_API_USE_CLIENT_CERTIFICATE, "false")
+        if not use_client_cert in ("true", "false"):
+            raise MutualTLSChannelError(
+                "Unsupported GOOGLE_API_USE_CLIENT_CERTIFICATE value. Accepted values: true, false"
+            )
         if client_options and client_options.client_cert_source:
             raise MutualTLSChannelError(
                 "ClientOptions.client_cert_source is not supported, please use ClientOptions.client_encrypted_cert_source."
             )
-        if (
-            client_options
-            and hasattr(client_options, "client_encrypted_cert_source")
-            and client_options.client_encrypted_cert_source
-        ):
-            client_cert_to_use = client_options.client_encrypted_cert_source
-        elif adc_cert_path and adc_key_path and mtls.has_default_client_cert_source():
-            client_cert_to_use = mtls.default_client_encrypted_cert_source(
-                adc_cert_path, adc_key_path
-            )
+        if use_client_cert == "true":
+            if (
+                client_options
+                and hasattr(client_options, "client_encrypted_cert_source")
+                and client_options.client_encrypted_cert_source
+            ):
+                client_cert_to_use = client_options.client_encrypted_cert_source
+            elif adc_cert_path and adc_key_path and mtls.has_default_client_cert_source():
+                client_cert_to_use = mtls.default_client_encrypted_cert_source(
+                    adc_cert_path, adc_key_path
+                )
         if client_cert_to_use:
             cert_path, key_path, passphrase = client_cert_to_use()
 
@@ -503,17 +543,17 @@
             not client_options or not client_options.api_endpoint
         ):
             mtls_endpoint = urljoin(service["mtlsRootUrl"], service["servicePath"])
-            use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS", "never")
+            use_mtls_endpoint = os.getenv(GOOGLE_API_USE_MTLS_ENDPOINT, "auto")
 
-            if not use_mtls_env in ("never", "auto", "always"):
+            if not use_mtls_endpoint in ("never", "auto", "always"):
                 raise MutualTLSChannelError(
-                    "Unsupported GOOGLE_API_USE_MTLS value. Accepted values: never, auto, always"
+                    "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always"
                 )
 
             # Switch to mTLS endpoint, if environment variable is "always", or
             # environment varibable is "auto" and client cert exists.
-            if use_mtls_env == "always" or (
-                use_mtls_env == "auto" and client_cert_to_use
+            if use_mtls_endpoint == "always" or (
+                use_mtls_endpoint == "auto" and client_cert_to_use
             ):
                 base = mtls_endpoint
 
diff --git a/tests/test_discovery.py b/tests/test_discovery.py
index 87cc8ed..7e44a3e 100644
--- a/tests/test_discovery.py
+++ b/tests/test_discovery.py
@@ -595,12 +595,12 @@
     ADC_KEY_PATH = "adc_key_path"
     ADC_PASSPHRASE = "adc_passphrase"
 
-    def check_http_client_cert(self, resource, has_client_cert=False):
+    def check_http_client_cert(self, resource, has_client_cert="false"):
         if isinstance(resource._http, google_auth_httplib2.AuthorizedHttp):
             certs = list(resource._http.http.certificates.iter(""))
         else:
             certs = list(resource._http.certificates.iter(""))
-        if has_client_cert:
+        if has_client_cert == "true":
             self.assertEqual(len(certs), 1)
             self.assertEqual(
                 certs[0], (self.ADC_KEY_PATH, self.ADC_CERT_PATH, self.ADC_PASSPHRASE)
@@ -611,67 +611,127 @@
     def client_encrypted_cert_source(self):
         return self.ADC_CERT_PATH, self.ADC_KEY_PATH, self.ADC_PASSPHRASE
 
-    def test_mtls_not_trigger_if_http_provided(self):
+    @parameterized.expand(
+        [
+            ("never", "true"),
+            ("auto", "true"),
+            ("always", "true"),
+            ("never", "false"),
+            ("auto", "false"),
+            ("always", "false"),
+        ]
+    )
+    def test_mtls_not_trigger_if_http_provided(self, use_mtls_env, use_client_cert):
         discovery = read_datafile("plus.json")
-        plus = build_from_document(discovery, http=httplib2.Http())
-        self.assertIsNotNone(plus)
-        self.assertEqual(plus._baseUrl, REGULAR_ENDPOINT)
-        self.check_http_client_cert(plus, has_client_cert=False)
 
-    def test_exception_with_client_cert_source(self):
-        discovery = read_datafile("plus.json")
-        with self.assertRaises(MutualTLSChannelError):
-            build_from_document(
-                discovery,
-                credentials=self.MOCK_CREDENTIALS,
-                client_options={"client_cert_source": mock.Mock()},
-            )
+        with mock.patch.dict(
+            "os.environ", {"GOOGLE_API_USE_MTLS_ENDPOINT": use_mtls_env}
+        ):
+            with mock.patch.dict(
+                "os.environ", {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert}
+            ):
+                plus = build_from_document(discovery, http=httplib2.Http())
+                self.assertIsNotNone(plus)
+                self.assertEqual(plus._baseUrl, REGULAR_ENDPOINT)
+                self.check_http_client_cert(plus, has_client_cert="false")
 
     @parameterized.expand(
         [
-            ("never", REGULAR_ENDPOINT),
-            ("auto", MTLS_ENDPOINT),
-            ("always", MTLS_ENDPOINT),
+            ("never", "true"),
+            ("auto", "true"),
+            ("always", "true"),
+            ("never", "false"),
+            ("auto", "false"),
+            ("always", "false"),
         ]
     )
-    def test_mtls_with_provided_client_cert(self, use_mtls_env, base_url):
+    def test_exception_with_client_cert_source(self, use_mtls_env, use_client_cert):
+        discovery = read_datafile("plus.json")
+        with mock.patch.dict(
+            "os.environ", {"GOOGLE_API_USE_MTLS_ENDPOINT": use_mtls_env}
+        ):
+            with mock.patch.dict(
+                "os.environ", {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert}
+            ):
+                with self.assertRaises(MutualTLSChannelError):
+                    build_from_document(
+                        discovery,
+                        credentials=self.MOCK_CREDENTIALS,
+                        client_options={"client_cert_source": mock.Mock()},
+                    )
+
+    @parameterized.expand(
+        [
+            ("never", "true", REGULAR_ENDPOINT),
+            ("auto", "true", MTLS_ENDPOINT),
+            ("always", "true", MTLS_ENDPOINT),
+            ("never", "false", REGULAR_ENDPOINT),
+            ("auto", "false", REGULAR_ENDPOINT),
+            ("always", "false", MTLS_ENDPOINT),
+        ]
+    )
+    def test_mtls_with_provided_client_cert(
+        self, use_mtls_env, use_client_cert, base_url
+    ):
         discovery = read_datafile("plus.json")
 
-        with mock.patch.dict("os.environ", {"GOOGLE_API_USE_MTLS": use_mtls_env}):
-            plus = build_from_document(
-                discovery,
-                credentials=self.MOCK_CREDENTIALS,
-                client_options={
-                    "client_encrypted_cert_source": self.client_encrypted_cert_source
-                },
-            )
-            self.assertIsNotNone(plus)
-            self.check_http_client_cert(plus, has_client_cert=True)
-            self.assertEqual(plus._baseUrl, base_url)
+        with mock.patch.dict(
+            "os.environ", {"GOOGLE_API_USE_MTLS_ENDPOINT": use_mtls_env}
+        ):
+            with mock.patch.dict(
+                "os.environ", {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert}
+            ):
+                plus = build_from_document(
+                    discovery,
+                    credentials=self.MOCK_CREDENTIALS,
+                    client_options={
+                        "client_encrypted_cert_source": self.client_encrypted_cert_source
+                    },
+                )
+                self.assertIsNotNone(plus)
+                self.check_http_client_cert(plus, has_client_cert=use_client_cert)
+                self.assertEqual(plus._baseUrl, base_url)
 
-    @parameterized.expand(["never", "auto", "always"])
-    def test_endpoint_not_switch(self, use_mtls_env):
+    @parameterized.expand(
+        [
+            ("never", "true"),
+            ("auto", "true"),
+            ("always", "true"),
+            ("never", "false"),
+            ("auto", "false"),
+            ("always", "false"),
+        ]
+    )
+    def test_endpoint_not_switch(self, use_mtls_env, use_client_cert):
         # Test endpoint is not switched if user provided api endpoint
         discovery = read_datafile("plus.json")
 
-        with mock.patch.dict("os.environ", {"GOOGLE_API_USE_MTLS": use_mtls_env}):
-            plus = build_from_document(
-                discovery,
-                credentials=self.MOCK_CREDENTIALS,
-                client_options={
-                    "api_endpoint": "https://foo.googleapis.com",
-                    "client_encrypted_cert_source": self.client_encrypted_cert_source,
-                },
-            )
-            self.assertIsNotNone(plus)
-            self.check_http_client_cert(plus, has_client_cert=True)
-            self.assertEqual(plus._baseUrl, "https://foo.googleapis.com")
+        with mock.patch.dict(
+            "os.environ", {"GOOGLE_API_USE_MTLS_ENDPOINT": use_mtls_env}
+        ):
+            with mock.patch.dict(
+                "os.environ", {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert}
+            ):
+                plus = build_from_document(
+                    discovery,
+                    credentials=self.MOCK_CREDENTIALS,
+                    client_options={
+                        "api_endpoint": "https://foo.googleapis.com",
+                        "client_encrypted_cert_source": self.client_encrypted_cert_source,
+                    },
+                )
+                self.assertIsNotNone(plus)
+                self.check_http_client_cert(plus, has_client_cert=use_client_cert)
+                self.assertEqual(plus._baseUrl, "https://foo.googleapis.com")
 
     @parameterized.expand(
         [
-            ("never", REGULAR_ENDPOINT),
-            ("auto", MTLS_ENDPOINT),
-            ("always", MTLS_ENDPOINT),
+            ("never", "true", REGULAR_ENDPOINT),
+            ("auto", "true", MTLS_ENDPOINT),
+            ("always", "true", MTLS_ENDPOINT),
+            ("never", "false", REGULAR_ENDPOINT),
+            ("auto", "false", REGULAR_ENDPOINT),
+            ("always", "false", MTLS_ENDPOINT),
         ]
     )
     @mock.patch(
@@ -683,6 +743,7 @@
     def test_mtls_with_default_client_cert(
         self,
         use_mtls_env,
+        use_client_cert,
         base_url,
         default_client_encrypted_cert_source,
         has_default_client_cert_source,
@@ -693,43 +754,56 @@
         )
         discovery = read_datafile("plus.json")
 
-        with mock.patch.dict("os.environ", {"GOOGLE_API_USE_MTLS": use_mtls_env}):
-            plus = build_from_document(
-                discovery,
-                credentials=self.MOCK_CREDENTIALS,
-                adc_cert_path=self.ADC_CERT_PATH,
-                adc_key_path=self.ADC_KEY_PATH,
-            )
-            self.assertIsNotNone(plus)
-            self.check_http_client_cert(plus, has_client_cert=True)
-            self.assertEqual(plus._baseUrl, base_url)
+        with mock.patch.dict(
+            "os.environ", {"GOOGLE_API_USE_MTLS_ENDPOINT": use_mtls_env}
+        ):
+            with mock.patch.dict(
+                "os.environ", {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert}
+            ):
+                plus = build_from_document(
+                    discovery,
+                    credentials=self.MOCK_CREDENTIALS,
+                    adc_cert_path=self.ADC_CERT_PATH,
+                    adc_key_path=self.ADC_KEY_PATH,
+                )
+                self.assertIsNotNone(plus)
+                self.check_http_client_cert(plus, has_client_cert=use_client_cert)
+                self.assertEqual(plus._baseUrl, base_url)
 
     @parameterized.expand(
         [
-            ("never", REGULAR_ENDPOINT),
-            ("auto", REGULAR_ENDPOINT),
-            ("always", MTLS_ENDPOINT),
+            ("never", "true", REGULAR_ENDPOINT),
+            ("auto", "true", REGULAR_ENDPOINT),
+            ("always", "true", MTLS_ENDPOINT),
+            ("never", "false", REGULAR_ENDPOINT),
+            ("auto", "false", REGULAR_ENDPOINT),
+            ("always", "false", MTLS_ENDPOINT),
         ]
     )
     @mock.patch(
         "google.auth.transport.mtls.has_default_client_cert_source", autospec=True
     )
     def test_mtls_with_no_client_cert(
-        self, use_mtls_env, base_url, has_default_client_cert_source
+        self, use_mtls_env, use_client_cert, base_url, has_default_client_cert_source
     ):
         has_default_client_cert_source.return_value = False
         discovery = read_datafile("plus.json")
 
-        with mock.patch.dict("os.environ", {"GOOGLE_API_USE_MTLS": use_mtls_env}):
-            plus = build_from_document(
-                discovery,
-                credentials=self.MOCK_CREDENTIALS,
-                adc_cert_path=self.ADC_CERT_PATH,
-                adc_key_path=self.ADC_KEY_PATH,
-            )
-            self.assertIsNotNone(plus)
-            self.check_http_client_cert(plus, has_client_cert=False)
-            self.assertEqual(plus._baseUrl, base_url)
+        with mock.patch.dict(
+            "os.environ", {"GOOGLE_API_USE_MTLS_ENDPOINT": use_mtls_env}
+        ):
+            with mock.patch.dict(
+                "os.environ", {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert}
+            ):
+                plus = build_from_document(
+                    discovery,
+                    credentials=self.MOCK_CREDENTIALS,
+                    adc_cert_path=self.ADC_CERT_PATH,
+                    adc_key_path=self.ADC_KEY_PATH,
+                )
+                self.assertIsNotNone(plus)
+                self.check_http_client_cert(plus, has_client_cert="false")
+                self.assertEqual(plus._baseUrl, base_url)
 
 
 class DiscoveryFromHttp(unittest.TestCase):