@@ -39,6 +39,7 @@ import (
3939 corev1 "github.com/kdubbo/xds-api/core/v1"
4040 endpointv1 "github.com/kdubbo/xds-api/endpoint/v1"
4141 hcmv1 "github.com/kdubbo/xds-api/extensions/filters/v1/network/http_connection_manager"
42+ tlsv1 "github.com/kdubbo/xds-api/extensions/transport_sockets/tls/v1"
4243 xdsresolver "github.com/kdubbo/xds-api/grpc/resolver"
4344 listenerv1 "github.com/kdubbo/xds-api/listener/v1"
4445 routev1 "github.com/kdubbo/xds-api/route/v1"
@@ -85,7 +86,11 @@ type xdsDestination struct {
8586 Host string `json:"host"`
8687 Subset string `json:"subset,omitempty"`
8788 Weight uint32 `json:"weight"`
89+ TLSMode string `json:"tlsMode,omitempty"`
90+ SNI string `json:"sni,omitempty"`
8891 Endpoints []xdsEndpoint `json:"endpoints,omitempty"`
92+
93+ tlsContext * tlsv1.UpstreamTlsContext
8994}
9095
9196type xdsRouteSnapshot struct {
@@ -102,12 +107,15 @@ type sampleADSClient struct {
102107 host string
103108 port int
104109
105- mu sync.RWMutex
106- subs map [string ][]string
107- route map [string ]uint32
108- endpoints map [string ][]xdsEndpoint
109- updates chan struct {}
110- errs chan error
110+ mu sync.RWMutex
111+ subs map [string ][]string
112+ route map [string ]uint32
113+ endpoints map [string ][]xdsEndpoint
114+ clusterTLS map [string ]* tlsv1.UpstreamTlsContext
115+ updates chan struct {}
116+ errs chan error
117+ bootstrapPath string
118+ bootstrap * xdsresolver.BootstrapConfig
111119}
112120
113121func newXClientCommand () * cobra.Command {
@@ -232,17 +240,19 @@ func newSampleADSClient(ctx context.Context, opts *xdsClientOptions) (*sampleADS
232240 return nil , fmt .Errorf ("open ADS stream: %w" , err )
233241 }
234242 return & sampleADSClient {
235- conn : conn ,
236- stream : stream ,
237- node : node ,
238- target : opts .target ,
239- host : opts .host ,
240- port : opts .port ,
241- subs : map [string ][]string {},
242- route : map [string ]uint32 {},
243- endpoints : map [string ][]xdsEndpoint {},
244- updates : make (chan struct {}, 1 ),
245- errs : make (chan error , 1 ),
243+ conn : conn ,
244+ stream : stream ,
245+ node : node ,
246+ target : opts .target ,
247+ host : opts .host ,
248+ port : opts .port ,
249+ subs : map [string ][]string {},
250+ route : map [string ]uint32 {},
251+ endpoints : map [string ][]xdsEndpoint {},
252+ clusterTLS : map [string ]* tlsv1.UpstreamTlsContext {},
253+ updates : make (chan struct {}, 1 ),
254+ errs : make (chan error , 1 ),
255+ bootstrapPath : opts .bootstrapPath ,
246256 }, nil
247257}
248258
@@ -410,10 +420,16 @@ func (c *sampleADSClient) handleResponse(resp *discovery.DiscoveryResponse) erro
410420 return c .subscribe (v1 .ClusterType , clusters )
411421 }
412422 case v1 .ClusterType :
413- edsNames , err := edsNamesFromClusters (resp .Resources )
423+ edsNames , clusterTLS , err := edsNamesAndTLSFromClusters (resp .Resources )
414424 if err != nil {
415425 return err
416426 }
427+ c .mu .Lock ()
428+ for clusterName , tlsContext := range clusterTLS {
429+ c .clusterTLS [clusterName ] = tlsContext
430+ }
431+ c .mu .Unlock ()
432+ c .notify ()
417433 if len (edsNames ) > 0 {
418434 return c .subscribe (v1 .EndpointType , edsNames )
419435 }
@@ -478,7 +494,7 @@ func (c *sampleADSClient) readySnapshot(expected map[string]uint32) (xdsRouteSna
478494 continue
479495 }
480496 eps := append ([]xdsEndpoint (nil ), c .endpoints [clusterName ]... )
481- dest := destinationFromCluster (clusterName , weight , eps )
497+ dest := destinationFromCluster (clusterName , weight , eps , c . clusterTLS [ clusterName ] )
482498 snapshot .Destinations = append (snapshot .Destinations , dest )
483499 }
484500 sort .Slice (snapshot .Destinations , func (i , j int ) bool {
@@ -569,13 +585,15 @@ func routeWeightsFromRoutes(resources []*anypb.Any) (map[string]uint32, []string
569585 return weights , sortedUnique (clusters ), nil
570586}
571587
572- func edsNamesFromClusters (resources []* anypb.Any ) ([]string , error ) {
588+ func edsNamesAndTLSFromClusters (resources []* anypb.Any ) ([]string , map [ string ] * tlsv1. UpstreamTlsContext , error ) {
573589 out := make ([]string , 0 , len (resources ))
590+ clusterTLS := map [string ]* tlsv1.UpstreamTlsContext {}
574591 for _ , resource := range resources {
575592 c := & clusterv1.Cluster {}
576593 if err := proto .Unmarshal (resource .Value , c ); err != nil {
577- return nil , err
594+ return nil , nil , err
578595 }
596+ clusterTLS [c .Name ] = upstreamTLSContextFromCluster (c )
579597 serviceName := c .GetName ()
580598 if eds := c .GetEdsClusterConfig (); eds != nil && eds .GetServiceName () != "" {
581599 serviceName = eds .GetServiceName ()
@@ -584,7 +602,22 @@ func edsNamesFromClusters(resources []*anypb.Any) ([]string, error) {
584602 out = append (out , serviceName )
585603 }
586604 }
587- return sortedUnique (out ), nil
605+ return sortedUnique (out ), clusterTLS , nil
606+ }
607+
608+ func upstreamTLSContextFromCluster (c * clusterv1.Cluster ) * tlsv1.UpstreamTlsContext {
609+ if c == nil || c .TransportSocket == nil {
610+ return nil
611+ }
612+ typedConfig := c .TransportSocket .GetTypedConfig ()
613+ if typedConfig == nil {
614+ return nil
615+ }
616+ upstreamTLS := & tlsv1.UpstreamTlsContext {}
617+ if err := anypb .UnmarshalTo (typedConfig , upstreamTLS , proto.UnmarshalOptions {}); err != nil {
618+ return nil
619+ }
620+ return upstreamTLS
588621}
589622
590623func endpointsFromAssignments (resources []* anypb.Any ) (map [string ][]xdsEndpoint , error ) {
@@ -622,13 +655,17 @@ func endpointsFromAssignments(resources []*anypb.Any) (map[string][]xdsEndpoint,
622655 return out , nil
623656}
624657
625- func destinationFromCluster (clusterName string , weight uint32 , endpoints []xdsEndpoint ) xdsDestination {
658+ func destinationFromCluster (clusterName string , weight uint32 , endpoints []xdsEndpoint , tlsContext * tlsv1. UpstreamTlsContext ) xdsDestination {
626659 parts := strings .Split (clusterName , "|" )
627- dest := xdsDestination {Cluster : clusterName , Weight : weight , Endpoints : endpoints }
660+ dest := xdsDestination {Cluster : clusterName , Weight : weight , Endpoints : endpoints , tlsContext : tlsContext }
628661 if len (parts ) == 4 {
629662 dest .Host = parts [3 ]
630663 dest .Subset = parts [2 ]
631664 }
665+ if tlsContext != nil {
666+ dest .TLSMode = "DUBBO_MUTUAL"
667+ dest .SNI = tlsContext .Sni
668+ }
632669 return dest
633670}
634671
@@ -638,7 +675,7 @@ func runSampleRequests(ctx context.Context, adsClient *sampleADSClient, snapshot
638675 return err
639676 }
640677 currentSignature := snapshotSignature (snapshot )
641- client := & http. Client { Timeout : requestTimeout }
678+ clients := newSampleRequestClients ( adsClient , requestTimeout )
642679 for i := 0 ; i < count ; i ++ {
643680 if updated , ok := adsClient .readySnapshot (nil ); ok {
644681 updatedSignature := snapshotSignature (updated )
@@ -651,17 +688,21 @@ func runSampleRequests(ctx context.Context, adsClient *sampleADSClient, snapshot
651688 }
652689 }
653690 }
654- _ , endpoint , err := picker .Next ()
691+ destination , endpoint , err := picker .Next ()
692+ if err != nil {
693+ return err
694+ }
695+ httpClient , scheme , err := clients .clientForDestination (destination )
655696 if err != nil {
656697 return err
657698 }
658699 req , err := http .NewRequestWithContext (ctx , http .MethodGet ,
659- fmt .Sprintf ("http ://%s/" , net .JoinHostPort (endpoint .Address , strconv .Itoa (int (endpoint .Port )))), nil )
700+ fmt .Sprintf ("%s ://%s/" , scheme , net .JoinHostPort (endpoint .Address , strconv .Itoa (int (endpoint .Port )))), nil )
660701 if err != nil {
661702 return err
662703 }
663704 req .Host = snapshot .Host
664- resp , err := client .Do (req )
705+ resp , err := httpClient .Do (req )
665706 if err != nil {
666707 return err
667708 }
@@ -686,6 +727,70 @@ func runSampleRequests(ctx context.Context, adsClient *sampleADSClient, snapshot
686727 return nil
687728}
688729
730+ type sampleRequestClients struct {
731+ adsClient * sampleADSClient
732+ requestTimeout time.Duration
733+ plaintext * http.Client
734+ tlsClients map [string ]* http.Client
735+ }
736+
737+ func newSampleRequestClients (adsClient * sampleADSClient , requestTimeout time.Duration ) * sampleRequestClients {
738+ return & sampleRequestClients {
739+ adsClient : adsClient ,
740+ requestTimeout : requestTimeout ,
741+ plaintext : & http.Client {Timeout : requestTimeout },
742+ tlsClients : map [string ]* http.Client {},
743+ }
744+ }
745+
746+ func (c * sampleRequestClients ) clientForDestination (destination xdsDestination ) (* http.Client , string , error ) {
747+ if destination .tlsContext == nil {
748+ return c .plaintext , "http" , nil
749+ }
750+ bootstrap , err := c .adsClient .bootstrapConfig ()
751+ if err != nil {
752+ return nil , "" , err
753+ }
754+ tlsConfig , err := xdsresolver .DataPlaneTLSConfigFromBootstrap (bootstrap , destination .tlsContext , destination .Host )
755+ if err != nil {
756+ return nil , "" , err
757+ }
758+ key := destination .TLSMode + "|" + destination .SNI
759+ if key == "|" {
760+ key = destination .Cluster
761+ }
762+ if cached := c .tlsClients [key ]; cached != nil {
763+ return cached , "https" , nil
764+ }
765+ client := & http.Client {
766+ Timeout : c .requestTimeout ,
767+ Transport : & http.Transport {
768+ TLSClientConfig : tlsConfig ,
769+ },
770+ }
771+ c .tlsClients [key ] = client
772+ return client , "https" , nil
773+ }
774+
775+ func (c * sampleADSClient ) bootstrapConfig () (* xdsresolver.BootstrapConfig , error ) {
776+ if c .bootstrap != nil {
777+ return c .bootstrap , nil
778+ }
779+ path := c .bootstrapPath
780+ if path == "" {
781+ path = os .Getenv ("GRPC_XDS_BOOTSTRAP" )
782+ }
783+ if path == "" {
784+ return nil , fmt .Errorf ("data-plane mTLS requires GRPC_XDS_BOOTSTRAP or --bootstrap" )
785+ }
786+ bootstrap , err := xdsresolver .ParseBootstrap (path )
787+ if err != nil {
788+ return nil , err
789+ }
790+ c .bootstrap = bootstrap
791+ return c .bootstrap , nil
792+ }
793+
689794func activeDestinations (snapshot xdsRouteSnapshot ) []xdsDestination {
690795 out := make ([]xdsDestination , 0 , len (snapshot .Destinations ))
691796 for _ , dest := range snapshot .Destinations {
0 commit comments