server: Error out if loopback addr is used for Distributed Erasure (#4105)

master
Bala FA 8 years ago committed by Harshavardhana
parent 6683247080
commit d103d5fb7c
  1. 38
      cmd/endpoint.go
  2. 180
      cmd/endpoint_test.go

@ -305,9 +305,11 @@ func CreateEndpoints(serverAddr string, args ...string) (string, EndpointList, S
hostIPSet, _ := getHostIP4(host) hostIPSet, _ := getHostIP4(host)
if IPSet, ok := pathIPMap[endpoint.Path]; ok { if IPSet, ok := pathIPMap[endpoint.Path]; ok {
if !IPSet.Intersection(hostIPSet).IsEmpty() { if !IPSet.Intersection(hostIPSet).IsEmpty() {
err = fmt.Errorf("path '%s' can not be served from different address/port", endpoint.Path) err = fmt.Errorf("path '%s' can not be served by different port on same address", endpoint.Path)
return serverAddr, endpoints, setupType, err return serverAddr, endpoints, setupType, err
} }
pathIPMap[endpoint.Path] = IPSet.Union(hostIPSet)
} else { } else {
pathIPMap[endpoint.Path] = hostIPSet pathIPMap[endpoint.Path] = hostIPSet
} }
@ -327,8 +329,10 @@ func CreateEndpoints(serverAddr string, args ...string) (string, EndpointList, S
} }
} }
// If all endpoints are pointing to local host and having same port number, then this is XL setup using URL style endpoints. // All endpoints are pointing to local host
if len(endpoints) == localEndpointCount && len(localPortSet) == 1 { if len(endpoints) == localEndpointCount {
// If all endpoints have same port number, then this is XL setup using URL style endpoints.
if len(localPortSet) == 1 {
if len(localServerAddrSet) > 1 { if len(localServerAddrSet) > 1 {
// TODO: Eventhough all endpoints are local, the local host is referred by different IP/name. // TODO: Eventhough all endpoints are local, the local host is referred by different IP/name.
// eg '172.0.0.1', 'localhost' and 'mylocalhostname' point to same local host. // eg '172.0.0.1', 'localhost' and 'mylocalhostname' point to same local host.
@ -344,6 +348,33 @@ func CreateEndpoints(serverAddr string, args ...string) (string, EndpointList, S
return serverAddr, endpoints, setupType, nil return serverAddr, endpoints, setupType, nil
} }
// Eventhough all endpoints are local, but those endpoints use different ports.
// This means it is DistXL setup.
} else {
// This is DistXL setup.
// Check whether local server address are not 127.x.x.x
for _, localServerAddr := range localServerAddrSet.ToSlice() {
host, _, err := net.SplitHostPort(localServerAddr)
if err != nil {
host = localServerAddr
}
ipList, err := getHostIP4(host)
fatalIf(err, "unexpected error when resolving host '%s'", host)
// Filter ipList by IPs those start with '127.'.
loopBackIPs := ipList.FuncMatch(func(ip string, matchString string) bool {
return strings.HasPrefix(ip, "127.")
}, "")
// If loop back IP is found and ipList contains only loop back IPs, then error out.
if len(loopBackIPs) > 0 && len(loopBackIPs) == len(ipList) {
err = fmt.Errorf("'%s' resolves to loopback address is not allowed for distributed XL", localServerAddr)
return serverAddr, endpoints, setupType, err
}
}
}
// Add missing port in all endpoints. // Add missing port in all endpoints.
for i := range endpoints { for i := range endpoints {
_, port, err := net.SplitHostPort(endpoints[i].Host) _, port, err := net.SplitHostPort(endpoints[i].Host)
@ -355,7 +386,6 @@ func CreateEndpoints(serverAddr string, args ...string) (string, EndpointList, S
} }
} }
// This is DistXL setup.
setupType = DistXLSetupType setupType = DistXLSetupType
return serverAddr, endpoints, setupType, nil return serverAddr, endpoints, setupType, nil
} }

@ -21,6 +21,7 @@ import (
"net/url" "net/url"
"reflect" "reflect"
"runtime" "runtime"
"sort"
"strings" "strings"
"testing" "testing"
) )
@ -143,35 +144,86 @@ func TestNewEndpointList(t *testing.T) {
} }
func TestCreateEndpoints(t *testing.T) { func TestCreateEndpoints(t *testing.T) {
case1u1, _ := url.Parse("http://example.com:10000/d4") // Filter ipList by IPs those do not start with '127.'.
case1u2, _ := url.Parse("http://example.org:10000/d3") nonLoopBackIPs := localIP4.FuncMatch(func(ip string, matchString string) bool {
case1u3, _ := url.Parse("http://localhost:10000/d1") return !strings.HasPrefix(ip, "127.")
case1u4, _ := url.Parse("http://localhost:10000/d2") }, "")
if len(nonLoopBackIPs) == 0 {
case2u1, _ := url.Parse("http://example.com:10000/d4") t.Fatalf("No non-loop back IP address found for this host")
case2u2, _ := url.Parse("http://example.org:10000/d3") }
case2u3, _ := url.Parse("http://localhost:10000/d1") nonLoopBackIP := nonLoopBackIPs.ToSlice()[0]
case2u4, _ := url.Parse("http://localhost:9000/d2")
getExpectedEndpoints := func(args []string, prefix string) ([]*url.URL, []bool) {
case3u1, _ := url.Parse("http://example.com:80/d3") var URLs []*url.URL
case3u2, _ := url.Parse("http://example.net:80/d4") var localFlags []bool
case3u3, _ := url.Parse("http://example.org:9000/d2") sort.Strings(args)
case3u4, _ := url.Parse("http://localhost:80/d1") for _, arg := range args {
u, _ := url.Parse(arg)
case4u1, _ := url.Parse("http://example.com:9000/d3") URLs = append(URLs, u)
case4u2, _ := url.Parse("http://example.net:9000/d4") localFlags = append(localFlags, strings.HasPrefix(arg, prefix))
case4u3, _ := url.Parse("http://example.org:9000/d2") }
case4u4, _ := url.Parse("http://localhost:9000/d1")
return URLs, localFlags
case5u1, _ := url.Parse("http://localhost:9000/d1") }
case5u2, _ := url.Parse("http://localhost:9001/d2")
case5u3, _ := url.Parse("http://localhost:9002/d3") case1Endpoint1 := "http://" + nonLoopBackIP + "/d1"
case5u4, _ := url.Parse("http://localhost:9003/d4") case1Endpoint2 := "http://" + nonLoopBackIP + "/d2"
args := []string{
case6u1, _ := url.Parse("http://10.0.0.1:9000/export") "http://" + nonLoopBackIP + ":10000/d1",
case6u2, _ := url.Parse("http://10.0.0.2:9000/export") "http://" + nonLoopBackIP + ":10000/d2",
case6u3, _ := url.Parse("http://10.0.0.3:9000/export") "http://example.com:10000/d4",
case6u4, _ := url.Parse("http://localhost:9001/export") "http://example.org:10000/d3",
}
case1URLs, case1LocalFlags := getExpectedEndpoints(args, "http://"+nonLoopBackIP+":10000/")
case2Endpoint1 := "http://" + nonLoopBackIP + "/d1"
case2Endpoint2 := "http://" + nonLoopBackIP + ":9000/d2"
args = []string{
"http://" + nonLoopBackIP + ":10000/d1",
"http://" + nonLoopBackIP + ":9000/d2",
"http://example.com:10000/d4",
"http://example.org:10000/d3",
}
case2URLs, case2LocalFlags := getExpectedEndpoints(args, "http://"+nonLoopBackIP+":10000/")
case3Endpoint1 := "http://" + nonLoopBackIP + "/d1"
args = []string{
"http://" + nonLoopBackIP + ":80/d1",
"http://example.com:80/d3",
"http://example.net:80/d4",
"http://example.org:9000/d2",
}
case3URLs, case3LocalFlags := getExpectedEndpoints(args, "http://"+nonLoopBackIP+":80/")
case4Endpoint1 := "http://" + nonLoopBackIP + "/d1"
args = []string{
"http://" + nonLoopBackIP + ":9000/d1",
"http://example.com:9000/d3",
"http://example.net:9000/d4",
"http://example.org:9000/d2",
}
case4URLs, case4LocalFlags := getExpectedEndpoints(args, "http://"+nonLoopBackIP+":9000/")
case5Endpoint1 := "http://" + nonLoopBackIP + ":9000/d1"
case5Endpoint2 := "http://" + nonLoopBackIP + ":9001/d2"
case5Endpoint3 := "http://" + nonLoopBackIP + ":9002/d3"
case5Endpoint4 := "http://" + nonLoopBackIP + ":9003/d4"
args = []string{
case5Endpoint1,
case5Endpoint2,
case5Endpoint3,
case5Endpoint4,
}
case5URLs, case5LocalFlags := getExpectedEndpoints(args, "http://"+nonLoopBackIP+":9000/")
case6Endpoint := "http://" + nonLoopBackIP + ":9003/d4"
args = []string{
"http://localhost:9000/d1",
"http://localhost:9001/d2",
"http://127.0.0.1:9002/d3",
case6Endpoint,
}
case6URLs, case6LocalFlags := getExpectedEndpoints(args, "http://"+nonLoopBackIP+":9003/")
testCases := []struct { testCases := []struct {
serverAddr string serverAddr string
@ -192,7 +244,7 @@ func TestCreateEndpoints(t *testing.T) {
{"localhost:10000", []string{`.\d1`}, "localhost:10000", EndpointList{Endpoint{URL: &url.URL{Path: `.\d1`}, IsLocal: true}}, FSSetupType, nil}, {"localhost:10000", []string{`.\d1`}, "localhost:10000", EndpointList{Endpoint{URL: &url.URL{Path: `.\d1`}, IsLocal: true}}, FSSetupType, nil},
{":8080", []string{"https://example.org/d1", "https://example.org/d2", "https://example.org/d3", "https://example.org/d4"}, "", EndpointList{}, -1, fmt.Errorf("no endpoint found for this host")}, {":8080", []string{"https://example.org/d1", "https://example.org/d2", "https://example.org/d3", "https://example.org/d4"}, "", EndpointList{}, -1, fmt.Errorf("no endpoint found for this host")},
{":8080", []string{"https://example.org/d1", "https://example.com/d2", "https://example.net:8000/d3", "https://example.edu/d1"}, "", EndpointList{}, -1, fmt.Errorf("no endpoint found for this host")}, {":8080", []string{"https://example.org/d1", "https://example.com/d2", "https://example.net:8000/d3", "https://example.edu/d1"}, "", EndpointList{}, -1, fmt.Errorf("no endpoint found for this host")},
{"localhost:9000", []string{"https://127.0.0.1:9000/d1", "https://localhost:9001/d1", "https://example.com/d1", "https://example.com/d2"}, "", EndpointList{}, -1, fmt.Errorf("path '/d1' can not be served from different address/port")}, {"localhost:9000", []string{"https://127.0.0.1:9000/d1", "https://localhost:9001/d1", "https://example.com/d1", "https://example.com/d2"}, "", EndpointList{}, -1, fmt.Errorf("path '/d1' can not be served by different port on same address")},
{"localhost:9000", []string{"https://127.0.0.1:8000/d1", "https://localhost:9001/d2", "https://example.com/d1", "https://example.com/d2"}, "", EndpointList{}, -1, fmt.Errorf("port number in server address must match with one of the port in local endpoints")}, {"localhost:9000", []string{"https://127.0.0.1:8000/d1", "https://localhost:9001/d2", "https://example.com/d1", "https://example.com/d2"}, "", EndpointList{}, -1, fmt.Errorf("port number in server address must match with one of the port in local endpoints")},
{"localhost:10000", []string{"https://127.0.0.1:8000/d1", "https://localhost:8000/d2", "https://example.com/d1", "https://example.com/d2"}, "", EndpointList{}, -1, fmt.Errorf("server address and local endpoint have different ports")}, {"localhost:10000", []string{"https://127.0.0.1:8000/d1", "https://localhost:8000/d2", "https://example.com/d1", "https://example.com/d2"}, "", EndpointList{}, -1, fmt.Errorf("server address and local endpoint have different ports")},
@ -218,44 +270,52 @@ func TestCreateEndpoints(t *testing.T) {
Endpoint{URL: &url.URL{Path: "/d3"}, IsLocal: true}, Endpoint{URL: &url.URL{Path: "/d3"}, IsLocal: true},
Endpoint{URL: &url.URL{Path: "/d4"}, IsLocal: true}, Endpoint{URL: &url.URL{Path: "/d4"}, IsLocal: true},
}, XLSetupType, nil}, }, XLSetupType, nil},
{":9001", []string{"http://10.0.0.1:9000/export", "http://10.0.0.2:9000/export", "http://" + nonLoopBackIP + ":9001/export", "http://10.0.0.2:9001/export"}, "", EndpointList{}, -1, fmt.Errorf("path '/export' can not be served by different port on same address")},
{":9000", []string{"http://localhost/d1", "http://localhost/d2", "http://example.org/d3", "http://example.com/d4"}, "", EndpointList{}, -1, fmt.Errorf("'localhost' resolves to loopback address is not allowed for distributed XL")},
// DistXL type // DistXL type
{"127.0.0.1:10000", []string{"http://localhost/d1", "http://localhost/d2", "http://example.org/d3", "http://example.com/d4"}, "127.0.0.1:10000", EndpointList{ {"127.0.0.1:10000", []string{case1Endpoint1, case1Endpoint2, "http://example.org/d3", "http://example.com/d4"}, "127.0.0.1:10000", EndpointList{
Endpoint{URL: case1u1, IsLocal: false}, Endpoint{URL: case1URLs[0], IsLocal: case1LocalFlags[0]},
Endpoint{URL: case1u2, IsLocal: false}, Endpoint{URL: case1URLs[1], IsLocal: case1LocalFlags[1]},
Endpoint{URL: case1u3, IsLocal: true}, Endpoint{URL: case1URLs[2], IsLocal: case1LocalFlags[2]},
Endpoint{URL: case1u4, IsLocal: true}, Endpoint{URL: case1URLs[3], IsLocal: case1LocalFlags[3]},
}, DistXLSetupType, nil}, }, DistXLSetupType, nil},
{"127.0.0.1:10000", []string{"http://localhost/d1", "http://localhost:9000/d2", "http://example.org/d3", "http://example.com/d4"}, "127.0.0.1:10000", EndpointList{
Endpoint{URL: case2u1, IsLocal: false}, {"127.0.0.1:10000", []string{case2Endpoint1, case2Endpoint2, "http://example.org/d3", "http://example.com/d4"}, "127.0.0.1:10000", EndpointList{
Endpoint{URL: case2u2, IsLocal: false}, Endpoint{URL: case2URLs[0], IsLocal: case2LocalFlags[0]},
Endpoint{URL: case2u3, IsLocal: true}, Endpoint{URL: case2URLs[1], IsLocal: case2LocalFlags[1]},
Endpoint{URL: case2u4, IsLocal: false}, Endpoint{URL: case2URLs[2], IsLocal: case2LocalFlags[2]},
Endpoint{URL: case2URLs[3], IsLocal: case2LocalFlags[3]},
}, DistXLSetupType, nil}, }, DistXLSetupType, nil},
{":80", []string{"http://localhost/d1", "http://example.org:9000/d2", "http://example.com/d3", "http://example.net/d4"}, ":80", EndpointList{
Endpoint{URL: case3u1, IsLocal: false}, {":80", []string{case3Endpoint1, "http://example.org:9000/d2", "http://example.com/d3", "http://example.net/d4"}, ":80", EndpointList{
Endpoint{URL: case3u2, IsLocal: false}, Endpoint{URL: case3URLs[0], IsLocal: case3LocalFlags[0]},
Endpoint{URL: case3u3, IsLocal: false}, Endpoint{URL: case3URLs[1], IsLocal: case3LocalFlags[1]},
Endpoint{URL: case3u4, IsLocal: true}, Endpoint{URL: case3URLs[2], IsLocal: case3LocalFlags[2]},
Endpoint{URL: case3URLs[3], IsLocal: case3LocalFlags[3]},
}, DistXLSetupType, nil}, }, DistXLSetupType, nil},
{":9000", []string{"http://localhost/d1", "http://example.org/d2", "http://example.com/d3", "http://example.net/d4"}, ":9000", EndpointList{
Endpoint{URL: case4u1, IsLocal: false}, {":9000", []string{case4Endpoint1, "http://example.org/d2", "http://example.com/d3", "http://example.net/d4"}, ":9000", EndpointList{
Endpoint{URL: case4u2, IsLocal: false}, Endpoint{URL: case4URLs[0], IsLocal: case4LocalFlags[0]},
Endpoint{URL: case4u3, IsLocal: false}, Endpoint{URL: case4URLs[1], IsLocal: case4LocalFlags[1]},
Endpoint{URL: case4u4, IsLocal: true}, Endpoint{URL: case4URLs[2], IsLocal: case4LocalFlags[2]},
Endpoint{URL: case4URLs[3], IsLocal: case4LocalFlags[3]},
}, DistXLSetupType, nil}, }, DistXLSetupType, nil},
{":9000", []string{"http://localhost:9000/d1", "http://localhost:9001/d2", "http://localhost:9002/d3", "http://localhost:9003/d4"}, ":9000", EndpointList{
Endpoint{URL: case5u1, IsLocal: true}, {":9000", []string{case5Endpoint1, case5Endpoint2, case5Endpoint3, case5Endpoint4}, ":9000", EndpointList{
Endpoint{URL: case5u2, IsLocal: false}, Endpoint{URL: case5URLs[0], IsLocal: case5LocalFlags[0]},
Endpoint{URL: case5u3, IsLocal: false}, Endpoint{URL: case5URLs[1], IsLocal: case5LocalFlags[1]},
Endpoint{URL: case5u4, IsLocal: false}, Endpoint{URL: case5URLs[2], IsLocal: case5LocalFlags[2]},
Endpoint{URL: case5URLs[3], IsLocal: case5LocalFlags[3]},
}, DistXLSetupType, nil}, }, DistXLSetupType, nil},
{":9001", []string{"http://10.0.0.1:9000/export", "http://10.0.0.2:9000/export", "http://localhost:9001/export", "http://10.0.0.3:9000/export"}, ":9001", EndpointList{ // DistXL Setup using only local host.
Endpoint{URL: case6u1, IsLocal: false}, {":9003", []string{"http://localhost:9000/d1", "http://localhost:9001/d2", "http://127.0.0.1:9002/d3", case6Endpoint}, ":9003", EndpointList{
Endpoint{URL: case6u2, IsLocal: false}, Endpoint{URL: case6URLs[0], IsLocal: case6LocalFlags[0]},
Endpoint{URL: case6u3, IsLocal: false}, Endpoint{URL: case6URLs[1], IsLocal: case6LocalFlags[1]},
Endpoint{URL: case6u4, IsLocal: true}, Endpoint{URL: case6URLs[2], IsLocal: case6LocalFlags[2]},
Endpoint{URL: case6URLs[3], IsLocal: case6LocalFlags[3]},
}, DistXLSetupType, nil}, }, DistXLSetupType, nil},
} }

Loading…
Cancel
Save