From cb607013da9a120678211c80228208a886d55bcb Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Sat, 2 May 2015 15:34:29 -0700 Subject: [PATCH 1/3] physical: Adding optional interface for addr detection --- physical/physical.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/physical/physical.go b/physical/physical.go index 404ad281e9..2a40670a08 100644 --- a/physical/physical.go +++ b/physical/physical.go @@ -32,6 +32,14 @@ type HABackend interface { LockWith(key, value string) (Lock, error) } +// AdvertiseDetect is an optional interface that an HABackend +// can implement. If they do, an advertise address can be automatically +// detected. +type AdvertiseDetect interface { + // DetectHostAddr is used to detect the host address + DetectHostAddr() (string, error) +} + type Lock interface { // Lock is used to acquire the given lock // The stopCh is optional and if closed should interrupt the lock From b08560be57b447cde9583d58f27ac9029488d302 Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Sat, 2 May 2015 15:34:39 -0700 Subject: [PATCH 2/3] physical/consul: Support address detection using the agent --- physical/consul.go | 11 +++++++++++ physical/consul_test.go | 12 ++++++++++++ 2 files changed, 23 insertions(+) diff --git a/physical/consul.go b/physical/consul.go index 1dc8901edd..29807fb420 100644 --- a/physical/consul.go +++ b/physical/consul.go @@ -132,6 +132,17 @@ func (c *ConsulBackend) LockWith(key, value string) (Lock, error) { return cl, nil } +// DetectHostAddr is used to detect the host address by asking the Consul agent +func (c *ConsulBackend) DetectHostAddr() (string, error) { + agent := c.client.Agent() + self, err := agent.Self() + if err != nil { + return "", err + } + addr := self["Member"]["Addr"].(string) + return addr, nil +} + // ConsulLock is used to provide the Lock interface backed by Consul type ConsulLock struct { client *api.Client diff --git a/physical/consul_test.go b/physical/consul_test.go index 38a0da6ce4..9894393829 100644 --- a/physical/consul_test.go +++ b/physical/consul_test.go @@ -43,4 +43,16 @@ func TestConsulBackend(t *testing.T) { t.Fatalf("consul does not implement HABackend") } testHABackend(t, ha, ha) + + detect, ok := b.(AdvertiseDetect) + if !ok { + t.Fatalf("consul does not implement AdvertiseDetect") + } + host, err := detect.DetectHostAddr() + if err != nil { + t.Fatalf("err: %s", err) + } + if host == "" { + t.Fatalf("bad addr: %v", host) + } } From 942e0ecf7daf8a16541186be4abcbed01365836b Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Sat, 2 May 2015 15:57:40 -0700 Subject: [PATCH 3/3] command/server: Attempt advertise address detection --- command/server.go | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/command/server.go b/command/server.go index 8cd7c099cd..48a3386a35 100644 --- a/command/server.go +++ b/command/server.go @@ -6,8 +6,10 @@ import ( "log" "net" "net/http" + "net/url" "os" "sort" + "strconv" "strings" "time" @@ -102,6 +104,18 @@ func (c *ServerCommand) Run(args []string) int { return 1 } + // Attempt to detect the advertise address possible + if detect, ok := backend.(physical.AdvertiseDetect); ok && config.Backend.AdvertiseAddr == "" { + advertise, err := c.detectAdvertise(detect, config) + if err != nil { + c.Ui.Error(fmt.Sprintf("Error detecting advertise address: %s", err)) + } else if advertise == "" { + c.Ui.Error("Failed to detect advertise address.") + } else { + config.Backend.AdvertiseAddr = advertise + } + } + // Initialize the core core, err := vault.NewCore(&vault.CoreConfig{ AdvertiseAddr: config.Backend.AdvertiseAddr, @@ -156,6 +170,8 @@ func (c *ServerCommand) Run(args []string) int { // If the backend supports HA, then note it if _, ok := backend.(physical.HABackend); ok { info["backend"] += " (HA available)" + info["advertise address"] = config.Backend.AdvertiseAddr + infoKeys = append(infoKeys, "advertise address") } // Initialize the telemetry @@ -254,6 +270,64 @@ func (c *ServerCommand) enableDev(core *vault.Core) (*vault.InitResult, error) { return init, nil } +// detectAdvertise is used to attempt advertise address detection +func (c *ServerCommand) detectAdvertise(detect physical.AdvertiseDetect, + config *server.Config) (string, error) { + // Get the hostname + host, err := detect.DetectHostAddr() + if err != nil { + return "", err + } + + // Default the port and scheme + scheme := "https" + port := 8200 + + // Attempt to detect overrides + for _, list := range config.Listeners { + // Only attempt TCP + if list.Type != "tcp" { + continue + } + + // Check if TLS is disabled + if _, ok := list.Config["tls_disable"]; ok { + scheme = "http" + } + + // Check for address override + addr, ok := list.Config["address"] + if !ok { + addr = "127.0.0.1:8200" + } + + // Check for localhost + hostStr, portStr, err := net.SplitHostPort(addr) + if err != nil { + continue + } + if hostStr == "127.0.0.1" { + host = hostStr + } + + // Check for custom port + listPort, err := strconv.Atoi(portStr) + if err != nil { + continue + } + port = listPort + } + + // Build a URL + url := &url.URL{ + Scheme: scheme, + Host: fmt.Sprintf("%s:%d", host, port), + } + + // Return the URL string + return url.String(), nil +} + // setupTelementry is used ot setup the telemetry sub-systems func (c *ServerCommand) setupTelementry(config *server.Config) error { /* Setup telemetry