31ffaa0e71
Users can specify IPs with the annotation "allowed-location-ips". It makes no difference which node of a location is annotated. The IP should be routable from the particular location, e.g. a printer in the same LAN. This way these IPs become routable from other location. Signed-off-by: leonnicolas <leonloechner@gmx.de> Co-authored-by: Lucas Servén Marín <lserven@gmail.com>
1112 lines
34 KiB
Go
1112 lines
34 KiB
Go
// Copyright 2019 the Kilo authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package mesh
|
|
|
|
import (
|
|
"net"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/go-kit/kit/log"
|
|
"github.com/kylelemons/godebug/pretty"
|
|
|
|
"github.com/squat/kilo/pkg/wireguard"
|
|
)
|
|
|
|
func allowedIPs(ips ...string) string {
|
|
return strings.Join(ips, ", ")
|
|
}
|
|
|
|
func mustParseCIDR(s string) (r *net.IPNet) {
|
|
if _, ip, err := net.ParseCIDR(s); err != nil {
|
|
panic("failed to parse CIDR")
|
|
} else {
|
|
r = ip
|
|
}
|
|
return
|
|
}
|
|
|
|
func setup(t *testing.T) (map[string]*Node, map[string]*Peer, []byte, uint32) {
|
|
key := []byte("private")
|
|
e1 := &net.IPNet{IP: net.ParseIP("10.1.0.1").To4(), Mask: net.CIDRMask(16, 32)}
|
|
e2 := &net.IPNet{IP: net.ParseIP("10.1.0.2").To4(), Mask: net.CIDRMask(16, 32)}
|
|
e3 := &net.IPNet{IP: net.ParseIP("10.1.0.3").To4(), Mask: net.CIDRMask(16, 32)}
|
|
e4 := &net.IPNet{IP: net.ParseIP("10.1.0.4").To4(), Mask: net.CIDRMask(16, 32)}
|
|
i1 := &net.IPNet{IP: net.ParseIP("192.168.0.1").To4(), Mask: net.CIDRMask(32, 32)}
|
|
i2 := &net.IPNet{IP: net.ParseIP("192.168.0.2").To4(), Mask: net.CIDRMask(32, 32)}
|
|
i3 := &net.IPNet{IP: net.ParseIP("192.168.178.3").To4(), Mask: net.CIDRMask(32, 32)}
|
|
nodes := map[string]*Node{
|
|
"a": {
|
|
Name: "a",
|
|
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: e1.IP}, Port: DefaultKiloPort},
|
|
InternalIP: i1,
|
|
Location: "1",
|
|
Subnet: &net.IPNet{IP: net.ParseIP("10.2.1.0"), Mask: net.CIDRMask(24, 32)},
|
|
Key: []byte("key1"),
|
|
PersistentKeepalive: 25,
|
|
},
|
|
"b": {
|
|
Name: "b",
|
|
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: e2.IP}, Port: DefaultKiloPort},
|
|
InternalIP: i1,
|
|
Location: "2",
|
|
Subnet: &net.IPNet{IP: net.ParseIP("10.2.2.0"), Mask: net.CIDRMask(24, 32)},
|
|
Key: []byte("key2"),
|
|
AllowedLocationIPs: []*net.IPNet{i3},
|
|
},
|
|
"c": {
|
|
Name: "c",
|
|
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: e3.IP}, Port: DefaultKiloPort},
|
|
InternalIP: i2,
|
|
// Same location as node b.
|
|
Location: "2",
|
|
Subnet: &net.IPNet{IP: net.ParseIP("10.2.3.0"), Mask: net.CIDRMask(24, 32)},
|
|
Key: []byte("key3"),
|
|
},
|
|
"d": {
|
|
Name: "d",
|
|
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: e4.IP}, Port: DefaultKiloPort},
|
|
// Same location as node a, but without private IP
|
|
Location: "1",
|
|
Subnet: &net.IPNet{IP: net.ParseIP("10.2.4.0"), Mask: net.CIDRMask(24, 32)},
|
|
Key: []byte("key4"),
|
|
},
|
|
}
|
|
peers := map[string]*Peer{
|
|
"a": {
|
|
Name: "a",
|
|
Peer: wireguard.Peer{
|
|
AllowedIPs: []*net.IPNet{
|
|
{IP: net.ParseIP("10.5.0.1"), Mask: net.CIDRMask(24, 32)},
|
|
{IP: net.ParseIP("10.5.0.2"), Mask: net.CIDRMask(24, 32)},
|
|
},
|
|
PublicKey: []byte("key4"),
|
|
},
|
|
},
|
|
"b": {
|
|
Name: "b",
|
|
Peer: wireguard.Peer{
|
|
AllowedIPs: []*net.IPNet{
|
|
{IP: net.ParseIP("10.5.0.3"), Mask: net.CIDRMask(24, 32)},
|
|
},
|
|
Endpoint: &wireguard.Endpoint{
|
|
DNSOrIP: wireguard.DNSOrIP{IP: net.ParseIP("192.168.0.1")},
|
|
Port: DefaultKiloPort,
|
|
},
|
|
PublicKey: []byte("key5"),
|
|
},
|
|
},
|
|
}
|
|
return nodes, peers, key, DefaultKiloPort
|
|
}
|
|
|
|
func TestNewTopology(t *testing.T) {
|
|
nodes, peers, key, port := setup(t)
|
|
|
|
w1 := net.ParseIP("10.4.0.1").To4()
|
|
w2 := net.ParseIP("10.4.0.2").To4()
|
|
w3 := net.ParseIP("10.4.0.3").To4()
|
|
w4 := net.ParseIP("10.4.0.4").To4()
|
|
for _, tc := range []struct {
|
|
name string
|
|
granularity Granularity
|
|
hostname string
|
|
result *Topology
|
|
}{
|
|
{
|
|
name: "logical from a",
|
|
granularity: LogicalGranularity,
|
|
hostname: nodes["a"].Name,
|
|
result: &Topology{
|
|
hostname: nodes["a"].Name,
|
|
leader: true,
|
|
location: logicalLocationPrefix + nodes["a"].Location,
|
|
subnet: nodes["a"].Subnet,
|
|
privateIP: nodes["a"].InternalIP,
|
|
wireGuardCIDR: &net.IPNet{IP: w1, Mask: net.CIDRMask(16, 32)},
|
|
segments: []*segment{
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["a"].Endpoint,
|
|
key: nodes["a"].Key,
|
|
persistentKeepalive: nodes["a"].PersistentKeepalive,
|
|
location: logicalLocationPrefix + nodes["a"].Location,
|
|
cidrs: []*net.IPNet{nodes["a"].Subnet},
|
|
hostnames: []string{"a"},
|
|
privateIPs: []net.IP{nodes["a"].InternalIP.IP},
|
|
wireGuardIP: w1,
|
|
},
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["b"].Endpoint,
|
|
key: nodes["b"].Key,
|
|
persistentKeepalive: nodes["b"].PersistentKeepalive,
|
|
location: logicalLocationPrefix + nodes["b"].Location,
|
|
cidrs: []*net.IPNet{nodes["b"].Subnet, nodes["c"].Subnet},
|
|
hostnames: []string{"b", "c"},
|
|
privateIPs: []net.IP{nodes["b"].InternalIP.IP, nodes["c"].InternalIP.IP},
|
|
wireGuardIP: w2,
|
|
allowedLocationIPs: nodes["b"].AllowedLocationIPs,
|
|
},
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w3, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["d"].Endpoint,
|
|
key: nodes["d"].Key,
|
|
persistentKeepalive: nodes["d"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["d"].Name,
|
|
cidrs: []*net.IPNet{nodes["d"].Subnet},
|
|
hostnames: []string{"d"},
|
|
privateIPs: nil,
|
|
wireGuardIP: w3,
|
|
},
|
|
},
|
|
peers: []*Peer{peers["a"], peers["b"]},
|
|
logger: log.NewNopLogger(),
|
|
},
|
|
},
|
|
{
|
|
name: "logical from b",
|
|
granularity: LogicalGranularity,
|
|
hostname: nodes["b"].Name,
|
|
result: &Topology{
|
|
hostname: nodes["b"].Name,
|
|
leader: true,
|
|
location: logicalLocationPrefix + nodes["b"].Location,
|
|
subnet: nodes["b"].Subnet,
|
|
privateIP: nodes["b"].InternalIP,
|
|
wireGuardCIDR: &net.IPNet{IP: w2, Mask: net.CIDRMask(16, 32)},
|
|
segments: []*segment{
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["a"].Endpoint,
|
|
key: nodes["a"].Key,
|
|
persistentKeepalive: nodes["a"].PersistentKeepalive,
|
|
location: logicalLocationPrefix + nodes["a"].Location,
|
|
cidrs: []*net.IPNet{nodes["a"].Subnet},
|
|
hostnames: []string{"a"},
|
|
privateIPs: []net.IP{nodes["a"].InternalIP.IP},
|
|
wireGuardIP: w1,
|
|
},
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["b"].Endpoint,
|
|
key: nodes["b"].Key,
|
|
persistentKeepalive: nodes["b"].PersistentKeepalive,
|
|
location: logicalLocationPrefix + nodes["b"].Location,
|
|
cidrs: []*net.IPNet{nodes["b"].Subnet, nodes["c"].Subnet},
|
|
hostnames: []string{"b", "c"},
|
|
privateIPs: []net.IP{nodes["b"].InternalIP.IP, nodes["c"].InternalIP.IP},
|
|
wireGuardIP: w2,
|
|
allowedLocationIPs: nodes["b"].AllowedLocationIPs,
|
|
},
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w3, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["d"].Endpoint,
|
|
key: nodes["d"].Key,
|
|
persistentKeepalive: nodes["d"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["d"].Name,
|
|
cidrs: []*net.IPNet{nodes["d"].Subnet},
|
|
hostnames: []string{"d"},
|
|
privateIPs: nil,
|
|
wireGuardIP: w3,
|
|
},
|
|
},
|
|
peers: []*Peer{peers["a"], peers["b"]},
|
|
logger: log.NewNopLogger(),
|
|
},
|
|
},
|
|
{
|
|
name: "logical from c",
|
|
granularity: LogicalGranularity,
|
|
hostname: nodes["c"].Name,
|
|
result: &Topology{
|
|
hostname: nodes["c"].Name,
|
|
leader: false,
|
|
location: logicalLocationPrefix + nodes["b"].Location,
|
|
subnet: nodes["c"].Subnet,
|
|
privateIP: nodes["c"].InternalIP,
|
|
wireGuardCIDR: DefaultKiloSubnet,
|
|
segments: []*segment{
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["a"].Endpoint,
|
|
key: nodes["a"].Key,
|
|
persistentKeepalive: nodes["a"].PersistentKeepalive,
|
|
location: logicalLocationPrefix + nodes["a"].Location,
|
|
cidrs: []*net.IPNet{nodes["a"].Subnet},
|
|
hostnames: []string{"a"},
|
|
privateIPs: []net.IP{nodes["a"].InternalIP.IP},
|
|
wireGuardIP: w1,
|
|
},
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["b"].Endpoint,
|
|
key: nodes["b"].Key,
|
|
persistentKeepalive: nodes["b"].PersistentKeepalive,
|
|
location: logicalLocationPrefix + nodes["b"].Location,
|
|
cidrs: []*net.IPNet{nodes["b"].Subnet, nodes["c"].Subnet},
|
|
hostnames: []string{"b", "c"},
|
|
privateIPs: []net.IP{nodes["b"].InternalIP.IP, nodes["c"].InternalIP.IP},
|
|
wireGuardIP: w2,
|
|
allowedLocationIPs: nodes["b"].AllowedLocationIPs,
|
|
},
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w3, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["d"].Endpoint,
|
|
key: nodes["d"].Key,
|
|
persistentKeepalive: nodes["d"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["d"].Name,
|
|
cidrs: []*net.IPNet{nodes["d"].Subnet},
|
|
hostnames: []string{"d"},
|
|
privateIPs: nil,
|
|
wireGuardIP: w3,
|
|
},
|
|
},
|
|
peers: []*Peer{peers["a"], peers["b"]},
|
|
logger: log.NewNopLogger(),
|
|
},
|
|
},
|
|
{
|
|
name: "full from a",
|
|
granularity: FullGranularity,
|
|
hostname: nodes["a"].Name,
|
|
result: &Topology{
|
|
hostname: nodes["a"].Name,
|
|
leader: true,
|
|
location: nodeLocationPrefix + nodes["a"].Name,
|
|
subnet: nodes["a"].Subnet,
|
|
privateIP: nodes["a"].InternalIP,
|
|
wireGuardCIDR: &net.IPNet{IP: w1, Mask: net.CIDRMask(16, 32)},
|
|
segments: []*segment{
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["a"].Endpoint,
|
|
key: nodes["a"].Key,
|
|
persistentKeepalive: nodes["a"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["a"].Name,
|
|
cidrs: []*net.IPNet{nodes["a"].Subnet},
|
|
hostnames: []string{"a"},
|
|
privateIPs: []net.IP{nodes["a"].InternalIP.IP},
|
|
wireGuardIP: w1,
|
|
},
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["b"].Endpoint,
|
|
key: nodes["b"].Key,
|
|
persistentKeepalive: nodes["b"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["b"].Name,
|
|
cidrs: []*net.IPNet{nodes["b"].Subnet},
|
|
hostnames: []string{"b"},
|
|
privateIPs: []net.IP{nodes["b"].InternalIP.IP},
|
|
wireGuardIP: w2,
|
|
allowedLocationIPs: nodes["b"].AllowedLocationIPs,
|
|
},
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["c"].Endpoint,
|
|
key: nodes["c"].Key,
|
|
persistentKeepalive: nodes["c"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["c"].Name,
|
|
cidrs: []*net.IPNet{nodes["c"].Subnet},
|
|
hostnames: []string{"c"},
|
|
privateIPs: []net.IP{nodes["c"].InternalIP.IP},
|
|
wireGuardIP: w3,
|
|
},
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w4, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["d"].Endpoint,
|
|
key: nodes["d"].Key,
|
|
persistentKeepalive: nodes["d"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["d"].Name,
|
|
cidrs: []*net.IPNet{nodes["d"].Subnet},
|
|
hostnames: []string{"d"},
|
|
privateIPs: nil,
|
|
wireGuardIP: w4,
|
|
},
|
|
},
|
|
peers: []*Peer{peers["a"], peers["b"]},
|
|
logger: log.NewNopLogger(),
|
|
},
|
|
},
|
|
{
|
|
name: "full from b",
|
|
granularity: FullGranularity,
|
|
hostname: nodes["b"].Name,
|
|
result: &Topology{
|
|
hostname: nodes["b"].Name,
|
|
leader: true,
|
|
location: nodeLocationPrefix + nodes["b"].Name,
|
|
subnet: nodes["b"].Subnet,
|
|
privateIP: nodes["b"].InternalIP,
|
|
wireGuardCIDR: &net.IPNet{IP: w2, Mask: net.CIDRMask(16, 32)},
|
|
segments: []*segment{
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["a"].Endpoint,
|
|
key: nodes["a"].Key,
|
|
persistentKeepalive: nodes["a"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["a"].Name,
|
|
cidrs: []*net.IPNet{nodes["a"].Subnet},
|
|
hostnames: []string{"a"},
|
|
privateIPs: []net.IP{nodes["a"].InternalIP.IP},
|
|
wireGuardIP: w1,
|
|
},
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["b"].Endpoint,
|
|
key: nodes["b"].Key,
|
|
persistentKeepalive: nodes["b"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["b"].Name,
|
|
cidrs: []*net.IPNet{nodes["b"].Subnet},
|
|
hostnames: []string{"b"},
|
|
privateIPs: []net.IP{nodes["b"].InternalIP.IP},
|
|
wireGuardIP: w2,
|
|
allowedLocationIPs: nodes["b"].AllowedLocationIPs,
|
|
},
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["c"].Endpoint,
|
|
key: nodes["c"].Key,
|
|
persistentKeepalive: nodes["c"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["c"].Name,
|
|
cidrs: []*net.IPNet{nodes["c"].Subnet},
|
|
hostnames: []string{"c"},
|
|
privateIPs: []net.IP{nodes["c"].InternalIP.IP},
|
|
wireGuardIP: w3,
|
|
},
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w4, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["d"].Endpoint,
|
|
key: nodes["d"].Key,
|
|
persistentKeepalive: nodes["d"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["d"].Name,
|
|
cidrs: []*net.IPNet{nodes["d"].Subnet},
|
|
hostnames: []string{"d"},
|
|
privateIPs: nil,
|
|
wireGuardIP: w4,
|
|
},
|
|
},
|
|
peers: []*Peer{peers["a"], peers["b"]},
|
|
logger: log.NewNopLogger(),
|
|
},
|
|
},
|
|
{
|
|
name: "full from c",
|
|
granularity: FullGranularity,
|
|
hostname: nodes["c"].Name,
|
|
result: &Topology{
|
|
hostname: nodes["c"].Name,
|
|
leader: true,
|
|
location: nodeLocationPrefix + nodes["c"].Name,
|
|
subnet: nodes["c"].Subnet,
|
|
privateIP: nodes["c"].InternalIP,
|
|
wireGuardCIDR: &net.IPNet{IP: w3, Mask: net.CIDRMask(16, 32)},
|
|
segments: []*segment{
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["a"].Endpoint,
|
|
key: nodes["a"].Key,
|
|
persistentKeepalive: nodes["a"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["a"].Name,
|
|
cidrs: []*net.IPNet{nodes["a"].Subnet},
|
|
hostnames: []string{"a"},
|
|
privateIPs: []net.IP{nodes["a"].InternalIP.IP},
|
|
wireGuardIP: w1,
|
|
},
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["b"].Endpoint,
|
|
key: nodes["b"].Key,
|
|
persistentKeepalive: nodes["b"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["b"].Name,
|
|
cidrs: []*net.IPNet{nodes["b"].Subnet},
|
|
hostnames: []string{"b"},
|
|
privateIPs: []net.IP{nodes["b"].InternalIP.IP},
|
|
wireGuardIP: w2,
|
|
allowedLocationIPs: nodes["b"].AllowedLocationIPs,
|
|
},
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["c"].Endpoint,
|
|
key: nodes["c"].Key,
|
|
persistentKeepalive: nodes["c"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["c"].Name,
|
|
cidrs: []*net.IPNet{nodes["c"].Subnet},
|
|
hostnames: []string{"c"},
|
|
privateIPs: []net.IP{nodes["c"].InternalIP.IP},
|
|
wireGuardIP: w3,
|
|
},
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w4, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["d"].Endpoint,
|
|
key: nodes["d"].Key,
|
|
persistentKeepalive: nodes["d"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["d"].Name,
|
|
cidrs: []*net.IPNet{nodes["d"].Subnet},
|
|
hostnames: []string{"d"},
|
|
privateIPs: nil,
|
|
wireGuardIP: w4,
|
|
},
|
|
},
|
|
peers: []*Peer{peers["a"], peers["b"]},
|
|
logger: log.NewNopLogger(),
|
|
},
|
|
},
|
|
{
|
|
name: "full from d",
|
|
granularity: FullGranularity,
|
|
hostname: nodes["d"].Name,
|
|
result: &Topology{
|
|
hostname: nodes["d"].Name,
|
|
leader: true,
|
|
location: nodeLocationPrefix + nodes["d"].Name,
|
|
subnet: nodes["d"].Subnet,
|
|
privateIP: nil,
|
|
wireGuardCIDR: &net.IPNet{IP: w4, Mask: net.CIDRMask(16, 32)},
|
|
segments: []*segment{
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["a"].Endpoint,
|
|
key: nodes["a"].Key,
|
|
persistentKeepalive: nodes["a"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["a"].Name,
|
|
cidrs: []*net.IPNet{nodes["a"].Subnet},
|
|
hostnames: []string{"a"},
|
|
privateIPs: []net.IP{nodes["a"].InternalIP.IP},
|
|
wireGuardIP: w1,
|
|
},
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["b"].Subnet, nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["b"].Endpoint,
|
|
key: nodes["b"].Key,
|
|
persistentKeepalive: nodes["b"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["b"].Name,
|
|
cidrs: []*net.IPNet{nodes["b"].Subnet},
|
|
hostnames: []string{"b"},
|
|
privateIPs: []net.IP{nodes["b"].InternalIP.IP},
|
|
wireGuardIP: w2,
|
|
allowedLocationIPs: nodes["b"].AllowedLocationIPs,
|
|
},
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["c"].Subnet, nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["c"].Endpoint,
|
|
key: nodes["c"].Key,
|
|
persistentKeepalive: nodes["c"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["c"].Name,
|
|
cidrs: []*net.IPNet{nodes["c"].Subnet},
|
|
hostnames: []string{"c"},
|
|
privateIPs: []net.IP{nodes["c"].InternalIP.IP},
|
|
wireGuardIP: w3,
|
|
},
|
|
{
|
|
allowedIPs: []*net.IPNet{nodes["d"].Subnet, {IP: w4, Mask: net.CIDRMask(32, 32)}},
|
|
endpoint: nodes["d"].Endpoint,
|
|
key: nodes["d"].Key,
|
|
persistentKeepalive: nodes["d"].PersistentKeepalive,
|
|
location: nodeLocationPrefix + nodes["d"].Name,
|
|
cidrs: []*net.IPNet{nodes["d"].Subnet},
|
|
hostnames: []string{"d"},
|
|
privateIPs: nil,
|
|
wireGuardIP: w4,
|
|
},
|
|
},
|
|
peers: []*Peer{peers["a"], peers["b"]},
|
|
logger: log.NewNopLogger(),
|
|
},
|
|
},
|
|
} {
|
|
tc.result.key = key
|
|
tc.result.port = port
|
|
topo, err := NewTopology(nodes, peers, tc.granularity, tc.hostname, port, key, DefaultKiloSubnet, 0, nil)
|
|
if err != nil {
|
|
t.Errorf("test case %q: failed to generate Topology: %v", tc.name, err)
|
|
}
|
|
if diff := pretty.Compare(topo, tc.result); diff != "" {
|
|
t.Errorf("test case %q: got diff: %v", tc.name, diff)
|
|
}
|
|
}
|
|
}
|
|
|
|
func mustTopo(t *testing.T, nodes map[string]*Node, peers map[string]*Peer, granularity Granularity, hostname string, port uint32, key []byte, subnet *net.IPNet, persistentKeepalive int) *Topology {
|
|
topo, err := NewTopology(nodes, peers, granularity, hostname, port, key, subnet, persistentKeepalive, nil)
|
|
if err != nil {
|
|
t.Errorf("failed to generate Topology: %v", err)
|
|
}
|
|
return topo
|
|
}
|
|
|
|
func TestConf(t *testing.T) {
|
|
nodes, peers, key, port := setup(t)
|
|
for _, tc := range []struct {
|
|
name string
|
|
topology *Topology
|
|
result string
|
|
}{
|
|
{
|
|
name: "logical from a",
|
|
topology: mustTopo(t, nodes, peers, LogicalGranularity, nodes["a"].Name, port, key, DefaultKiloSubnet, nodes["a"].PersistentKeepalive),
|
|
result: `[Interface]
|
|
PrivateKey = private
|
|
ListenPort = 51820
|
|
|
|
[Peer]
|
|
PublicKey = key2
|
|
Endpoint = 10.1.0.2:51820
|
|
AllowedIPs = 10.2.2.0/24, 192.168.0.1/32, 10.2.3.0/24, 192.168.0.2/32, 10.4.0.2/32, 192.168.178.3/32
|
|
PersistentKeepalive = 25
|
|
|
|
[Peer]
|
|
PublicKey = key4
|
|
Endpoint = 10.1.0.4:51820
|
|
AllowedIPs = 10.2.4.0/24, 10.4.0.3/32
|
|
PersistentKeepalive = 25
|
|
|
|
[Peer]
|
|
PublicKey = key4
|
|
AllowedIPs = 10.5.0.1/24, 10.5.0.2/24
|
|
PersistentKeepalive = 25
|
|
|
|
[Peer]
|
|
PublicKey = key5
|
|
Endpoint = 192.168.0.1:51820
|
|
AllowedIPs = 10.5.0.3/24
|
|
PersistentKeepalive = 25
|
|
`,
|
|
},
|
|
{
|
|
name: "logical from b",
|
|
topology: mustTopo(t, nodes, peers, LogicalGranularity, nodes["b"].Name, port, key, DefaultKiloSubnet, nodes["b"].PersistentKeepalive),
|
|
result: `[Interface]
|
|
PrivateKey = private
|
|
ListenPort = 51820
|
|
|
|
[Peer]
|
|
PublicKey = key1
|
|
Endpoint = 10.1.0.1:51820
|
|
AllowedIPs = 10.2.1.0/24, 192.168.0.1/32, 10.4.0.1/32
|
|
|
|
[Peer]
|
|
PublicKey = key4
|
|
Endpoint = 10.1.0.4:51820
|
|
AllowedIPs = 10.2.4.0/24, 10.4.0.3/32
|
|
|
|
[Peer]
|
|
PublicKey = key4
|
|
AllowedIPs = 10.5.0.1/24, 10.5.0.2/24
|
|
|
|
[Peer]
|
|
PublicKey = key5
|
|
Endpoint = 192.168.0.1:51820
|
|
AllowedIPs = 10.5.0.3/24
|
|
`,
|
|
},
|
|
{
|
|
name: "logical from c",
|
|
topology: mustTopo(t, nodes, peers, LogicalGranularity, nodes["c"].Name, port, key, DefaultKiloSubnet, nodes["c"].PersistentKeepalive),
|
|
result: `[Interface]
|
|
PrivateKey = private
|
|
ListenPort = 51820
|
|
|
|
[Peer]
|
|
PublicKey = key1
|
|
Endpoint = 10.1.0.1:51820
|
|
AllowedIPs = 10.2.1.0/24, 192.168.0.1/32, 10.4.0.1/32
|
|
|
|
[Peer]
|
|
PublicKey = key4
|
|
Endpoint = 10.1.0.4:51820
|
|
AllowedIPs = 10.2.4.0/24, 10.4.0.3/32
|
|
|
|
[Peer]
|
|
PublicKey = key4
|
|
AllowedIPs = 10.5.0.1/24, 10.5.0.2/24
|
|
|
|
[Peer]
|
|
PublicKey = key5
|
|
Endpoint = 192.168.0.1:51820
|
|
AllowedIPs = 10.5.0.3/24
|
|
`,
|
|
},
|
|
{
|
|
name: "full from a",
|
|
topology: mustTopo(t, nodes, peers, FullGranularity, nodes["a"].Name, port, key, DefaultKiloSubnet, nodes["a"].PersistentKeepalive),
|
|
result: `[Interface]
|
|
PrivateKey = private
|
|
ListenPort = 51820
|
|
|
|
[Peer]
|
|
PublicKey = key2
|
|
Endpoint = 10.1.0.2:51820
|
|
AllowedIPs = 10.2.2.0/24, 192.168.0.1/32, 10.4.0.2/32, 192.168.178.3/32
|
|
PersistentKeepalive = 25
|
|
|
|
[Peer]
|
|
PublicKey = key3
|
|
Endpoint = 10.1.0.3:51820
|
|
AllowedIPs = 10.2.3.0/24, 192.168.0.2/32, 10.4.0.3/32
|
|
PersistentKeepalive = 25
|
|
|
|
[Peer]
|
|
PublicKey = key4
|
|
Endpoint = 10.1.0.4:51820
|
|
AllowedIPs = 10.2.4.0/24, 10.4.0.4/32
|
|
PersistentKeepalive = 25
|
|
|
|
[Peer]
|
|
PublicKey = key4
|
|
AllowedIPs = 10.5.0.1/24, 10.5.0.2/24
|
|
PersistentKeepalive = 25
|
|
|
|
[Peer]
|
|
PublicKey = key5
|
|
Endpoint = 192.168.0.1:51820
|
|
AllowedIPs = 10.5.0.3/24
|
|
PersistentKeepalive = 25
|
|
`,
|
|
},
|
|
{
|
|
name: "full from b",
|
|
topology: mustTopo(t, nodes, peers, FullGranularity, nodes["b"].Name, port, key, DefaultKiloSubnet, nodes["b"].PersistentKeepalive),
|
|
result: `[Interface]
|
|
PrivateKey = private
|
|
ListenPort = 51820
|
|
|
|
[Peer]
|
|
PublicKey = key1
|
|
Endpoint = 10.1.0.1:51820
|
|
AllowedIPs = 10.2.1.0/24, 192.168.0.1/32, 10.4.0.1/32
|
|
|
|
[Peer]
|
|
PublicKey = key3
|
|
Endpoint = 10.1.0.3:51820
|
|
AllowedIPs = 10.2.3.0/24, 192.168.0.2/32, 10.4.0.3/32
|
|
|
|
[Peer]
|
|
PublicKey = key4
|
|
Endpoint = 10.1.0.4:51820
|
|
AllowedIPs = 10.2.4.0/24, 10.4.0.4/32
|
|
|
|
[Peer]
|
|
PublicKey = key4
|
|
AllowedIPs = 10.5.0.1/24, 10.5.0.2/24
|
|
|
|
[Peer]
|
|
PublicKey = key5
|
|
Endpoint = 192.168.0.1:51820
|
|
AllowedIPs = 10.5.0.3/24
|
|
`,
|
|
},
|
|
{
|
|
name: "full from c",
|
|
topology: mustTopo(t, nodes, peers, FullGranularity, nodes["c"].Name, port, key, DefaultKiloSubnet, nodes["c"].PersistentKeepalive),
|
|
result: `[Interface]
|
|
PrivateKey = private
|
|
ListenPort = 51820
|
|
|
|
[Peer]
|
|
PublicKey = key1
|
|
Endpoint = 10.1.0.1:51820
|
|
AllowedIPs = 10.2.1.0/24, 192.168.0.1/32, 10.4.0.1/32
|
|
|
|
[Peer]
|
|
PublicKey = key2
|
|
Endpoint = 10.1.0.2:51820
|
|
AllowedIPs = 10.2.2.0/24, 192.168.0.1/32, 10.4.0.2/32, 192.168.178.3/32
|
|
|
|
[Peer]
|
|
PublicKey = key4
|
|
Endpoint = 10.1.0.4:51820
|
|
AllowedIPs = 10.2.4.0/24, 10.4.0.4/32
|
|
|
|
[Peer]
|
|
PublicKey = key4
|
|
AllowedIPs = 10.5.0.1/24, 10.5.0.2/24
|
|
|
|
[Peer]
|
|
PublicKey = key5
|
|
Endpoint = 192.168.0.1:51820
|
|
AllowedIPs = 10.5.0.3/24
|
|
`,
|
|
},
|
|
} {
|
|
conf := tc.topology.Conf()
|
|
if !conf.Equal(wireguard.Parse([]byte(tc.result))) {
|
|
buf, err := conf.Bytes()
|
|
if err != nil {
|
|
t.Errorf("test case %q: failed to render conf: %v", tc.name, err)
|
|
}
|
|
t.Errorf("test case %q: expected %s got %s", tc.name, tc.result, string(buf))
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFindLeader(t *testing.T) {
|
|
ip, e1, err := net.ParseCIDR("10.0.0.1/32")
|
|
if err != nil {
|
|
t.Fatalf("failed to parse external IP CIDR: %v", err)
|
|
}
|
|
e1.IP = ip
|
|
ip, e2, err := net.ParseCIDR("8.8.8.8/32")
|
|
if err != nil {
|
|
t.Fatalf("failed to parse external IP CIDR: %v", err)
|
|
}
|
|
e2.IP = ip
|
|
|
|
nodes := []*Node{
|
|
{
|
|
Name: "a",
|
|
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: e1.IP}, Port: DefaultKiloPort},
|
|
},
|
|
{
|
|
Name: "b",
|
|
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: e2.IP}, Port: DefaultKiloPort},
|
|
},
|
|
{
|
|
Name: "c",
|
|
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: e2.IP}, Port: DefaultKiloPort},
|
|
},
|
|
{
|
|
Name: "d",
|
|
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: e1.IP}, Port: DefaultKiloPort},
|
|
Leader: true,
|
|
},
|
|
{
|
|
Name: "2",
|
|
Endpoint: &wireguard.Endpoint{DNSOrIP: wireguard.DNSOrIP{IP: e2.IP}, Port: DefaultKiloPort},
|
|
Leader: true,
|
|
},
|
|
}
|
|
for _, tc := range []struct {
|
|
name string
|
|
nodes []*Node
|
|
out int
|
|
}{
|
|
{
|
|
name: "nil",
|
|
nodes: nil,
|
|
out: 0,
|
|
},
|
|
{
|
|
name: "one",
|
|
nodes: []*Node{nodes[0]},
|
|
out: 0,
|
|
},
|
|
{
|
|
name: "non-leaders",
|
|
nodes: []*Node{nodes[0], nodes[1], nodes[2]},
|
|
out: 1,
|
|
},
|
|
{
|
|
name: "leaders",
|
|
nodes: []*Node{nodes[3], nodes[4]},
|
|
out: 1,
|
|
},
|
|
{
|
|
name: "public",
|
|
nodes: []*Node{nodes[1], nodes[2], nodes[4]},
|
|
out: 2,
|
|
},
|
|
{
|
|
name: "private",
|
|
nodes: []*Node{nodes[0], nodes[3]},
|
|
out: 1,
|
|
},
|
|
{
|
|
name: "all",
|
|
nodes: nodes,
|
|
out: 4,
|
|
},
|
|
} {
|
|
l := findLeader(tc.nodes)
|
|
if l != tc.out {
|
|
t.Errorf("test case %q: expected %d got %d", tc.name, tc.out, l)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDeduplicatePeerIPs(t *testing.T) {
|
|
p1 := &Peer{
|
|
Name: "1",
|
|
Peer: wireguard.Peer{
|
|
PublicKey: []byte("key1"),
|
|
AllowedIPs: []*net.IPNet{
|
|
{IP: net.ParseIP("10.0.0.1"), Mask: net.CIDRMask(24, 32)},
|
|
{IP: net.ParseIP("10.0.0.2"), Mask: net.CIDRMask(24, 32)},
|
|
},
|
|
},
|
|
}
|
|
p2 := &Peer{
|
|
Name: "2",
|
|
Peer: wireguard.Peer{
|
|
PublicKey: []byte("key2"),
|
|
AllowedIPs: []*net.IPNet{
|
|
{IP: net.ParseIP("10.0.0.1"), Mask: net.CIDRMask(24, 32)},
|
|
{IP: net.ParseIP("10.0.0.3"), Mask: net.CIDRMask(24, 32)},
|
|
},
|
|
},
|
|
}
|
|
p3 := &Peer{
|
|
Name: "3",
|
|
Peer: wireguard.Peer{
|
|
PublicKey: []byte("key3"),
|
|
AllowedIPs: []*net.IPNet{
|
|
{IP: net.ParseIP("10.0.0.2"), Mask: net.CIDRMask(24, 32)},
|
|
{IP: net.ParseIP("10.0.0.3"), Mask: net.CIDRMask(24, 32)},
|
|
{IP: net.ParseIP("10.0.0.1"), Mask: net.CIDRMask(24, 32)},
|
|
},
|
|
},
|
|
}
|
|
|
|
p4 := &Peer{
|
|
Name: "4",
|
|
Peer: wireguard.Peer{
|
|
PublicKey: []byte("key4"),
|
|
AllowedIPs: []*net.IPNet{
|
|
{IP: net.ParseIP("10.0.0.3"), Mask: net.CIDRMask(24, 32)},
|
|
{IP: net.ParseIP("10.0.0.3"), Mask: net.CIDRMask(24, 32)},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range []struct {
|
|
name string
|
|
peers []*Peer
|
|
out []*Peer
|
|
}{
|
|
{
|
|
name: "nil",
|
|
peers: nil,
|
|
out: nil,
|
|
},
|
|
{
|
|
name: "simple dupe",
|
|
peers: []*Peer{p1, p2},
|
|
out: []*Peer{
|
|
p1,
|
|
{
|
|
Name: "2",
|
|
Peer: wireguard.Peer{
|
|
PublicKey: []byte("key2"),
|
|
AllowedIPs: []*net.IPNet{
|
|
{IP: net.ParseIP("10.0.0.3"), Mask: net.CIDRMask(24, 32)},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "simple dupe reversed",
|
|
peers: []*Peer{p2, p1},
|
|
out: []*Peer{
|
|
p2,
|
|
{
|
|
Name: "1",
|
|
Peer: wireguard.Peer{
|
|
PublicKey: []byte("key1"),
|
|
AllowedIPs: []*net.IPNet{
|
|
{IP: net.ParseIP("10.0.0.2"), Mask: net.CIDRMask(24, 32)},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "one duplicates all",
|
|
peers: []*Peer{p3, p2, p1, p4},
|
|
out: []*Peer{
|
|
p3,
|
|
{
|
|
Name: "2",
|
|
Peer: wireguard.Peer{
|
|
PublicKey: []byte("key2"),
|
|
},
|
|
},
|
|
{
|
|
Name: "1",
|
|
Peer: wireguard.Peer{
|
|
PublicKey: []byte("key1"),
|
|
},
|
|
},
|
|
{
|
|
Name: "4",
|
|
Peer: wireguard.Peer{
|
|
PublicKey: []byte("key4"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "one duplicates itself",
|
|
peers: []*Peer{p4, p1},
|
|
out: []*Peer{
|
|
{
|
|
Name: "4",
|
|
Peer: wireguard.Peer{
|
|
PublicKey: []byte("key4"),
|
|
AllowedIPs: []*net.IPNet{
|
|
{IP: net.ParseIP("10.0.0.3"), Mask: net.CIDRMask(24, 32)},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "1",
|
|
Peer: wireguard.Peer{
|
|
PublicKey: []byte("key1"),
|
|
AllowedIPs: []*net.IPNet{
|
|
{IP: net.ParseIP("10.0.0.1"), Mask: net.CIDRMask(24, 32)},
|
|
{IP: net.ParseIP("10.0.0.2"), Mask: net.CIDRMask(24, 32)},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
} {
|
|
out := deduplicatePeerIPs(tc.peers)
|
|
if diff := pretty.Compare(out, tc.out); diff != "" {
|
|
t.Errorf("test case %q: got diff: %v", tc.name, diff)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFilterAllowedIPs(t *testing.T) {
|
|
nodes, peers, key, port := setup(t)
|
|
topo := mustTopo(t, nodes, peers, LogicalGranularity, nodes["a"].Name, port, key, DefaultKiloSubnet, nodes["a"].PersistentKeepalive)
|
|
for _, tc := range []struct {
|
|
name string
|
|
allowedLocationIPs map[int][]*net.IPNet
|
|
result map[int][]*net.IPNet
|
|
}{
|
|
{
|
|
name: "nothing to filter",
|
|
allowedLocationIPs: map[int][]*net.IPNet{
|
|
0: {
|
|
mustParseCIDR("192.168.178.4/32"),
|
|
},
|
|
1: {
|
|
mustParseCIDR("192.168.178.5/32"),
|
|
},
|
|
2: {
|
|
mustParseCIDR("192.168.178.6/32"),
|
|
mustParseCIDR("192.168.178.7/32"),
|
|
},
|
|
},
|
|
result: map[int][]*net.IPNet{
|
|
0: {
|
|
mustParseCIDR("192.168.178.4/32"),
|
|
},
|
|
1: {
|
|
mustParseCIDR("192.168.178.5/32"),
|
|
},
|
|
2: {
|
|
mustParseCIDR("192.168.178.6/32"),
|
|
mustParseCIDR("192.168.178.7/32"),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "intersections between segments",
|
|
allowedLocationIPs: map[int][]*net.IPNet{
|
|
0: {
|
|
mustParseCIDR("192.168.178.4/32"),
|
|
mustParseCIDR("192.168.178.8/32"),
|
|
},
|
|
1: {
|
|
mustParseCIDR("192.168.178.5/32"),
|
|
},
|
|
2: {
|
|
mustParseCIDR("192.168.178.6/32"),
|
|
mustParseCIDR("192.168.178.7/32"),
|
|
mustParseCIDR("192.168.178.4/32"),
|
|
},
|
|
},
|
|
result: map[int][]*net.IPNet{
|
|
0: {
|
|
mustParseCIDR("192.168.178.8/32"),
|
|
},
|
|
1: {
|
|
mustParseCIDR("192.168.178.5/32"),
|
|
},
|
|
2: {
|
|
mustParseCIDR("192.168.178.6/32"),
|
|
mustParseCIDR("192.168.178.7/32"),
|
|
mustParseCIDR("192.168.178.4/32"),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "intersections with wireGuardCIDR",
|
|
allowedLocationIPs: map[int][]*net.IPNet{
|
|
0: {
|
|
mustParseCIDR("10.4.0.1/32"),
|
|
mustParseCIDR("192.168.178.8/32"),
|
|
},
|
|
1: {
|
|
mustParseCIDR("192.168.178.5/32"),
|
|
},
|
|
2: {
|
|
mustParseCIDR("192.168.178.6/32"),
|
|
mustParseCIDR("192.168.178.7/32"),
|
|
},
|
|
},
|
|
result: map[int][]*net.IPNet{
|
|
0: {
|
|
mustParseCIDR("192.168.178.8/32"),
|
|
},
|
|
1: {
|
|
mustParseCIDR("192.168.178.5/32"),
|
|
},
|
|
2: {
|
|
mustParseCIDR("192.168.178.6/32"),
|
|
mustParseCIDR("192.168.178.7/32"),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "intersections with more than one allowedLocationIPs",
|
|
allowedLocationIPs: map[int][]*net.IPNet{
|
|
0: {
|
|
mustParseCIDR("192.168.178.8/32"),
|
|
},
|
|
1: {
|
|
mustParseCIDR("192.168.178.5/32"),
|
|
},
|
|
2: {
|
|
mustParseCIDR("192.168.178.7/24"),
|
|
},
|
|
},
|
|
result: map[int][]*net.IPNet{
|
|
0: {},
|
|
1: {},
|
|
2: {
|
|
mustParseCIDR("192.168.178.7/24"),
|
|
},
|
|
},
|
|
},
|
|
} {
|
|
for k, v := range tc.allowedLocationIPs {
|
|
topo.segments[k].allowedLocationIPs = v
|
|
}
|
|
for k, v := range topo.segments {
|
|
f := topo.filterAllowedLocationIPs(v.allowedLocationIPs, v.location)
|
|
// Overwrite the allowedLocationIPs to mimic the actual usage of the filterAllowedLocationIPs function.
|
|
topo.segments[k].allowedLocationIPs = f
|
|
if !ipNetSlicesEqual(f, tc.result[k]) {
|
|
t.Errorf("test case %q:\n\texpected:\n\t%q\n\tgot:\n\t%q\n", tc.name, tc.result[k], f)
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|