mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-29 01:32:33 +00:00
Add Ability to Disable Replication Status Endpoints in Listener Configuration (#23547)
* CI: Pre-emptively delete logs dir after cache restore in test-collect-reports (#23600) * Fix OktaNumberChallenge (#23565) * remove arg * changelog * exclude changelog in verifying doc/ui PRs (#23601) * Audit: eventlogger sink node reopen on SIGHUP (#23598) * ensure nodes are asked to reload audit files on SIGHUP * added changelog * Capture errors emitted from all nodes during proccessing of audit pipelines (#23582) * Update security-scan.yml * Listeners: Redaction only for TCP (#23592) * redaction should only work for TCP listeners, also fix bug that allowed custom response headers for unix listeners * fix failing test * updates from PR feedback * fix panic when unlocking unlocked user (#23611) * VAULT-18307: update rotation period for aws static roles on update (#23528) * add disable_replication_status_endpoints tcp listener config parameter * add wrapping handler for disabled replication status endpoints setting * adapt disable_replication_status_endpoints configuration parsing code to refactored parsing code * refactor configuration parsing code to facilitate testing * fix a panic when parsing configuration * update refactored configuration parsing code * fix merge corruption * add changelog file * document new TCP listener configuration parameter * make sure disable_replication_status_endpoints only has effect on TCP listeners * use active voice for explanation of disable_replication_status_endpoints * fix minor merge issue --------- Co-authored-by: Kuba Wieczorek <kuba.wieczorek@hashicorp.com> Co-authored-by: Angel Garbarino <Monkeychip@users.noreply.github.com> Co-authored-by: Hamid Ghaf <83242695+hghaf099@users.noreply.github.com> Co-authored-by: Peter Wilson <peter.wilson@hashicorp.com> Co-authored-by: Mark Collao <106274486+mcollao-hc@users.noreply.github.com> Co-authored-by: davidadeleon <56207066+davidadeleon@users.noreply.github.com> Co-authored-by: kpcraig <3031348+kpcraig@users.noreply.github.com>
This commit is contained in:
3
changelog/23547.txt
Normal file
3
changelog/23547.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
```release-note:feature
|
||||
config/listener: allow per-listener configuration setting to disable replication status endpoints.
|
||||
```
|
||||
@@ -237,20 +237,27 @@ func handler(props *vault.HandlerProperties) http.Handler {
|
||||
additionalRoutes(mux, core)
|
||||
}
|
||||
|
||||
// Wrap the handler in another handler to trigger all help paths.
|
||||
helpWrappedHandler := wrapHelpHandler(mux, core)
|
||||
corsWrappedHandler := wrapCORSHandler(helpWrappedHandler, core)
|
||||
quotaWrappedHandler := rateLimitQuotaWrapping(corsWrappedHandler, core)
|
||||
genericWrappedHandler := genericWrapping(core, quotaWrappedHandler, props)
|
||||
// Build up a chain of wrapping handlers.
|
||||
wrappedHandler := wrapHelpHandler(mux, core)
|
||||
wrappedHandler = wrapCORSHandler(wrappedHandler, core)
|
||||
wrappedHandler = rateLimitQuotaWrapping(wrappedHandler, core)
|
||||
wrappedHandler = genericWrapping(core, wrappedHandler, props)
|
||||
|
||||
// Wrap the handler with PrintablePathCheckHandler to check for non-printable
|
||||
// characters in the request path.
|
||||
printablePathCheckHandler := genericWrappedHandler
|
||||
// Add an extra wrapping handler if the DisablePrintableCheck listener
|
||||
// setting isn't true that checks for non-printable characters in the
|
||||
// request path.
|
||||
if !props.DisablePrintableCheck {
|
||||
printablePathCheckHandler = cleanhttp.PrintablePathCheckHandler(genericWrappedHandler, nil)
|
||||
wrappedHandler = cleanhttp.PrintablePathCheckHandler(wrappedHandler, nil)
|
||||
}
|
||||
|
||||
return printablePathCheckHandler
|
||||
// Add an extra wrapping handler if the DisableReplicationStatusEndpoints
|
||||
// setting is true that will create a new request with a context that has
|
||||
// a value indicating that the replication status endpoints are disabled.
|
||||
if props.ListenerConfig != nil && props.ListenerConfig.DisableReplicationStatusEndpoints {
|
||||
wrappedHandler = disableReplicationStatusEndpointWrapping(wrappedHandler)
|
||||
}
|
||||
|
||||
return wrappedHandler
|
||||
}
|
||||
|
||||
type copyResponseWriter struct {
|
||||
|
||||
@@ -133,6 +133,14 @@ func rateLimitQuotaWrapping(handler http.Handler, core *vault.Core) http.Handler
|
||||
})
|
||||
}
|
||||
|
||||
func disableReplicationStatusEndpointWrapping(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
request := r.WithContext(context.WithValue(r.Context(), "disable_replication_status_endpoints", true))
|
||||
|
||||
h.ServeHTTP(w, request)
|
||||
})
|
||||
}
|
||||
|
||||
func parseRemoteIPAddress(r *http.Request) string {
|
||||
ip, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||
if err != nil {
|
||||
|
||||
@@ -139,6 +139,10 @@ type Listener struct {
|
||||
RedactClusterName bool `hcl:"-"`
|
||||
RedactVersionRaw any `hcl:"redact_version"`
|
||||
RedactVersion bool `hcl:"-"`
|
||||
|
||||
// DisableReplicationStatusEndpoint disables the unauthenticated replication status endpoints
|
||||
DisableReplicationStatusEndpointsRaw interface{} `hcl:"disable_replication_status_endpoints"`
|
||||
DisableReplicationStatusEndpoints bool `hcl:"-"`
|
||||
}
|
||||
|
||||
// AgentAPI allows users to select which parts of the Agent API they want enabled.
|
||||
@@ -252,6 +256,7 @@ func parseListener(item *ast.ObjectItem) (*Listener, error) {
|
||||
l.parseHTTPHeaderSettings,
|
||||
l.parseChrootNamespaceSettings,
|
||||
l.parseRedactionSettings,
|
||||
l.parseDisableReplicationStatusEndpointSettings,
|
||||
} {
|
||||
err := parser()
|
||||
if err != nil {
|
||||
@@ -272,22 +277,114 @@ func (t ListenerType) String() string {
|
||||
return string(t.Normalize())
|
||||
}
|
||||
|
||||
// parseAndClearBool parses a raw setting as a bool configuration parameter. If
|
||||
// the raw value is successfully parsed, the parsedSetting argument is set to it
|
||||
// and the rawSetting argument is cleared. Otherwise, the rawSetting argument is
|
||||
// left unchanged and an error is returned.
|
||||
func parseAndClearBool(rawSetting *interface{}, parsedSetting *bool) error {
|
||||
var err error
|
||||
|
||||
if *rawSetting != nil {
|
||||
*parsedSetting, err = parseutil.ParseBool(*rawSetting)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*rawSetting = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseAndClearString parses a raw setting as a string configuration parameter.
|
||||
// If the raw value is successfully parsed, the parsedSetting argument is set to
|
||||
// it and the rawSetting argument is cleared. Otherwise, the rawSetting argument
|
||||
// is left unchanged and an error is returned.
|
||||
func parseAndClearString(rawSetting *interface{}, parsedSetting *string) error {
|
||||
var err error
|
||||
|
||||
if *rawSetting != nil {
|
||||
*parsedSetting, err = parseutil.ParseString(*rawSetting)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*rawSetting = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseAndClearInt parses a raw setting as an integer configuration parameter.
|
||||
// If the raw value is successfully parsed, the parsedSetting argument is set to
|
||||
// it and the rawSetting argument is cleared. Otherwise, the rawSetting argument
|
||||
// is left unchanged and an error is returned.
|
||||
func parseAndClearInt(rawSetting *interface{}, parsedSetting *int64) error {
|
||||
var err error
|
||||
|
||||
if *rawSetting != nil {
|
||||
*parsedSetting, err = parseutil.ParseInt(*rawSetting)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*rawSetting = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseAndClearDurationSecond parses a raw setting as a time duration
|
||||
// configuration parameter. If the raw value is successfully parsed, the
|
||||
// parsedSetting argument is set to it and the rawSetting argument is cleared.
|
||||
// Otherwise, the rawSetting argument is left unchanged and an error is
|
||||
// returned.
|
||||
func parseAndClearDurationSecond(rawSetting *interface{}, parsedSetting *time.Duration) error {
|
||||
var err error
|
||||
|
||||
if *rawSetting != nil {
|
||||
*parsedSetting, err = parseutil.ParseDurationSecond(*rawSetting)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*rawSetting = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseDisableReplicationStatusEndpointSettings attempts to parse the raw
|
||||
// disable_replication_status_endpoints setting. The receiving Listener's
|
||||
// DisableReplicationStatusEndpoints field will be set with the successfully
|
||||
// parsed value.
|
||||
func (l *Listener) parseDisableReplicationStatusEndpointSettings() error {
|
||||
if l.Type != TCP {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := parseAndClearBool(&l.DisableReplicationStatusEndpointsRaw, &l.DisableReplicationStatusEndpoints); err != nil {
|
||||
return fmt.Errorf("invalid value for disable_replication_status_endpoints: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseChrootNamespace attempts to parse the raw listener chroot namespace settings.
|
||||
// The state of the listener will be modified, raw data will be cleared upon
|
||||
// successful parsing.
|
||||
func (l *Listener) parseChrootNamespaceSettings() error {
|
||||
var err error
|
||||
var (
|
||||
err error
|
||||
setting string
|
||||
)
|
||||
|
||||
// If a valid ChrootNamespace value exists, then canonicalize the namespace value
|
||||
if l.ChrootNamespaceRaw != nil {
|
||||
l.ChrootNamespace, err = parseutil.ParseString(l.ChrootNamespaceRaw)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid value for chroot_namespace: %w", err)
|
||||
}
|
||||
l.ChrootNamespace = namespace.Canonicalize(l.ChrootNamespace)
|
||||
err = parseAndClearString(&l.ChrootNamespaceRaw, &setting)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid value for chroot_namespace: %w", err)
|
||||
}
|
||||
|
||||
l.ChrootNamespaceRaw = nil
|
||||
l.ChrootNamespace = namespace.Canonicalize(setting)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -327,13 +424,8 @@ func (l *Listener) parseType(fallback string) error {
|
||||
// The state of the listener will be modified, raw data will be cleared upon
|
||||
// successful parsing.
|
||||
func (l *Listener) parseRequestSettings() error {
|
||||
if l.MaxRequestSizeRaw != nil {
|
||||
maxRequestSize, err := parseutil.ParseInt(l.MaxRequestSizeRaw)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing max_request_size: %w", err)
|
||||
}
|
||||
|
||||
l.MaxRequestSize = maxRequestSize
|
||||
if err := parseAndClearInt(&l.MaxRequestSizeRaw, &l.MaxRequestSize); err != nil {
|
||||
return fmt.Errorf("error parsing max_request_size: %w", err)
|
||||
}
|
||||
|
||||
if l.MaxRequestDurationRaw != nil {
|
||||
@@ -347,22 +439,13 @@ func (l *Listener) parseRequestSettings() error {
|
||||
}
|
||||
|
||||
l.MaxRequestDuration = maxRequestDuration
|
||||
l.MaxRequestDurationRaw = nil
|
||||
}
|
||||
|
||||
if l.RequireRequestHeaderRaw != nil {
|
||||
requireRequestHeader, err := parseutil.ParseBool(l.RequireRequestHeaderRaw)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid value for require_request_header: %w", err)
|
||||
}
|
||||
|
||||
l.RequireRequestHeader = requireRequestHeader
|
||||
if err := parseAndClearBool(&l.RequireRequestHeaderRaw, &l.RequireRequestHeader); err != nil {
|
||||
return fmt.Errorf("invalid value for require_request_header: %w", err)
|
||||
}
|
||||
|
||||
// Clear raw values after successful parsing.
|
||||
l.MaxRequestSizeRaw = nil
|
||||
l.MaxRequestDurationRaw = nil
|
||||
l.RequireRequestHeaderRaw = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -370,12 +453,8 @@ func (l *Listener) parseRequestSettings() error {
|
||||
// The state of the listener will be modified, raw data will be cleared upon
|
||||
// successful parsing.
|
||||
func (l *Listener) parseTLSSettings() error {
|
||||
if l.TLSDisableRaw != nil {
|
||||
tlsDisable, err := parseutil.ParseBool(l.TLSDisableRaw)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid value for tls_disable: %w", err)
|
||||
}
|
||||
l.TLSDisable = tlsDisable
|
||||
if err := parseAndClearBool(&l.TLSDisableRaw, &l.TLSDisable); err != nil {
|
||||
return fmt.Errorf("invalid value for tls_disable: %w", err)
|
||||
}
|
||||
|
||||
if l.TLSCipherSuitesRaw != "" {
|
||||
@@ -386,27 +465,16 @@ func (l *Listener) parseTLSSettings() error {
|
||||
l.TLSCipherSuites = tlsCipherSuites
|
||||
}
|
||||
|
||||
if l.TLSRequireAndVerifyClientCertRaw != nil {
|
||||
tlsRequireAndVerifyClientCert, err := parseutil.ParseBool(l.TLSRequireAndVerifyClientCertRaw)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid value for tls_require_and_verify_client_cert: %w", err)
|
||||
}
|
||||
l.TLSRequireAndVerifyClientCert = tlsRequireAndVerifyClientCert
|
||||
if err := parseAndClearBool(&l.TLSRequireAndVerifyClientCertRaw, &l.TLSRequireAndVerifyClientCert); err != nil {
|
||||
return fmt.Errorf("invalid value for tls_require_and_verify_client_cert: %w", err)
|
||||
}
|
||||
|
||||
if l.TLSDisableClientCertsRaw != nil {
|
||||
tlsDisableClientCerts, err := parseutil.ParseBool(l.TLSDisableClientCertsRaw)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid value for tls_disable_client_certs: %w", err)
|
||||
}
|
||||
l.TLSDisableClientCerts = tlsDisableClientCerts
|
||||
if err := parseAndClearBool(&l.TLSDisableClientCertsRaw, &l.TLSDisableClientCerts); err != nil {
|
||||
return fmt.Errorf("invalid value for tls_disable_client_certs: %w", err)
|
||||
}
|
||||
|
||||
// Clear raw values after successful parsing.
|
||||
l.TLSDisableRaw = nil
|
||||
l.TLSCipherSuitesRaw = ""
|
||||
l.TLSRequireAndVerifyClientCertRaw = nil
|
||||
l.TLSDisableClientCertsRaw = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -438,38 +506,22 @@ func (l *Listener) parseHTTPHeaderSettings() error {
|
||||
// The state of the listener will be modified, raw data will be cleared upon
|
||||
// successful parsing.
|
||||
func (l *Listener) parseHTTPTimeoutSettings() error {
|
||||
var err error
|
||||
|
||||
if l.HTTPReadTimeoutRaw != nil {
|
||||
if l.HTTPReadTimeout, err = parseutil.ParseDurationSecond(l.HTTPReadTimeoutRaw); err != nil {
|
||||
return fmt.Errorf("error parsing http_read_timeout: %w", err)
|
||||
}
|
||||
if err := parseAndClearDurationSecond(&l.HTTPReadTimeoutRaw, &l.HTTPReadTimeout); err != nil {
|
||||
return fmt.Errorf("error parsing http_read_timeout: %w", err)
|
||||
}
|
||||
|
||||
if l.HTTPReadHeaderTimeoutRaw != nil {
|
||||
if l.HTTPReadHeaderTimeout, err = parseutil.ParseDurationSecond(l.HTTPReadHeaderTimeoutRaw); err != nil {
|
||||
return fmt.Errorf("error parsing http_read_header_timeout: %w", err)
|
||||
}
|
||||
if err := parseAndClearDurationSecond(&l.HTTPReadHeaderTimeoutRaw, &l.HTTPReadHeaderTimeout); err != nil {
|
||||
return fmt.Errorf("error parsing http_read_header_timeout: %w", err)
|
||||
}
|
||||
|
||||
if l.HTTPWriteTimeoutRaw != nil {
|
||||
if l.HTTPWriteTimeout, err = parseutil.ParseDurationSecond(l.HTTPWriteTimeoutRaw); err != nil {
|
||||
return fmt.Errorf("error parsing http_write_timeout: %w", err)
|
||||
}
|
||||
if err := parseAndClearDurationSecond(&l.HTTPWriteTimeoutRaw, &l.HTTPWriteTimeout); err != nil {
|
||||
return fmt.Errorf("error parsing http_write_timeout: %w", err)
|
||||
}
|
||||
|
||||
if l.HTTPIdleTimeoutRaw != nil {
|
||||
if l.HTTPIdleTimeout, err = parseutil.ParseDurationSecond(l.HTTPIdleTimeoutRaw); err != nil {
|
||||
return fmt.Errorf("error parsing http_idle_timeout: %w", err)
|
||||
}
|
||||
if err := parseAndClearDurationSecond(&l.HTTPIdleTimeoutRaw, &l.HTTPIdleTimeout); err != nil {
|
||||
return fmt.Errorf("error parsing http_idle_timeout: %w", err)
|
||||
}
|
||||
|
||||
// Clear raw values after successful parsing.
|
||||
l.HTTPReadTimeoutRaw = nil
|
||||
l.HTTPReadHeaderTimeoutRaw = nil
|
||||
l.HTTPWriteTimeoutRaw = nil
|
||||
l.HTTPIdleTimeoutRaw = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -524,25 +576,20 @@ func (l *Listener) parseForwardedForSettings() error {
|
||||
if l.XForwardedForHopSkips < 0 {
|
||||
return fmt.Errorf("x_forwarded_for_hop_skips cannot be negative but set to %d", l.XForwardedForHopSkips)
|
||||
}
|
||||
|
||||
l.XForwardedForHopSkipsRaw = nil
|
||||
}
|
||||
|
||||
if l.XForwardedForRejectNotAuthorizedRaw != nil {
|
||||
if l.XForwardedForRejectNotAuthorized, err = parseutil.ParseBool(l.XForwardedForRejectNotAuthorizedRaw); err != nil {
|
||||
return fmt.Errorf("invalid value for x_forwarded_for_reject_not_authorized: %w", err)
|
||||
}
|
||||
if err := parseAndClearBool(&l.XForwardedForRejectNotAuthorizedRaw, &l.XForwardedForRejectNotAuthorized); err != nil {
|
||||
return fmt.Errorf("invalid value for x_forwarded_for_reject_not_authorized: %w", err)
|
||||
}
|
||||
|
||||
if l.XForwardedForRejectNotPresentRaw != nil {
|
||||
if l.XForwardedForRejectNotPresent, err = parseutil.ParseBool(l.XForwardedForRejectNotPresentRaw); err != nil {
|
||||
return fmt.Errorf("invalid value for x_forwarded_for_reject_not_present: %w", err)
|
||||
}
|
||||
if err := parseAndClearBool(&l.XForwardedForRejectNotPresentRaw, &l.XForwardedForRejectNotPresent); err != nil {
|
||||
return fmt.Errorf("invalid value for x_forwarded_for_reject_not_present: %w", err)
|
||||
}
|
||||
|
||||
// Clear raw values after successful parsing.
|
||||
l.XForwardedForAuthorizedAddrsRaw = nil
|
||||
l.XForwardedForHopSkipsRaw = nil
|
||||
l.XForwardedForRejectNotAuthorizedRaw = nil
|
||||
l.XForwardedForRejectNotPresentRaw = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -551,16 +598,10 @@ func (l *Listener) parseForwardedForSettings() error {
|
||||
// The state of the listener will be modified, raw data will be cleared upon
|
||||
// successful parsing.
|
||||
func (l *Listener) parseTelemetrySettings() error {
|
||||
var err error
|
||||
|
||||
if l.Telemetry.UnauthenticatedMetricsAccessRaw != nil {
|
||||
if l.Telemetry.UnauthenticatedMetricsAccess, err = parseutil.ParseBool(l.Telemetry.UnauthenticatedMetricsAccessRaw); err != nil {
|
||||
return fmt.Errorf("invalid value for telemetry.unauthenticated_metrics_access: %w", err)
|
||||
}
|
||||
if err := parseAndClearBool(&l.Telemetry.UnauthenticatedMetricsAccessRaw, &l.Telemetry.UnauthenticatedMetricsAccess); err != nil {
|
||||
return fmt.Errorf("invalid value for telemetry.unauthenticated_metrics_access: %w", err)
|
||||
}
|
||||
|
||||
l.Telemetry.UnauthenticatedMetricsAccessRaw = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -568,16 +609,10 @@ func (l *Listener) parseTelemetrySettings() error {
|
||||
// The state of the listener will be modified, raw data will be cleared upon
|
||||
// successful parsing.
|
||||
func (l *Listener) parseProfilingSettings() error {
|
||||
var err error
|
||||
|
||||
if l.Profiling.UnauthenticatedPProfAccessRaw != nil {
|
||||
if l.Profiling.UnauthenticatedPProfAccess, err = parseutil.ParseBool(l.Profiling.UnauthenticatedPProfAccessRaw); err != nil {
|
||||
return fmt.Errorf("invalid value for profiling.unauthenticated_pprof_access: %w", err)
|
||||
}
|
||||
if err := parseAndClearBool(&l.Profiling.UnauthenticatedPProfAccessRaw, &l.Profiling.UnauthenticatedPProfAccess); err != nil {
|
||||
return fmt.Errorf("invalid value for profiling.unauthenticated_pprof_access: %w", err)
|
||||
}
|
||||
|
||||
l.Profiling.UnauthenticatedPProfAccessRaw = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -585,16 +620,10 @@ func (l *Listener) parseProfilingSettings() error {
|
||||
// The state of the listener will be modified, raw data will be cleared upon
|
||||
// successful parsing.
|
||||
func (l *Listener) parseInFlightRequestSettings() error {
|
||||
var err error
|
||||
|
||||
if l.InFlightRequestLogging.UnauthenticatedInFlightAccessRaw != nil {
|
||||
if l.InFlightRequestLogging.UnauthenticatedInFlightAccess, err = parseutil.ParseBool(l.InFlightRequestLogging.UnauthenticatedInFlightAccessRaw); err != nil {
|
||||
return fmt.Errorf("invalid value for inflight_requests_logging.unauthenticated_in_flight_requests_access: %w", err)
|
||||
}
|
||||
if err := parseAndClearBool(&l.InFlightRequestLogging.UnauthenticatedInFlightAccessRaw, &l.InFlightRequestLogging.UnauthenticatedInFlightAccess); err != nil {
|
||||
return fmt.Errorf("invalid value for inflight_requests_logging.unauthenticated_in_flight_requests_access: %w", err)
|
||||
}
|
||||
|
||||
l.InFlightRequestLogging.UnauthenticatedInFlightAccessRaw = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -602,12 +631,8 @@ func (l *Listener) parseInFlightRequestSettings() error {
|
||||
// The state of the listener will be modified, raw data will be cleared upon
|
||||
// successful parsing.
|
||||
func (l *Listener) parseCORSSettings() error {
|
||||
var err error
|
||||
|
||||
if l.CorsEnabledRaw != nil {
|
||||
if l.CorsEnabled, err = parseutil.ParseBool(l.CorsEnabledRaw); err != nil {
|
||||
return fmt.Errorf("invalid value for cors_enabled: %w", err)
|
||||
}
|
||||
if err := parseAndClearBool(&l.CorsEnabledRaw, &l.CorsEnabled); err != nil {
|
||||
return fmt.Errorf("invalid value for cors_enabled: %w", err)
|
||||
}
|
||||
|
||||
if strutil.StrListContains(l.CorsAllowedOrigins, "*") && len(l.CorsAllowedOrigins) > 1 {
|
||||
@@ -620,7 +645,6 @@ func (l *Listener) parseCORSSettings() error {
|
||||
}
|
||||
}
|
||||
|
||||
l.CorsEnabledRaw = nil
|
||||
l.CorsAllowedHeadersRaw = nil
|
||||
|
||||
return nil
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@@ -1095,3 +1096,269 @@ func TestListener_parseRedactionSettings(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseAndClearBool(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
raw interface{}
|
||||
rawAssertion func(assert.TestingT, any, ...any) bool
|
||||
expectedParsed bool
|
||||
errorAssertion func(assert.TestingT, error, ...any) bool
|
||||
}{
|
||||
{
|
||||
name: "valid-true-as-string",
|
||||
raw: "true",
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: true,
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "valid-false-as-string",
|
||||
raw: "false",
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: false,
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "valid-true-as-bool",
|
||||
raw: true,
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: true,
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "valid-false-as-bool",
|
||||
raw: false,
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: false,
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "valid-true-as-string-mix-case",
|
||||
raw: "True",
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: true,
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "valid-false-as-integer",
|
||||
raw: 0,
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: false,
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "valid-true-as-integer",
|
||||
raw: 2,
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: true,
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "valid-true-as-float",
|
||||
raw: 3.14,
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: true,
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "valid-false-as-float",
|
||||
raw: 0.0,
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: false,
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "invalid-as-string",
|
||||
raw: "0.0.0.0:8200",
|
||||
rawAssertion: assert.NotNil,
|
||||
errorAssertion: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "invalid-as-struct",
|
||||
raw: struct{}{},
|
||||
rawAssertion: assert.NotNil,
|
||||
errorAssertion: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "not-set",
|
||||
raw: nil,
|
||||
rawAssertion: assert.Nil,
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testcase := range testcases {
|
||||
var parsed bool
|
||||
err := parseAndClearBool(&testcase.raw, &parsed)
|
||||
|
||||
testcase.errorAssertion(t, err, testcase.name)
|
||||
assert.Equal(t, testcase.expectedParsed, parsed, testcase.name)
|
||||
testcase.rawAssertion(t, testcase.raw, testcase.name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseAndClearString(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
raw any
|
||||
rawAssertion func(assert.TestingT, any, ...any) bool
|
||||
expectedParsed string
|
||||
errorAssertion func(assert.TestingT, error, ...any) bool
|
||||
}{
|
||||
{
|
||||
name: "valid-empty-string",
|
||||
raw: "",
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: "",
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "valid-some-string",
|
||||
raw: "blah blah",
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: "blah blah",
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "valid-as-integer",
|
||||
raw: 8,
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: "8",
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "valid-as-bool",
|
||||
raw: true,
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: "1",
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "not-set",
|
||||
raw: nil,
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: "",
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "invalid-as-struct",
|
||||
raw: struct{}{},
|
||||
rawAssertion: assert.NotNil,
|
||||
errorAssertion: assert.Error,
|
||||
},
|
||||
}
|
||||
for _, testcase := range testcases {
|
||||
var parsed string
|
||||
err := parseAndClearString(&testcase.raw, &parsed)
|
||||
|
||||
testcase.errorAssertion(t, err, testcase.name)
|
||||
assert.Equal(t, testcase.expectedParsed, parsed, testcase.name)
|
||||
testcase.rawAssertion(t, testcase.raw, testcase.name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseAndClearInt(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
raw any
|
||||
rawAssertion func(assert.TestingT, any, ...any) bool
|
||||
expectedParsed int64
|
||||
errorAssertion func(assert.TestingT, error, ...any) bool
|
||||
}{
|
||||
{
|
||||
name: "valid-as-int",
|
||||
raw: 200,
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: int64(200),
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "valid-as-string",
|
||||
raw: "53",
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: int64(53),
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "invalid-as-hex-string",
|
||||
raw: "0xa",
|
||||
rawAssertion: assert.NotNil,
|
||||
errorAssertion: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "not-set",
|
||||
raw: nil,
|
||||
rawAssertion: assert.Nil,
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testcase := range testcases {
|
||||
var parsed int64
|
||||
err := parseAndClearInt(&testcase.raw, &parsed)
|
||||
|
||||
testcase.errorAssertion(t, err, testcase.name)
|
||||
assert.Equal(t, testcase.expectedParsed, parsed, testcase.name)
|
||||
testcase.rawAssertion(t, testcase.raw, testcase.name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseAndClearDurationSecond(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
raw any
|
||||
rawAssertion func(assert.TestingT, any, ...any) bool
|
||||
expectedParsed time.Duration
|
||||
errorAssertion func(assert.TestingT, error, ...any) bool
|
||||
}{
|
||||
{
|
||||
name: "valid-as-string",
|
||||
raw: "30s",
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: time.Duration(30 * time.Second),
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "valid-as-string-more-complex",
|
||||
raw: "29h24m49s",
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: time.Duration((29 * time.Hour) + (24 * time.Minute) + (49 * time.Second)),
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "invalid-as-string-using-days",
|
||||
raw: "1d3s",
|
||||
rawAssertion: assert.NotNil,
|
||||
errorAssertion: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "valid-as-integer",
|
||||
raw: 87,
|
||||
rawAssertion: assert.Nil,
|
||||
expectedParsed: time.Duration(87 * time.Second),
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "not-set",
|
||||
raw: nil,
|
||||
rawAssertion: assert.Nil,
|
||||
errorAssertion: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "invalid-as-struct",
|
||||
raw: struct{}{},
|
||||
rawAssertion: assert.NotNil,
|
||||
errorAssertion: assert.Error,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testcase := range testcases {
|
||||
var parsed time.Duration
|
||||
|
||||
err := parseAndClearDurationSecond(&testcase.raw, &parsed)
|
||||
testcase.errorAssertion(t, err, testcase.name)
|
||||
assert.Equal(t, testcase.expectedParsed, parsed)
|
||||
testcase.rawAssertion(t, testcase.raw, testcase.name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,6 +202,9 @@ default value in the `"/sys/config/ui"` [API endpoint](/vault/api-docs/system/co
|
||||
there is no X-Forwarded-For header or it is empty, the client address will be
|
||||
used as-is, rather than the client connection rejected.
|
||||
|
||||
- `disable_replication_status_endpoints` `(bool: false)` - Disables replication
|
||||
status endpoints for the configured listener when set to `true`.
|
||||
|
||||
### `telemetry` parameters
|
||||
|
||||
- `unauthenticated_metrics_access` `(bool: false)` - If set to true, allows
|
||||
|
||||
Reference in New Issue
Block a user