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

     1  //go:build !386
     2  // +build !386
     3  
     4  /*
     5   *
     6   * Copyright 2021 gRPC authors.
     7   *
     8   * Licensed under the Apache License, Version 2.0 (the "License");
     9   * you may not use this file except in compliance with the License.
    10   * You may obtain a copy of the License at
    11   *
    12   *     http://www.apache.org/licenses/LICENSE-2.0
    13   *
    14   * Unless required by applicable law or agreed to in writing, software
    15   * distributed under the License is distributed on an "AS IS" BASIS,
    16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    17   * See the License for the specific language governing permissions and
    18   * limitations under the License.
    19   *
    20   */
    21  
    22  package xds_test
    23  
    24  import (
    25  	"context"
    26  	"fmt"
    27  	"testing"
    28  
    29  	grpc "github.com/hxx258456/ccgo/grpc"
    30  	"github.com/hxx258456/ccgo/grpc/credentials/insecure"
    31  	xdscreds "github.com/hxx258456/ccgo/grpc/credentials/xds"
    32  	"github.com/hxx258456/ccgo/grpc/internal/testutils"
    33  	"github.com/hxx258456/ccgo/grpc/xds/internal/testutils/e2e"
    34  
    35  	v3corepb "github.com/hxx258456/ccgo/go-control-plane/envoy/config/core/v3"
    36  	v3tlspb "github.com/hxx258456/ccgo/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
    37  	testpb "github.com/hxx258456/ccgo/grpc/test/grpc_testing"
    38  )
    39  
    40  func (s) TestUnmarshalListener_WithUpdateValidatorFunc(t *testing.T) {
    41  	const (
    42  		serviceName                     = "my-service-client-side-xds"
    43  		missingIdentityProviderInstance = "missing-identity-provider-instance"
    44  		missingRootProviderInstance     = "missing-root-provider-instance"
    45  	)
    46  	managementServer, nodeID, bootstrapContents, resolver, cleanup1 := setupManagementServer(t)
    47  	defer cleanup1()
    48  
    49  	lis, cleanup2 := setupGRPCServer(t, bootstrapContents)
    50  	defer cleanup2()
    51  
    52  	// Grab the host and port of the server and create client side xDS
    53  	// resources corresponding to it.
    54  	host, port, err := hostPortFromListener(lis)
    55  	if err != nil {
    56  		t.Fatalf("failed to retrieve host and port of server: %v", err)
    57  	}
    58  
    59  	// Create xDS resources to be consumed on the client side. This
    60  	// includes the listener, route configuration, cluster (with
    61  	// security configuration) and endpoint resources.
    62  	resources := e2e.DefaultClientResources(e2e.ResourceParams{
    63  		DialTarget: serviceName,
    64  		NodeID:     nodeID,
    65  		Host:       host,
    66  		Port:       port,
    67  		SecLevel:   e2e.SecurityLevelMTLS,
    68  	})
    69  
    70  	tests := []struct {
    71  		name           string
    72  		securityConfig *v3corepb.TransportSocket
    73  		wantErr        bool
    74  	}{
    75  		{
    76  			name: "both identity and root providers are not present in bootstrap",
    77  			securityConfig: &v3corepb.TransportSocket{
    78  				Name: "envoy.transport_sockets.tls",
    79  				ConfigType: &v3corepb.TransportSocket_TypedConfig{
    80  					TypedConfig: testutils.MarshalAny(&v3tlspb.DownstreamTlsContext{
    81  						CommonTlsContext: &v3tlspb.CommonTlsContext{
    82  							TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
    83  								InstanceName: missingIdentityProviderInstance,
    84  							},
    85  							ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContext{
    86  								ValidationContext: &v3tlspb.CertificateValidationContext{
    87  									CaCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
    88  										InstanceName: missingRootProviderInstance,
    89  									},
    90  								},
    91  							},
    92  						},
    93  					}),
    94  				},
    95  			},
    96  			wantErr: true,
    97  		},
    98  		{
    99  			name: "only identity provider is not present in bootstrap",
   100  			securityConfig: &v3corepb.TransportSocket{
   101  				Name: "envoy.transport_sockets.tls",
   102  				ConfigType: &v3corepb.TransportSocket_TypedConfig{
   103  					TypedConfig: testutils.MarshalAny(&v3tlspb.DownstreamTlsContext{
   104  						CommonTlsContext: &v3tlspb.CommonTlsContext{
   105  							TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
   106  								InstanceName: missingIdentityProviderInstance,
   107  							},
   108  							ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContext{
   109  								ValidationContext: &v3tlspb.CertificateValidationContext{
   110  									CaCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
   111  										InstanceName: e2e.ServerSideCertProviderInstance,
   112  									},
   113  								},
   114  							},
   115  						},
   116  					}),
   117  				},
   118  			},
   119  			wantErr: true,
   120  		},
   121  		{
   122  			name: "only root provider is not present in bootstrap",
   123  			securityConfig: &v3corepb.TransportSocket{
   124  				Name: "envoy.transport_sockets.tls",
   125  				ConfigType: &v3corepb.TransportSocket_TypedConfig{
   126  					TypedConfig: testutils.MarshalAny(&v3tlspb.DownstreamTlsContext{
   127  						CommonTlsContext: &v3tlspb.CommonTlsContext{
   128  							TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
   129  								InstanceName: e2e.ServerSideCertProviderInstance,
   130  							},
   131  							ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContext{
   132  								ValidationContext: &v3tlspb.CertificateValidationContext{
   133  									CaCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
   134  										InstanceName: missingRootProviderInstance,
   135  									},
   136  								},
   137  							},
   138  						},
   139  					}),
   140  				},
   141  			},
   142  			wantErr: true,
   143  		},
   144  		{
   145  			name: "both identity and root providers are present in bootstrap",
   146  			securityConfig: &v3corepb.TransportSocket{
   147  				Name: "envoy.transport_sockets.tls",
   148  				ConfigType: &v3corepb.TransportSocket_TypedConfig{
   149  					TypedConfig: testutils.MarshalAny(&v3tlspb.DownstreamTlsContext{
   150  						CommonTlsContext: &v3tlspb.CommonTlsContext{
   151  							TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
   152  								InstanceName: e2e.ServerSideCertProviderInstance,
   153  							},
   154  							ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContext{
   155  								ValidationContext: &v3tlspb.CertificateValidationContext{
   156  									CaCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
   157  										InstanceName: e2e.ServerSideCertProviderInstance,
   158  									},
   159  								},
   160  							},
   161  						},
   162  					}),
   163  				},
   164  			},
   165  			wantErr: false,
   166  		},
   167  	}
   168  
   169  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   170  	defer cancel()
   171  	for _, test := range tests {
   172  		t.Run(test.name, func(t *testing.T) {
   173  			// Create an inbound xDS listener resource for the server side.
   174  			inboundLis := e2e.DefaultServerListener(host, port, e2e.SecurityLevelMTLS)
   175  			for _, fc := range inboundLis.GetFilterChains() {
   176  				fc.TransportSocket = test.securityConfig
   177  			}
   178  
   179  			// Setup the management server with client and server resources.
   180  			if len(resources.Listeners) == 1 {
   181  				resources.Listeners = append(resources.Listeners, inboundLis)
   182  			} else {
   183  				resources.Listeners[1] = inboundLis
   184  			}
   185  			if err := managementServer.Update(ctx, resources); err != nil {
   186  				t.Fatal(err)
   187  			}
   188  
   189  			// Create client-side xDS credentials with an insecure fallback.
   190  			creds, err := xdscreds.NewClientCredentials(xdscreds.ClientOptions{FallbackCreds: insecure.NewCredentials()})
   191  			if err != nil {
   192  				t.Fatal(err)
   193  			}
   194  
   195  			// Create a ClientConn with the xds scheme and make an RPC.
   196  			cc, err := grpc.DialContext(ctx, fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(creds), grpc.WithResolvers(resolver))
   197  			if err != nil {
   198  				t.Fatalf("failed to dial local test server: %v", err)
   199  			}
   200  			defer cc.Close()
   201  
   202  			// Make a context with a shorter timeout from the top level test
   203  			// context for cases where we expect failures.
   204  			timeout := defaultTestTimeout
   205  			if test.wantErr {
   206  				timeout = defaultTestShortTimeout
   207  			}
   208  			ctx2, cancel2 := context.WithTimeout(ctx, timeout)
   209  			defer cancel2()
   210  			client := testpb.NewTestServiceClient(cc)
   211  			if _, err := client.EmptyCall(ctx2, &testpb.Empty{}, grpc.WaitForReady(true)); (err != nil) != test.wantErr {
   212  				t.Fatalf("EmptyCall() returned err: %v, wantErr %v", err, test.wantErr)
   213  			}
   214  		})
   215  	}
   216  }
   217  
   218  func (s) TestUnmarshalCluster_WithUpdateValidatorFunc(t *testing.T) {
   219  	const (
   220  		serviceName                     = "my-service-client-side-xds"
   221  		missingIdentityProviderInstance = "missing-identity-provider-instance"
   222  		missingRootProviderInstance     = "missing-root-provider-instance"
   223  	)
   224  
   225  	tests := []struct {
   226  		name           string
   227  		securityConfig *v3corepb.TransportSocket
   228  		wantErr        bool
   229  	}{
   230  		{
   231  			name: "both identity and root providers are not present in bootstrap",
   232  			securityConfig: &v3corepb.TransportSocket{
   233  				Name: "envoy.transport_sockets.tls",
   234  				ConfigType: &v3corepb.TransportSocket_TypedConfig{
   235  					TypedConfig: testutils.MarshalAny(&v3tlspb.UpstreamTlsContext{
   236  						CommonTlsContext: &v3tlspb.CommonTlsContext{
   237  							TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
   238  								InstanceName: missingIdentityProviderInstance,
   239  							},
   240  							ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContext{
   241  								ValidationContext: &v3tlspb.CertificateValidationContext{
   242  									CaCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
   243  										InstanceName: missingRootProviderInstance,
   244  									},
   245  								},
   246  							},
   247  						},
   248  					}),
   249  				},
   250  			},
   251  			wantErr: true,
   252  		},
   253  		{
   254  			name: "only identity provider is not present in bootstrap",
   255  			securityConfig: &v3corepb.TransportSocket{
   256  				Name: "envoy.transport_sockets.tls",
   257  				ConfigType: &v3corepb.TransportSocket_TypedConfig{
   258  					TypedConfig: testutils.MarshalAny(&v3tlspb.UpstreamTlsContext{
   259  						CommonTlsContext: &v3tlspb.CommonTlsContext{
   260  							TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
   261  								InstanceName: missingIdentityProviderInstance,
   262  							},
   263  							ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContext{
   264  								ValidationContext: &v3tlspb.CertificateValidationContext{
   265  									CaCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
   266  										InstanceName: e2e.ClientSideCertProviderInstance,
   267  									},
   268  								},
   269  							},
   270  						},
   271  					}),
   272  				},
   273  			},
   274  			wantErr: true,
   275  		},
   276  		{
   277  			name: "only root provider is not present in bootstrap",
   278  			securityConfig: &v3corepb.TransportSocket{
   279  				Name: "envoy.transport_sockets.tls",
   280  				ConfigType: &v3corepb.TransportSocket_TypedConfig{
   281  					TypedConfig: testutils.MarshalAny(&v3tlspb.UpstreamTlsContext{
   282  						CommonTlsContext: &v3tlspb.CommonTlsContext{
   283  							TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
   284  								InstanceName: e2e.ClientSideCertProviderInstance,
   285  							},
   286  							ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContext{
   287  								ValidationContext: &v3tlspb.CertificateValidationContext{
   288  									CaCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
   289  										InstanceName: missingRootProviderInstance,
   290  									},
   291  								},
   292  							},
   293  						},
   294  					}),
   295  				},
   296  			},
   297  			wantErr: true,
   298  		},
   299  		{
   300  			name: "both identity and root providers are present in bootstrap",
   301  			securityConfig: &v3corepb.TransportSocket{
   302  				Name: "envoy.transport_sockets.tls",
   303  				ConfigType: &v3corepb.TransportSocket_TypedConfig{
   304  					TypedConfig: testutils.MarshalAny(&v3tlspb.UpstreamTlsContext{
   305  						CommonTlsContext: &v3tlspb.CommonTlsContext{
   306  							TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
   307  								InstanceName: e2e.ClientSideCertProviderInstance,
   308  							},
   309  							ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContext{
   310  								ValidationContext: &v3tlspb.CertificateValidationContext{
   311  									CaCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
   312  										InstanceName: e2e.ClientSideCertProviderInstance,
   313  									},
   314  								},
   315  							},
   316  						},
   317  					}),
   318  				},
   319  			},
   320  			wantErr: false,
   321  		},
   322  	}
   323  
   324  	for _, test := range tests {
   325  		t.Run(test.name, func(t *testing.T) {
   326  			// setupManagementServer() sets up a bootstrap file with certificate
   327  			// provider instance names: `e2e.ServerSideCertProviderInstance` and
   328  			// `e2e.ClientSideCertProviderInstance`.
   329  			managementServer, nodeID, _, resolver, cleanup1 := setupManagementServer(t)
   330  			defer cleanup1()
   331  
   332  			port, cleanup2 := clientSetup(t, &testService{})
   333  			defer cleanup2()
   334  
   335  			// This creates a `Cluster` resource with a security config which
   336  			// refers to `e2e.ClientSideCertProviderInstance` for both root and
   337  			// identity certs.
   338  			resources := e2e.DefaultClientResources(e2e.ResourceParams{
   339  				DialTarget: serviceName,
   340  				NodeID:     nodeID,
   341  				Host:       "localhost",
   342  				Port:       port,
   343  				SecLevel:   e2e.SecurityLevelMTLS,
   344  			})
   345  			resources.Clusters[0].TransportSocket = test.securityConfig
   346  			ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   347  			defer cancel()
   348  			if err := managementServer.Update(ctx, resources); err != nil {
   349  				t.Fatal(err)
   350  			}
   351  
   352  			cc, err := grpc.Dial(fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(resolver))
   353  			if err != nil {
   354  				t.Fatalf("failed to dial local test server: %v", err)
   355  			}
   356  			defer cc.Close()
   357  
   358  			// Make a context with a shorter timeout from the top level test
   359  			// context for cases where we expect failures.
   360  			timeout := defaultTestTimeout
   361  			if test.wantErr {
   362  				timeout = defaultTestShortTimeout
   363  			}
   364  			ctx2, cancel2 := context.WithTimeout(ctx, timeout)
   365  			defer cancel2()
   366  			client := testpb.NewTestServiceClient(cc)
   367  			if _, err := client.EmptyCall(ctx2, &testpb.Empty{}, grpc.WaitForReady(true)); (err != nil) != test.wantErr {
   368  				t.Fatalf("EmptyCall() returned err: %v, wantErr %v", err, test.wantErr)
   369  			}
   370  		})
   371  	}
   372  }