From 1e0e3d5d3d8cc62abd7fabb31d558e4c86c43311 Mon Sep 17 00:00:00 2001 From: Joe Betz Date: Tue, 8 Oct 2019 13:01:53 -0700 Subject: [PATCH] Replace endpoint.ParseHostPort with net.SplitHostPort to fix IPv6 client endpoints --- .../balancer/resolver/endpoint/endpoint.go | 11 -------- clientv3/client.go | 14 +++++++--- integration/fixtures/server-ca-csr-ipv6.json | 19 +++++++++++++ integration/fixtures/server-ipv6.crt | 24 +++++++++++++++++ integration/fixtures/server-ipv6.key.insecure | 27 +++++++++++++++++++ 5 files changed, 80 insertions(+), 15 deletions(-) create mode 100644 integration/fixtures/server-ca-csr-ipv6.json create mode 100644 integration/fixtures/server-ipv6.crt create mode 100644 integration/fixtures/server-ipv6.key.insecure diff --git a/clientv3/balancer/resolver/endpoint/endpoint.go b/clientv3/balancer/resolver/endpoint/endpoint.go index b840d929c741..864b5df6426f 100644 --- a/clientv3/balancer/resolver/endpoint/endpoint.go +++ b/clientv3/balancer/resolver/endpoint/endpoint.go @@ -230,17 +230,6 @@ func ParseTarget(target string) (string, string, error) { return parts[0], parts[1], nil } -// ParseHostPort splits a ":" string into the host and port parts. -// The port part is optional. -func ParseHostPort(hostPort string) (host string, port string) { - parts := strings.SplitN(hostPort, ":", 2) - host = parts[0] - if len(parts) > 1 { - port = parts[1] - } - return host, port -} - // Dialer dials a endpoint using net.Dialer. // Context cancelation and timeout are supported. func Dialer(ctx context.Context, dialEp string) (net.Conn, error) { diff --git a/clientv3/client.go b/clientv3/client.go index d6c2154c0f70..b5285725239f 100644 --- a/clientv3/client.go +++ b/clientv3/client.go @@ -259,7 +259,10 @@ func (c *Client) dialSetupOpts(creds grpccredentials.TransportCredentials, dopts // Dial connects to a single endpoint using the client's config. func (c *Client) Dial(ep string) (*grpc.ClientConn, error) { - creds := c.directDialCreds(ep) + creds, err := c.directDialCreds(ep) + if err != nil { + return nil, err + } // Use the grpc passthrough resolver to directly dial a single endpoint. // This resolver passes through the 'unix' and 'unixs' endpoints schemes used // by etcd without modification, allowing us to directly dial endpoints and @@ -362,7 +365,7 @@ func (c *Client) dial(target string, creds grpccredentials.TransportCredentials, return conn, nil } -func (c *Client) directDialCreds(ep string) grpccredentials.TransportCredentials { +func (c *Client) directDialCreds(ep string) (grpccredentials.TransportCredentials, error) { _, hostPort, scheme := endpoint.ParseEndpoint(ep) creds := c.creds if len(scheme) != 0 { @@ -372,12 +375,15 @@ func (c *Client) directDialCreds(ep string) grpccredentials.TransportCredentials // Set the server name must to the endpoint hostname without port since grpc // otherwise attempts to check if x509 cert is valid for the full endpoint // including the scheme and port, which fails. - host, _ := endpoint.ParseHostPort(hostPort) + host, _, err := net.SplitHostPort(hostPort) + if err != nil { + return nil, err + } clone.OverrideServerName(host) creds = clone } } - return creds + return creds, nil } func (c *Client) dialWithBalancerCreds(ep string) grpccredentials.TransportCredentials { diff --git a/integration/fixtures/server-ca-csr-ipv6.json b/integration/fixtures/server-ca-csr-ipv6.json new file mode 100644 index 000000000000..2b2c4350ba14 --- /dev/null +++ b/integration/fixtures/server-ca-csr-ipv6.json @@ -0,0 +1,19 @@ +{ + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "O": "etcd", + "OU": "etcd Security", + "L": "San Francisco", + "ST": "California", + "C": "USA" + } + ], + "CN": "example.com", + "hosts": [ + "127.0.0.1" + ] +} diff --git a/integration/fixtures/server-ipv6.crt b/integration/fixtures/server-ipv6.crt new file mode 100644 index 000000000000..3454a7b02371 --- /dev/null +++ b/integration/fixtures/server-ipv6.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIECDCCAvCgAwIBAgIUVidA2BA1FGpvYIR8qVAXSmjEMsswDQYJKoZIhvcNAQEL +BQAwbzEMMAoGA1UEBhMDVVNBMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQH +Ew1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQKEwRldGNkMRYwFAYDVQQLEw1ldGNkIFNl +Y3VyaXR5MQswCQYDVQQDEwJjYTAeFw0xOTEwMDgxOTQ3MDBaFw0yOTEwMDUxOTQ3 +MDBaMHgxDDAKBgNVBAYTA1VTQTETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UE +BxMNU2FuIEZyYW5jaXNjbzENMAsGA1UEChMEZXRjZDEWMBQGA1UECxMNZXRjZCBT +ZWN1cml0eTEUMBIGA1UEAxMLZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQDo/UZ4i/n97iLJck0CrynaUpmKCagV21YsYzfFXvA/7biB +nF7YzEbZkXv+YjTwo8huHGm0XFUs0WzS7OoIK7n1QPfPntb+3AoVpD2amsEt/9VY +P5O42xfN+C+3MqRBAKeAuRzwFODuJi4qYsvJasBkfd78/QIn2YeHoyfhGO0wicmo +DWeBwNNkEqxdWsVjRAg5g3njBrabPJRbhvlri9S7/1cEa5Jdy1PRw/foUtDAbDl4 +2Zm9zDOj/1Hu5pUJoggsXycOty+xV9HwEHCBRZHxZgBgNElyZ5AhZ5aHc8tnpIVH +eLTlraYVxVWSvPgVXoZEO7fXxFTIlJPZdFiY39jvAgMBAAGjgZIwgY8wDgYDVR0P +AQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMB +Af8EAjAAMB0GA1UdDgQWBBRudySJBv0gSG51P7OpNWefd+YO6TAfBgNVHSMEGDAW +gBQ7mNcVfPjzEpOqH60986Kz0mUotjAQBgNVHREECTAHggVbOjoxXTANBgkqhkiG +9w0BAQsFAAOCAQEASGjBhkv/e9jjHLXCJSd2PtM0QhW1HQla2Ug/NvFvoTYdeTdU +Rs/dGsDYFm0G0zIYb1j7fjngWYVCjfMA8ccAlCPvlrC4+t3QDXqTrz2XLR72xzfs +Hmrr3nz7KRITIs6PCuBocGYQI64dkWvTHmfHsxRMqXOPQfaXAYruP6HUxOArGJsQ +Fs/B2C4hh5L9y+4KApTax4WIPSlp52MS7P7dKEK5HdNfzwvzAip4SBCSTwJ2w8Co +r3z/Lze0u4Ny/0C9AiOnKYlhcL0FacfxC41+a2SlxOc+0giGJMria5dHiWFkLFvg +hJ+SvGg2RVcdosh/+CiSHjqtGqFRZMdn/m+QVA== +-----END CERTIFICATE----- diff --git a/integration/fixtures/server-ipv6.key.insecure b/integration/fixtures/server-ipv6.key.insecure new file mode 100644 index 000000000000..549870a88955 --- /dev/null +++ b/integration/fixtures/server-ipv6.key.insecure @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpgIBAAKCAQEA6P1GeIv5/e4iyXJNAq8p2lKZigmoFdtWLGM3xV7wP+24gZxe +2MxG2ZF7/mI08KPIbhxptFxVLNFs0uzqCCu59UD3z57W/twKFaQ9mprBLf/VWD+T +uNsXzfgvtzKkQQCngLkc8BTg7iYuKmLLyWrAZH3e/P0CJ9mHh6Mn4RjtMInJqA1n +gcDTZBKsXVrFY0QIOYN54wa2mzyUW4b5a4vUu/9XBGuSXctT0cP36FLQwGw5eNmZ +vcwzo/9R7uaVCaIILF8nDrcvsVfR8BBwgUWR8WYAYDRJcmeQIWeWh3PLZ6SFR3i0 +5a2mFcVVkrz4FV6GRDu318RUyJST2XRYmN/Y7wIDAQABAoIBAQC2dgNGTHjPADuF +/1mIDJ1+OMm9bKqR01+9C0aV7y+/IPApsMgmiHPD10d/hHFpMxq4ANBXSyf5HVlY +Jelx1KyhAOwRUJeWp8POBv2noiI/X+c4YTHSxuHxj7fuhF5V+ak0CcQ70F4Goyfs +Ucq+Rje9e0WyYoHZq2WUN5X3lonKQ99ZPfWiyMGjxHWiHCsydC4OVqvJWxpAJ0OX +8DRQtGfpfu4V54i1kIb5E8BoEHl5wcGvbr4+bPIR3YYJrr8soNiNiwscpBZeK+yH +Mbjqbk77tyyDF9Qrdxz10dI1JFeCrQmvgTC83mYIGdjTJ/u1d6iVh23TH+QGBQIK +H5n+djxBAoGBAO2Jmc6oZrsw5mf1suWE3mOOElvWPA1d/ZmfCio7qrQpogz68F9s +Rd871lmfpRdO7iLGeDB2FIKLchzO6+FWBBCZthBsmOupGO6VKyLuwaL6gl78B0YM +iHDBFe/8gGPjujxhudoBfWeVw5pTrW338xtBhM6sW/VtMHYThQQ3G6aXAoGBAPsZ +LYMthCFvVjLaxJkv0q03ZjaSCNUd39nhPVJifkN6Sdu9b/QCp1Snq+4SU2pX/4Sa +y6VE3lXxTwTEGRBrkkoZ4AMaJspBftwTvJ75cy/bbMby8scq1o+o3oyXP46BenQr +gJCPozYRZS+ZekliamkCb2MkMlPgEInV98TCaUNpAoGBAKXZUziFP+UnCVhApn22 +PYgJJCxW8mrq2ywtbO17534PK4QgmUAm2so4fzroSl5xz7ccF8LOTxeuwSf4GZ2l +bwUgLYxeJo8z66J5KDsltLFUcz5afcGc8o63YdfD1ujnkZqjKR5bt/FhEcdo8Ug8 +vNKk9lNO6I39hL6Mdm0xBO9VAoGBAKAfLia4n8mydgV3/GazWGWdLlEeTwOYSWdn +evNOW7YsBW1bIEk6Z/pT8g+fIBJwi0DEdZiukhm8B+fCJTmTX3ZhibhwtMvFeGBf +Nakq6YlbI8K6qpbXenuh9EkzKhR1/OCX3SRSdIHGFgCEnratS64rH1zZeD6EZAeB +qr6OOxIBAoGBALsVC4Ygper5KEzNFGQN6c9MBxnrBpLOEGl61K49Jv1u4+14uG/6 +Z/e6ZU7PJBJh2/QbhjSGp0+0nyu9Pxlq9276/ZdxUeQdRlb5PPg2NJjkWGTgEzXI +zO8OCqYroni1PUSwozcz5IN+V/rr4X13uIuQZmQC0U2KJ+g3Yhau212x +-----END RSA PRIVATE KEY-----