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