Add ability to set public cluster address (#761)

This commit is contained in:
Jeff Mitchell authored and GitHub committed 2020-10-30 16:54:53 -04:00
1 parent 038540f9ad
commit e2e4631929
14 files changed
+84 -16

No files matched your search

+3
View File
@@ -8,6 +8,9 @@ Canonical reference for changes, improvements, and bugfixes for Boundary.
* docker: Official Docker image for `hashicorp/boundary`
([PR](https://github.com/hashicorp/boundary/pull/755))
* controller: Add ability to set public address for cluster purposes
([Issue](https://github.com/hashicorp/boundary/pull/758))
([PR](https://github.com/hashicorp/boundary/pull/761))
### Bug Fixes
+5
View File
@@ -171,6 +171,11 @@ func tcpListenerFactory(purpose string, l *configutil.Listener, logger hclog.Log
return "", nil, err
}
// If we used a random port, for a test, we need to save it back so we can set the public address appropriately
if l.RandomPort {
l.Address = ln.Addr().String()
}
ln = TCPKeepAliveListener{ln.(*net.TCPListener)}
return finalListenAddr, ln, nil
+31
View File
@@ -596,6 +596,37 @@ func (b *Server) DestroyDevDatabase() error {
return nil
}
func (b *Server) SetupControllerPublicClusterAddress(conf *config.Config, flagValue string) error {
if conf.Controller == nil {
conf.Controller = new(config.Controller)
}
if flagValue != "" {
conf.Controller.PublicClusterAddr = flagValue
}
if conf.Controller.PublicClusterAddr == "" {
FindAddr:
for _, listener := range conf.Listeners {
for _, purpose := range listener.Purpose {
if purpose == "cluster" {
conf.Controller.PublicClusterAddr = listener.Address
break FindAddr
}
}
}
}
host, port, err := net.SplitHostPort(conf.Controller.PublicClusterAddr)
if err != nil {
if strings.Contains(err.Error(), "missing port") {
port = "9201"
host = conf.Controller.PublicClusterAddr
} else {
return fmt.Errorf("Error splitting public cluster adddress host/port: %w", err)
}
}
conf.Controller.PublicClusterAddr = net.JoinHostPort(host, port)
return nil
}
func (b *Server) SetupWorkerPublicAddress(conf *config.Config, flagValue string) error {
if conf.Worker == nil {
conf.Worker = new(config.Worker)
+15
View File
@@ -48,6 +48,7 @@ type Command struct {
flagTargetSessionConnectionLimit int
flagControllerAPIListenAddr string
flagControllerClusterListenAddr string
flagControllerPublicClusterAddr string
flagWorkerProxyListenAddr string
flagWorkerPublicAddr string
flagPassthroughDirectory string
@@ -163,6 +164,13 @@ func (c *Command) Flags() *base.FlagSets {
Usage: "Address to bind to for controller \"cluster\" purpose. If this begins with a forward slash, it will be assumed to be a Unix domain socket path.",
})
f.StringVar(&base.StringVar{
Name: "controller-public-cluster-address",
Target: &c.flagControllerPublicClusterAddr,
EnvVar: "BOUNDARY_DEV_CONTROLLER_PUBLIC_CLUSTER_ADDRESS",
Usage: "Public address at which the controller is reachable for cluster tasks (like worker connections).",
})
f.StringVar(&base.StringVar{
Name: "proxy-listen-address",
Target: &c.flagWorkerProxyListenAddr,
@@ -356,6 +364,13 @@ func (c *Command) Run(args []string) int {
return 1
}
if err := c.SetupControllerPublicClusterAddress(c.Config, c.flagControllerPublicClusterAddr); err != nil {
c.UI.Error(err.Error())
return 1
}
c.InfoKeys = append(c.InfoKeys, "controller public cluster addr")
c.Info["controller public cluster addr"] = c.Config.Controller.PublicClusterAddr
if err := c.SetupWorkerPublicAddress(c.Config, c.flagWorkerPublicAddr); err != nil {
c.UI.Error(err.Error())
return 1
+8
View File
@@ -246,6 +246,14 @@ func (c *Command) Run(args []string) int {
c.InfoKeys = append(c.InfoKeys, "public addr")
c.Info["public addr"] = c.Config.Worker.PublicAddr
}
if c.Config.Controller != nil {
if err := c.SetupControllerPublicClusterAddress(c.Config, ""); err != nil {
c.UI.Error(err.Error())
return 1
}
c.InfoKeys = append(c.InfoKeys, "public cluster addr")
c.Info["public cluster addr"] = c.Config.Controller.PublicClusterAddr
}
// Write out the PID to the file now that server has successfully started
if err := c.StorePidFile(c.Config.PidFile); err != nil {
+4 -3
View File
@@ -95,9 +95,10 @@ type Config struct {
}
type Controller struct {
Name string `hcl:"name"`
Description string `hcl:"description"`
Database *Database `hcl:"database"`
Name string `hcl:"name"`
Description string `hcl:"description"`
Database *Database `hcl:"database"`
PublicClusterAddr string `hcl:"public_cluster_addr"`
}
type Worker struct {
@@ -47,8 +47,6 @@ type Controller struct {
TargetRepoFn common.TargetRepoFactory
kms *kms.Kms
clusterAddress string
}
func New(conf *Config) (*Controller, error) {
@@ -162,7 +160,6 @@ func (c *Controller) Shutdown(serversOnly bool) error {
if err := c.stopListeners(serversOnly); err != nil {
return fmt.Errorf("error stopping controller listeners: %w", err)
}
c.clusterAddress = ""
c.started.Store(false)
return nil
}
+1 -7
View File
@@ -114,8 +114,6 @@ func (c *Controller) startListeners() error {
if err != nil {
return fmt.Errorf("error getting sub-listener for worker proto: %w", err)
}
c.clusterAddress = l.Addr().String()
c.logger.Info("cluster address", "addr", c.clusterAddress)
workerServer := grpc.NewServer(
grpc.MaxRecvMsgSize(math.MaxInt32),
@@ -142,11 +140,7 @@ func (c *Controller) startListeners() error {
case "api":
err = configureForAPI(ln)
case "cluster":
if c.clusterAddress != "" {
err = errors.New("more than one cluster listener found")
} else {
err = configureForCluster(ln)
}
err = configureForCluster(ln)
case "proxy":
// Do nothing, in a dev mode we might see it here
default:
+3
View File
@@ -406,6 +406,9 @@ func NewTestController(t *testing.T, opts *TestControllerOpts) *TestController {
if err := tc.b.SetupListeners(nil, opts.Config.SharedConfig, []string{"api", "cluster"}); err != nil {
t.Fatal(err)
}
if err := tc.b.SetupControllerPublicClusterAddress(opts.Config, ""); err != nil {
t.Fatal(err)
}
if opts.DatabaseUrl != "" {
tc.b.DatabaseUrl = opts.DatabaseUrl
+1 -1
View File
@@ -33,7 +33,7 @@ func (c *Controller) startStatusTicking(cancelCtx context.Context) {
Name: c.conf.RawConfig.Controller.Name,
Type: resource.Controller.String(),
Description: c.conf.RawConfig.Controller.Description,
Address: c.clusterAddress,
Address: c.conf.RawConfig.Controller.PublicClusterAddr,
}
repo, err := c.ServersRepoFn()
if err != nil {
+3
View File
@@ -188,6 +188,9 @@ func NewTestWorker(t *testing.T, opts *TestWorkerOpts) *TestWorker {
if err := tw.b.SetupListeners(nil, opts.Config.SharedConfig, []string{"proxy"}); err != nil {
t.Fatal(err)
}
if err := tw.b.SetupWorkerPublicAddress(opts.Config, ""); err != nil {
t.Fatal(err)
}
conf := &Config{
RawConfig: opts.Config,
+1 -1
View File
@@ -60,7 +60,7 @@ func TestIPv6Listener(t *testing.T) {
// expecting it we'll see an out-of-date entry
return true
}
assert.WithinDuration(time.Now(), v.(time.Time), 35*time.Second)
assert.WithinDuration(time.Now(), v.(time.Time), 60*time.Second)
delete(workerMap, k.(string))
return true
})
+1 -1
View File
@@ -72,7 +72,7 @@ func TestUnixListener(t *testing.T) {
// expecting it we'll see an out-of-date entry
return true
}
assert.WithinDuration(time.Now(), v.(time.Time), 35*time.Second)
assert.WithinDuration(time.Now(), v.(time.Time), 60*time.Second)
delete(workerMap, k.(string))
return true
})
@@ -32,6 +32,14 @@ controller {
Either can refer to a file on disk (file://) from which a URL will be read; an env
var (env://) from which the URL will be read; or a direct database URL (postgres://).
- `public_cluster_addr` - Specifies the public host or IP address (and
optionally port) at which the worker can be reached _by workers_. This will be
used by workers after initial connection to controllers via the worker's
`controllers` block. This defaults to the address of the listener marked for
`cluster` purpose. This is especially useful for cloud environments that do not
bind a publicly accessible IP to a NIC on the host directly, such as an Amazon
EIP.
## KMS Configuration
The controller requires two KMS stanzas for `root` and `worker-auth` purposes: