Refactoring and the worker is more distinct now (#3)

This commit is contained in:
Jeff Mitchell authored and GitHub committed 2020-03-20 12:51:39 -04:00
1 parent 75dc91fdb6
commit 07032f6908
10 files changed
+210 -346

No files matched your search

-4
View File
@@ -12,10 +12,6 @@ import (
"github.com/hashicorp/go-hclog"
)
func init() {
memProfilerEnabled = true
}
func StartMemProfiler(logger hclog.Logger) {
profileDir := filepath.Join(os.TempDir(), "watchtowerprof")
if err := os.MkdirAll(profileDir, 0700); err != nil {
+5 -4
View File
@@ -8,6 +8,7 @@ import (
"errors"
"fmt"
"io"
"net"
"net/http"
"os"
"sort"
@@ -38,9 +39,10 @@ import (
)
type ServerListener struct {
Mux *alpnmux.ALPNMux
Config *configutil.Listener
HTTPServer *http.Server
Mux *alpnmux.ALPNMux
Config *configutil.Listener
HTTPServer *http.Server
ALPNListener net.Listener
}
type Server struct {
@@ -299,7 +301,6 @@ func (b *Server) SetupListeners(ui cli.Ui, config *configutil.SharedConfig) erro
b.InfoKeys = append(b.InfoKeys, key)
b.Info[key] = fmt.Sprintf(
"%s (%s)", lnConfig.Type, strings.Join(propsList, ", "))
}
return nil
+21 -29
View File
@@ -11,7 +11,7 @@ import (
"github.com/hashicorp/vault/sdk/helper/mlock"
"github.com/hashicorp/watchtower/globals"
"github.com/hashicorp/watchtower/internal/cmd/base"
"github.com/hashicorp/watchtower/internal/cmd/commands/controller/config"
"github.com/hashicorp/watchtower/internal/cmd/config"
"github.com/hashicorp/watchtower/internal/servers/controller"
"github.com/mitchellh/cli"
"github.com/posener/complete"
@@ -20,8 +20,6 @@ import (
var _ cli.Command = (*Command)(nil)
var _ cli.CommandAutocomplete = (*Command)(nil)
var memProfilerEnabled = false
type Command struct {
*base.Command
*base.Server
@@ -39,7 +37,7 @@ type Command struct {
flagLogLevel string
flagLogFormat string
flagDev bool
flagDevAdminToken string
flagDevAdminPassword string
flagDevControllerListenAddr string
flagCombineLogs bool
}
@@ -105,11 +103,11 @@ func (c *Command) Flags() *base.FlagSets {
})
f.StringVar(&base.StringVar{
Name: "dev-admin-token",
Target: &c.flagDevAdminToken,
Name: "dev-admin-password",
Target: &c.flagDevAdminPassword,
Default: "",
EnvVar: "WATCHTWER_DEV_ADMIN_TOKEN",
Usage: "Initial admin token. This only applies when running in \"dev\" " +
EnvVar: "WATCHTWER_DEV_ADMIN_PASSWORD",
Usage: "Initial admin password. This only applies when running in \"dev\" " +
"mode.",
})
@@ -152,9 +150,7 @@ func (c *Command) Run(args []string) int {
return 1
}
if memProfilerEnabled {
base.StartMemProfiler(c.Logger)
}
base.StartMemProfiler(c.Logger)
if err := c.SetupMetrics(c.UI, c.Config.Telemetry); err != nil {
c.UI.Error(err.Error())
@@ -171,14 +167,14 @@ func (c *Command) Run(args []string) int {
}
// If mlockall(2) isn't supported, show a warning. We disable this in dev
// because it is quite scary to see when first using Vault. We also disable
// because it is quite scary to see when first using Watchtower. We also disable
// this if the user has explicitly disabled mlock in configuration.
if !c.flagDev && !c.Config.DisableMlock && !mlock.Supported() {
c.UI.Warn(base.WrapAtLength(
"WARNING! mlock is not supported on this system! An mlockall(2)-like " +
"syscall to prevent memory from being swapped to disk is not " +
"supported on this system. For better security, only run Vault on " +
"systems where this call is supported. If you are running Vault " +
"supported on this system. For better security, only run Watchtower on " +
"systems where this call is supported. If you are running Watchtower" +
"in a Docker container, provide the IPC_LOCK cap to the container."))
}
@@ -189,13 +185,13 @@ func (c *Command) Run(args []string) int {
// Write out the PID to the file now that server has successfully started
if err := c.StorePidFile(c.Config.PidFile); err != nil {
c.UI.Error(fmt.Sprintf("Error storing PID: %w", err))
c.UI.Error(fmt.Errorf("Error storing PID: %w", err).Error())
return 1
}
if c.flagDev {
if err := c.CreateDevDatabase(); err != nil {
c.UI.Error(fmt.Sprintf("Error creating dev database container: %s", err.Error()))
c.UI.Error(fmt.Errorf("Error creating dev database container: %s", err.Error()).Error())
return 1
}
c.ShutdownFuncs = append(c.ShutdownFuncs, c.DestroyDevDatabase)
@@ -225,17 +221,13 @@ func (c *Command) ParseFlagsAndConfig(args []string) int {
case len(c.flagConfig) == 0:
c.UI.Error("Must specify a config file using -config")
return 1
case c.flagDevAdminToken != "":
case c.flagDevAdminPassword != "":
c.UI.Warn(base.WrapAtLength(
"You cannot specify a custom admin token ID outside of \"dev\" mode. " +
"You cannot specify a custom admin password outside of \"dev\" mode. " +
"Your request has been ignored."))
c.flagDevAdminToken = ""
c.flagDevAdminPassword = ""
}
if len(c.flagConfig) == 0 {
c.UI.Error("Must supply a config file with -config")
return 1
}
c.Config, err = config.LoadFile(c.flagConfig)
if err != nil {
c.UI.Error("Error parsing config: " + err.Error())
@@ -243,9 +235,9 @@ func (c *Command) ParseFlagsAndConfig(args []string) int {
}
} else {
c.Config, err = config.Dev()
c.Config, err = config.DevController()
if err != nil {
c.UI.Error(fmt.Sprintf("Error creating dev config: %s", err))
c.UI.Error(fmt.Errorf("Error creating dev config: %s", err).Error())
return 1
}
@@ -267,14 +259,14 @@ func (c *Command) Start() int {
// Initialize the core
ctlr, err := controller.New(conf)
if err != nil {
c.UI.Error(fmt.Sprintf("Error initializing controller: %w", err))
c.UI.Error(fmt.Errorf("Error initializing controller: %w", err).Error())
return 1
}
if err := ctlr.Start(); err != nil {
c.UI.Error(fmt.Sprint("Error starting controller: %w", err))
if err := ctlr.Shutdown(); err != nil {
c.UI.Error(fmt.Sprintf("Error with controller shutdown: %w", err))
c.UI.Error(fmt.Errorf("Error with controller shutdown: %w", err).Error())
}
return 1
}
@@ -288,7 +280,7 @@ func (c *Command) Start() int {
c.UI.Output("==> Watchtower controller shutdown triggered")
if err := ctlr.Shutdown(); err != nil {
c.UI.Error(fmt.Sprintf("Error with controller shutdown: %w", err))
c.UI.Error(fmt.Errorf("Error with controller shutdown: %w", err).Error())
}
shutdownTriggered = true
@@ -342,7 +334,7 @@ func (c *Command) Start() int {
RUNRELOADFUNCS:
if err := c.Reload(); err != nil {
c.UI.Error(fmt.Sprintf("Error(s) were encountered during controller reload: %w", err))
c.UI.Error(fmt.Errorf("Error(s) were encountered during controller reload: %w", err).Error())
}
case <-c.SigUSR2Ch:
+29 -21
View File
@@ -8,7 +8,8 @@ import (
"github.com/hashicorp/watchtower/internal/cmd/base"
controllercmd "github.com/hashicorp/watchtower/internal/cmd/commands/controller"
controllerconfig "github.com/hashicorp/watchtower/internal/cmd/commands/controller/config"
workercmd "github.com/hashicorp/watchtower/internal/cmd/commands/worker"
"github.com/hashicorp/watchtower/internal/cmd/config"
"github.com/mitchellh/cli"
"github.com/posener/complete"
)
@@ -16,8 +17,6 @@ import (
var _ cli.Command = (*Command)(nil)
var _ cli.CommandAutocomplete = (*Command)(nil)
var memProfilerEnabled = false
type Command struct {
*base.Command
*base.Server
@@ -34,7 +33,7 @@ type Command struct {
flagLogLevel string
flagLogFormat string
flagDev bool
flagDevAdminToken string
flagDevAdminPassword string
flagDevControllerListenAddr string
flagCombineLogs bool
}
@@ -83,11 +82,11 @@ func (c *Command) Flags() *base.FlagSets {
f = set.NewFlagSet("Dev Options")
f.StringVar(&base.StringVar{
Name: "dev-admin-token",
Target: &c.flagDevAdminToken,
Name: "dev-admin-password",
Target: &c.flagDevAdminPassword,
Default: "",
EnvVar: "WATCHTWER_DEV_ADMIN_TOKEN",
Usage: "Initial admin token. This only applies when running in \"dev\" " +
EnvVar: "WATCHTWER_DEV_ADMIN_PASSWORD",
Usage: "Initial admin password. This only applies when running in \"dev\" " +
"mode.",
})
@@ -132,9 +131,9 @@ func (c *Command) Run(args []string) int {
childShutdownCh := make(chan struct{})
devControllerConfig, err := controllerconfig.Dev()
devConfig, err := config.DevController()
if err != nil {
c.UI.Error(fmt.Sprintf("Error creating controller dev config: %s", err))
c.UI.Error(fmt.Errorf("Error creating controller dev config: %s", err).Error())
return 1
}
@@ -143,29 +142,27 @@ func (c *Command) Run(args []string) int {
return 1
}
if memProfilerEnabled {
base.StartMemProfiler(c.Logger)
}
base.StartMemProfiler(c.Logger)
if err := c.SetupMetrics(c.UI, devControllerConfig.Telemetry); err != nil {
if err := c.SetupMetrics(c.UI, devConfig.Telemetry); err != nil {
c.UI.Error(err.Error())
return 1
}
if err := c.SetupKMSes(c.UI, devControllerConfig.SharedConfig, 2); err != nil {
if err := c.SetupKMSes(c.UI, devConfig.SharedConfig, 2); err != nil {
c.UI.Error(err.Error())
return 1
}
// Initialize the listeners
if err := c.SetupListeners(c.UI, devControllerConfig.SharedConfig); err != nil {
if err := c.SetupListeners(c.UI, devConfig.SharedConfig); err != nil {
c.UI.Error(err.Error())
return 1
}
// Write out the PID to the file now that server has successfully started
if err := c.StorePidFile(devControllerConfig.PidFile); err != nil {
c.UI.Error(fmt.Sprintf("Error storing PID: %w", err))
if err := c.StorePidFile(devConfig.PidFile); err != nil {
c.UI.Error(fmt.Errorf("Error storing PID: %w", err).Error())
return 1
}
@@ -208,7 +205,7 @@ func (c *Command) Run(args []string) int {
defer c.RunShutdownFuncs(c.UI)
if err := c.CreateDevDatabase(); err != nil {
c.UI.Error(fmt.Sprintf("Error creating dev database container: %s", err.Error()))
c.UI.Error(fmt.Errorf("Error creating dev database container: %w", err).Error())
return 1
}
c.ShutdownFuncs = append(c.ShutdownFuncs, c.DestroyDevDatabase)
@@ -218,7 +215,7 @@ func (c *Command) Run(args []string) int {
// Instantiate the wait group
shutdownWg := &sync.WaitGroup{}
shutdownWg.Add(1)
shutdownWg.Add(2)
controllerSighupCh := make(chan struct{})
c.childSighupCh = append(c.childSighupCh, controllerSighupCh)
go func() {
@@ -228,10 +225,21 @@ func (c *Command) Run(args []string) int {
Server: c.Server,
ShutdownCh: childShutdownCh,
SighupCh: controllerSighupCh,
Config: devControllerConfig,
Config: devConfig,
}
devController.Start()
}()
go func() {
defer shutdownWg.Done()
devWorker := &workercmd.Command{
Command: c.Command,
Server: c.Server,
ShutdownCh: childShutdownCh,
SighupCh: controllerSighupCh,
Config: devConfig,
}
devWorker.Start()
}()
// Wait for shutdown
shutdownTriggered := false
@@ -1,122 +0,0 @@
package config
import (
"bytes"
"crypto/rand"
"encoding/base64"
"fmt"
"io"
"io/ioutil"
"github.com/hashicorp/hcl"
"github.com/hashicorp/vault/internalshared/configutil"
)
// Config is the configuration for the watchtower controller
type Config struct {
*configutil.SharedConfig `hcl:"-"`
}
// Dev is a Config that is used for dev mode of Watchtower
func Dev() (*Config, error) {
randBuf := new(bytes.Buffer)
n, err := randBuf.ReadFrom(&io.LimitedReader{
R: rand.Reader,
N: 64,
})
if err != nil {
return nil, err
}
if n != 64 {
return nil, fmt.Errorf("expected to read 64 bytes, read %d", n)
}
controllerKey := base64.StdEncoding.EncodeToString(randBuf.Bytes()[0:32])
workerAuthKey := base64.StdEncoding.EncodeToString(randBuf.Bytes()[32:64])
hclStr := `
disable_mlock = true
listener "tcp" {
tls_disable = true
proxy_protocol_behavior = "allow_authorized"
proxy_protocol_authorized_addrs = "127.0.0.1"
}
telemetry {
prometheus_retention_time = "24h"
disable_hostname = true
}
`
hclStr = fmt.Sprintf(hclStr, controllerKey, workerAuthKey)
parsed, err := Parse(hclStr)
if err != nil {
return nil, fmt.Errorf("error parsing dev config: %w", err)
}
return parsed, nil
}
func New() *Config {
return &Config{
SharedConfig: new(configutil.SharedConfig),
}
}
// LoadFile loads the configuration from the given file.
func LoadFile(path string) (*Config, error) {
// Read the file
d, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
conf, err := Parse(string(d))
if err != nil {
return nil, err
}
return conf, nil
}
func Parse(d string) (*Config, error) {
obj, err := hcl.Parse(d)
if err != nil {
return nil, err
}
// Nothing to do here right now
result := New()
if err := hcl.DecodeObject(result, obj); err != nil {
return nil, err
}
sharedConfig, err := configutil.ParseConfig(d)
if err != nil {
return nil, err
}
result.SharedConfig = sharedConfig
return result, nil
}
// Sanitized returns a copy of the config with all values that are considered
// sensitive stripped. It also strips all `*Raw` values that are mainly
// used for parsing.
//
// Specifically, the fields that this method strips are:
// - KMS.Config
// - Telemetry.CirconusAPIToken
func (c *Config) Sanitized() map[string]interface{} {
// Create shared config if it doesn't exist (e.g. in tests) so that map
// keys are actually populated
if c.SharedConfig == nil {
c.SharedConfig = new(configutil.SharedConfig)
}
sharedResult := c.SharedConfig.Sanitized()
result := map[string]interface{}{}
for k, v := range sharedResult {
result[k] = v
}
return result
}
+14 -52
View File
@@ -9,9 +9,8 @@ import (
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/vault/sdk/helper/mlock"
"github.com/hashicorp/watchtower/globals"
"github.com/hashicorp/watchtower/internal/cmd/base"
"github.com/hashicorp/watchtower/internal/cmd/commands/worker/config"
"github.com/hashicorp/watchtower/internal/cmd/config"
"github.com/hashicorp/watchtower/internal/servers/worker"
"github.com/mitchellh/cli"
"github.com/posener/complete"
@@ -20,8 +19,6 @@ import (
var _ cli.Command = (*Command)(nil)
var _ cli.CommandAutocomplete = (*Command)(nil)
var memProfilerEnabled = false
type Command struct {
*base.Command
*base.Server
@@ -39,7 +36,6 @@ type Command struct {
flagLogLevel string
flagLogFormat string
flagDev bool
flagDevAdminToken string
flagDevWorkerListenAddr string
flagCombineLogs bool
}
@@ -104,15 +100,6 @@ func (c *Command) Flags() *base.FlagSets {
"production.",
})
f.StringVar(&base.StringVar{
Name: "dev-admin-token",
Target: &c.flagDevAdminToken,
Default: "",
EnvVar: "WATCHTWER_DEV_ADMIN_TOKEN",
Usage: "Initial admin token. This only applies when running in \"dev\" " +
"mode.",
})
f.StringVar(&base.StringVar{
Name: "dev-listen-address",
Target: &c.flagDevWorkerListenAddr,
@@ -152,33 +139,27 @@ func (c *Command) Run(args []string) int {
return 1
}
if memProfilerEnabled {
base.StartMemProfiler(c.Logger)
}
base.StartMemProfiler(c.Logger)
if err := c.SetupMetrics(c.UI, c.Config.Telemetry); err != nil {
c.UI.Error(err.Error())
return 1
}
if err := c.SetupKMSes(c.UI, c.Config.SharedConfig, 2); err != nil {
if err := c.SetupKMSes(c.UI, c.Config.SharedConfig, 1); err != nil {
c.UI.Error(err.Error())
return 1
}
if c.Config.DefaultMaxRequestDuration != 0 {
globals.DefaultMaxRequestDuration = c.Config.DefaultMaxRequestDuration
}
// If mlockall(2) isn't supported, show a warning. We disable this in dev
// because it is quite scary to see when first using Vault. We also disable
// because it is quite scary to see when first using Watchtower. We also disable
// this if the user has explicitly disabled mlock in configuration.
if !c.flagDev && !c.Config.DisableMlock && !mlock.Supported() {
c.UI.Warn(base.WrapAtLength(
"WARNING! mlock is not supported on this system! An mlockall(2)-like " +
"syscall to prevent memory from being swapped to disk is not " +
"supported on this system. For better security, only run Vault on " +
"systems where this call is supported. If you are running Vault " +
"supported on this system. For better security, only run Watchtower on " +
"systems where this call is supported. If you are running Watchtower" +
"in a Docker container, provide the IPC_LOCK cap to the container."))
}
@@ -189,18 +170,10 @@ func (c *Command) Run(args []string) int {
// Write out the PID to the file now that server has successfully started
if err := c.StorePidFile(c.Config.PidFile); err != nil {
c.UI.Error(fmt.Sprintf("Error storing PID: %w", err))
c.UI.Error(fmt.Errorf("Error storing PID: %w", err).Error())
return 1
}
if c.flagDev {
if err := c.CreateDevDatabase(); err != nil {
c.UI.Error(fmt.Sprintf("Error creating dev database container: %s", err.Error()))
return 1
}
c.ShutdownFuncs = append(c.ShutdownFuncs, c.DestroyDevDatabase)
}
defer c.RunShutdownFuncs(c.UI)
c.PrintInfo(c.UI, "worker")
@@ -221,17 +194,6 @@ func (c *Command) ParseFlagsAndConfig(args []string) int {
// Validation
if !c.flagDev {
switch {
case len(c.flagConfig) == 0:
c.UI.Error("Must specify a config file using -config")
return 1
case c.flagDevAdminToken != "":
c.UI.Warn(base.WrapAtLength(
"You cannot specify a custom admin token ID outside of \"dev\" mode. " +
"Your request has been ignored."))
c.flagDevAdminToken = ""
}
if len(c.flagConfig) == 0 {
c.UI.Error("Must supply a config file with -config")
return 1
@@ -243,9 +205,9 @@ func (c *Command) ParseFlagsAndConfig(args []string) int {
}
} else {
c.Config, err = config.Dev()
c.Config, err = config.DevWorker()
if err != nil {
c.UI.Error(fmt.Sprintf("Error creating dev config: %s", err))
c.UI.Error(fmt.Errorf("Error creating dev config: %s", err).Error())
return 1
}
@@ -267,14 +229,14 @@ func (c *Command) Start() int {
// Initialize the core
wrkr, err := worker.New(conf)
if err != nil {
c.UI.Error(fmt.Sprintf("Error initializing worker: %w", err))
c.UI.Error(fmt.Errorf("Error initializing worker: %w", err).Error())
return 1
}
if err := wrkr.Start(); err != nil {
c.UI.Error(fmt.Sprint("Error starting worker: %w", err))
c.UI.Error(fmt.Errorf("Error starting worker: %w", err).Error())
if err := wrkr.Shutdown(); err != nil {
c.UI.Error(fmt.Sprintf("Error with worker shutdown: %w", err))
c.UI.Error(fmt.Errorf("Error with worker shutdown: %w", err).Error())
}
return 1
}
@@ -288,7 +250,7 @@ func (c *Command) Start() int {
c.UI.Output("==> Watchtower worker shutdown triggered")
if err := wrkr.Shutdown(); err != nil {
c.UI.Error(fmt.Sprintf("Error with worker shutdown: %w", err))
c.UI.Error(fmt.Errorf("Error with worker shutdown: %w", err).Error())
}
shutdownTriggered = true
@@ -342,7 +304,7 @@ func (c *Command) Start() int {
RUNRELOADFUNCS:
if err := c.Reload(); err != nil {
c.UI.Error(fmt.Sprintf("Error(s) were encountered during worker reload: %w", err))
c.UI.Error(fmt.Errorf("Error(s) were encountered during worker reload: %w", err).Error())
}
case <-c.SigUSR2Ch:
@@ -12,13 +12,58 @@ import (
"github.com/hashicorp/vault/internalshared/configutil"
)
const (
devConfig = `
disable_mlock = true
listener "tcp" {
tls_disable = true
proxy_protocol_behavior = "allow_authorized"
proxy_protocol_authorized_addrs = "127.0.0.1"
}
telemetry {
prometheus_retention_time = "24h"
disable_hostname = true
}
`
devControllerExtraConfig = `
kms "aead" {
purpose = "controller"
aead_type = "aes-gcm"
key = "%s"
}
kms "aead" {
purpose = "worker-auth"
aead_type = "aes-gcm"
key = "%s"
}
`
)
// Config is the configuration for the watchtower controller
type Config struct {
*configutil.SharedConfig `hcl:"-"`
DevController bool `hcl:"-"`
}
// Dev is a Config that is used for dev mode of Watchtower
func Dev() (*Config, error) {
// DevWorker is a Config that is used for dev mode of Watchtower
// workers
func DevWorker() (*Config, error) {
parsed, err := Parse(devConfig)
if err != nil {
return nil, fmt.Errorf("error parsing dev config: %w", err)
}
return parsed, nil
}
// DevController is a Config that is used for dev mode of Watchtower
// controllers
func DevController() (*Config, error) {
randBuf := new(bytes.Buffer)
n, err := randBuf.ReadFrom(&io.LimitedReader{
R: rand.Reader,
@@ -33,38 +78,12 @@ func Dev() (*Config, error) {
controllerKey := base64.StdEncoding.EncodeToString(randBuf.Bytes()[0:32])
workerAuthKey := base64.StdEncoding.EncodeToString(randBuf.Bytes()[32:64])
hclStr := `
disable_mlock = true
listener "tcp" {
tls_disable = true
proxy_protocol_behavior = "allow_authorized"
proxy_protocol_authorized_addrs = "127.0.0.1"
}
telemetry {
prometheus_retention_time = "24h"
disable_hostname = true
}
kms "aead" {
purpose = "controller"
aead_type = "aes-gcm"
key = "%s"
}
kms "aead" {
purpose = "worker-auth"
aead_type = "aes-gcm"
key = "%s"
}
`
hclStr = fmt.Sprintf(hclStr, controllerKey, workerAuthKey)
hclStr := fmt.Sprintf(devConfig+devControllerExtraConfig, controllerKey, workerAuthKey)
parsed, err := Parse(hclStr)
if err != nil {
return nil, fmt.Errorf("error parsing dev config: %w", err)
}
parsed.DevController = true
return parsed, nil
}
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"context"
"github.com/hashicorp/watchtower/internal/cmd/base"
"github.com/hashicorp/watchtower/internal/cmd/commands/controller/config"
"github.com/hashicorp/watchtower/internal/cmd/config"
)
type Config struct {
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"context"
"github.com/hashicorp/watchtower/internal/cmd/base"
"github.com/hashicorp/watchtower/internal/cmd/commands/worker/config"
"github.com/hashicorp/watchtower/internal/cmd/config"
)
type Config struct {
+90 -82
View File
@@ -17,97 +17,92 @@ func (c *Worker) startListeners() error {
var retErr *multierror.Error
servers := make([]func(), 0, len(c.conf.Listeners))
for _, ln := range c.conf.Listeners {
handler := c.Handler(HandlerProperties{
ListenerConfig: ln.Config,
})
/*
// TODO: As I write this Vault's having this code audited, make sure to
// port over any recommendations
//
// We perform validation on the config earlier, we can just cast here
if _, ok := ln.config["x_forwarded_for_authorized_addrs"]; ok {
hopSkips := ln.config["x_forwarded_for_hop_skips"].(int)
authzdAddrs := ln.config["x_forwarded_for_authorized_addrs"].([]*sockaddr.SockAddrMarshaler)
rejectNotPresent := ln.config["x_forwarded_for_reject_not_present"].(bool)
rejectNonAuthz := ln.config["x_forwarded_for_reject_not_authorized"].(bool)
if len(authzdAddrs) > 0 {
handler = vaulthttp.WrapForwardedForHandler(handler, authzdAddrs, rejectNotPresent, rejectNonAuthz, hopSkips)
}
}
*/
server := &http.Server{
Handler: handler,
ReadHeaderTimeout: 10 * time.Second,
ReadTimeout: 30 * time.Second,
IdleTimeout: 5 * time.Minute,
ErrorLog: c.conf.Logger.StandardLogger(nil),
BaseContext: func(net.Listener) context.Context {
return c.baseContext
},
}
ln.HTTPServer = server
if ln.Config.HTTPReadHeaderTimeout > 0 {
server.ReadHeaderTimeout = ln.Config.HTTPReadHeaderTimeout
}
if ln.Config.HTTPReadTimeout > 0 {
server.ReadTimeout = ln.Config.HTTPReadTimeout
}
if ln.Config.HTTPWriteTimeout > 0 {
server.WriteTimeout = ln.Config.HTTPWriteTimeout
}
if ln.Config.HTTPIdleTimeout > 0 {
server.IdleTimeout = ln.Config.HTTPIdleTimeout
}
switch ln.Config.TLSDisable {
case true:
l := ln.Mux.GetListener(alpnmux.NoProto)
if l == nil {
retErr = multierror.Append(retErr, errors.New("could not get non-tls listener"))
continue
}
servers = append(servers, func() {
go server.Serve(l)
switch c.conf.RawConfig.DevController {
case false:
handler := c.Handler(HandlerProperties{
ListenerConfig: ln.Config,
})
default:
protos := []string{"", "http/1.1", "h2"}
for _, v := range protos {
l := ln.Mux.GetListener(v)
/*
// TODO: As I write this Vault's having this code audited, make sure to
// port over any recommendations
//
// We perform validation on the config earlier, we can just cast here
if _, ok := ln.config["x_forwarded_for_authorized_addrs"]; ok {
hopSkips := ln.config["x_forwarded_for_hop_skips"].(int)
authzdAddrs := ln.config["x_forwarded_for_authorized_addrs"].([]*sockaddr.SockAddrMarshaler)
rejectNotPresent := ln.config["x_forwarded_for_reject_not_present"].(bool)
rejectNonAuthz := ln.config["x_forwarded_for_reject_not_authorized"].(bool)
if len(authzdAddrs) > 0 {
handler = vaulthttp.WrapForwardedForHandler(handler, authzdAddrs, rejectNotPresent, rejectNonAuthz, hopSkips)
}
}
*/
server := &http.Server{
Handler: handler,
ReadHeaderTimeout: 10 * time.Second,
ReadTimeout: 30 * time.Second,
IdleTimeout: 5 * time.Minute,
ErrorLog: c.conf.Logger.StandardLogger(nil),
BaseContext: func(net.Listener) context.Context {
return c.baseContext
},
}
ln.HTTPServer = server
if ln.Config.HTTPReadHeaderTimeout > 0 {
server.ReadHeaderTimeout = ln.Config.HTTPReadHeaderTimeout
}
if ln.Config.HTTPReadTimeout > 0 {
server.ReadTimeout = ln.Config.HTTPReadTimeout
}
if ln.Config.HTTPWriteTimeout > 0 {
server.WriteTimeout = ln.Config.HTTPWriteTimeout
}
if ln.Config.HTTPIdleTimeout > 0 {
server.IdleTimeout = ln.Config.HTTPIdleTimeout
}
switch ln.Config.TLSDisable {
case true:
l := ln.Mux.GetListener(alpnmux.NoProto)
if l == nil {
retErr = multierror.Append(retErr, fmt.Errorf("could not get tls proto %q listener", v))
retErr = multierror.Append(retErr, errors.New("could not get non-tls listener"))
continue
}
servers = append(servers, func() {
go server.Serve(l)
})
default:
protos := []string{"", "http/1.1", "h2"}
for _, v := range protos {
l := ln.Mux.GetListener(v)
if l == nil {
retErr = multierror.Append(retErr, fmt.Errorf("could not get tls proto %q listener", v))
continue
}
servers = append(servers, func() {
go server.Serve(l)
})
}
}
}
workerTLSConfig, peeringInfo, err := c.workerTLS(workerTLSOpts{
Address: ln.Config.Address,
Protos: []string{"watchtower-worker-v1"},
})
if err != nil {
retErr = multierror.Append(retErr, fmt.Errorf("error getting TLS configuration: %w", err))
continue
}
l, err := ln.Mux.RegisterProto("watchtower-worker-v1", workerTLSConfig)
if err != nil {
retErr = multierror.Append(retErr, fmt.Errorf("error getting sub-listener for worker proto: %w", err))
continue
}
fallthrough
// TODO: Start listner for real; for now send it to the http server just for testing
servers = append(servers, func() {
go server.Serve(l)
})
// TODO: Add peering info into database
_ = peeringInfo
default:
if !ln.Config.TLSDisable {
l := ln.Mux.GetListener(alpnmux.DefaultProto)
if l == nil {
retErr = multierror.Append(retErr, fmt.Errorf("could not get tls proto %q listener", alpnmux.DefaultProto))
continue
}
ln.ALPNListener = l
// TODO: give this listener to a server to handle ALPN auth
}
// TODO: Register websocket handler against server on this listener
}
}
err := retErr.ErrorOrNil()
@@ -125,6 +120,11 @@ func (c *Worker) startListeners() error {
func (c *Worker) stopListeners() error {
serverWg := new(sync.WaitGroup)
for _, ln := range c.conf.Listeners {
if c.conf.RawConfig.DevController {
// These will get closed by the controller's dev instance
continue
}
if ln.HTTPServer == nil {
continue
}
@@ -140,8 +140,16 @@ func (c *Worker) stopListeners() error {
var retErr *multierror.Error
for _, ln := range c.conf.Listeners {
if err := ln.Mux.Close(); err != nil {
retErr = multierror.Append(retErr, err)
if ln.ALPNListener != nil {
if err := ln.ALPNListener.Close(); err != nil {
retErr = multierror.Append(retErr, err)
}
}
if !c.conf.RawConfig.DevController {
if err := ln.Mux.Close(); err != nil {
retErr = multierror.Append(retErr, err)
}
}
}
return retErr.ErrorOrNil()