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

     1  /*
     2   *
     3   * Copyright 2021 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 e2e
    20  
    21  import (
    22  	"fmt"
    23  	"net"
    24  	"strconv"
    25  
    26  	"github.com/golang/protobuf/proto"
    27  	"github.com/hxx258456/ccgo/go-control-plane/pkg/wellknown"
    28  	"github.com/hxx258456/ccgo/grpc/internal/testutils"
    29  
    30  	wrapperspb "github.com/golang/protobuf/ptypes/wrappers"
    31  	v3clusterpb "github.com/hxx258456/ccgo/go-control-plane/envoy/config/cluster/v3"
    32  	v3corepb "github.com/hxx258456/ccgo/go-control-plane/envoy/config/core/v3"
    33  	v3endpointpb "github.com/hxx258456/ccgo/go-control-plane/envoy/config/endpoint/v3"
    34  	v3listenerpb "github.com/hxx258456/ccgo/go-control-plane/envoy/config/listener/v3"
    35  	v3routepb "github.com/hxx258456/ccgo/go-control-plane/envoy/config/route/v3"
    36  	v3routerpb "github.com/hxx258456/ccgo/go-control-plane/envoy/extensions/filters/http/router/v3"
    37  	v3httppb "github.com/hxx258456/ccgo/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
    38  	v3tlspb "github.com/hxx258456/ccgo/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
    39  )
    40  
    41  const (
    42  	// ServerListenerResourceNameTemplate is the Listener resource name template
    43  	// used on the server side.
    44  	ServerListenerResourceNameTemplate = "grpc/server?xds.resource.listening_address=%s"
    45  	// ClientSideCertProviderInstance is the certificate provider instance name
    46  	// used in the Cluster resource on the client side.
    47  	ClientSideCertProviderInstance = "client-side-certificate-provider-instance"
    48  	// ServerSideCertProviderInstance is the certificate provider instance name
    49  	// used in the Listener resource on the server side.
    50  	ServerSideCertProviderInstance = "server-side-certificate-provider-instance"
    51  )
    52  
    53  // SecurityLevel allows the test to control the security level to be used in the
    54  // resource returned by this package.
    55  type SecurityLevel int
    56  
    57  const (
    58  	// SecurityLevelNone is used when no security configuration is required.
    59  	SecurityLevelNone SecurityLevel = iota
    60  	// SecurityLevelTLS is used when security configuration corresponding to TLS
    61  	// is required. Only the server presents an identity certificate in this
    62  	// configuration.
    63  	SecurityLevelTLS
    64  	// SecurityLevelMTLS is used when security ocnfiguration corresponding to
    65  	// mTLS is required. Both client and server present identity certificates in
    66  	// this configuration.
    67  	SecurityLevelMTLS
    68  )
    69  
    70  // ResourceParams wraps the arguments to be passed to DefaultClientResources.
    71  type ResourceParams struct {
    72  	// DialTarget is the client's dial target. This is used as the name of the
    73  	// Listener resource.
    74  	DialTarget string
    75  	// NodeID is the id of the xdsClient to which this update is to be pushed.
    76  	NodeID string
    77  	// Host is the host of the default Endpoint resource.
    78  	Host string
    79  	// port is the port of the default Endpoint resource.
    80  	Port uint32
    81  	// SecLevel controls the security configuration in the Cluster resource.
    82  	SecLevel SecurityLevel
    83  }
    84  
    85  // DefaultClientResources returns a set of resources (LDS, RDS, CDS, EDS) for a
    86  // client to generically connect to one server.
    87  func DefaultClientResources(params ResourceParams) UpdateOptions {
    88  	routeConfigName := "route-" + params.DialTarget
    89  	clusterName := "cluster-" + params.DialTarget
    90  	endpointsName := "endpoints-" + params.DialTarget
    91  	return UpdateOptions{
    92  		NodeID:    params.NodeID,
    93  		Listeners: []*v3listenerpb.Listener{DefaultClientListener(params.DialTarget, routeConfigName)},
    94  		Routes:    []*v3routepb.RouteConfiguration{DefaultRouteConfig(routeConfigName, params.DialTarget, clusterName)},
    95  		Clusters:  []*v3clusterpb.Cluster{DefaultCluster(clusterName, endpointsName, params.SecLevel)},
    96  		Endpoints: []*v3endpointpb.ClusterLoadAssignment{DefaultEndpoint(endpointsName, params.Host, []uint32{params.Port})},
    97  	}
    98  }
    99  
   100  // RouterHTTPFilter is the HTTP Filter configuration for the Router filter.
   101  var RouterHTTPFilter = HTTPFilter("router", &v3routerpb.Router{})
   102  
   103  // DefaultClientListener returns a basic xds Listener resource to be used on
   104  // the client side.
   105  func DefaultClientListener(target, routeName string) *v3listenerpb.Listener {
   106  	hcm := testutils.MarshalAny(&v3httppb.HttpConnectionManager{
   107  		RouteSpecifier: &v3httppb.HttpConnectionManager_Rds{Rds: &v3httppb.Rds{
   108  			ConfigSource: &v3corepb.ConfigSource{
   109  				ConfigSourceSpecifier: &v3corepb.ConfigSource_Ads{Ads: &v3corepb.AggregatedConfigSource{}},
   110  			},
   111  			RouteConfigName: routeName,
   112  		}},
   113  		HttpFilters: []*v3httppb.HttpFilter{HTTPFilter("router", &v3routerpb.Router{})}, // router fields are unused by grpc
   114  	})
   115  	return &v3listenerpb.Listener{
   116  		Name:        target,
   117  		ApiListener: &v3listenerpb.ApiListener{ApiListener: hcm},
   118  		FilterChains: []*v3listenerpb.FilterChain{{
   119  			Name: "filter-chain-name",
   120  			Filters: []*v3listenerpb.Filter{{
   121  				Name:       wellknown.HTTPConnectionManager,
   122  				ConfigType: &v3listenerpb.Filter_TypedConfig{TypedConfig: hcm},
   123  			}},
   124  		}},
   125  	}
   126  }
   127  
   128  // DefaultServerListener returns a basic xds Listener resource to be used on
   129  // the server side.
   130  func DefaultServerListener(host string, port uint32, secLevel SecurityLevel) *v3listenerpb.Listener {
   131  	var tlsContext *v3tlspb.DownstreamTlsContext
   132  	switch secLevel {
   133  	case SecurityLevelNone:
   134  	case SecurityLevelTLS:
   135  		tlsContext = &v3tlspb.DownstreamTlsContext{
   136  			CommonTlsContext: &v3tlspb.CommonTlsContext{
   137  				TlsCertificateCertificateProviderInstance: &v3tlspb.CommonTlsContext_CertificateProviderInstance{
   138  					InstanceName: ServerSideCertProviderInstance,
   139  				},
   140  			},
   141  		}
   142  	case SecurityLevelMTLS:
   143  		tlsContext = &v3tlspb.DownstreamTlsContext{
   144  			RequireClientCertificate: &wrapperspb.BoolValue{Value: true},
   145  			CommonTlsContext: &v3tlspb.CommonTlsContext{
   146  				TlsCertificateCertificateProviderInstance: &v3tlspb.CommonTlsContext_CertificateProviderInstance{
   147  					InstanceName: ServerSideCertProviderInstance,
   148  				},
   149  				ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContextCertificateProviderInstance{
   150  					ValidationContextCertificateProviderInstance: &v3tlspb.CommonTlsContext_CertificateProviderInstance{
   151  						InstanceName: ServerSideCertProviderInstance,
   152  					},
   153  				},
   154  			},
   155  		}
   156  	}
   157  
   158  	var ts *v3corepb.TransportSocket
   159  	if tlsContext != nil {
   160  		ts = &v3corepb.TransportSocket{
   161  			Name: "envoy.transport_sockets.tls",
   162  			ConfigType: &v3corepb.TransportSocket_TypedConfig{
   163  				TypedConfig: testutils.MarshalAny(tlsContext),
   164  			},
   165  		}
   166  	}
   167  	return &v3listenerpb.Listener{
   168  		Name: fmt.Sprintf(ServerListenerResourceNameTemplate, net.JoinHostPort(host, strconv.Itoa(int(port)))),
   169  		Address: &v3corepb.Address{
   170  			Address: &v3corepb.Address_SocketAddress{
   171  				SocketAddress: &v3corepb.SocketAddress{
   172  					Address: host,
   173  					PortSpecifier: &v3corepb.SocketAddress_PortValue{
   174  						PortValue: port,
   175  					},
   176  				},
   177  			},
   178  		},
   179  		FilterChains: []*v3listenerpb.FilterChain{
   180  			{
   181  				Name: "v4-wildcard",
   182  				FilterChainMatch: &v3listenerpb.FilterChainMatch{
   183  					PrefixRanges: []*v3corepb.CidrRange{
   184  						{
   185  							AddressPrefix: "0.0.0.0",
   186  							PrefixLen: &wrapperspb.UInt32Value{
   187  								Value: uint32(0),
   188  							},
   189  						},
   190  					},
   191  					SourceType: v3listenerpb.FilterChainMatch_SAME_IP_OR_LOOPBACK,
   192  					SourcePrefixRanges: []*v3corepb.CidrRange{
   193  						{
   194  							AddressPrefix: "0.0.0.0",
   195  							PrefixLen: &wrapperspb.UInt32Value{
   196  								Value: uint32(0),
   197  							},
   198  						},
   199  					},
   200  				},
   201  				Filters: []*v3listenerpb.Filter{
   202  					{
   203  						Name: "filter-1",
   204  						ConfigType: &v3listenerpb.Filter_TypedConfig{
   205  							TypedConfig: testutils.MarshalAny(&v3httppb.HttpConnectionManager{
   206  								RouteSpecifier: &v3httppb.HttpConnectionManager_RouteConfig{
   207  									RouteConfig: &v3routepb.RouteConfiguration{
   208  										Name: "routeName",
   209  										VirtualHosts: []*v3routepb.VirtualHost{{
   210  											// This "*" string matches on any incoming authority. This is to ensure any
   211  											// incoming RPC matches to Route_NonForwardingAction and will proceed as
   212  											// normal.
   213  											Domains: []string{"*"},
   214  											Routes: []*v3routepb.Route{{
   215  												Match: &v3routepb.RouteMatch{
   216  													PathSpecifier: &v3routepb.RouteMatch_Prefix{Prefix: "/"},
   217  												},
   218  												Action: &v3routepb.Route_NonForwardingAction{},
   219  											}}}}},
   220  								},
   221  								HttpFilters: []*v3httppb.HttpFilter{RouterHTTPFilter},
   222  							}),
   223  						},
   224  					},
   225  				},
   226  				TransportSocket: ts,
   227  			},
   228  			{
   229  				Name: "v6-wildcard",
   230  				FilterChainMatch: &v3listenerpb.FilterChainMatch{
   231  					PrefixRanges: []*v3corepb.CidrRange{
   232  						{
   233  							AddressPrefix: "::",
   234  							PrefixLen: &wrapperspb.UInt32Value{
   235  								Value: uint32(0),
   236  							},
   237  						},
   238  					},
   239  					SourceType: v3listenerpb.FilterChainMatch_SAME_IP_OR_LOOPBACK,
   240  					SourcePrefixRanges: []*v3corepb.CidrRange{
   241  						{
   242  							AddressPrefix: "::",
   243  							PrefixLen: &wrapperspb.UInt32Value{
   244  								Value: uint32(0),
   245  							},
   246  						},
   247  					},
   248  				},
   249  				Filters: []*v3listenerpb.Filter{
   250  					{
   251  						Name: "filter-1",
   252  						ConfigType: &v3listenerpb.Filter_TypedConfig{
   253  							TypedConfig: testutils.MarshalAny(&v3httppb.HttpConnectionManager{
   254  								RouteSpecifier: &v3httppb.HttpConnectionManager_RouteConfig{
   255  									RouteConfig: &v3routepb.RouteConfiguration{
   256  										Name: "routeName",
   257  										VirtualHosts: []*v3routepb.VirtualHost{{
   258  											// This "*" string matches on any incoming authority. This is to ensure any
   259  											// incoming RPC matches to Route_NonForwardingAction and will proceed as
   260  											// normal.
   261  											Domains: []string{"*"},
   262  											Routes: []*v3routepb.Route{{
   263  												Match: &v3routepb.RouteMatch{
   264  													PathSpecifier: &v3routepb.RouteMatch_Prefix{Prefix: "/"},
   265  												},
   266  												Action: &v3routepb.Route_NonForwardingAction{},
   267  											}}}}},
   268  								},
   269  								HttpFilters: []*v3httppb.HttpFilter{RouterHTTPFilter},
   270  							}),
   271  						},
   272  					},
   273  				},
   274  				TransportSocket: ts,
   275  			},
   276  		},
   277  	}
   278  }
   279  
   280  // HTTPFilter constructs an xds HttpFilter with the provided name and config.
   281  func HTTPFilter(name string, config proto.Message) *v3httppb.HttpFilter {
   282  	return &v3httppb.HttpFilter{
   283  		Name: name,
   284  		ConfigType: &v3httppb.HttpFilter_TypedConfig{
   285  			TypedConfig: testutils.MarshalAny(config),
   286  		},
   287  	}
   288  }
   289  
   290  // DefaultRouteConfig returns a basic xds RouteConfig resource.
   291  func DefaultRouteConfig(routeName, ldsTarget, clusterName string) *v3routepb.RouteConfiguration {
   292  	return &v3routepb.RouteConfiguration{
   293  		Name: routeName,
   294  		VirtualHosts: []*v3routepb.VirtualHost{{
   295  			Domains: []string{ldsTarget},
   296  			Routes: []*v3routepb.Route{{
   297  				Match: &v3routepb.RouteMatch{PathSpecifier: &v3routepb.RouteMatch_Prefix{Prefix: "/"}},
   298  				Action: &v3routepb.Route_Route{Route: &v3routepb.RouteAction{
   299  					ClusterSpecifier: &v3routepb.RouteAction_Cluster{Cluster: clusterName},
   300  				}},
   301  			}},
   302  		}},
   303  	}
   304  }
   305  
   306  // DefaultCluster returns a basic xds Cluster resource.
   307  func DefaultCluster(clusterName, edsServiceName string, secLevel SecurityLevel) *v3clusterpb.Cluster {
   308  	var tlsContext *v3tlspb.UpstreamTlsContext
   309  	switch secLevel {
   310  	case SecurityLevelNone:
   311  	case SecurityLevelTLS:
   312  		tlsContext = &v3tlspb.UpstreamTlsContext{
   313  			CommonTlsContext: &v3tlspb.CommonTlsContext{
   314  				ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContextCertificateProviderInstance{
   315  					ValidationContextCertificateProviderInstance: &v3tlspb.CommonTlsContext_CertificateProviderInstance{
   316  						InstanceName: ClientSideCertProviderInstance,
   317  					},
   318  				},
   319  			},
   320  		}
   321  	case SecurityLevelMTLS:
   322  		tlsContext = &v3tlspb.UpstreamTlsContext{
   323  			CommonTlsContext: &v3tlspb.CommonTlsContext{
   324  				ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContextCertificateProviderInstance{
   325  					ValidationContextCertificateProviderInstance: &v3tlspb.CommonTlsContext_CertificateProviderInstance{
   326  						InstanceName: ClientSideCertProviderInstance,
   327  					},
   328  				},
   329  				TlsCertificateCertificateProviderInstance: &v3tlspb.CommonTlsContext_CertificateProviderInstance{
   330  					InstanceName: ClientSideCertProviderInstance,
   331  				},
   332  			},
   333  		}
   334  	}
   335  
   336  	cluster := &v3clusterpb.Cluster{
   337  		Name:                 clusterName,
   338  		ClusterDiscoveryType: &v3clusterpb.Cluster_Type{Type: v3clusterpb.Cluster_EDS},
   339  		EdsClusterConfig: &v3clusterpb.Cluster_EdsClusterConfig{
   340  			EdsConfig: &v3corepb.ConfigSource{
   341  				ConfigSourceSpecifier: &v3corepb.ConfigSource_Ads{
   342  					Ads: &v3corepb.AggregatedConfigSource{},
   343  				},
   344  			},
   345  			ServiceName: edsServiceName,
   346  		},
   347  		LbPolicy: v3clusterpb.Cluster_ROUND_ROBIN,
   348  	}
   349  	if tlsContext != nil {
   350  		cluster.TransportSocket = &v3corepb.TransportSocket{
   351  			Name: "envoy.transport_sockets.tls",
   352  			ConfigType: &v3corepb.TransportSocket_TypedConfig{
   353  				TypedConfig: testutils.MarshalAny(tlsContext),
   354  			},
   355  		}
   356  	}
   357  	return cluster
   358  }
   359  
   360  // DefaultEndpoint returns a basic xds Endpoint resource.
   361  func DefaultEndpoint(clusterName string, host string, ports []uint32) *v3endpointpb.ClusterLoadAssignment {
   362  	var lbEndpoints []*v3endpointpb.LbEndpoint
   363  	for _, port := range ports {
   364  		lbEndpoints = append(lbEndpoints, &v3endpointpb.LbEndpoint{
   365  			HostIdentifier: &v3endpointpb.LbEndpoint_Endpoint{Endpoint: &v3endpointpb.Endpoint{
   366  				Address: &v3corepb.Address{Address: &v3corepb.Address_SocketAddress{
   367  					SocketAddress: &v3corepb.SocketAddress{
   368  						Protocol:      v3corepb.SocketAddress_TCP,
   369  						Address:       host,
   370  						PortSpecifier: &v3corepb.SocketAddress_PortValue{PortValue: port}},
   371  				}},
   372  			}},
   373  		})
   374  	}
   375  	return &v3endpointpb.ClusterLoadAssignment{
   376  		ClusterName: clusterName,
   377  		Endpoints: []*v3endpointpb.LocalityLbEndpoints{{
   378  			Locality:            &v3corepb.Locality{SubZone: "subzone"},
   379  			LbEndpoints:         lbEndpoints,
   380  			LoadBalancingWeight: &wrapperspb.UInt32Value{Value: 1},
   381  			Priority:            0,
   382  		}},
   383  	}
   384  }