Skip to content

Commit c213153

Browse files
authored
fix(transport/grpc): separate resolution of creds and certs (#1759)
* fix(transport/grpc): separate enforcement of WithoutAuthentication and WithInsecure * disallow NoAuth when insecure, refactor deprecated grpc option
1 parent 629e217 commit c213153

File tree

1 file changed

+29
-15
lines changed

1 file changed

+29
-15
lines changed

transport/grpc/dial.go

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"google.golang.org/grpc"
2626
"google.golang.org/grpc/credentials"
2727
grpcgoogle "google.golang.org/grpc/credentials/google"
28+
grpcinsecure "google.golang.org/grpc/credentials/insecure"
2829
"google.golang.org/grpc/credentials/oauth"
2930

3031
// Install grpclb, which is required for direct path.
@@ -126,10 +127,26 @@ func dial(ctx context.Context, insecure bool, o *internal.DialSettings) (*grpc.C
126127
if err != nil {
127128
return nil, err
128129
}
129-
var grpcOpts []grpc.DialOption
130+
131+
var transportCreds credentials.TransportCredentials
130132
if insecure {
131-
grpcOpts = []grpc.DialOption{grpc.WithInsecure()}
132-
} else if !o.NoAuth {
133+
transportCreds = grpcinsecure.NewCredentials()
134+
} else {
135+
transportCreds = credentials.NewTLS(&tls.Config{
136+
GetClientCertificate: clientCertSource,
137+
})
138+
}
139+
140+
// Initialize gRPC dial options with transport-level security options.
141+
grpcOpts := []grpc.DialOption{
142+
grpc.WithTransportCredentials(transportCreds),
143+
}
144+
145+
// Authentication can only be sent when communicating over a secure connection.
146+
//
147+
// TODO: Should we be more lenient in the future and allow sending credentials
148+
// when dialing an insecure connection?
149+
if !o.NoAuth && !insecure {
133150
if o.APIKey != "" {
134151
log.Print("API keys are not supported for gRPC APIs. Remove the WithAPIKey option from your client-creating call.")
135152
}
@@ -142,8 +159,17 @@ func dial(ctx context.Context, insecure bool, o *internal.DialSettings) (*grpc.C
142159
o.QuotaProject = internal.QuotaProjectFromCreds(creds)
143160
}
144161

162+
grpcOpts = append(grpcOpts,
163+
grpc.WithPerRPCCredentials(grpcTokenSource{
164+
TokenSource: oauth.TokenSource{creds.TokenSource},
165+
quotaProject: o.QuotaProject,
166+
requestReason: o.RequestReason,
167+
}),
168+
)
169+
145170
// Attempt Direct Path:
146171
if isDirectPathEnabled(endpoint, o) && isTokenSourceDirectPathCompatible(creds.TokenSource, o) && metadata.OnGCE() {
172+
// Overwrite all of the previously specific DialOptions, DirectPath uses its own set of credentials and certificates.
147173
grpcOpts = []grpc.DialOption{
148174
grpc.WithCredentialsBundle(grpcgoogle.NewDefaultCredentialsWithOptions(grpcgoogle.DefaultCredentialsOptions{oauth.TokenSource{creds.TokenSource}}))}
149175
if timeoutDialerOption != nil {
@@ -169,18 +195,6 @@ func dial(ctx context.Context, insecure bool, o *internal.DialSettings) (*grpc.C
169195
grpc.WithDefaultServiceConfig(`{"loadBalancingConfig":[{"grpclb":{"childPolicy":[{"pick_first":{}}]}}]}`))
170196
}
171197
// TODO(cbro): add support for system parameters (quota project, request reason) via chained interceptor.
172-
} else {
173-
tlsConfig := &tls.Config{
174-
GetClientCertificate: clientCertSource,
175-
}
176-
grpcOpts = []grpc.DialOption{
177-
grpc.WithPerRPCCredentials(grpcTokenSource{
178-
TokenSource: oauth.TokenSource{creds.TokenSource},
179-
quotaProject: o.QuotaProject,
180-
requestReason: o.RequestReason,
181-
}),
182-
grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)),
183-
}
184198
}
185199
}
186200

0 commit comments

Comments
 (0)