transport.go

  1// Copyright 2023 Google LLC
  2//
  3// Licensed under the Apache License, Version 2.0 (the "License");
  4// you may not use this file except in compliance with the License.
  5// You may obtain a copy of the License at
  6//
  7//      http://www.apache.org/licenses/LICENSE-2.0
  8//
  9// Unless required by applicable law or agreed to in writing, software
 10// distributed under the License is distributed on an "AS IS" BASIS,
 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12// See the License for the specific language governing permissions and
 13// limitations under the License.
 14
 15// Package transport provided internal helpers for the two transport packages
 16// (grpctransport and httptransport).
 17package transport
 18
 19import (
 20	"crypto/tls"
 21	"fmt"
 22	"net"
 23	"net/http"
 24	"time"
 25
 26	"cloud.google.com/go/auth/credentials"
 27)
 28
 29// CloneDetectOptions clones a user set detect option into some new memory that
 30// we can internally manipulate before sending onto the detect package.
 31func CloneDetectOptions(oldDo *credentials.DetectOptions) *credentials.DetectOptions {
 32	if oldDo == nil {
 33		// it is valid for users not to set this, but we will need to to default
 34		// some options for them in this case so return some initialized memory
 35		// to work with.
 36		return &credentials.DetectOptions{}
 37	}
 38	newDo := &credentials.DetectOptions{
 39		// Simple types
 40		Audience:          oldDo.Audience,
 41		Subject:           oldDo.Subject,
 42		EarlyTokenRefresh: oldDo.EarlyTokenRefresh,
 43		TokenURL:          oldDo.TokenURL,
 44		STSAudience:       oldDo.STSAudience,
 45		CredentialsFile:   oldDo.CredentialsFile,
 46		UseSelfSignedJWT:  oldDo.UseSelfSignedJWT,
 47		UniverseDomain:    oldDo.UniverseDomain,
 48
 49		// These fields are are pointer types that we just want to use exactly
 50		// as the user set, copy the ref
 51		Client:             oldDo.Client,
 52		Logger:             oldDo.Logger,
 53		AuthHandlerOptions: oldDo.AuthHandlerOptions,
 54	}
 55
 56	// Smartly size this memory and copy below.
 57	if len(oldDo.CredentialsJSON) > 0 {
 58		newDo.CredentialsJSON = make([]byte, len(oldDo.CredentialsJSON))
 59		copy(newDo.CredentialsJSON, oldDo.CredentialsJSON)
 60	}
 61	if len(oldDo.Scopes) > 0 {
 62		newDo.Scopes = make([]string, len(oldDo.Scopes))
 63		copy(newDo.Scopes, oldDo.Scopes)
 64	}
 65
 66	return newDo
 67}
 68
 69// ValidateUniverseDomain verifies that the universe domain configured for the
 70// client matches the universe domain configured for the credentials.
 71func ValidateUniverseDomain(clientUniverseDomain, credentialsUniverseDomain string) error {
 72	if clientUniverseDomain != credentialsUniverseDomain {
 73		return fmt.Errorf(
 74			"the configured universe domain (%q) does not match the universe "+
 75				"domain found in the credentials (%q). If you haven't configured "+
 76				"the universe domain explicitly, \"googleapis.com\" is the default",
 77			clientUniverseDomain,
 78			credentialsUniverseDomain)
 79	}
 80	return nil
 81}
 82
 83// DefaultHTTPClientWithTLS constructs an HTTPClient using the provided tlsConfig, to support mTLS.
 84func DefaultHTTPClientWithTLS(tlsConfig *tls.Config) *http.Client {
 85	trans := BaseTransport()
 86	trans.TLSClientConfig = tlsConfig
 87	return &http.Client{Transport: trans}
 88}
 89
 90// BaseTransport returns a default [http.Transport] which can be used if
 91// [http.DefaultTransport] has been overwritten.
 92func BaseTransport() *http.Transport {
 93	return &http.Transport{
 94		Proxy: http.ProxyFromEnvironment,
 95		DialContext: (&net.Dialer{
 96			Timeout:   30 * time.Second,
 97			KeepAlive: 30 * time.Second,
 98			DualStack: true,
 99		}).DialContext,
100		MaxIdleConns:          100,
101		MaxIdleConnsPerHost:   100,
102		IdleConnTimeout:       90 * time.Second,
103		TLSHandshakeTimeout:   10 * time.Second,
104		ExpectContinueTimeout: 1 * time.Second,
105	}
106}