Add ability to set public cluster address (#761)
This commit is contained in:
1 parent
038540f9ad
commit
e2e4631929
14 files changed
+84
-16
No files matched your search
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
})
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in new issue
Block a user