From 129291e84872920d2ec97bd9d4eefdfd14bcbc8b Mon Sep 17 00:00:00 2001 From: kaiyou Date: Sun, 17 May 2020 12:18:55 +0200 Subject: [PATCH] Use interface name instead of cluster name The cluster name option is not required anymore and removed, the interface name is used to name the cluster directly. For backward compatibility, the old path for storing cluster state is tried as a fallback when loading. --- README.md | 11 ++++++++++- cluster/state.go | 22 ++++++++++++++++------ cluster/state_test.go | 2 +- config.go | 1 - main.go | 4 ++-- tests/e2e.sh | 4 ++-- 6 files changed, 31 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 306a97d..6921c0e 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,6 @@ All options can be passed either as command-line flags or environment variables: | `--cluster-key KEY` | WESHER_CLUSTER_KEY | shared key for cluster membership; must be 32 bytes base64 encoded; will be generated if not provided | autogenerated/loaded | | `--join HOST,...` | WESHER_JOIN | comma separated list of hostnames or IP addresses to existing cluster members; if not provided, will attempt resuming any known state or otherwise wait for further members | | | `--init` | WESHER_INIT | whether to explicitly (re)initialize the cluster; any known state from previous runs will be forgotten | `false` | -| `--cluster-name` | WESHER_CLUSTER_NAME | Identifier for the wesher cluster; can be used to peer with multiple clusters | `default` | | `--bind-addr ADDR` | WESHER_BIND_ADDR | IP address to bind to for cluster membership (cannot be used with --bind-iface) | autodetected | | `--bind-iface IFACE` | WESHER_BIND_IFACE | Interface to bind to for cluster membership (cannot be used with --bind-addr)| | | `--cluster-port PORT` | WESHER_CLUSTER_PORT | port used for membership gossip traffic (both TCP and UDP); must be the same across cluster | `7946` | @@ -147,6 +146,16 @@ All options can be passed either as command-line flags or environment variables: | `--no-etc-hosts` | WESHER_NO_ETC_HOSTS | whether to skip writing hosts entries for each node in mesh | `false` | | `--log-level LEVEL` | WESHER_LOG_LEVEL | set the verbosity (one of debug/info/warn/error) | `warn` | +## Running multiple clusters + +Wesher supports having a node be a member of multiple clusters. The following settings must be explicitely set to non-conflicting values: +- `--interface`, so that wireguard does not mix up traffic, the interface name is also used for naming the state file +- `--cluster-port` or `--bind-addr` or `--bind-iface`, so that wesher can properly bind to its port +- `--wireguard-port`, so that wireguard can properly bind to its port + +One should also use different overlay networks. Even though using the same network on different devices will work in some cases, it is not the intended use. + +Finally, one should use different cluster keys for different clusters, as a security best practice. ## Security considerations diff --git a/cluster/state.go b/cluster/state.go index 66b54b3..7a7117b 100644 --- a/cluster/state.go +++ b/cluster/state.go @@ -17,10 +17,12 @@ type state struct { Nodes []common.Node } -var defaultStatePath = "/var/lib/wesher/%s.json" +var statePathTemplate = "/var/lib/wesher/%s.json" + +const deprecatedStatePath = "/var/lib/wesher/state.json" func (s *state) save(clusterName string) error { - statePath := fmt.Sprintf(defaultStatePath, clusterName) + statePath := fmt.Sprintf(statePathTemplate, clusterName) if err := os.MkdirAll(path.Dir(statePath), 0700); err != nil { return err } @@ -34,13 +36,21 @@ func (s *state) save(clusterName string) error { } func loadState(cs *state, clusterName string) { - statePath := fmt.Sprintf(defaultStatePath, clusterName) + statePath := fmt.Sprintf(statePathTemplate, clusterName) content, err := ioutil.ReadFile(statePath) if err != nil { - if !os.IsNotExist(err) { - logrus.Warnf("could not open state in %s: %s", statePath, err) + // try the deprecated pre 0.3 state path, it will later + // be saved to the proper path + if os.IsNotExist(err) { + content, err = ioutil.ReadFile(deprecatedStatePath) + } + + if err != nil { + if !os.IsNotExist(err) { + logrus.Warnf("could not open state in %s: %s", statePath, err) + } + return } - return } // avoid partially unmarshalled content by using a temp var diff --git a/cluster/state_test.go b/cluster/state_test.go index af422ce..38be58a 100644 --- a/cluster/state_test.go +++ b/cluster/state_test.go @@ -9,7 +9,7 @@ import ( ) func Test_state_save_soad(t *testing.T) { - defaultStatePath = "/tmp/%s.json" + statePathTemplate = "/tmp/%s.json" key := "abcdefghijklmnopqrstuvwxyzABCDEF" node := common.Node{ Name: "node", diff --git a/config.go b/config.go index 48f4713..2f4ea4f 100644 --- a/config.go +++ b/config.go @@ -14,7 +14,6 @@ type config struct { ClusterKey []byte `id:"cluster-key" desc:"shared key for cluster membership; must be 32 bytes base64 encoded; will be generated if not provided"` Join []string `desc:"comma separated list of hostnames or IP addresses to existing cluster members; if not provided, will attempt resuming any known state or otherwise wait for further members."` Init bool `desc:"whether to explicitly (re)initialize the cluster; any known state from previous runs will be forgotten"` - ClusterName string `id:"cluster-name" desc:"identifier for the wesher cluster; can be used to peer with multiple clusters" default:"default"` BindAddr string `id:"bind-addr" desc:"IP address to bind to for cluster membership traffic (cannot be used with --bind-iface)"` BindIface string `id:"bind-iface" desc:"Interface to bind to for cluster membership traffic (cannot be used with --bind-addr)"` ClusterPort int `id:"cluster-port" desc:"port used for membership gossip traffic (both TCP and UDP); must be the same across cluster" default:"7946"` diff --git a/main.go b/main.go index e7b1ba1..570eb97 100644 --- a/main.go +++ b/main.go @@ -35,7 +35,7 @@ func main() { logrus.SetLevel(logLevel) // Create the wireguard and cluster configuration - cluster, err := cluster.New(config.ClusterName, config.Init, config.ClusterKey, config.BindAddr, config.ClusterPort, config.UseIPAsName) + cluster, err := cluster.New(config.Interface, config.Init, config.ClusterKey, config.BindAddr, config.ClusterPort, config.UseIPAsName) if err != nil { logrus.WithError(err).Fatal("could not create cluster") } @@ -46,7 +46,7 @@ func main() { // Prepare the /etc/hosts writer hostsFile := &etchosts.EtcHosts{ - Banner: "# ! managed automatically by wesher " + config.ClusterName, + Banner: "# ! managed automatically by wesher interface " + config.Interface, Logger: logrus.StandardLogger(), } diff --git a/tests/e2e.sh b/tests/e2e.sh index 1165b31..e133719 100755 --- a/tests/e2e.sh +++ b/tests/e2e.sh @@ -101,8 +101,8 @@ test_cluster_simultaneous_start() { } test_multiple_clusters_restart() { - cluster1='--cluster-port 7946 --wireguard-port 51820 --cluster-name cluster1 --interface wgoverlay --overlay-net 10.10.0.0/16' - cluster2='--cluster-port 7947 --wireguard-port 51821 --cluster-name cluster2 --interface wgoverlay2 --overlay-net 10.11.0.0/16' + cluster1='--cluster-port 7946 --wireguard-port 51820 --interface wgoverlay --overlay-net 10.10.0.0/16' + cluster2='--cluster-port 7947 --wireguard-port 51821 --interface wgoverlay2 --overlay-net 10.11.0.0/16' setup_wireguard='wireguard-go wgoverlay2 2>/dev/null >/dev/null' join_cluster2="nohup /app/wesher --cluster-key 'ILICZ3yBMCGAWNIq5Pn0bewBVimW3Q2yRVJ/Be+b1Uc=' --join test2-orig $cluster2 2>/dev/null &"