diff --git a/transport/cert/default_cert.go b/internal/cert/default_cert.go similarity index 100% rename from transport/cert/default_cert.go rename to internal/cert/default_cert.go diff --git a/transport/cert/enterprise_cert.go b/internal/cert/enterprise_cert.go similarity index 100% rename from transport/cert/enterprise_cert.go rename to internal/cert/enterprise_cert.go diff --git a/transport/cert/enterprise_cert_test.go b/internal/cert/enterprise_cert_test.go similarity index 100% rename from transport/cert/enterprise_cert_test.go rename to internal/cert/enterprise_cert_test.go diff --git a/transport/cert/secureconnect_cert.go b/internal/cert/secureconnect_cert.go similarity index 100% rename from transport/cert/secureconnect_cert.go rename to internal/cert/secureconnect_cert.go diff --git a/transport/cert/secureconnect_cert_test.go b/internal/cert/secureconnect_cert_test.go similarity index 100% rename from transport/cert/secureconnect_cert_test.go rename to internal/cert/secureconnect_cert_test.go diff --git a/transport/cert/testdata/certificate_config.json b/internal/cert/testdata/certificate_config.json similarity index 100% rename from transport/cert/testdata/certificate_config.json rename to internal/cert/testdata/certificate_config.json diff --git a/transport/cert/testdata/certificate_config_invalid_pem.json b/internal/cert/testdata/certificate_config_invalid_pem.json similarity index 100% rename from transport/cert/testdata/certificate_config_invalid_pem.json rename to internal/cert/testdata/certificate_config_invalid_pem.json diff --git a/transport/cert/testdata/context_aware_metadata.json b/internal/cert/testdata/context_aware_metadata.json similarity index 100% rename from transport/cert/testdata/context_aware_metadata.json rename to internal/cert/testdata/context_aware_metadata.json diff --git a/transport/cert/testdata/context_aware_metadata_invalid_pem.json b/internal/cert/testdata/context_aware_metadata_invalid_pem.json similarity index 100% rename from transport/cert/testdata/context_aware_metadata_invalid_pem.json rename to internal/cert/testdata/context_aware_metadata_invalid_pem.json diff --git a/transport/cert/testdata/context_aware_metadata_nonexpiring_pem.json b/internal/cert/testdata/context_aware_metadata_nonexpiring_pem.json similarity index 100% rename from transport/cert/testdata/context_aware_metadata_nonexpiring_pem.json rename to internal/cert/testdata/context_aware_metadata_nonexpiring_pem.json diff --git a/transport/cert/testdata/invalid.pem b/internal/cert/testdata/invalid.pem similarity index 100% rename from transport/cert/testdata/invalid.pem rename to internal/cert/testdata/invalid.pem diff --git a/transport/cert/testdata/nonexpiring.pem b/internal/cert/testdata/nonexpiring.pem similarity index 100% rename from transport/cert/testdata/nonexpiring.pem rename to internal/cert/testdata/nonexpiring.pem diff --git a/transport/cert/testdata/rsa2048bit.pem b/internal/cert/testdata/rsa2048bit.pem similarity index 100% rename from transport/cert/testdata/rsa2048bit.pem rename to internal/cert/testdata/rsa2048bit.pem diff --git a/transport/cert/testdata/signer.sh b/internal/cert/testdata/signer.sh similarity index 70% rename from transport/cert/testdata/signer.sh rename to internal/cert/testdata/signer.sh index 6b4fb6cd960..85f8b859ff1 100755 --- a/transport/cert/testdata/signer.sh +++ b/internal/cert/testdata/signer.sh @@ -4,4 +4,4 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -go run ../internal/ecp/test_signer.go testdata/rsa2048bit.pem +go run ../ecp/test_signer.go testdata/rsa2048bit.pem diff --git a/transport/cert/testdata/signer_invalid_pem.sh b/internal/cert/testdata/signer_invalid_pem.sh similarity index 71% rename from transport/cert/testdata/signer_invalid_pem.sh rename to internal/cert/testdata/signer_invalid_pem.sh index f97fb1489f9..c7d2fd775e4 100755 --- a/transport/cert/testdata/signer_invalid_pem.sh +++ b/internal/cert/testdata/signer_invalid_pem.sh @@ -4,4 +4,4 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -go run ../internal/ecp/test_signer.go testdata/invalid.pem +go run ../ecp/test_signer.go testdata/invalid.pem diff --git a/transport/cert/testdata/testcert.pem b/internal/cert/testdata/testcert.pem similarity index 100% rename from transport/cert/testdata/testcert.pem rename to internal/cert/testdata/testcert.pem diff --git a/internal/creds.go b/internal/creds.go index 32d52413b30..69b186b70a7 100644 --- a/internal/creds.go +++ b/internal/creds.go @@ -6,10 +6,14 @@ package internal import ( "context" + "crypto/tls" "encoding/json" "errors" "fmt" "io/ioutil" + "net" + "net/http" + "time" "golang.org/x/oauth2" "google.golang.org/api/internal/impersonate" @@ -80,8 +84,25 @@ const ( // - Otherwise, executes standard OAuth 2.0 flow // More details: google.aip.dev/auth/4111 func credentialsFromJSON(ctx context.Context, data []byte, ds *DialSettings) (*google.Credentials, error) { + var params google.CredentialsParams + params.Scopes = ds.GetScopes() + + // Determine configurations for the OAuth2 transport, which is separate from the API transport. + // The OAuth2 transport and endpoint will be configured for mTLS if applicable. + clientCertSource, oauth2Endpoint, err := GetClientCertificateSourceAndEndpoint(oauth2DialSettings(ds)) + if err != nil { + return nil, err + } + params.TokenURL = oauth2Endpoint + if clientCertSource != nil { + tlsConfig := &tls.Config{ + GetClientCertificate: clientCertSource, + } + ctx = context.WithValue(ctx, oauth2.HTTPClient, customHTTPClient(tlsConfig)) + } + // By default, a standard OAuth 2.0 token source is created - cred, err := google.CredentialsFromJSON(ctx, data, ds.GetScopes()...) + cred, err := google.CredentialsFromJSONWithParams(ctx, data, params) if err != nil { return nil, err } @@ -157,3 +178,35 @@ func impersonateCredentials(ctx context.Context, creds *google.Credentials, ds * ProjectID: creds.ProjectID, }, nil } + +// oauth2DialSettings returns the settings to be used by the OAuth2 transport, which is separate from the API transport. +func oauth2DialSettings(ds *DialSettings) *DialSettings { + var ods DialSettings + ods.DefaultEndpoint = google.Endpoint.TokenURL + ods.DefaultMTLSEndpoint = google.MTLSTokenURL + ods.ClientCertSource = ds.ClientCertSource + return &ods +} + +// customHTTPClient constructs an HTTPClient using the provided tlsConfig, to support mTLS. +func customHTTPClient(tlsConfig *tls.Config) *http.Client { + trans := baseTransport() + trans.TLSClientConfig = tlsConfig + return &http.Client{Transport: trans} +} + +func baseTransport() *http.Transport { + return &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + DualStack: true, + }).DialContext, + MaxIdleConns: 100, + MaxIdleConnsPerHost: 100, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + } +} diff --git a/transport/internal/dca/dca.go b/internal/dca.go similarity index 92% rename from transport/internal/dca/dca.go rename to internal/dca.go index 78004f0475f..204a3fd2f3f 100644 --- a/transport/internal/dca/dca.go +++ b/internal/dca.go @@ -23,15 +23,16 @@ // // This package is not intended for use by end developers. Use the // google.golang.org/api/option package to configure API clients. -package dca + +// Package internal supports the options and transport packages. +package internal import ( "net/url" "os" "strings" - "google.golang.org/api/internal" - "google.golang.org/api/transport/cert" + "google.golang.org/api/internal/cert" ) const ( @@ -43,7 +44,7 @@ const ( // GetClientCertificateSourceAndEndpoint is a convenience function that invokes // getClientCertificateSource and getEndpoint sequentially and returns the client // cert source and endpoint as a tuple. -func GetClientCertificateSourceAndEndpoint(settings *internal.DialSettings) (cert.Source, string, error) { +func GetClientCertificateSourceAndEndpoint(settings *DialSettings) (cert.Source, string, error) { clientCertSource, err := getClientCertificateSource(settings) if err != nil { return nil, "", err @@ -65,7 +66,7 @@ func GetClientCertificateSourceAndEndpoint(settings *internal.DialSettings) (cer // Important Note: For now, the environment variable GOOGLE_API_USE_CLIENT_CERTIFICATE // must be set to "true" to allow certificate to be used (including user provided // certificates). For details, see AIP-4114. -func getClientCertificateSource(settings *internal.DialSettings) (cert.Source, error) { +func getClientCertificateSource(settings *DialSettings) (cert.Source, error) { if !isClientCertificateEnabled() { return nil, nil } else if settings.ClientCertSource != nil { @@ -94,7 +95,7 @@ func isClientCertificateEnabled() bool { // URL (ex. https://...), then the user-provided address will be merged into // the default endpoint. For example, WithEndpoint("myhost:8000") and // WithDefaultEndpoint("https://foo.com/bar/baz") will return "https://myhost:8080/bar/baz" -func getEndpoint(settings *internal.DialSettings, clientCertSource cert.Source) (string, error) { +func getEndpoint(settings *DialSettings, clientCertSource cert.Source) (string, error) { if settings.Endpoint == "" { mtlsMode := getMTLSMode() if mtlsMode == mTLSModeAlways || (clientCertSource != nil && mtlsMode == mTLSModeAuto) { diff --git a/transport/internal/dca/dca_test.go b/internal/dca_test.go similarity index 95% rename from transport/internal/dca/dca_test.go rename to internal/dca_test.go index 8597d090815..6ff7ad91531 100644 --- a/transport/internal/dca/dca_test.go +++ b/internal/dca_test.go @@ -2,14 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package dca +package internal import ( "testing" "crypto/tls" - - "google.golang.org/api/internal" ) func TestGetEndpoint(t *testing.T) { @@ -51,7 +49,7 @@ func TestGetEndpoint(t *testing.T) { } for _, tc := range testCases { - got, err := getEndpoint(&internal.DialSettings{ + got, err := getEndpoint(&DialSettings{ Endpoint: tc.UserEndpoint, DefaultEndpoint: tc.DefaultEndpoint, }, nil) @@ -106,7 +104,7 @@ func TestGetEndpointWithClientCertSource(t *testing.T) { } for _, tc := range testCases { - got, err := getEndpoint(&internal.DialSettings{ + got, err := getEndpoint(&DialSettings{ Endpoint: tc.UserEndpoint, DefaultEndpoint: tc.DefaultEndpoint, DefaultMTLSEndpoint: tc.DefaultMTLSEndpoint, diff --git a/transport/internal/ecp/test_signer.go b/internal/ecp/test_signer.go similarity index 100% rename from transport/internal/ecp/test_signer.go rename to internal/ecp/test_signer.go diff --git a/transport/grpc/dial.go b/transport/grpc/dial.go index efcc8e6c641..c76894ff4c6 100644 --- a/transport/grpc/dial.go +++ b/transport/grpc/dial.go @@ -21,7 +21,6 @@ import ( "golang.org/x/oauth2" "google.golang.org/api/internal" "google.golang.org/api/option" - "google.golang.org/api/transport/internal/dca" "google.golang.org/grpc" "google.golang.org/grpc/credentials" grpcgoogle "google.golang.org/grpc/credentials/google" @@ -123,7 +122,7 @@ func dial(ctx context.Context, insecure bool, o *internal.DialSettings) (*grpc.C if o.GRPCConn != nil { return o.GRPCConn, nil } - clientCertSource, endpoint, err := dca.GetClientCertificateSourceAndEndpoint(o) + clientCertSource, endpoint, err := internal.GetClientCertificateSourceAndEndpoint(o) if err != nil { return nil, err } diff --git a/transport/http/dial.go b/transport/http/dial.go index 47568a4061d..4f7f44e8dbf 100644 --- a/transport/http/dial.go +++ b/transport/http/dial.go @@ -20,10 +20,9 @@ import ( "golang.org/x/oauth2" "google.golang.org/api/googleapi/transport" "google.golang.org/api/internal" + "google.golang.org/api/internal/cert" "google.golang.org/api/option" - "google.golang.org/api/transport/cert" "google.golang.org/api/transport/http/internal/propagation" - "google.golang.org/api/transport/internal/dca" ) // NewClient returns an HTTP client for use communicating with a Google cloud @@ -34,7 +33,7 @@ func NewClient(ctx context.Context, opts ...option.ClientOption) (*http.Client, if err != nil { return nil, "", err } - clientCertSource, endpoint, err := dca.GetClientCertificateSourceAndEndpoint(settings) + clientCertSource, endpoint, err := internal.GetClientCertificateSourceAndEndpoint(settings) if err != nil { return nil, "", err }