github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/proxy/dial.go (about)

     1  /*
     2  Copyright 2015 The Kubernetes Authors All rights reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package proxy
    18  
    19  import (
    20  	"crypto/tls"
    21  	"fmt"
    22  	"net"
    23  	"net/http"
    24  	"net/url"
    25  
    26  	"github.com/golang/glog"
    27  
    28  	"k8s.io/kubernetes/pkg/util"
    29  	"k8s.io/kubernetes/third_party/golang/netutil"
    30  )
    31  
    32  func DialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) {
    33  	dialAddr := netutil.CanonicalAddr(url)
    34  
    35  	dialer, _ := util.Dialer(transport)
    36  
    37  	switch url.Scheme {
    38  	case "http":
    39  		if dialer != nil {
    40  			return dialer("tcp", dialAddr)
    41  		}
    42  		return net.Dial("tcp", dialAddr)
    43  	case "https":
    44  		// Get the tls config from the transport if we recognize it
    45  		var tlsConfig *tls.Config
    46  		var tlsConn *tls.Conn
    47  		var err error
    48  		tlsConfig, _ = util.TLSClientConfig(transport)
    49  
    50  		if dialer != nil {
    51  			// We have a dialer; use it to open the connection, then
    52  			// create a tls client using the connection.
    53  			netConn, err := dialer("tcp", dialAddr)
    54  			if err != nil {
    55  				return nil, err
    56  			}
    57  			if tlsConfig == nil {
    58  				// tls.Client requires non-nil config
    59  				glog.Warningf("using custom dialer with no TLSClientConfig. Defaulting to InsecureSkipVerify")
    60  				// tls.Handshake() requires ServerName or InsecureSkipVerify
    61  				tlsConfig = &tls.Config{
    62  					InsecureSkipVerify: true,
    63  				}
    64  			} else if len(tlsConfig.ServerName) == 0 && !tlsConfig.InsecureSkipVerify {
    65  				// tls.Handshake() requires ServerName or InsecureSkipVerify
    66  				// infer the ServerName from the hostname we're connecting to.
    67  				inferredHost := dialAddr
    68  				if host, _, err := net.SplitHostPort(dialAddr); err == nil {
    69  					inferredHost = host
    70  				}
    71  				// Make a copy to avoid polluting the provided config
    72  				tlsConfigCopy := *tlsConfig
    73  				tlsConfigCopy.ServerName = inferredHost
    74  				tlsConfig = &tlsConfigCopy
    75  			}
    76  			tlsConn = tls.Client(netConn, tlsConfig)
    77  			if err := tlsConn.Handshake(); err != nil {
    78  				netConn.Close()
    79  				return nil, err
    80  			}
    81  
    82  		} else {
    83  			// Dial
    84  			tlsConn, err = tls.Dial("tcp", dialAddr, tlsConfig)
    85  			if err != nil {
    86  				return nil, err
    87  			}
    88  		}
    89  
    90  		// Return if we were configured to skip validation
    91  		if tlsConfig != nil && tlsConfig.InsecureSkipVerify {
    92  			return tlsConn, nil
    93  		}
    94  
    95  		// Verify
    96  		host, _, _ := net.SplitHostPort(dialAddr)
    97  		if err := tlsConn.VerifyHostname(host); err != nil {
    98  			tlsConn.Close()
    99  			return nil, err
   100  		}
   101  
   102  		return tlsConn, nil
   103  	default:
   104  		return nil, fmt.Errorf("Unknown scheme: %s", url.Scheme)
   105  	}
   106  }