From 0620352c146c2efdbac04b988352172f12496500 Mon Sep 17 00:00:00 2001 From: PapaCharlie Date: Wed, 25 Oct 2023 17:32:12 -0700 Subject: [PATCH 1/3] Enable xDS credentials This change should be relatively straightforward. It is a noop outside of the context of xDS (as demonstrated by the fact that the tests all pass), but it enables xDS-provided certificates (i.e. the ones that would be provided/specified in GRPC_XDS_BOOTSTRAP). See proposal [A29](https://github.com/grpc/proposal/blob/master/A29-xds-tls-security.md#go) for additional detail. --- grpcurl.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/grpcurl.go b/grpcurl.go index 6010b3ac..891b447e 100644 --- a/grpcurl.go +++ b/grpcurl.go @@ -28,6 +28,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" + xdsCredentials "google.golang.org/grpc/credentials/xds" "google.golang.org/grpc/metadata" protov2 "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/descriptorpb" @@ -629,7 +630,16 @@ func BlockingDial(ctx context.Context, network, address string, creds credential TransportCredentials: creds, writeResult: writeResult, } + } else { + creds = insecure.NewCredentials() + } + + var err error + creds, err = xdsCredentials.NewClientCredentials(xdsCredentials.ClientOptions{FallbackCreds: creds}) + if err != nil { + return nil, err } + dialer := func(ctx context.Context, address string) (net.Conn, error) { // NB: We *could* handle the TLS handshake ourselves, in the custom // dialer (instead of customizing both the dialer and the credentials). @@ -655,13 +665,8 @@ func BlockingDial(ctx context.Context, network, address string, creds credential opts = append([]grpc.DialOption{grpc.FailOnNonTempDialError(true)}, opts...) // But we don't want caller to be able to override these two, so we put // them *after* the explicitly provided options. - opts = append(opts, grpc.WithBlock(), grpc.WithContextDialer(dialer)) + opts = append(opts, grpc.WithBlock(), grpc.WithContextDialer(dialer), grpc.WithTransportCredentials(creds)) - if creds == nil { - opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) - } else { - opts = append(opts, grpc.WithTransportCredentials(creds)) - } conn, err := grpc.DialContext(ctx, address, opts...) var res interface{} if err != nil { From 14ea0196276a433e0ee59d86a5bc51862151dc87 Mon Sep 17 00:00:00 2001 From: PapaCharlie Date: Tue, 23 Jan 2024 14:40:42 -0800 Subject: [PATCH 2/3] Only enable xds credentials if the target is an xDS target --- grpcurl.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/grpcurl.go b/grpcurl.go index 891b447e..a3d62f46 100644 --- a/grpcurl.go +++ b/grpcurl.go @@ -635,9 +635,14 @@ func BlockingDial(ctx context.Context, network, address string, creds credential } var err error - creds, err = xdsCredentials.NewClientCredentials(xdsCredentials.ClientOptions{FallbackCreds: creds}) - if err != nil { - return nil, err + if strings.HasPrefix(address, "xds:///") { + // The xds:/// prefix is used to signal to the gRPC client to use an xDS server to resolve the + // target. The relevant credentials will be automatically pulled from the GRPC_XDS_BOOTSTRAP or + // GRPC_XDS_BOOTSTRAP_CONFIG env vars. + creds, err = xdsCredentials.NewClientCredentials(xdsCredentials.ClientOptions{FallbackCreds: creds}) + if err != nil { + return nil, err + } } dialer := func(ctx context.Context, address string) (net.Conn, error) { From 3fc2238b92766a810cc83770779cf01a038c7d43 Mon Sep 17 00:00:00 2001 From: PapaCharlie Date: Tue, 23 Jan 2024 15:38:18 -0800 Subject: [PATCH 3/3] Update after merge --- grpcurl.go | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/grpcurl.go b/grpcurl.go index a3d62f46..c609f47c 100644 --- a/grpcurl.go +++ b/grpcurl.go @@ -610,6 +610,21 @@ func ServerTransportCredentials(cacertFile, serverCertFile, serverKeyFile string // and blocking until the returned connection is ready. If the given credentials are nil, the // connection will be insecure (plain-text). func BlockingDial(ctx context.Context, network, address string, creds credentials.TransportCredentials, opts ...grpc.DialOption) (*grpc.ClientConn, error) { + if creds == nil { + creds = insecure.NewCredentials() + } + + var err error + if strings.HasPrefix(address, "xds:///") { + // The xds:/// prefix is used to signal to the gRPC client to use an xDS server to resolve the + // target. The relevant credentials will be automatically pulled from the GRPC_XDS_BOOTSTRAP or + // GRPC_XDS_BOOTSTRAP_CONFIG env vars. + creds, err = xdsCredentials.NewClientCredentials(xdsCredentials.ClientOptions{FallbackCreds: creds}) + if err != nil { + return nil, err + } + } + // grpc.Dial doesn't provide any information on permanent connection errors (like // TLS handshake failures). So in order to provide good error messages, we need a // custom dialer that can provide that info. That means we manage the TLS handshake. @@ -625,24 +640,9 @@ func BlockingDial(ctx context.Context, network, address string, creds credential // custom credentials and dialer will notify on error via the // writeResult function - if creds != nil { - creds = &errSignalingCreds{ - TransportCredentials: creds, - writeResult: writeResult, - } - } else { - creds = insecure.NewCredentials() - } - - var err error - if strings.HasPrefix(address, "xds:///") { - // The xds:/// prefix is used to signal to the gRPC client to use an xDS server to resolve the - // target. The relevant credentials will be automatically pulled from the GRPC_XDS_BOOTSTRAP or - // GRPC_XDS_BOOTSTRAP_CONFIG env vars. - creds, err = xdsCredentials.NewClientCredentials(xdsCredentials.ClientOptions{FallbackCreds: creds}) - if err != nil { - return nil, err - } + creds = &errSignalingCreds{ + TransportCredentials: creds, + writeResult: writeResult, } dialer := func(ctx context.Context, address string) (net.Conn, error) {