From 48cd5951fb7e364ff3e8bbb620f69ba184f65234 Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Thu, 5 Oct 2023 17:01:30 +0100 Subject: [PATCH 01/13] add redaction config settings to listener --- command/server/config_test_helpers.go | 6 ++ internalshared/configutil/listener.go | 80 ++++++++++++++------ internalshared/configutil/listener_test.go | 87 ++++++++++++++++++++++ 3 files changed, 152 insertions(+), 21 deletions(-) diff --git a/command/server/config_test_helpers.go b/command/server/config_test_helpers.go index 4a09e8de2ed5..f7fe62ec9e95 100644 --- a/command/server/config_test_helpers.go +++ b/command/server/config_test_helpers.go @@ -886,6 +886,9 @@ listener "tcp" { enable_quit = true } chroot_namespace = "admin" + redact_addresses = true + redact_cluster_name = true + redact_version = true }`)) config := Config{ @@ -938,6 +941,9 @@ listener "tcp" { }, CustomResponseHeaders: DefaultCustomHeaders, ChrootNamespace: "admin/", + RedactAddresses: true, + RedactClusterName: true, + RedactVersion: true, }, }, }, diff --git a/internalshared/configutil/listener.go b/internalshared/configutil/listener.go index 18507df767f9..20cc7bdfc52b 100644 --- a/internalshared/configutil/listener.go +++ b/internalshared/configutil/listener.go @@ -123,6 +123,14 @@ type Listener struct { // ChrootNamespace will prepend the specified namespace to requests ChrootNamespaceRaw interface{} `hcl:"chroot_namespace"` ChrootNamespace string `hcl:"-"` + + // Per-listener redaction configuration + RedactAddressesRaw any `hcl:"redact_addresses"` + RedactAddresses bool `hcl:"-"` + RedactClusterNameRaw any `hcl:"redact_cluster_name"` + RedactClusterName bool `hcl:"-"` + RedactVersionRaw any `hcl:"redact_version"` + RedactVersion bool `hcl:"-"` } // AgentAPI allows users to select which parts of the Agent API they want enabled. @@ -144,6 +152,32 @@ func (l *Listener) Validate(path string) []ConfigError { return append(results, ValidateUnusedFields(l.Profiling.UnusedKeys, path)...) } +// ParseSingleIPTemplate is used as a helper function to parse out a single IP +// address from a config parameter. +// If the input doesn't appear to contain the 'template' format, +// it will return the specified input unchanged. +func ParseSingleIPTemplate(ipTmpl string) (string, error) { + r := regexp.MustCompile("{{.*?}}") + if !r.MatchString(ipTmpl) { + return ipTmpl, nil + } + + out, err := template.Parse(ipTmpl) + if err != nil { + return "", fmt.Errorf("unable to parse address template %q: %v", ipTmpl, err) + } + + ips := strings.Split(out, " ") + switch len(ips) { + case 0: + return "", errors.New("no addresses found, please configure one") + case 1: + return strings.TrimSpace(ips[0]), nil + default: + return "", fmt.Errorf("multiple addresses found (%q), please configure one", out) + } +} + // ParseListeners attempts to parse the AST list of objects into listeners. func ParseListeners(list *ast.ObjectList) ([]*Listener, error) { listeners := make([]*Listener, len(list.Items)) @@ -209,6 +243,7 @@ func parseListener(item *ast.ObjectItem) (*Listener, error) { l.parseCORSSettings, l.parseHTTPHeaderSettings, l.parseChrootNamespaceSettings, + l.parseRedactionSettings, } { err := parser() if err != nil { @@ -565,28 +600,31 @@ func (l *Listener) parseCORSSettings() error { return nil } -// ParseSingleIPTemplate is used as a helper function to parse out a single IP -// address from a config parameter. -// If the input doesn't appear to contain the 'template' format, -// it will return the specified input unchanged. -func ParseSingleIPTemplate(ipTmpl string) (string, error) { - r := regexp.MustCompile("{{.*?}}") - if !r.MatchString(ipTmpl) { - return ipTmpl, nil - } +// parseRedactionSettings attempts to parse the raw listener redaction settings. +// The state of the listener will be modified, raw data will be cleared upon +// successful parsing. +func (l *Listener) parseRedactionSettings() error { + var err error - out, err := template.Parse(ipTmpl) - if err != nil { - return "", fmt.Errorf("unable to parse address template %q: %v", ipTmpl, err) + if l.RedactAddressesRaw != nil { + if l.RedactAddresses, err = parseutil.ParseBool(l.RedactAddressesRaw); err != nil { + return fmt.Errorf("invalid value for redact_addresses: %w", err) + } } - - ips := strings.Split(out, " ") - switch len(ips) { - case 0: - return "", errors.New("no addresses found, please configure one") - case 1: - return strings.TrimSpace(ips[0]), nil - default: - return "", fmt.Errorf("multiple addresses found (%q), please configure one", out) + if l.RedactClusterNameRaw != nil { + if l.RedactClusterName, err = parseutil.ParseBool(l.RedactClusterNameRaw); err != nil { + return fmt.Errorf("invalid value for redact_cluster_name: %w", err) + } + } + if l.RedactVersionRaw != nil { + if l.RedactVersion, err = parseutil.ParseBool(l.RedactVersionRaw); err != nil { + return fmt.Errorf("invalid value for redact_version: %w", err) + } } + + l.RedactAddressesRaw = nil + l.RedactClusterNameRaw = nil + l.RedactVersionRaw = nil + + return nil } diff --git a/internalshared/configutil/listener_test.go b/internalshared/configutil/listener_test.go index 13346495b420..ac4239efc1ff 100644 --- a/internalshared/configutil/listener_test.go +++ b/internalshared/configutil/listener_test.go @@ -972,3 +972,90 @@ func TestListener_parseChrootNamespaceSettings(t *testing.T) { }) } } + +// TestListener_parseRedactionSettings exercises the listener receiver parseRedactionSettings. +// We check various inputs to ensure we can parse the values as expected and +// assign the relevant value on the SharedConfig struct. +func TestListener_parseRedactionSettings(t *testing.T) { + tests := map[string]struct { + rawRedactAddresses any + expectedRedactAddresses bool + rawRedactClusterName any + expectedRedactClusterName bool + rawRedactVersion any + expectedRedactVersion bool + isErrorExpected bool + errorMessage string + }{ + "missing": { + isErrorExpected: false, + expectedRedactAddresses: false, + expectedRedactClusterName: false, + expectedRedactVersion: false, + }, + "redact-addresses-bad": { + rawRedactAddresses: "juan", + isErrorExpected: true, + errorMessage: "invalid value for redact_addresses", + }, + "redact-addresses-good": { + rawRedactAddresses: "true", + expectedRedactAddresses: true, + isErrorExpected: false, + }, + "redact-cluster-name-bad": { + rawRedactClusterName: "juan", + isErrorExpected: true, + errorMessage: "invalid value for redact_cluster_name", + }, + "redact-cluster-name-good": { + rawRedactClusterName: "true", + expectedRedactClusterName: true, + isErrorExpected: false, + }, + "redact-version-bad": { + rawRedactVersion: "juan", + isErrorExpected: true, + errorMessage: "invalid value for redact_version", + }, + "redact-version-good": { + rawRedactVersion: "true", + expectedRedactVersion: true, + isErrorExpected: false, + }, + } + + for name, tc := range tests { + name := name + tc := tc + t.Run(name, func(t *testing.T) { + t.Parallel() + + // Configure listener with raw values + l := &Listener{ + RedactAddressesRaw: tc.rawRedactAddresses, + RedactClusterNameRaw: tc.rawRedactClusterName, + RedactVersionRaw: tc.rawRedactVersion, + } + + err := l.parseRedactionSettings() + + switch { + case tc.isErrorExpected: + require.Error(t, err) + require.ErrorContains(t, err, tc.errorMessage) + default: + // Assert we got the relevant values. + require.NoError(t, err) + require.Equal(t, tc.expectedRedactAddresses, l.RedactAddresses) + require.Equal(t, tc.expectedRedactClusterName, l.RedactClusterName) + require.Equal(t, tc.expectedRedactVersion, l.RedactVersion) + + // Ensure the state was modified for the raw values. + require.Nil(t, l.RedactAddressesRaw) + require.Nil(t, l.RedactClusterNameRaw) + require.Nil(t, l.RedactVersionRaw) + } + }) + } +} From 8e24625ee0a79d2e37fcc3493a3eab163430ee6a Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Thu, 5 Oct 2023 18:05:29 +0100 Subject: [PATCH 02/13] sys seal redaction + test modification for default handler properties --- helper/testhelpers/teststorage/teststorage.go | 5 ++ http/events_test.go | 5 +- http/forwarded_for_test.go | 3 +- http/forwarding_test.go | 8 ++- http/handler.go | 4 +- http/options.go | 71 +++++++++++++++++++ http/sys_seal.go | 20 ++++-- vault/external_tests/misc/recovery_test.go | 7 +- 8 files changed, 111 insertions(+), 12 deletions(-) create mode 100644 http/options.go diff --git a/helper/testhelpers/teststorage/teststorage.go b/helper/testhelpers/teststorage/teststorage.go index 9c588078fab1..75431867a274 100644 --- a/helper/testhelpers/teststorage/teststorage.go +++ b/helper/testhelpers/teststorage/teststorage.go @@ -10,6 +10,8 @@ import ( "os" "time" + "github.com/hashicorp/vault/internalshared/configutil" + "github.com/hashicorp/go-hclog" logicalKv "github.com/hashicorp/vault-plugin-secrets-kv" "github.com/hashicorp/vault/audit" @@ -242,6 +244,9 @@ func ClusterSetup(conf *vault.CoreConfig, opts *vault.TestClusterOptions, setup } localOpts := vault.TestClusterOptions{ HandlerFunc: vaulthttp.Handler, + DefaultHandlerProperties: vault.HandlerProperties{ + ListenerConfig: &configutil.Listener{}, + }, } if opts != nil { localOpts = *opts diff --git a/http/events_test.go b/http/events_test.go index 1ae014364bea..55db98cbdf82 100644 --- a/http/events_test.go +++ b/http/events_test.go @@ -15,6 +15,8 @@ import ( "testing" "time" + "github.com/hashicorp/vault/internalshared/configutil" + "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-uuid" "github.com/hashicorp/vault/api" @@ -331,7 +333,8 @@ func TestCanForwardEventConnections(t *testing.T) { "nop": corehelpers.NoopAuditFactory(nil), }, }, &vault.TestClusterOptions{ - ClusterLayers: inmemCluster, + ClusterLayers: inmemCluster, + DefaultHandlerProperties: vault.HandlerProperties{ListenerConfig: &configutil.Listener{}}, }) cores := testCluster.Cores testCluster.Start() diff --git a/http/forwarded_for_test.go b/http/forwarded_for_test.go index c0409bab30f0..239e1f8843cf 100644 --- a/http/forwarded_for_test.go +++ b/http/forwarded_for_test.go @@ -49,7 +49,8 @@ func TestHandler_XForwardedFor(t *testing.T) { } cluster := vault.NewTestCluster(t, nil, &vault.TestClusterOptions{ - HandlerFunc: HandlerFunc(testHandler), + HandlerFunc: HandlerFunc(testHandler), + DefaultHandlerProperties: vault.HandlerProperties{ListenerConfig: &configutil.Listener{}}, }) cluster.Start() defer cluster.Cleanup() diff --git a/http/forwarding_test.go b/http/forwarding_test.go index c2fdfcb25646..1da639194439 100644 --- a/http/forwarding_test.go +++ b/http/forwarding_test.go @@ -17,6 +17,8 @@ import ( "testing" "time" + "github.com/hashicorp/vault/internalshared/configutil" + "golang.org/x/net/http2" cleanhttp "github.com/hashicorp/go-cleanhttp" @@ -38,7 +40,8 @@ func TestHTTP_Fallback_Bad_Address(t *testing.T) { } cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{ - HandlerFunc: Handler, + HandlerFunc: Handler, + DefaultHandlerProperties: vault.HandlerProperties{ListenerConfig: &configutil.Listener{}}, }) cluster.Start() defer cluster.Cleanup() @@ -86,7 +89,8 @@ func TestHTTP_Fallback_Disabled(t *testing.T) { } cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{ - HandlerFunc: Handler, + HandlerFunc: Handler, + DefaultHandlerProperties: vault.HandlerProperties{ListenerConfig: &configutil.Listener{}}, }) cluster.Start() defer cluster.Cleanup() diff --git a/http/handler.go b/http/handler.go index 735d2c9ffc44..0c501451789e 100644 --- a/http/handler.go +++ b/http/handler.go @@ -165,7 +165,9 @@ func handler(props *vault.HandlerProperties) http.Handler { mux.Handle("/v1/sys/host-info", handleLogicalNoForward(core)) mux.Handle("/v1/sys/init", handleSysInit(core)) - mux.Handle("/v1/sys/seal-status", handleSysSealStatus(core)) + mux.Handle("/v1/sys/seal-status", handleSysSealStatus(core, + WithRedactClusterName(props.ListenerConfig.RedactClusterName), + WithRedactVersion(props.ListenerConfig.RedactVersion))) mux.Handle("/v1/sys/seal-backend-status", handleSysSealBackendStatus(core)) mux.Handle("/v1/sys/seal", handleSysSeal(core)) mux.Handle("/v1/sys/step-down", handleRequestForwarding(core, handleSysStepDown(core))) diff --git a/http/options.go b/http/options.go new file mode 100644 index 000000000000..1af43c33cc9d --- /dev/null +++ b/http/options.go @@ -0,0 +1,71 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package http + +// Option is how options are passed as arguments. +type Option func(*options) error + +// options are used to represent configuration for http handlers. +type options struct { + withRedactionValue string + withRedactAddresses bool + withRedactClusterName bool + withRedactVersion bool +} + +// getDefaultOptions returns options with their default values. +func getDefaultOptions() options { + return options{ + withRedactionValue: "", // Redact using empty string. + } +} + +// getOpts applies each supplied Option and returns the fully configured options. +// Each Option is applied in the order it appears in the argument list, so it is +// possible to supply the same Option numerous times and the 'last write wins'. +func getOpts(opt ...Option) (options, error) { + opts := getDefaultOptions() + for _, o := range opt { + if o == nil { + continue + } + if err := o(&opts); err != nil { + return options{}, err + } + } + return opts, nil +} + +// WithRedactionValue provides an Option to represent the value used to redact +// values which require redaction. +func WithRedactionValue(r string) Option { + return func(o *options) error { + o.withRedactionValue = r + return nil + } +} + +// WithRedactAddresses provides an Option to represent whether redaction of addresses is required. +func WithRedactAddresses(r bool) Option { + return func(o *options) error { + o.withRedactAddresses = r + return nil + } +} + +// WithRedactClusterName provides an Option to represent whether redaction of cluster names is required. +func WithRedactClusterName(r bool) Option { + return func(o *options) error { + o.withRedactClusterName = r + return nil + } +} + +// WithRedactVersion provides an Option to represent whether redaction of version is required. +func WithRedactVersion(r bool) Option { + return func(o *options) error { + o.withRedactVersion = r + return nil + } +} diff --git a/http/sys_seal.go b/http/sys_seal.go index 6dc69b844711..5d5c107432df 100644 --- a/http/sys_seal.go +++ b/http/sys_seal.go @@ -98,7 +98,7 @@ func handleSysUnseal(core *vault.Core) http.Handler { return } core.ResetUnsealProcess() - handleSysSealStatusRaw(core, w, r) + handleSysSealStatusRaw(core, w) return } @@ -148,18 +148,18 @@ func handleSysUnseal(core *vault.Core) http.Handler { } // Return the seal status - handleSysSealStatusRaw(core, w, r) + handleSysSealStatusRaw(core, w) }) } -func handleSysSealStatus(core *vault.Core) http.Handler { +func handleSysSealStatus(core *vault.Core, opt ...Option) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { respondError(w, http.StatusMethodNotAllowed, nil) return } - handleSysSealStatusRaw(core, w, r) + handleSysSealStatusRaw(core, w, opt...) }) } @@ -174,7 +174,7 @@ func handleSysSealBackendStatus(core *vault.Core) http.Handler { }) } -func handleSysSealStatusRaw(core *vault.Core, w http.ResponseWriter, r *http.Request) { +func handleSysSealStatusRaw(core *vault.Core, w http.ResponseWriter, opt ...Option) { ctx := context.Background() status, err := core.GetSealStatus(ctx) if err != nil { @@ -182,6 +182,16 @@ func handleSysSealStatusRaw(core *vault.Core, w http.ResponseWriter, r *http.Req return } + opts, err := getOpts(opt...) + + if opts.withRedactVersion { + status.Version = opts.withRedactionValue + } + + if opts.withRedactClusterName { + status.ClusterName = opts.withRedactionValue + } + respondOk(w, status) } diff --git a/vault/external_tests/misc/recovery_test.go b/vault/external_tests/misc/recovery_test.go index 5939f282de6b..96ac9e01ea9d 100644 --- a/vault/external_tests/misc/recovery_test.go +++ b/vault/external_tests/misc/recovery_test.go @@ -7,6 +7,8 @@ import ( "path" "testing" + "github.com/hashicorp/vault/internalshared/configutil" + "github.com/go-test/deep" "github.com/hashicorp/vault/helper/testhelpers" "github.com/hashicorp/vault/helper/testhelpers/corehelpers" @@ -77,8 +79,9 @@ func TestRecovery(t *testing.T) { NumCores: 1, SkipInit: true, DefaultHandlerProperties: vault.HandlerProperties{ - RecoveryMode: true, - RecoveryToken: &tokenRef, + RecoveryMode: true, + RecoveryToken: &tokenRef, + ListenerConfig: &configutil.Listener{}, }, } cluster := vault.NewTestCluster(t, &conf, &opts) From ea64159ea89e07f742e2ff6fdda5a5b17012a1ce Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Thu, 5 Oct 2023 20:11:35 +0100 Subject: [PATCH 03/13] build date should be redacted by 'redact_version' too --- http/sys_seal.go | 1 + 1 file changed, 1 insertion(+) diff --git a/http/sys_seal.go b/http/sys_seal.go index 5d5c107432df..f04cb0462617 100644 --- a/http/sys_seal.go +++ b/http/sys_seal.go @@ -186,6 +186,7 @@ func handleSysSealStatusRaw(core *vault.Core, w http.ResponseWriter, opt ...Opti if opts.withRedactVersion { status.Version = opts.withRedactionValue + status.BuildDate = opts.withRedactionValue } if opts.withRedactClusterName { From 5656c3828949dc83879ea7e589748a549fc5bf28 Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Thu, 5 Oct 2023 20:32:46 +0100 Subject: [PATCH 04/13] sys-health redaction + test fiddling --- helper/testhelpers/teststorage/teststorage.go | 5 ----- http/events_test.go | 5 +---- http/forwarded_for_test.go | 3 +-- http/forwarding_test.go | 8 ++------ http/handler.go | 4 +++- http/handler_test.go | 3 +++ http/sys_health.go | 16 +++++++++++++--- vault/external_tests/misc/recovery_test.go | 7 ++----- vault/testing.go | 7 +++++++ 9 files changed, 32 insertions(+), 26 deletions(-) diff --git a/helper/testhelpers/teststorage/teststorage.go b/helper/testhelpers/teststorage/teststorage.go index 75431867a274..9c588078fab1 100644 --- a/helper/testhelpers/teststorage/teststorage.go +++ b/helper/testhelpers/teststorage/teststorage.go @@ -10,8 +10,6 @@ import ( "os" "time" - "github.com/hashicorp/vault/internalshared/configutil" - "github.com/hashicorp/go-hclog" logicalKv "github.com/hashicorp/vault-plugin-secrets-kv" "github.com/hashicorp/vault/audit" @@ -244,9 +242,6 @@ func ClusterSetup(conf *vault.CoreConfig, opts *vault.TestClusterOptions, setup } localOpts := vault.TestClusterOptions{ HandlerFunc: vaulthttp.Handler, - DefaultHandlerProperties: vault.HandlerProperties{ - ListenerConfig: &configutil.Listener{}, - }, } if opts != nil { localOpts = *opts diff --git a/http/events_test.go b/http/events_test.go index 55db98cbdf82..1ae014364bea 100644 --- a/http/events_test.go +++ b/http/events_test.go @@ -15,8 +15,6 @@ import ( "testing" "time" - "github.com/hashicorp/vault/internalshared/configutil" - "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-uuid" "github.com/hashicorp/vault/api" @@ -333,8 +331,7 @@ func TestCanForwardEventConnections(t *testing.T) { "nop": corehelpers.NoopAuditFactory(nil), }, }, &vault.TestClusterOptions{ - ClusterLayers: inmemCluster, - DefaultHandlerProperties: vault.HandlerProperties{ListenerConfig: &configutil.Listener{}}, + ClusterLayers: inmemCluster, }) cores := testCluster.Cores testCluster.Start() diff --git a/http/forwarded_for_test.go b/http/forwarded_for_test.go index 239e1f8843cf..c0409bab30f0 100644 --- a/http/forwarded_for_test.go +++ b/http/forwarded_for_test.go @@ -49,8 +49,7 @@ func TestHandler_XForwardedFor(t *testing.T) { } cluster := vault.NewTestCluster(t, nil, &vault.TestClusterOptions{ - HandlerFunc: HandlerFunc(testHandler), - DefaultHandlerProperties: vault.HandlerProperties{ListenerConfig: &configutil.Listener{}}, + HandlerFunc: HandlerFunc(testHandler), }) cluster.Start() defer cluster.Cleanup() diff --git a/http/forwarding_test.go b/http/forwarding_test.go index 1da639194439..c2fdfcb25646 100644 --- a/http/forwarding_test.go +++ b/http/forwarding_test.go @@ -17,8 +17,6 @@ import ( "testing" "time" - "github.com/hashicorp/vault/internalshared/configutil" - "golang.org/x/net/http2" cleanhttp "github.com/hashicorp/go-cleanhttp" @@ -40,8 +38,7 @@ func TestHTTP_Fallback_Bad_Address(t *testing.T) { } cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{ - HandlerFunc: Handler, - DefaultHandlerProperties: vault.HandlerProperties{ListenerConfig: &configutil.Listener{}}, + HandlerFunc: Handler, }) cluster.Start() defer cluster.Cleanup() @@ -89,8 +86,7 @@ func TestHTTP_Fallback_Disabled(t *testing.T) { } cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{ - HandlerFunc: Handler, - DefaultHandlerProperties: vault.HandlerProperties{ListenerConfig: &configutil.Listener{}}, + HandlerFunc: Handler, }) cluster.Start() defer cluster.Cleanup() diff --git a/http/handler.go b/http/handler.go index 0c501451789e..0ef5a123fea8 100644 --- a/http/handler.go +++ b/http/handler.go @@ -173,7 +173,9 @@ func handler(props *vault.HandlerProperties) http.Handler { mux.Handle("/v1/sys/step-down", handleRequestForwarding(core, handleSysStepDown(core))) mux.Handle("/v1/sys/unseal", handleSysUnseal(core)) mux.Handle("/v1/sys/leader", handleSysLeader(core)) - mux.Handle("/v1/sys/health", handleSysHealth(core)) + mux.Handle("/v1/sys/health", handleSysHealth(core, + WithRedactClusterName(props.ListenerConfig.RedactClusterName), + WithRedactVersion(props.ListenerConfig.RedactVersion))) mux.Handle("/v1/sys/monitor", handleLogicalNoForward(core)) mux.Handle("/v1/sys/generate-root/attempt", handleRequestForwarding(core, handleAuditNonLogical(core, handleSysGenerateRootAttempt(core, vault.GenerateStandardRootTokenStrategy)))) diff --git a/http/handler_test.go b/http/handler_test.go index 039ffb08e274..a669672b60fb 100644 --- a/http/handler_test.go +++ b/http/handler_test.go @@ -17,6 +17,8 @@ import ( "strings" "testing" + "github.com/hashicorp/vault/internalshared/configutil" + "github.com/go-test/deep" "github.com/hashicorp/go-cleanhttp" "github.com/hashicorp/vault/helper/namespace" @@ -806,6 +808,7 @@ func testNonPrintable(t *testing.T, disable bool) { props := &vault.HandlerProperties{ Core: core, DisablePrintableCheck: disable, + ListenerConfig: &configutil.Listener{}, } TestServerWithListenerAndProperties(t, ln, addr, core, props) defer ln.Close() diff --git a/http/sys_health.go b/http/sys_health.go index 65dbb051f43d..6e27afb90d77 100644 --- a/http/sys_health.go +++ b/http/sys_health.go @@ -17,11 +17,11 @@ import ( "github.com/hashicorp/vault/version" ) -func handleSysHealth(core *vault.Core) http.Handler { +func handleSysHealth(core *vault.Core, opt ...Option) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": - handleSysHealthGet(core, w, r) + handleSysHealthGet(core, w, r, opt...) case "HEAD": handleSysHealthHead(core, w, r) default: @@ -43,7 +43,7 @@ func fetchStatusCode(r *http.Request, field string) (int, bool, bool) { return statusCode, false, true } -func handleSysHealthGet(core *vault.Core, w http.ResponseWriter, r *http.Request) { +func handleSysHealthGet(core *vault.Core, w http.ResponseWriter, r *http.Request, opt ...Option) { code, body, err := getSysHealth(core, r) if err != nil { core.Logger().Error("error checking health", "error", err) @@ -56,6 +56,16 @@ func handleSysHealthGet(core *vault.Core, w http.ResponseWriter, r *http.Request return } + opts, err := getOpts(opt...) + + if opts.withRedactVersion { + body.Version = opts.withRedactionValue + } + + if opts.withRedactClusterName { + body.ClusterName = opts.withRedactionValue + } + w.Header().Set("Content-Type", "application/json") w.WriteHeader(code) diff --git a/vault/external_tests/misc/recovery_test.go b/vault/external_tests/misc/recovery_test.go index 96ac9e01ea9d..5939f282de6b 100644 --- a/vault/external_tests/misc/recovery_test.go +++ b/vault/external_tests/misc/recovery_test.go @@ -7,8 +7,6 @@ import ( "path" "testing" - "github.com/hashicorp/vault/internalshared/configutil" - "github.com/go-test/deep" "github.com/hashicorp/vault/helper/testhelpers" "github.com/hashicorp/vault/helper/testhelpers/corehelpers" @@ -79,9 +77,8 @@ func TestRecovery(t *testing.T) { NumCores: 1, SkipInit: true, DefaultHandlerProperties: vault.HandlerProperties{ - RecoveryMode: true, - RecoveryToken: &tokenRef, - ListenerConfig: &configutil.Listener{}, + RecoveryMode: true, + RecoveryToken: &tokenRef, }, } cluster := vault.NewTestCluster(t, &conf, &opts) diff --git a/vault/testing.go b/vault/testing.go index ba612eae50df..59eb8f724b44 100644 --- a/vault/testing.go +++ b/vault/testing.go @@ -1279,6 +1279,13 @@ type certInfo struct { func NewTestCluster(t testing.T, base *CoreConfig, opts *TestClusterOptions) *TestCluster { var err error + if opts == nil { + opts = &TestClusterOptions{} + } + if opts.DefaultHandlerProperties.ListenerConfig == nil { + opts.DefaultHandlerProperties.ListenerConfig = &configutil.Listener{} + } + var numCores int if opts == nil || opts.NumCores == 0 { numCores = DefaultNumCores From 144143a8ec24d236050ae28ca902ae4aa9e508f3 Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Thu, 5 Oct 2023 20:38:10 +0100 Subject: [PATCH 05/13] sys-leader redaction --- http/handler.go | 3 ++- http/sys_leader.go | 13 ++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/http/handler.go b/http/handler.go index 0ef5a123fea8..ac8258eca89f 100644 --- a/http/handler.go +++ b/http/handler.go @@ -172,7 +172,8 @@ func handler(props *vault.HandlerProperties) http.Handler { mux.Handle("/v1/sys/seal", handleSysSeal(core)) mux.Handle("/v1/sys/step-down", handleRequestForwarding(core, handleSysStepDown(core))) mux.Handle("/v1/sys/unseal", handleSysUnseal(core)) - mux.Handle("/v1/sys/leader", handleSysLeader(core)) + mux.Handle("/v1/sys/leader", handleSysLeader(core, + WithRedactAddresses(props.ListenerConfig.RedactAddresses))) mux.Handle("/v1/sys/health", handleSysHealth(core, WithRedactClusterName(props.ListenerConfig.RedactClusterName), WithRedactVersion(props.ListenerConfig.RedactVersion))) diff --git a/http/sys_leader.go b/http/sys_leader.go index 7a14164f4be7..474db1561ec9 100644 --- a/http/sys_leader.go +++ b/http/sys_leader.go @@ -11,22 +11,29 @@ import ( // This endpoint is needed to answer queries before Vault unseals // or becomes the leader. -func handleSysLeader(core *vault.Core) http.Handler { +func handleSysLeader(core *vault.Core, opt ...Option) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": - handleSysLeaderGet(core, w, r) + handleSysLeaderGet(core, w, opt...) default: respondError(w, http.StatusMethodNotAllowed, nil) } }) } -func handleSysLeaderGet(core *vault.Core, w http.ResponseWriter, r *http.Request) { +func handleSysLeaderGet(core *vault.Core, w http.ResponseWriter, opt ...Option) { resp, err := core.GetLeaderStatus() if err != nil { respondError(w, http.StatusInternalServerError, err) return } + + opts, err := getOpts(opt...) + if opts.withRedactAddresses { + resp.LeaderAddress = opts.withRedactionValue + resp.LeaderClusterAddress = opts.withRedactionValue + } + respondOk(w, resp) } From 7a262222774dac579936b8cdd413555b9ef420ce Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Thu, 5 Oct 2023 20:51:43 +0100 Subject: [PATCH 06/13] added changelog --- changelog/23534.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 changelog/23534.txt diff --git a/changelog/23534.txt b/changelog/23534.txt new file mode 100644 index 000000000000..c5231594e1cc --- /dev/null +++ b/changelog/23534.txt @@ -0,0 +1,3 @@ +```release-note:improvement +config/listener: allow per-listener configuration settings to redact parts of response to unauthenticated endpoints. +``` \ No newline at end of file From ecbec32c01a4d63fe2eefb43b30b654e5cfc04df Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Thu, 5 Oct 2023 22:00:02 +0100 Subject: [PATCH 07/13] Lots of places need ListenerConfig --- command/server.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/command/server.go b/command/server.go index 855c7a628aee..bc29a999f7e0 100644 --- a/command/server.go +++ b/command/server.go @@ -1529,7 +1529,8 @@ func (c *ServerCommand) Run(args []string) int { // mode if it's set core.SetClusterListenerAddrs(clusterAddrs) core.SetClusterHandler(vaulthttp.Handler.Handler(&vault.HandlerProperties{ - Core: core, + Core: core, + ListenerConfig: &configutil.Listener{}, })) // Attempt unsealing in a background goroutine. This is needed for when a From 990779e297ffd671cf52a06c0f8bcbcbc1c6ccb6 Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Thu, 5 Oct 2023 22:04:50 +0100 Subject: [PATCH 08/13] Renamed options to something more specific for now --- http/options.go | 48 +++++++++++++++++++++++----------------------- http/sys_health.go | 4 ++-- http/sys_leader.go | 4 ++-- http/sys_seal.go | 4 ++-- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/http/options.go b/http/options.go index 1af43c33cc9d..864618c56e1b 100644 --- a/http/options.go +++ b/http/options.go @@ -3,68 +3,68 @@ package http -// Option is how options are passed as arguments. -type Option func(*options) error +// ListenerConfigOption is how listenerConfigOptions are passed as arguments. +type ListenerConfigOption func(*listenerConfigOptions) error -// options are used to represent configuration for http handlers. -type options struct { +// listenerConfigOptions are used to represent configuration of listeners for http handlers. +type listenerConfigOptions struct { withRedactionValue string withRedactAddresses bool withRedactClusterName bool withRedactVersion bool } -// getDefaultOptions returns options with their default values. -func getDefaultOptions() options { - return options{ +// getDefaultOptions returns listenerConfigOptions with their default values. +func getDefaultOptions() listenerConfigOptions { + return listenerConfigOptions{ withRedactionValue: "", // Redact using empty string. } } -// getOpts applies each supplied Option and returns the fully configured options. -// Each Option is applied in the order it appears in the argument list, so it is -// possible to supply the same Option numerous times and the 'last write wins'. -func getOpts(opt ...Option) (options, error) { +// getOpts applies each supplied ListenerConfigOption and returns the fully configured listenerConfigOptions. +// Each ListenerConfigOption is applied in the order it appears in the argument list, so it is +// possible to supply the same ListenerConfigOption numerous times and the 'last write wins'. +func getOpts(opt ...ListenerConfigOption) (listenerConfigOptions, error) { opts := getDefaultOptions() for _, o := range opt { if o == nil { continue } if err := o(&opts); err != nil { - return options{}, err + return listenerConfigOptions{}, err } } return opts, nil } -// WithRedactionValue provides an Option to represent the value used to redact +// WithRedactionValue provides an ListenerConfigOption to represent the value used to redact // values which require redaction. -func WithRedactionValue(r string) Option { - return func(o *options) error { +func WithRedactionValue(r string) ListenerConfigOption { + return func(o *listenerConfigOptions) error { o.withRedactionValue = r return nil } } -// WithRedactAddresses provides an Option to represent whether redaction of addresses is required. -func WithRedactAddresses(r bool) Option { - return func(o *options) error { +// WithRedactAddresses provides an ListenerConfigOption to represent whether redaction of addresses is required. +func WithRedactAddresses(r bool) ListenerConfigOption { + return func(o *listenerConfigOptions) error { o.withRedactAddresses = r return nil } } -// WithRedactClusterName provides an Option to represent whether redaction of cluster names is required. -func WithRedactClusterName(r bool) Option { - return func(o *options) error { +// WithRedactClusterName provides an ListenerConfigOption to represent whether redaction of cluster names is required. +func WithRedactClusterName(r bool) ListenerConfigOption { + return func(o *listenerConfigOptions) error { o.withRedactClusterName = r return nil } } -// WithRedactVersion provides an Option to represent whether redaction of version is required. -func WithRedactVersion(r bool) Option { - return func(o *options) error { +// WithRedactVersion provides an ListenerConfigOption to represent whether redaction of version is required. +func WithRedactVersion(r bool) ListenerConfigOption { + return func(o *listenerConfigOptions) error { o.withRedactVersion = r return nil } diff --git a/http/sys_health.go b/http/sys_health.go index 6e27afb90d77..99edb95caff7 100644 --- a/http/sys_health.go +++ b/http/sys_health.go @@ -17,7 +17,7 @@ import ( "github.com/hashicorp/vault/version" ) -func handleSysHealth(core *vault.Core, opt ...Option) http.Handler { +func handleSysHealth(core *vault.Core, opt ...ListenerConfigOption) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": @@ -43,7 +43,7 @@ func fetchStatusCode(r *http.Request, field string) (int, bool, bool) { return statusCode, false, true } -func handleSysHealthGet(core *vault.Core, w http.ResponseWriter, r *http.Request, opt ...Option) { +func handleSysHealthGet(core *vault.Core, w http.ResponseWriter, r *http.Request, opt ...ListenerConfigOption) { code, body, err := getSysHealth(core, r) if err != nil { core.Logger().Error("error checking health", "error", err) diff --git a/http/sys_leader.go b/http/sys_leader.go index 474db1561ec9..c0c0cfd7d851 100644 --- a/http/sys_leader.go +++ b/http/sys_leader.go @@ -11,7 +11,7 @@ import ( // This endpoint is needed to answer queries before Vault unseals // or becomes the leader. -func handleSysLeader(core *vault.Core, opt ...Option) http.Handler { +func handleSysLeader(core *vault.Core, opt ...ListenerConfigOption) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": @@ -22,7 +22,7 @@ func handleSysLeader(core *vault.Core, opt ...Option) http.Handler { }) } -func handleSysLeaderGet(core *vault.Core, w http.ResponseWriter, opt ...Option) { +func handleSysLeaderGet(core *vault.Core, w http.ResponseWriter, opt ...ListenerConfigOption) { resp, err := core.GetLeaderStatus() if err != nil { respondError(w, http.StatusInternalServerError, err) diff --git a/http/sys_seal.go b/http/sys_seal.go index f04cb0462617..4448d9b2c0c7 100644 --- a/http/sys_seal.go +++ b/http/sys_seal.go @@ -152,7 +152,7 @@ func handleSysUnseal(core *vault.Core) http.Handler { }) } -func handleSysSealStatus(core *vault.Core, opt ...Option) http.Handler { +func handleSysSealStatus(core *vault.Core, opt ...ListenerConfigOption) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { respondError(w, http.StatusMethodNotAllowed, nil) @@ -174,7 +174,7 @@ func handleSysSealBackendStatus(core *vault.Core) http.Handler { }) } -func handleSysSealStatusRaw(core *vault.Core, w http.ResponseWriter, opt ...Option) { +func handleSysSealStatusRaw(core *vault.Core, w http.ResponseWriter, opt ...ListenerConfigOption) { ctx := context.Background() status, err := core.GetSealStatus(ctx) if err != nil { From a01cd2dc25d2da75741a53992ea3b36f3046ead4 Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Fri, 6 Oct 2023 11:48:28 +0100 Subject: [PATCH 09/13] tests for listener config options --- http/options_test.go | 183 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 http/options_test.go diff --git a/http/options_test.go b/http/options_test.go new file mode 100644 index 000000000000..2c2a961ba527 --- /dev/null +++ b/http/options_test.go @@ -0,0 +1,183 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package http + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +// TestOptions_Default ensures that the default values are as expected. +func TestOptions_Default(t *testing.T) { + opts := getDefaultOptions() + require.NotNil(t, opts) + require.Equal(t, "", opts.withRedactionValue) +} + +// TestOptions_WithRedactionValue ensures that we set the correct value to use for +// redaction when required. +func TestOptions_WithRedactionValue(t *testing.T) { + t.Parallel() + + tests := map[string]struct { + Value string + ExpectedValue string + IsErrorExpected bool + }{ + "empty": { + Value: "", + ExpectedValue: "", + IsErrorExpected: false, + }, + "whitespace": { + Value: " ", + ExpectedValue: " ", + IsErrorExpected: false, + }, + "value": { + Value: "*****", + ExpectedValue: "*****", + IsErrorExpected: false, + }, + } + + for name, tc := range tests { + name := name + tc := tc + t.Run(name, func(t *testing.T) { + t.Parallel() + opts := &listenerConfigOptions{} + applyOption := WithRedactionValue(tc.Value) + err := applyOption(opts) + switch { + case tc.IsErrorExpected: + require.Error(t, err) + default: + require.NoError(t, err) + require.Equal(t, tc.ExpectedValue, opts.withRedactionValue) + } + }) + } +} + +// TestOptions_WithRedactAddresses ensures that the option works as intended. +func TestOptions_WithRedactAddresses(t *testing.T) { + t.Parallel() + + tests := map[string]struct { + Value bool + ExpectedValue bool + IsErrorExpected bool + }{ + "true": { + Value: true, + ExpectedValue: true, + IsErrorExpected: false, + }, + "false": { + Value: false, + ExpectedValue: false, + IsErrorExpected: false, + }, + } + + for name, tc := range tests { + name := name + tc := tc + t.Run(name, func(t *testing.T) { + t.Parallel() + opts := &listenerConfigOptions{} + applyOption := WithRedactAddresses(tc.Value) + err := applyOption(opts) + switch { + case tc.IsErrorExpected: + require.Error(t, err) + default: + require.NoError(t, err) + require.Equal(t, tc.ExpectedValue, opts.withRedactAddresses) + } + }) + } +} + +// TestOptions_WithRedactClusterName ensures that the option works as intended. +func TestOptions_WithRedactClusterName(t *testing.T) { + t.Parallel() + + tests := map[string]struct { + Value bool + ExpectedValue bool + IsErrorExpected bool + }{ + "true": { + Value: true, + ExpectedValue: true, + IsErrorExpected: false, + }, + "false": { + Value: false, + ExpectedValue: false, + IsErrorExpected: false, + }, + } + + for name, tc := range tests { + name := name + tc := tc + t.Run(name, func(t *testing.T) { + t.Parallel() + opts := &listenerConfigOptions{} + applyOption := WithRedactClusterName(tc.Value) + err := applyOption(opts) + switch { + case tc.IsErrorExpected: + require.Error(t, err) + default: + require.NoError(t, err) + require.Equal(t, tc.ExpectedValue, opts.withRedactClusterName) + } + }) + } +} + +// TestOptions_WithRedactVersion ensures that the option works as intended. +func TestOptions_WithRedactVersion(t *testing.T) { + t.Parallel() + + tests := map[string]struct { + Value bool + ExpectedValue bool + IsErrorExpected bool + }{ + "true": { + Value: true, + ExpectedValue: true, + IsErrorExpected: false, + }, + "false": { + Value: false, + ExpectedValue: false, + IsErrorExpected: false, + }, + } + + for name, tc := range tests { + name := name + tc := tc + t.Run(name, func(t *testing.T) { + t.Parallel() + opts := &listenerConfigOptions{} + applyOption := WithRedactVersion(tc.Value) + err := applyOption(opts) + switch { + case tc.IsErrorExpected: + require.Error(t, err) + default: + require.NoError(t, err) + require.Equal(t, tc.ExpectedValue, opts.withRedactVersion) + } + }) + } +} From cd5849e57228518e4e84407648b21ea9cac765a5 Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Fri, 6 Oct 2023 15:17:02 +0100 Subject: [PATCH 10/13] changelog updated --- changelog/23534.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/23534.txt b/changelog/23534.txt index c5231594e1cc..aef3e4024d58 100644 --- a/changelog/23534.txt +++ b/changelog/23534.txt @@ -1,3 +1,3 @@ ```release-note:improvement -config/listener: allow per-listener configuration settings to redact parts of response to unauthenticated endpoints. +config/listener: allow per-listener configuration settings to redact sensitive parts of response to unauthenticated endpoints. ``` \ No newline at end of file From e0c80fb427be715630630e835020da7c33bfac84 Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Fri, 6 Oct 2023 15:44:10 +0100 Subject: [PATCH 11/13] updates based on PR comments --- changelog/23534.txt | 2 +- http/options.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog/23534.txt b/changelog/23534.txt index aef3e4024d58..5f101cb18a75 100644 --- a/changelog/23534.txt +++ b/changelog/23534.txt @@ -1,3 +1,3 @@ -```release-note:improvement +```release-note:feature config/listener: allow per-listener configuration settings to redact sensitive parts of response to unauthenticated endpoints. ``` \ No newline at end of file diff --git a/http/options.go b/http/options.go index 864618c56e1b..b1200c018e72 100644 --- a/http/options.go +++ b/http/options.go @@ -17,7 +17,7 @@ type listenerConfigOptions struct { // getDefaultOptions returns listenerConfigOptions with their default values. func getDefaultOptions() listenerConfigOptions { return listenerConfigOptions{ - withRedactionValue: "", // Redact using empty string. + withRedactionValue: "", // Redacted values will be set to an empty string by default. } } From 12a11a7c40ccf7244bf99849833df5f2f5ec10c0 Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Fri, 6 Oct 2023 16:05:47 +0100 Subject: [PATCH 12/13] updates based on PR comments - removed unrequired test case field --- http/options_test.go | 72 +++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 48 deletions(-) diff --git a/http/options_test.go b/http/options_test.go index 2c2a961ba527..cee30c85c19e 100644 --- a/http/options_test.go +++ b/http/options_test.go @@ -67,19 +67,16 @@ func TestOptions_WithRedactAddresses(t *testing.T) { t.Parallel() tests := map[string]struct { - Value bool - ExpectedValue bool - IsErrorExpected bool + Value bool + ExpectedValue bool }{ "true": { - Value: true, - ExpectedValue: true, - IsErrorExpected: false, + Value: true, + ExpectedValue: true, }, "false": { - Value: false, - ExpectedValue: false, - IsErrorExpected: false, + Value: false, + ExpectedValue: false, }, } @@ -91,13 +88,8 @@ func TestOptions_WithRedactAddresses(t *testing.T) { opts := &listenerConfigOptions{} applyOption := WithRedactAddresses(tc.Value) err := applyOption(opts) - switch { - case tc.IsErrorExpected: - require.Error(t, err) - default: - require.NoError(t, err) - require.Equal(t, tc.ExpectedValue, opts.withRedactAddresses) - } + require.NoError(t, err) + require.Equal(t, tc.ExpectedValue, opts.withRedactAddresses) }) } } @@ -107,19 +99,16 @@ func TestOptions_WithRedactClusterName(t *testing.T) { t.Parallel() tests := map[string]struct { - Value bool - ExpectedValue bool - IsErrorExpected bool + Value bool + ExpectedValue bool }{ "true": { - Value: true, - ExpectedValue: true, - IsErrorExpected: false, + Value: true, + ExpectedValue: true, }, "false": { - Value: false, - ExpectedValue: false, - IsErrorExpected: false, + Value: false, + ExpectedValue: false, }, } @@ -131,13 +120,8 @@ func TestOptions_WithRedactClusterName(t *testing.T) { opts := &listenerConfigOptions{} applyOption := WithRedactClusterName(tc.Value) err := applyOption(opts) - switch { - case tc.IsErrorExpected: - require.Error(t, err) - default: - require.NoError(t, err) - require.Equal(t, tc.ExpectedValue, opts.withRedactClusterName) - } + require.NoError(t, err) + require.Equal(t, tc.ExpectedValue, opts.withRedactClusterName) }) } } @@ -147,19 +131,16 @@ func TestOptions_WithRedactVersion(t *testing.T) { t.Parallel() tests := map[string]struct { - Value bool - ExpectedValue bool - IsErrorExpected bool + Value bool + ExpectedValue bool }{ "true": { - Value: true, - ExpectedValue: true, - IsErrorExpected: false, + Value: true, + ExpectedValue: true, }, "false": { - Value: false, - ExpectedValue: false, - IsErrorExpected: false, + Value: false, + ExpectedValue: false, }, } @@ -171,13 +152,8 @@ func TestOptions_WithRedactVersion(t *testing.T) { opts := &listenerConfigOptions{} applyOption := WithRedactVersion(tc.Value) err := applyOption(opts) - switch { - case tc.IsErrorExpected: - require.Error(t, err) - default: - require.NoError(t, err) - require.Equal(t, tc.ExpectedValue, opts.withRedactVersion) - } + require.NoError(t, err) + require.Equal(t, tc.ExpectedValue, opts.withRedactVersion) }) } } From e994bee6e910899018cf1afa7c7eb396d72f41cd Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Fri, 6 Oct 2023 17:21:08 +0100 Subject: [PATCH 13/13] fixes for docker tests and potentially server dev mode related flags --- command/server.go | 3 ++- vault/testing.go | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/command/server.go b/command/server.go index 12567a0028f5..cf5b18bbff1f 100644 --- a/command/server.go +++ b/command/server.go @@ -2162,7 +2162,8 @@ func (c *ServerCommand) enableThreeNodeDevCluster(base *vault.CoreConfig, info m for _, core := range testCluster.Cores { core.Server.Handler = vaulthttp.Handler.Handler(&vault.HandlerProperties{ - Core: core.Core, + Core: core.Core, + ListenerConfig: &configutil.Listener{}, }) core.SetClusterHandler(core.Server.Handler) } diff --git a/vault/testing.go b/vault/testing.go index 59eb8f724b44..25c1bf71ed65 100644 --- a/vault/testing.go +++ b/vault/testing.go @@ -1303,7 +1303,7 @@ func NewTestCluster(t testing.T, base *CoreConfig, opts *TestClusterOptions) *Te testCluster.base = base switch { - case opts != nil && opts.Logger != nil: + case opts != nil && opts.Logger != nil && !reflect.ValueOf(opts.Logger).IsNil(): testCluster.Logger = opts.Logger default: testCluster.Logger = corehelpers.NewTestLogger(t) @@ -1317,7 +1317,7 @@ func NewTestCluster(t testing.T, base *CoreConfig, opts *TestClusterOptions) *Te } testCluster.TempDir = opts.TempDir } else { - tempDir, err := ioutil.TempDir("", "vault-test-cluster-") + tempDir, err := os.MkdirTemp("", "vault-test-cluster-") if err != nil { t.Fatal(err) }