transport: support GOOGLE_API_USE_MTLS

Allow GOOGLE_API_USE_MTLS overriding the mTLS endpoint
behavior for the HTTP client.

The variable has the following values:
- always: The mTLS endpoint is always used
- never: The regular endpoint is always used
- auto: The mTLS will be enabled if the client ceritificate is found

Change-Id: I096f80fcac7a1a79b9f0d8b7ab200b58b5448c6a
Reviewed-on: https://code-review.googlesource.com/c/google-api-go-client/+/56370
Reviewed-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Chris Broadfoot <cbro@google.com>
diff --git a/transport/http/dial.go b/transport/http/dial.go
index 075ef87..c8d79b8 100644
--- a/transport/http/dial.go
+++ b/transport/http/dial.go
@@ -13,6 +13,7 @@
 	"errors"
 	"net/http"
 	"net/url"
+	"os"
 	"strings"
 
 	"go.opencensus.io/plugin/ochttp"
@@ -24,6 +25,12 @@
 	"google.golang.org/api/transport/http/internal/propagation"
 )
 
+const (
+	mTLSModeAlways = "always"
+	mTLSModeNever  = "never"
+	mTLSModeAuto   = "auto"
+)
+
 // NewClient returns an HTTP client for use communicating with a Google cloud
 // service, configured with the given ClientOptions. It also returns the endpoint
 // for the service as specified in the options.
@@ -207,26 +214,24 @@
 // We would like to avoid introducing client-side logic that parses whether the
 // endpoint override is an mTLS url, since the url pattern may change at anytime.
 func getClientCertificateSource(settings *internal.DialSettings) (cert.Source, error) {
-	return settings.ClientCertSource, nil
-	// TODO(andyzhao): Currently, many services including compute, storage, and bigquery
-	// do not have working mTLS endpoints, so we will disable the ADC for DCA logic
-	// until we can confirm that all services have working mTLS endpoints.
-	/*
-		if settings.HTTPClient != nil {
-			return nil, nil // HTTPClient is incompatible with ClientCertificateSource
-		} else if settings.ClientCertSource != nil {
-			return settings.ClientCertSource, nil
-		} else {
-			return cert.DefaultSoure()
-		}
-	*/
+	if settings.HTTPClient != nil {
+		return nil, nil // HTTPClient is incompatible with ClientCertificateSource
+	} else if settings.ClientCertSource != nil {
+		return settings.ClientCertSource, nil
+	} else {
+		return cert.DefaultSource()
+	}
+
 }
 
 // getEndpoint returns the endpoint for the service, taking into account the
 // user-provided endpoint override "settings.Endpoint"
 //
-// If no endpoint override is specified, we will return the default endpoint (or
-// the default mTLS endpoint if a client certificate is available).
+// If no endpoint override is specified, we will either return the default endpoint or
+// the default mTLS endpoint if a client certificate is available.
+//
+// You can override the default endpoint (mtls vs. regular) by setting the
+// GOOGLE_API_USE_MTLS environment variable.
 //
 // If the endpoint override is an address (host:port) rather than full base
 // URL (ex. https://...), then the user-provided address will be merged into
@@ -234,7 +239,8 @@
 // WithDefaultEndpoint("https://foo.com/bar/baz") will return "https://myhost:8080/bar/baz"
 func getEndpoint(settings *internal.DialSettings, clientCertSource cert.Source) (string, error) {
 	if settings.Endpoint == "" {
-		if clientCertSource != nil {
+		mtlsMode := getMTLSMode()
+		if mtlsMode == mTLSModeAlways || (clientCertSource != nil && mtlsMode == mTLSModeAuto) {
 			return generateDefaultMtlsEndpoint(settings.DefaultEndpoint), nil
 		}
 		return settings.DefaultEndpoint, nil
@@ -251,6 +257,15 @@
 	return mergeEndpoints(settings.DefaultEndpoint, settings.Endpoint)
 }
 
+func getMTLSMode() string {
+	mode := os.Getenv("GOOGLE_API_USE_MTLS")
+	if mode == "" {
+		// TODO(shinfan): Update this to "auto" when the mTLS feature is fully released.
+		return mTLSModeNever
+	}
+	return strings.ToLower(mode)
+}
+
 func mergeEndpoints(base, newHost string) (string, error) {
 	u, err := url.Parse(base)
 	if err != nil {
diff --git a/transport/http/dial_test.go b/transport/http/dial_test.go
index ab4369d..0dfab10 100644
--- a/transport/http/dial_test.go
+++ b/transport/http/dial_test.go
@@ -70,11 +70,11 @@
 	}{
 		{
 			DefaultEndpoint: "https://foo.googleapis.com/bar/baz",
-			Want:            "https://foo.mtls.googleapis.com/bar/baz",
+			Want:            "https://foo.googleapis.com/bar/baz",
 		},
 		{
 			DefaultEndpoint: "https://staging-foo.sandbox.googleapis.com/bar/baz",
-			Want:            "https://staging-foo.mtls.sandbox.googleapis.com/bar/baz",
+			Want:            "https://staging-foo.sandbox.googleapis.com/bar/baz",
 		},
 		{
 			UserEndpoint:    "myhost:3999",