[#1351] cli: Fix connection scheme loss during endpoint parsing

In previous implementation NeoFS CLI app used `network.Address.HostAddr`
as a server URI, which caused scheme loss since host address doesn't
contain it.

Rename `HostAddr` to `URIAddr` and make it to return URI address with
`grpcs` scheme if TLS is enabled. Make `TLSEnabled` unexported since it
was used to provide default `tls.Config` only (it is used by default in
SDK).

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2022-05-04 15:34:26 +03:00 committed by LeL
parent 3a44010180
commit cd545f0160
11 changed files with 39 additions and 53 deletions

View file

@ -3,6 +3,9 @@ Changelog for NeoFS Node
## [Unreleased] ## [Unreleased]
### Fixed
- Loss of the connection scheme during address parsing in NeoFS CLI (#1351)
## [0.28.0] - 2022-04-29 - Heuksando (흑산도, 黑山島) ## [0.28.0] - 2022-04-29 - Heuksando (흑산도, 黑山島)
### Added ### Added

View file

@ -2,7 +2,6 @@ package internal
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"crypto/tls"
"fmt" "fmt"
"github.com/nspcc-dev/neofs-node/pkg/network" "github.com/nspcc-dev/neofs-node/pkg/network"
@ -19,11 +18,7 @@ func GetSDKClient(key *ecdsa.PrivateKey, addr network.Address) (*client.Client,
prmInit.SetDefaultPrivateKey(*key) prmInit.SetDefaultPrivateKey(*key)
prmInit.ResolveNeoFSFailures() prmInit.ResolveNeoFSFailures()
prmDial.SetServerURI(addr.HostAddr()) prmDial.SetServerURI(addr.URIAddr())
if addr.TLSEnabled() {
prmDial.SetTLSConfig(&tls.Config{})
}
c.Init(prmInit) c.Init(prmInit)

View file

@ -2,7 +2,6 @@ package cmd
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"crypto/tls"
"fmt" "fmt"
"github.com/mr-tron/base58" "github.com/mr-tron/base58"
@ -457,30 +456,9 @@ func listShards(cmd *cobra.Command, _ []string) {
prettyPrintShards(cmd, resp.GetBody().GetShards()) prettyPrintShards(cmd, resp.GetBody().GetShards())
} }
// getControlSDKClient is the same getSDKClient but with // getControlSDKClient calls getSDKClientFlag with "endpoint" flag.
// another RPC endpoint flag.
func getControlSDKClient(key *ecdsa.PrivateKey) (*client.Client, error) { func getControlSDKClient(key *ecdsa.PrivateKey) (*client.Client, error) {
var ( return getSDKClientFlag(key, controlRPC)
c client.Client
prmInit client.PrmInit
prmDial client.PrmDial
)
netAddr, err := getEndpointAddress(controlRPC)
if err != nil {
return nil, err
}
prmInit.SetDefaultPrivateKey(*key)
prmDial.SetServerURI(netAddr.HostAddr())
if netAddr.TLSEnabled() {
prmDial.SetTLSConfig(&tls.Config{})
}
c.Init(prmInit)
return &c, c.Dial(prmDial)
} }
func prettyPrintShards(cmd *cobra.Command, ii []*control.ShardInfo) { func prettyPrintShards(cmd *cobra.Command, ii []*control.ShardInfo) {

View file

@ -188,7 +188,7 @@ func getEndpointAddress(endpointFlag string) (addr network.Address, err error) {
err = addr.FromString(endpoint) err = addr.FromString(endpoint)
if err != nil { if err != nil {
err = errInvalidEndpoint err = fmt.Errorf("%v: %w", errInvalidEndpoint, err)
} }
return return
@ -227,13 +227,19 @@ func prepareBearerPrm(cmd *cobra.Command, prm bearerPrm) {
prm.SetBearerToken(btok) prm.SetBearerToken(btok)
} }
// getSDKClient returns default neofs-api-go sdk client. Consider using // getSDKClient calls getSDKGClientFlag with "rpc-endpoint" flag.
// opts... to provide TTL or other global configuration flags.
func getSDKClient(key *ecdsa.PrivateKey) (*client.Client, error) { func getSDKClient(key *ecdsa.PrivateKey) (*client.Client, error) {
netAddr, err := getEndpointAddress(rpc) return getSDKClientFlag(key, rpc)
}
// getSDKClientFlag returns NeoFS API client connection to the network address
// set by the given flag.
func getSDKClientFlag(key *ecdsa.PrivateKey, endpointFlag string) (*client.Client, error) {
netAddr, err := getEndpointAddress(endpointFlag)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return internalclient.GetSDKClient(key, netAddr) return internalclient.GetSDKClient(key, netAddr)
} }

View file

@ -89,12 +89,10 @@ func TestNodeSection(t *testing.T) {
expectedAddr := []struct { expectedAddr := []struct {
str string str string
host string host string
tls bool
}{ }{
{ {
str: "/dns4/localhost/tcp/8083/tls", str: "/dns4/localhost/tcp/8083/tls",
host: "localhost:8083", host: "grpcs://localhost:8083",
tls: true,
}, },
{ {
str: "/dns4/s01.neofs.devenv/tcp/8080", str: "/dns4/s01.neofs.devenv/tcp/8080",
@ -118,8 +116,7 @@ func TestNodeSection(t *testing.T) {
addrs.IterateAddresses(func(addr network.Address) bool { addrs.IterateAddresses(func(addr network.Address) bool {
require.Equal(t, expectedAddr[ind].str, addr.String()) require.Equal(t, expectedAddr[ind].str, addr.String())
require.Equal(t, expectedAddr[ind].host, addr.HostAddr()) require.Equal(t, expectedAddr[ind].host, addr.URIAddr())
require.Equal(t, expectedAddr[ind].tls, addr.TLSEnabled())
ind++ ind++

View file

@ -3,6 +3,7 @@ package network
import ( import (
"fmt" "fmt"
"net" "net"
"net/url"
"strings" "strings"
"github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr"
@ -33,10 +34,12 @@ func (a Address) equal(addr Address) bool {
return a.ma.Equal(addr.ma) return a.ma.Equal(addr.ma)
} }
// HostAddr returns host address in string format. // URIAddr returns Address as a URI.
// //
// Panics if host address cannot be fetched from Address. // Panics if host address cannot be fetched from Address.
func (a Address) HostAddr() string { //
// See also FromString.
func (a Address) URIAddr() string {
_, host, err := manet.DialArgs(a.ma) _, host, err := manet.DialArgs(a.ma)
if err != nil { if err != nil {
// the only correct way to construct Address is AddressFromString // the only correct way to construct Address is AddressFromString
@ -44,9 +47,16 @@ func (a Address) HostAddr() string {
panic(fmt.Errorf("could not get host addr: %w", err)) panic(fmt.Errorf("could not get host addr: %w", err))
} }
if !a.isTLSEnabled() {
return host return host
} }
return (&url.URL{
Scheme: "grpcs",
Host: host,
}).String()
}
// FromString restores Address from a string representation. // FromString restores Address from a string representation.
// //
// Supports URIAddr, MultiAddr and HostAddr strings. // Supports URIAddr, MultiAddr and HostAddr strings.

View file

@ -50,12 +50,13 @@ func TestAddress_HostAddrString(t *testing.T) {
}{ }{
{buildMultiaddr("/dns4/neofs.bigcorp.com/tcp/8080", t), "neofs.bigcorp.com:8080"}, {buildMultiaddr("/dns4/neofs.bigcorp.com/tcp/8080", t), "neofs.bigcorp.com:8080"},
{buildMultiaddr("/ip4/172.16.14.1/tcp/8080", t), "172.16.14.1:8080"}, {buildMultiaddr("/ip4/172.16.14.1/tcp/8080", t), "172.16.14.1:8080"},
{buildMultiaddr("/ip4/192.168.0.1/tcp/8888/tls", t), "grpcs://192.168.0.1:8888"},
} }
for _, testcase := range testcases { for _, testcase := range testcases {
addr := Address{testcase.ma} addr := Address{testcase.ma}
got := addr.HostAddr() got := addr.URIAddr()
require.Equal(t, testcase.exp, got) require.Equal(t, testcase.exp, got)
} }
@ -68,7 +69,7 @@ func TestAddress_HostAddrString(t *testing.T) {
for _, testcase := range testcases { for _, testcase := range testcases {
addr := Address{testcase} addr := Address{testcase}
require.Panics(t, func() { addr.HostAddr() }) require.Panics(t, func() { addr.URIAddr() })
} }
}) })
} }

View file

@ -2,7 +2,6 @@ package cache
import ( import (
"context" "context"
"crypto/tls"
"errors" "errors"
"sync" "sync"
@ -38,10 +37,7 @@ func (x *multiClient) createForAddress(addr network.Address) clientcore.Client {
prmDial client.PrmDial prmDial client.PrmDial
) )
prmDial.SetServerURI(addr.HostAddr()) prmDial.SetServerURI(addr.URIAddr())
if addr.TLSEnabled() {
prmDial.SetTLSConfig(&tls.Config{})
}
if x.opts.Key != nil { if x.opts.Key != nil {
prmInit.SetDefaultPrivateKey(*x.opts.Key) prmInit.SetDefaultPrivateKey(*x.opts.Key)

View file

@ -57,7 +57,7 @@ func (x AddressGroup) Len() int {
// Less returns true if i-th address in AddressGroup supports TLS // Less returns true if i-th address in AddressGroup supports TLS
// and j-th one doesn't. // and j-th one doesn't.
func (x AddressGroup) Less(i, j int) bool { func (x AddressGroup) Less(i, j int) bool {
return x[i].TLSEnabled() && !x[j].TLSEnabled() return x[i].isTLSEnabled() && !x[j].isTLSEnabled()
} }
// Swap swaps i-th and j-th addresses in AddressGroup. // Swap swaps i-th and j-th addresses in AddressGroup.

View file

@ -11,8 +11,8 @@ const (
// tls var is used for (un)wrapping other multiaddrs around TLS multiaddr. // tls var is used for (un)wrapping other multiaddrs around TLS multiaddr.
var tls, _ = multiaddr.NewMultiaddr("/" + tlsProtocolName) var tls, _ = multiaddr.NewMultiaddr("/" + tlsProtocolName)
// TLSEnabled searches for wrapped TLS protocol in multiaddr. // isTLSEnabled searches for wrapped TLS protocol in multiaddr.
func (a Address) TLSEnabled() bool { func (a Address) isTLSEnabled() bool {
for _, protoc := range a.ma.Protocols() { for _, protoc := range a.ma.Protocols() {
if protoc.Code == multiaddr.P_TLS { if protoc.Code == multiaddr.P_TLS {
return true return true

View file

@ -24,6 +24,6 @@ func TestAddress_TLSEnabled(t *testing.T) {
err := addr.FromString(test.input) err := addr.FromString(test.input)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, test.wantTLS, addr.TLSEnabled(), test.input) require.Equal(t, test.wantTLS, addr.isTLSEnabled(), test.input)
} }
} }