Add logic to error on certain invalid listener configs (#838)

This adds logic to error on certain invalid listener config:

* If an address in the worker's "controller" set is unspecified or
multicast or global unicast, error
* If the controller's cluster address is unspecified, ensure
public_cluster_addr is set

This has been a source of some confusing behavior on some GitHub tickets
and even on the team, so preventing it is probably a good idea.

It also relaxes the restriction around controller address matching cluster address in single-server mode when using DNS names.
This commit is contained in:
Jeff Mitchell authored and GitHub committed 2020-12-18 12:12:25 -05:00
1 parent 1d3cdbe630
commit e6c98f1454
2 files changed
+70 -2

No files matched your search

+3
View File
@@ -30,6 +30,9 @@ Canonical reference for changes, improvements, and bugfixes for Boundary.
* cli/connect/kube: New `kube` subcommand for `boundary connect` that makes it
easy to route `kubectl` commands through Boundary, including when using
`kubectl proxy` ([PR](https://github.com/hashicorp/boundary/pull/816))
* cli/server: Add some extra checks around valid/invalid combinations of
addresses to avoid hard-to-understand runtime issues
([PR](https://github.com/hashicorp/boundary/pull/838))
### Bug Fixes
+67 -2
View File
@@ -2,6 +2,7 @@ package server
import (
"fmt"
"net"
"runtime"
"strings"
@@ -221,16 +222,56 @@ func (c *Command) Run(args []string) int {
if c.Config.Controller != nil {
switch len(c.Config.Worker.Controllers) {
case 0:
c.Config.Worker.Controllers = []string{clusterAddr}
case 1:
if c.Config.Worker.Controllers[0] == clusterAddr {
break
}
// Best effort see if it's a domain name and if not assume it must match
host, _, err := net.SplitHostPort(c.Config.Worker.Controllers[0])
if err != nil && strings.Contains(err.Error(), "missing port in address") {
err = nil
host = c.Config.Worker.Controllers[0]
}
if err == nil {
ip := net.ParseIP(host)
if ip == nil {
// Assume it's a domain name
break
}
}
fallthrough
default:
c.UI.Error(`When running a combined controller and worker, it's invalid to specify a "controllers" key in the worker block with any value other than the controller cluster address`)
c.UI.Error(`When running a combined controller and worker, it's invalid to specify a "controllers" key in the worker block with any value other than the controller cluster address/port when using IPs rather than DNS names`)
return 1
}
c.Config.Worker.Controllers = []string{clusterAddr}
}
for _, controller := range c.Config.Worker.Controllers {
host, _, err := net.SplitHostPort(controller)
if err != nil {
if strings.Contains(err.Error(), "missing port in address") {
host = controller
} else {
c.UI.Error(fmt.Errorf("Invalid controller address %q: %w", controller, err).Error())
return 1
}
}
ip := net.ParseIP(host)
if ip != nil {
var errMsg string
switch {
case ip.IsUnspecified():
errMsg = "an unspecified"
case ip.IsMulticast():
errMsg = "a multicast"
case ip.IsGlobalUnicast():
errMsg = "a global unicast"
}
if errMsg != "" {
c.UI.Error(fmt.Sprintf("Controller address %q is invalid: cannot be %s address", controller, errMsg))
return 1
}
}
}
}
if err := c.SetupListeners(c.UI, c.Config.SharedConfig, []string{"api", "cluster", "proxy"}); err != nil {
@@ -247,6 +288,30 @@ func (c *Command) Run(args []string) int {
c.Info["public addr"] = c.Config.Worker.PublicAddr
}
if c.Config.Controller != nil {
for _, ln := range c.Config.Listeners {
for _, purpose := range ln.Purpose {
if purpose != "cluster" {
continue
}
host, _, err := net.SplitHostPort(ln.Address)
if err != nil {
if strings.Contains(err.Error(), "missing port in address") {
host = ln.Address
} else {
c.UI.Error(fmt.Errorf("Invalid cluster listener address %q: %w", ln.Address, err).Error())
return 1
}
}
ip := net.ParseIP(host)
if ip != nil {
if ip.IsUnspecified() && c.Config.Controller.PublicClusterAddr == "" {
c.UI.Error(fmt.Sprintf("When %q listener has an unspecified address, %q must be set", "cluster", "public_cluster_addr"))
return 1
}
}
}
}
if err := c.SetupControllerPublicClusterAddress(c.Config, ""); err != nil {
c.UI.Error(err.Error())
return 1