github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/xds/internal/server/conn_wrapper.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 server
    20  
    21  import (
    22  	"errors"
    23  	"fmt"
    24  	"net"
    25  	"sync"
    26  	"time"
    27  
    28  	"github.com/hxx258456/ccgo/grpc/credentials/tls/certprovider"
    29  	xdsinternal "github.com/hxx258456/ccgo/grpc/internal/credentials/xds"
    30  	"github.com/hxx258456/ccgo/grpc/xds/internal/xdsclient/xdsresource"
    31  )
    32  
    33  // connWrapper is a thin wrapper around a net.Conn returned by Accept(). It
    34  // provides the following additional functionality:
    35  // 1. A way to retrieve the configured deadline. This is required by the
    36  //    ServerHandshake() method of the xdsCredentials when it attempts to read
    37  //    key material from the certificate providers.
    38  // 2. Implements the XDSHandshakeInfo() method used by the xdsCredentials to
    39  //    retrieve the configured certificate providers.
    40  // 3. xDS filter_chain matching logic to select appropriate security
    41  //    configuration for the incoming connection.
    42  type connWrapper struct {
    43  	net.Conn
    44  
    45  	// The specific filter chain picked for handling this connection.
    46  	filterChain *xdsresource.FilterChain
    47  
    48  	// A reference fo the listenerWrapper on which this connection was accepted.
    49  	parent *listenerWrapper
    50  
    51  	// The certificate providers created for this connection.
    52  	rootProvider, identityProvider certprovider.Provider
    53  
    54  	// The connection deadline as configured by the grpc.Server on the rawConn
    55  	// that is returned by a call to Accept(). This is set to the connection
    56  	// timeout value configured by the user (or to a default value) before
    57  	// initiating the transport credential handshake, and set to zero after
    58  	// completing the HTTP2 handshake.
    59  	deadlineMu sync.Mutex
    60  	deadline   time.Time
    61  
    62  	// The virtual hosts with matchable routes and instantiated HTTP Filters per
    63  	// route.
    64  	virtualHosts []xdsresource.VirtualHostWithInterceptors
    65  }
    66  
    67  // VirtualHosts returns the virtual hosts to be used for server side routing.
    68  func (c *connWrapper) VirtualHosts() []xdsresource.VirtualHostWithInterceptors {
    69  	return c.virtualHosts
    70  }
    71  
    72  // SetDeadline makes a copy of the passed in deadline and forwards the call to
    73  // the underlying rawConn.
    74  func (c *connWrapper) SetDeadline(t time.Time) error {
    75  	c.deadlineMu.Lock()
    76  	c.deadline = t
    77  	c.deadlineMu.Unlock()
    78  	return c.Conn.SetDeadline(t)
    79  }
    80  
    81  // GetDeadline returns the configured deadline. This will be invoked by the
    82  // ServerHandshake() method of the XdsCredentials, which needs a deadline to
    83  // pass to the certificate provider.
    84  func (c *connWrapper) GetDeadline() time.Time {
    85  	c.deadlineMu.Lock()
    86  	t := c.deadline
    87  	c.deadlineMu.Unlock()
    88  	return t
    89  }
    90  
    91  // XDSHandshakeInfo returns a HandshakeInfo with appropriate security
    92  // configuration for this connection. This method is invoked by the
    93  // ServerHandshake() method of the XdsCredentials.
    94  func (c *connWrapper) XDSHandshakeInfo() (*xdsinternal.HandshakeInfo, error) {
    95  	// Ideally this should never happen, since xdsCredentials are the only ones
    96  	// which will invoke this method at handshake time. But to be on the safe
    97  	// side, we avoid acting on the security configuration received from the
    98  	// control plane when the user has not configured the use of xDS
    99  	// credentials, by checking the value of this flag.
   100  	if !c.parent.xdsCredsInUse {
   101  		return nil, errors.New("user has not configured xDS credentials")
   102  	}
   103  
   104  	if c.filterChain.SecurityCfg == nil {
   105  		// If the security config is empty, this means that the control plane
   106  		// did not provide any security configuration and therefore we should
   107  		// return an empty HandshakeInfo here so that the xdsCreds can use the
   108  		// configured fallback credentials.
   109  		return xdsinternal.NewHandshakeInfo(nil, nil), nil
   110  	}
   111  
   112  	cpc := c.parent.xdsC.BootstrapConfig().CertProviderConfigs
   113  	// Identity provider name is mandatory on the server-side, and this is
   114  	// enforced when the resource is received at the XDSClient layer.
   115  	secCfg := c.filterChain.SecurityCfg
   116  	ip, err := buildProviderFunc(cpc, secCfg.IdentityInstanceName, secCfg.IdentityCertName, true, false)
   117  	if err != nil {
   118  		return nil, err
   119  	}
   120  	// Root provider name is optional and required only when doing mTLS.
   121  	var rp certprovider.Provider
   122  	if instance, cert := secCfg.RootInstanceName, secCfg.RootCertName; instance != "" {
   123  		rp, err = buildProviderFunc(cpc, instance, cert, false, true)
   124  		if err != nil {
   125  			return nil, err
   126  		}
   127  	}
   128  	c.identityProvider = ip
   129  	c.rootProvider = rp
   130  
   131  	xdsHI := xdsinternal.NewHandshakeInfo(c.rootProvider, c.identityProvider)
   132  	xdsHI.SetRequireClientCert(secCfg.RequireClientCert)
   133  	return xdsHI, nil
   134  }
   135  
   136  // Close closes the providers and the underlying connection.
   137  func (c *connWrapper) Close() error {
   138  	if c.identityProvider != nil {
   139  		c.identityProvider.Close()
   140  	}
   141  	if c.rootProvider != nil {
   142  		c.rootProvider.Close()
   143  	}
   144  	return c.Conn.Close()
   145  }
   146  
   147  func buildProviderFunc(configs map[string]*certprovider.BuildableConfig, instanceName, certName string, wantIdentity, wantRoot bool) (certprovider.Provider, error) {
   148  	cfg, ok := configs[instanceName]
   149  	if !ok {
   150  		return nil, fmt.Errorf("certificate provider instance %q not found in bootstrap file", instanceName)
   151  	}
   152  	provider, err := cfg.Build(certprovider.BuildOptions{
   153  		CertName:     certName,
   154  		WantIdentity: wantIdentity,
   155  		WantRoot:     wantRoot,
   156  	})
   157  	if err != nil {
   158  		// This error is not expected since the bootstrap process parses the
   159  		// config and makes sure that it is acceptable to the plugin. Still, it
   160  		// is possible that the plugin parses the config successfully, but its
   161  		// Build() method errors out.
   162  		return nil, fmt.Errorf("failed to get security plugin instance (%+v): %v", cfg, err)
   163  	}
   164  	return provider, nil
   165  }