grpc: implement WithInsecure() using the insecure package (#4718)
This commit is contained in:

committed by
GitHub

parent
c25a52b769
commit
dd767416a6
@ -83,13 +83,13 @@ var (
|
||||
// errTransportCredsAndBundle indicates that creds bundle is used together
|
||||
// with other individual Transport Credentials.
|
||||
errTransportCredsAndBundle = errors.New("grpc: credentials.Bundle may not be used with individual TransportCredentials")
|
||||
// errTransportCredentialsMissing indicates that users want to transmit security
|
||||
// information (e.g., OAuth2 token) which requires secure connection on an insecure
|
||||
// connection.
|
||||
// errNoTransportCredsInBundle indicated that the configured creds bundle
|
||||
// returned a transport credentials which was nil.
|
||||
errNoTransportCredsInBundle = errors.New("grpc: credentials.Bundle must return non-nil transport credentials")
|
||||
// errTransportCredentialsMissing indicates that users want to transmit
|
||||
// security information (e.g., OAuth2 token) which requires secure
|
||||
// connection on an insecure connection.
|
||||
errTransportCredentialsMissing = errors.New("grpc: the credentials require transport level security (use grpc.WithTransportCredentials() to set)")
|
||||
// errCredentialsConflict indicates that grpc.WithTransportCredentials()
|
||||
// and grpc.WithInsecure() are both called for a connection.
|
||||
errCredentialsConflict = errors.New("grpc: transport credentials are set for an insecure connection (grpc.WithTransportCredentials() and grpc.WithInsecure() are both called)")
|
||||
)
|
||||
|
||||
const (
|
||||
@ -177,17 +177,20 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
|
||||
cc.csMgr.channelzID = cc.channelzID
|
||||
}
|
||||
|
||||
if !cc.dopts.insecure {
|
||||
if cc.dopts.copts.TransportCredentials == nil && cc.dopts.copts.CredsBundle == nil {
|
||||
return nil, errNoTransportSecurity
|
||||
}
|
||||
if cc.dopts.copts.TransportCredentials != nil && cc.dopts.copts.CredsBundle != nil {
|
||||
return nil, errTransportCredsAndBundle
|
||||
}
|
||||
} else {
|
||||
if cc.dopts.copts.TransportCredentials != nil || cc.dopts.copts.CredsBundle != nil {
|
||||
return nil, errCredentialsConflict
|
||||
}
|
||||
if cc.dopts.copts.TransportCredentials == nil && cc.dopts.copts.CredsBundle == nil {
|
||||
return nil, errNoTransportSecurity
|
||||
}
|
||||
if cc.dopts.copts.TransportCredentials != nil && cc.dopts.copts.CredsBundle != nil {
|
||||
return nil, errTransportCredsAndBundle
|
||||
}
|
||||
if cc.dopts.copts.CredsBundle != nil && cc.dopts.copts.CredsBundle.TransportCredentials() == nil {
|
||||
return nil, errNoTransportCredsInBundle
|
||||
}
|
||||
transportCreds := cc.dopts.copts.TransportCredentials
|
||||
if transportCreds == nil {
|
||||
transportCreds = cc.dopts.copts.CredsBundle.TransportCredentials()
|
||||
}
|
||||
if transportCreds.Info().SecurityProtocol == "insecure" {
|
||||
for _, cd := range cc.dopts.copts.PerRPCCredentials {
|
||||
if cd.RequireTransportSecurity() {
|
||||
return nil, errTransportCredentialsMissing
|
||||
|
@ -490,29 +490,52 @@ func (s) TestDialContextFailFast(t *testing.T) {
|
||||
}
|
||||
|
||||
// securePerRPCCredentials always requires transport security.
|
||||
type securePerRPCCredentials struct{}
|
||||
|
||||
func (c securePerRPCCredentials) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
|
||||
return nil, nil
|
||||
type securePerRPCCredentials struct {
|
||||
credentials.PerRPCCredentials
|
||||
}
|
||||
|
||||
func (c securePerRPCCredentials) RequireTransportSecurity() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type fakeBundleCreds struct {
|
||||
credentials.Bundle
|
||||
transportCreds credentials.TransportCredentials
|
||||
}
|
||||
|
||||
func (b *fakeBundleCreds) TransportCredentials() credentials.TransportCredentials {
|
||||
return b.transportCreds
|
||||
}
|
||||
|
||||
func (s) TestCredentialsMisuse(t *testing.T) {
|
||||
tlsCreds, err := credentials.NewClientTLSFromFile(testdata.Path("x509/server_ca_cert.pem"), "x.test.example.com")
|
||||
// Use of no transport creds and no creds bundle must fail.
|
||||
if _, err := Dial("passthrough:///Non-Existent.Server:80"); err != errNoTransportSecurity {
|
||||
t.Fatalf("Dial(_, _) = _, %v, want _, %v", err, errNoTransportSecurity)
|
||||
}
|
||||
|
||||
// Use of both transport creds and creds bundle must fail.
|
||||
creds, err := credentials.NewClientTLSFromFile(testdata.Path("x509/server_ca_cert.pem"), "x.test.example.com")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create authenticator %v", err)
|
||||
}
|
||||
// Two conflicting credential configurations
|
||||
if _, err := Dial("passthrough:///Non-Existent.Server:80", WithTransportCredentials(tlsCreds), WithBlock(), WithInsecure()); err != errCredentialsConflict {
|
||||
t.Fatalf("Dial(_, _) = _, %v, want _, %v", err, errCredentialsConflict)
|
||||
dopts := []DialOption{
|
||||
WithTransportCredentials(creds),
|
||||
WithCredentialsBundle(&fakeBundleCreds{transportCreds: creds}),
|
||||
}
|
||||
// security info on insecure connection
|
||||
if _, err := Dial("passthrough:///Non-Existent.Server:80", WithPerRPCCredentials(securePerRPCCredentials{}), WithBlock(), WithInsecure()); err != errTransportCredentialsMissing {
|
||||
if _, err := Dial("passthrough:///Non-Existent.Server:80", dopts...); err != errTransportCredsAndBundle {
|
||||
t.Fatalf("Dial(_, _) = _, %v, want _, %v", err, errTransportCredsAndBundle)
|
||||
}
|
||||
|
||||
// Use of perRPC creds requiring transport security over an insecure
|
||||
// transport must fail.
|
||||
if _, err := Dial("passthrough:///Non-Existent.Server:80", WithPerRPCCredentials(securePerRPCCredentials{}), WithInsecure()); err != errTransportCredentialsMissing {
|
||||
t.Fatalf("Dial(_, _) = _, %v, want _, %v", err, errTransportCredentialsMissing)
|
||||
}
|
||||
|
||||
// Use of a creds bundle with nil transport credentials must fail.
|
||||
if _, err := Dial("passthrough:///Non-Existent.Server:80", WithCredentialsBundle(&fakeBundleCreds{})); err != errNoTransportCredsInBundle {
|
||||
t.Fatalf("Dial(_, _) = _, %v, want _, %v", err, errTransportCredsAndBundle)
|
||||
}
|
||||
}
|
||||
|
||||
func (s) TestWithBackoffConfigDefault(t *testing.T) {
|
||||
|
@ -178,8 +178,18 @@ type TransportCredentials interface {
|
||||
//
|
||||
// This API is experimental.
|
||||
type Bundle interface {
|
||||
// TransportCredentials returns the transport credentials from the Bundle.
|
||||
//
|
||||
// Implementations must return non-nil transport credentials. If transport
|
||||
// security is not needed by the Bundle, implementations may choose to
|
||||
// return insecure.NewCredentials().
|
||||
TransportCredentials() TransportCredentials
|
||||
|
||||
// PerRPCCredentials returns the per-RPC credentials from the Bundle.
|
||||
//
|
||||
// May be nil if per-RPC credentials are not needed.
|
||||
PerRPCCredentials() PerRPCCredentials
|
||||
|
||||
// NewWithMode should make a copy of Bundle, and switch mode. Modifying the
|
||||
// existing Bundle may cause races.
|
||||
//
|
||||
|
@ -33,6 +33,9 @@ import (
|
||||
)
|
||||
|
||||
// NewCredentials returns a credentials which disables transport security.
|
||||
//
|
||||
// Note that using this credentials with per-RPC credentials which require
|
||||
// transport security is incompatible and will cause grpc.Dial() to fail.
|
||||
func NewCredentials() credentials.TransportCredentials {
|
||||
return insecureTC{}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"google.golang.org/grpc/backoff"
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/internal"
|
||||
internalbackoff "google.golang.org/grpc/internal/backoff"
|
||||
"google.golang.org/grpc/internal/transport"
|
||||
@ -49,7 +50,6 @@ type dialOptions struct {
|
||||
bs internalbackoff.Strategy
|
||||
block bool
|
||||
returnLastError bool
|
||||
insecure bool
|
||||
timeout time.Duration
|
||||
scChan <-chan ServiceConfig
|
||||
authority string
|
||||
@ -298,11 +298,17 @@ func WithReturnConnectionError() DialOption {
|
||||
}
|
||||
|
||||
// WithInsecure returns a DialOption which disables transport security for this
|
||||
// ClientConn. Note that transport security is required unless WithInsecure is
|
||||
// set.
|
||||
// ClientConn. Under the hood, it uses insecure.NewCredentials().
|
||||
//
|
||||
// Note that using this DialOption with per-RPC credentials (through
|
||||
// WithCredentialsBundle or WithPerRPCCredentials) which require transport
|
||||
// security is incompatible and will cause grpc.Dial() to fail.
|
||||
//
|
||||
// Deprecated: use insecure.NewCredentials() instead.
|
||||
// Will be supported throughout 1.x.
|
||||
func WithInsecure() DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.insecure = true
|
||||
o.copts.TransportCredentials = insecure.NewCredentials()
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ import (
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"google.golang.org/grpc/resolver/manual"
|
||||
@ -52,7 +53,7 @@ type testCredsBundle struct {
|
||||
|
||||
func (c *testCredsBundle) TransportCredentials() credentials.TransportCredentials {
|
||||
if c.mode == bundlePerRPCOnly {
|
||||
return nil
|
||||
return insecure.NewCredentials()
|
||||
}
|
||||
|
||||
creds, err := credentials.NewClientTLSFromFile(testdata.Path("x509/server_ca_cert.pem"), "x.test.example.com")
|
||||
|
@ -144,64 +144,66 @@ func (s) TestInsecureCreds(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s) TestInsecureCredsWithPerRPCCredentials(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
perRPCCredsViaDialOptions bool
|
||||
perRPCCredsViaCallOptions bool
|
||||
}{
|
||||
{
|
||||
desc: "send PerRPCCredentials via DialOptions",
|
||||
perRPCCredsViaDialOptions: true,
|
||||
perRPCCredsViaCallOptions: false,
|
||||
},
|
||||
{
|
||||
desc: "send PerRPCCredentials via CallOptions",
|
||||
perRPCCredsViaDialOptions: false,
|
||||
perRPCCredsViaCallOptions: true,
|
||||
func (s) TestInsecureCreds_WithPerRPCCredentials_AsCallOption(t *testing.T) {
|
||||
ss := &stubserver.StubServer{
|
||||
EmptyCallF: func(ctx context.Context, in *testpb.Empty) (*testpb.Empty, error) {
|
||||
return &testpb.Empty{}, nil
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
ss := &stubserver.StubServer{
|
||||
EmptyCallF: func(ctx context.Context, in *testpb.Empty) (*testpb.Empty, error) {
|
||||
return &testpb.Empty{}, nil
|
||||
},
|
||||
}
|
||||
|
||||
s := grpc.NewServer(grpc.Creds(insecure.NewCredentials()))
|
||||
defer s.Stop()
|
||||
testpb.RegisterTestServiceServer(s, ss)
|
||||
s := grpc.NewServer(grpc.Creds(insecure.NewCredentials()))
|
||||
defer s.Stop()
|
||||
testpb.RegisterTestServiceServer(s, ss)
|
||||
|
||||
lis, err := net.Listen("tcp", "localhost:0")
|
||||
if err != nil {
|
||||
t.Fatalf("net.Listen(tcp, localhost:0) failed: %v", err)
|
||||
}
|
||||
go s.Serve(lis)
|
||||
lis, err := net.Listen("tcp", "localhost:0")
|
||||
if err != nil {
|
||||
t.Fatalf("net.Listen(tcp, localhost:0) failed: %v", err)
|
||||
}
|
||||
go s.Serve(lis)
|
||||
|
||||
addr := lis.Addr().String()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
|
||||
defer cancel()
|
||||
addr := lis.Addr().String()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
dopts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
|
||||
if test.perRPCCredsViaDialOptions {
|
||||
dopts = append(dopts, grpc.WithPerRPCCredentials(testLegacyPerRPCCredentials{}))
|
||||
}
|
||||
copts := []grpc.CallOption{}
|
||||
if test.perRPCCredsViaCallOptions {
|
||||
copts = append(copts, grpc.PerRPCCredentials(testLegacyPerRPCCredentials{}))
|
||||
}
|
||||
cc, err := grpc.Dial(addr, dopts...)
|
||||
if err != nil {
|
||||
t.Fatalf("grpc.Dial(%q) failed: %v", addr, err)
|
||||
}
|
||||
defer cc.Close()
|
||||
dopts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
|
||||
copts := []grpc.CallOption{grpc.PerRPCCredentials(testLegacyPerRPCCredentials{})}
|
||||
cc, err := grpc.Dial(addr, dopts...)
|
||||
if err != nil {
|
||||
t.Fatalf("grpc.Dial(%q) failed: %v", addr, err)
|
||||
}
|
||||
defer cc.Close()
|
||||
|
||||
const wantErr = "transport: cannot send secure credentials on an insecure connection"
|
||||
c := testpb.NewTestServiceClient(cc)
|
||||
if _, err = c.EmptyCall(ctx, &testpb.Empty{}, copts...); err == nil || !strings.Contains(err.Error(), wantErr) {
|
||||
t.Fatalf("InsecureCredsWithPerRPCCredentials/send_PerRPCCredentials_via_CallOptions = %v; want %s", err, wantErr)
|
||||
}
|
||||
})
|
||||
const wantErr = "transport: cannot send secure credentials on an insecure connection"
|
||||
c := testpb.NewTestServiceClient(cc)
|
||||
if _, err = c.EmptyCall(ctx, &testpb.Empty{}, copts...); err == nil || !strings.Contains(err.Error(), wantErr) {
|
||||
t.Fatalf("insecure credentials with per-RPC credentials requiring transport security returned error: %v; want %s", err, wantErr)
|
||||
}
|
||||
}
|
||||
|
||||
func (s) TestInsecureCreds_WithPerRPCCredentials_AsDialOption(t *testing.T) {
|
||||
ss := &stubserver.StubServer{
|
||||
EmptyCallF: func(_ context.Context, _ *testpb.Empty) (*testpb.Empty, error) {
|
||||
return &testpb.Empty{}, nil
|
||||
},
|
||||
}
|
||||
|
||||
s := grpc.NewServer(grpc.Creds(insecure.NewCredentials()))
|
||||
defer s.Stop()
|
||||
testpb.RegisterTestServiceServer(s, ss)
|
||||
|
||||
lis, err := net.Listen("tcp", "localhost:0")
|
||||
if err != nil {
|
||||
t.Fatalf("net.Listen(tcp, localhost:0) failed: %v", err)
|
||||
}
|
||||
go s.Serve(lis)
|
||||
|
||||
addr := lis.Addr().String()
|
||||
dopts := []grpc.DialOption{
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithPerRPCCredentials(testLegacyPerRPCCredentials{}),
|
||||
}
|
||||
const wantErr = "the credentials require transport level security"
|
||||
if _, err := grpc.Dial(addr, dopts...); err == nil || !strings.Contains(err.Error(), wantErr) {
|
||||
t.Fatalf("grpc.Dial(%q) returned err %v, want: %v", addr, err, wantErr)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user