github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/test/insecure_creds_test.go (about)

     1  /*
     2   *
     3   * Copyright 2020 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   */
    18  
    19  package test
    20  
    21  import (
    22  	"context"
    23  	"net"
    24  	"strings"
    25  	"testing"
    26  	"time"
    27  
    28  	grpc "github.com/hxx258456/ccgo/grpc"
    29  	"github.com/hxx258456/ccgo/grpc/codes"
    30  	"github.com/hxx258456/ccgo/grpc/credentials"
    31  	"github.com/hxx258456/ccgo/grpc/credentials/insecure"
    32  	"github.com/hxx258456/ccgo/grpc/internal/stubserver"
    33  	"github.com/hxx258456/ccgo/grpc/peer"
    34  	"github.com/hxx258456/ccgo/grpc/status"
    35  
    36  	testpb "github.com/hxx258456/ccgo/grpc/test/grpc_testing"
    37  )
    38  
    39  const defaultTestTimeout = 5 * time.Second
    40  
    41  // testLegacyPerRPCCredentials is a PerRPCCredentials that has yet incorporated security level.
    42  type testLegacyPerRPCCredentials struct{}
    43  
    44  func (cr testLegacyPerRPCCredentials) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
    45  	return nil, nil
    46  }
    47  
    48  func (cr testLegacyPerRPCCredentials) RequireTransportSecurity() bool {
    49  	return true
    50  }
    51  
    52  func getSecurityLevel(ai credentials.AuthInfo) credentials.SecurityLevel {
    53  	if c, ok := ai.(interface {
    54  		GetCommonAuthInfo() credentials.CommonAuthInfo
    55  	}); ok {
    56  		return c.GetCommonAuthInfo().SecurityLevel
    57  	}
    58  	return credentials.InvalidSecurityLevel
    59  }
    60  
    61  // TestInsecureCreds tests the use of insecure creds on the server and client
    62  // side, and verifies that expect security level and auth info are returned.
    63  // Also verifies that this credential can interop with existing `WithInsecure`
    64  // DialOption.
    65  func (s) TestInsecureCreds(t *testing.T) {
    66  	tests := []struct {
    67  		desc                string
    68  		clientInsecureCreds bool
    69  		serverInsecureCreds bool
    70  	}{
    71  		{
    72  			desc:                "client and server insecure creds",
    73  			clientInsecureCreds: true,
    74  			serverInsecureCreds: true,
    75  		},
    76  		{
    77  			desc:                "client only insecure creds",
    78  			clientInsecureCreds: true,
    79  		},
    80  		{
    81  			desc:                "server only insecure creds",
    82  			serverInsecureCreds: true,
    83  		},
    84  	}
    85  
    86  	for _, test := range tests {
    87  		t.Run(test.desc, func(t *testing.T) {
    88  			ss := &stubserver.StubServer{
    89  				EmptyCallF: func(ctx context.Context, in *testpb.Empty) (*testpb.Empty, error) {
    90  					if !test.serverInsecureCreds {
    91  						return &testpb.Empty{}, nil
    92  					}
    93  
    94  					pr, ok := peer.FromContext(ctx)
    95  					if !ok {
    96  						return nil, status.Error(codes.DataLoss, "Failed to get peer from ctx")
    97  					}
    98  					// Check security level.
    99  					secLevel := getSecurityLevel(pr.AuthInfo)
   100  					if secLevel == credentials.InvalidSecurityLevel {
   101  						return nil, status.Errorf(codes.Unauthenticated, "peer.AuthInfo does not implement GetCommonAuthInfo()")
   102  					}
   103  					if secLevel != credentials.NoSecurity {
   104  						return nil, status.Errorf(codes.Unauthenticated, "Wrong security level: got %q, want %q", secLevel, credentials.NoSecurity)
   105  					}
   106  					return &testpb.Empty{}, nil
   107  				},
   108  			}
   109  
   110  			sOpts := []grpc.ServerOption{}
   111  			if test.serverInsecureCreds {
   112  				sOpts = append(sOpts, grpc.Creds(insecure.NewCredentials()))
   113  			}
   114  			s := grpc.NewServer(sOpts...)
   115  			defer s.Stop()
   116  
   117  			testpb.RegisterTestServiceServer(s, ss)
   118  
   119  			lis, err := net.Listen("tcp", "localhost:0")
   120  			if err != nil {
   121  				t.Fatalf("net.Listen(tcp, localhost:0) failed: %v", err)
   122  			}
   123  
   124  			go s.Serve(lis)
   125  
   126  			addr := lis.Addr().String()
   127  			opts := []grpc.DialOption{grpc.WithInsecure()}
   128  			if test.clientInsecureCreds {
   129  				opts = []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
   130  			}
   131  			cc, err := grpc.Dial(addr, opts...)
   132  			if err != nil {
   133  				t.Fatalf("grpc.Dial(%q) failed: %v", addr, err)
   134  			}
   135  			defer cc.Close()
   136  
   137  			c := testpb.NewTestServiceClient(cc)
   138  			ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   139  			defer cancel()
   140  			if _, err = c.EmptyCall(ctx, &testpb.Empty{}); err != nil {
   141  				t.Fatalf("EmptyCall(_, _) = _, %v; want _, <nil>", err)
   142  			}
   143  		})
   144  	}
   145  }
   146  
   147  func (s) TestInsecureCreds_WithPerRPCCredentials_AsCallOption(t *testing.T) {
   148  	ss := &stubserver.StubServer{
   149  		EmptyCallF: func(ctx context.Context, in *testpb.Empty) (*testpb.Empty, error) {
   150  			return &testpb.Empty{}, nil
   151  		},
   152  	}
   153  
   154  	s := grpc.NewServer(grpc.Creds(insecure.NewCredentials()))
   155  	defer s.Stop()
   156  	testpb.RegisterTestServiceServer(s, ss)
   157  
   158  	lis, err := net.Listen("tcp", "localhost:0")
   159  	if err != nil {
   160  		t.Fatalf("net.Listen(tcp, localhost:0) failed: %v", err)
   161  	}
   162  	go s.Serve(lis)
   163  
   164  	addr := lis.Addr().String()
   165  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   166  	defer cancel()
   167  
   168  	dopts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
   169  	copts := []grpc.CallOption{grpc.PerRPCCredentials(testLegacyPerRPCCredentials{})}
   170  	cc, err := grpc.Dial(addr, dopts...)
   171  	if err != nil {
   172  		t.Fatalf("grpc.Dial(%q) failed: %v", addr, err)
   173  	}
   174  	defer cc.Close()
   175  
   176  	const wantErr = "transport: cannot send secure credentials on an insecure connection"
   177  	c := testpb.NewTestServiceClient(cc)
   178  	if _, err = c.EmptyCall(ctx, &testpb.Empty{}, copts...); err == nil || !strings.Contains(err.Error(), wantErr) {
   179  		t.Fatalf("insecure credentials with per-RPC credentials requiring transport security returned error: %v; want %s", err, wantErr)
   180  	}
   181  }
   182  
   183  func (s) TestInsecureCreds_WithPerRPCCredentials_AsDialOption(t *testing.T) {
   184  	ss := &stubserver.StubServer{
   185  		EmptyCallF: func(_ context.Context, _ *testpb.Empty) (*testpb.Empty, error) {
   186  			return &testpb.Empty{}, nil
   187  		},
   188  	}
   189  
   190  	s := grpc.NewServer(grpc.Creds(insecure.NewCredentials()))
   191  	defer s.Stop()
   192  	testpb.RegisterTestServiceServer(s, ss)
   193  
   194  	lis, err := net.Listen("tcp", "localhost:0")
   195  	if err != nil {
   196  		t.Fatalf("net.Listen(tcp, localhost:0) failed: %v", err)
   197  	}
   198  	go s.Serve(lis)
   199  
   200  	addr := lis.Addr().String()
   201  	dopts := []grpc.DialOption{
   202  		grpc.WithTransportCredentials(insecure.NewCredentials()),
   203  		grpc.WithPerRPCCredentials(testLegacyPerRPCCredentials{}),
   204  	}
   205  	const wantErr = "the credentials require transport level security"
   206  	if _, err := grpc.Dial(addr, dopts...); err == nil || !strings.Contains(err.Error(), wantErr) {
   207  		t.Fatalf("grpc.Dial(%q) returned err %v, want: %v", addr, err, wantErr)
   208  	}
   209  }