mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-03 20:17:59 +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)
|
additionalRoutes(mux, core)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap the handler in another handler to trigger all help paths.
|
// Build up a chain of wrapping handlers.
|
||||||
helpWrappedHandler := wrapHelpHandler(mux, core)
|
wrappedHandler := wrapHelpHandler(mux, core)
|
||||||
corsWrappedHandler := wrapCORSHandler(helpWrappedHandler, core)
|
wrappedHandler = wrapCORSHandler(wrappedHandler, core)
|
||||||
quotaWrappedHandler := rateLimitQuotaWrapping(corsWrappedHandler, core)
|
wrappedHandler = rateLimitQuotaWrapping(wrappedHandler, core)
|
||||||
genericWrappedHandler := genericWrapping(core, quotaWrappedHandler, props)
|
wrappedHandler = genericWrapping(core, wrappedHandler, props)
|
||||||
|
|
||||||
// Wrap the handler with PrintablePathCheckHandler to check for non-printable
|
// Add an extra wrapping handler if the DisablePrintableCheck listener
|
||||||
// characters in the request path.
|
// setting isn't true that checks for non-printable characters in the
|
||||||
printablePathCheckHandler := genericWrappedHandler
|
// request path.
|
||||||
if !props.DisablePrintableCheck {
|
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 {
|
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 {
|
func parseRemoteIPAddress(r *http.Request) string {
|
||||||
ip, _, err := net.SplitHostPort(r.RemoteAddr)
|
ip, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -139,6 +139,10 @@ type Listener struct {
|
|||||||
RedactClusterName bool `hcl:"-"`
|
RedactClusterName bool `hcl:"-"`
|
||||||
RedactVersionRaw any `hcl:"redact_version"`
|
RedactVersionRaw any `hcl:"redact_version"`
|
||||||
RedactVersion bool `hcl:"-"`
|
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.
|
// 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.parseHTTPHeaderSettings,
|
||||||
l.parseChrootNamespaceSettings,
|
l.parseChrootNamespaceSettings,
|
||||||
l.parseRedactionSettings,
|
l.parseRedactionSettings,
|
||||||
|
l.parseDisableReplicationStatusEndpointSettings,
|
||||||
} {
|
} {
|
||||||
err := parser()
|
err := parser()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -272,22 +277,114 @@ func (t ListenerType) String() string {
|
|||||||
return string(t.Normalize())
|
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.
|
// parseChrootNamespace attempts to parse the raw listener chroot namespace settings.
|
||||||
// The state of the listener will be modified, raw data will be cleared upon
|
// The state of the listener will be modified, raw data will be cleared upon
|
||||||
// successful parsing.
|
// successful parsing.
|
||||||
func (l *Listener) parseChrootNamespaceSettings() error {
|
func (l *Listener) parseChrootNamespaceSettings() error {
|
||||||
var err error
|
var (
|
||||||
|
err error
|
||||||
|
setting string
|
||||||
|
)
|
||||||
|
|
||||||
// If a valid ChrootNamespace value exists, then canonicalize the namespace value
|
err = parseAndClearString(&l.ChrootNamespaceRaw, &setting)
|
||||||
if l.ChrootNamespaceRaw != nil {
|
|
||||||
l.ChrootNamespace, err = parseutil.ParseString(l.ChrootNamespaceRaw)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid value for chroot_namespace: %w", err)
|
return fmt.Errorf("invalid value for chroot_namespace: %w", err)
|
||||||
}
|
}
|
||||||
l.ChrootNamespace = namespace.Canonicalize(l.ChrootNamespace)
|
|
||||||
}
|
|
||||||
|
|
||||||
l.ChrootNamespaceRaw = nil
|
l.ChrootNamespace = namespace.Canonicalize(setting)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -327,15 +424,10 @@ func (l *Listener) parseType(fallback string) error {
|
|||||||
// The state of the listener will be modified, raw data will be cleared upon
|
// The state of the listener will be modified, raw data will be cleared upon
|
||||||
// successful parsing.
|
// successful parsing.
|
||||||
func (l *Listener) parseRequestSettings() error {
|
func (l *Listener) parseRequestSettings() error {
|
||||||
if l.MaxRequestSizeRaw != nil {
|
if err := parseAndClearInt(&l.MaxRequestSizeRaw, &l.MaxRequestSize); err != nil {
|
||||||
maxRequestSize, err := parseutil.ParseInt(l.MaxRequestSizeRaw)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error parsing max_request_size: %w", err)
|
return fmt.Errorf("error parsing max_request_size: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
l.MaxRequestSize = maxRequestSize
|
|
||||||
}
|
|
||||||
|
|
||||||
if l.MaxRequestDurationRaw != nil {
|
if l.MaxRequestDurationRaw != nil {
|
||||||
maxRequestDuration, err := parseutil.ParseDurationSecond(l.MaxRequestDurationRaw)
|
maxRequestDuration, err := parseutil.ParseDurationSecond(l.MaxRequestDurationRaw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -347,22 +439,13 @@ func (l *Listener) parseRequestSettings() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
l.MaxRequestDuration = maxRequestDuration
|
l.MaxRequestDuration = maxRequestDuration
|
||||||
|
l.MaxRequestDurationRaw = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if l.RequireRequestHeaderRaw != nil {
|
if err := parseAndClearBool(&l.RequireRequestHeaderRaw, &l.RequireRequestHeader); err != nil {
|
||||||
requireRequestHeader, err := parseutil.ParseBool(l.RequireRequestHeaderRaw)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("invalid value for require_request_header: %w", err)
|
return fmt.Errorf("invalid value for require_request_header: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
l.RequireRequestHeader = requireRequestHeader
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear raw values after successful parsing.
|
|
||||||
l.MaxRequestSizeRaw = nil
|
|
||||||
l.MaxRequestDurationRaw = nil
|
|
||||||
l.RequireRequestHeaderRaw = nil
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,13 +453,9 @@ func (l *Listener) parseRequestSettings() error {
|
|||||||
// The state of the listener will be modified, raw data will be cleared upon
|
// The state of the listener will be modified, raw data will be cleared upon
|
||||||
// successful parsing.
|
// successful parsing.
|
||||||
func (l *Listener) parseTLSSettings() error {
|
func (l *Listener) parseTLSSettings() error {
|
||||||
if l.TLSDisableRaw != nil {
|
if err := parseAndClearBool(&l.TLSDisableRaw, &l.TLSDisable); err != nil {
|
||||||
tlsDisable, err := parseutil.ParseBool(l.TLSDisableRaw)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("invalid value for tls_disable: %w", err)
|
return fmt.Errorf("invalid value for tls_disable: %w", err)
|
||||||
}
|
}
|
||||||
l.TLSDisable = tlsDisable
|
|
||||||
}
|
|
||||||
|
|
||||||
if l.TLSCipherSuitesRaw != "" {
|
if l.TLSCipherSuitesRaw != "" {
|
||||||
tlsCipherSuites, err := tlsutil.ParseCiphers(l.TLSCipherSuitesRaw)
|
tlsCipherSuites, err := tlsutil.ParseCiphers(l.TLSCipherSuitesRaw)
|
||||||
@@ -386,27 +465,16 @@ func (l *Listener) parseTLSSettings() error {
|
|||||||
l.TLSCipherSuites = tlsCipherSuites
|
l.TLSCipherSuites = tlsCipherSuites
|
||||||
}
|
}
|
||||||
|
|
||||||
if l.TLSRequireAndVerifyClientCertRaw != nil {
|
if err := parseAndClearBool(&l.TLSRequireAndVerifyClientCertRaw, &l.TLSRequireAndVerifyClientCert); err != nil {
|
||||||
tlsRequireAndVerifyClientCert, err := parseutil.ParseBool(l.TLSRequireAndVerifyClientCertRaw)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("invalid value for tls_require_and_verify_client_cert: %w", err)
|
return fmt.Errorf("invalid value for tls_require_and_verify_client_cert: %w", err)
|
||||||
}
|
}
|
||||||
l.TLSRequireAndVerifyClientCert = tlsRequireAndVerifyClientCert
|
|
||||||
}
|
|
||||||
|
|
||||||
if l.TLSDisableClientCertsRaw != nil {
|
if err := parseAndClearBool(&l.TLSDisableClientCertsRaw, &l.TLSDisableClientCerts); err != nil {
|
||||||
tlsDisableClientCerts, err := parseutil.ParseBool(l.TLSDisableClientCertsRaw)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("invalid value for tls_disable_client_certs: %w", err)
|
return fmt.Errorf("invalid value for tls_disable_client_certs: %w", err)
|
||||||
}
|
}
|
||||||
l.TLSDisableClientCerts = tlsDisableClientCerts
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear raw values after successful parsing.
|
// Clear raw values after successful parsing.
|
||||||
l.TLSDisableRaw = nil
|
|
||||||
l.TLSCipherSuitesRaw = ""
|
l.TLSCipherSuitesRaw = ""
|
||||||
l.TLSRequireAndVerifyClientCertRaw = nil
|
|
||||||
l.TLSDisableClientCertsRaw = nil
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -438,37 +506,21 @@ func (l *Listener) parseHTTPHeaderSettings() error {
|
|||||||
// The state of the listener will be modified, raw data will be cleared upon
|
// The state of the listener will be modified, raw data will be cleared upon
|
||||||
// successful parsing.
|
// successful parsing.
|
||||||
func (l *Listener) parseHTTPTimeoutSettings() error {
|
func (l *Listener) parseHTTPTimeoutSettings() error {
|
||||||
var err error
|
if err := parseAndClearDurationSecond(&l.HTTPReadTimeoutRaw, &l.HTTPReadTimeout); err != nil {
|
||||||
|
|
||||||
if l.HTTPReadTimeoutRaw != nil {
|
|
||||||
if l.HTTPReadTimeout, err = parseutil.ParseDurationSecond(l.HTTPReadTimeoutRaw); err != nil {
|
|
||||||
return fmt.Errorf("error parsing http_read_timeout: %w", err)
|
return fmt.Errorf("error parsing http_read_timeout: %w", err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if l.HTTPReadHeaderTimeoutRaw != nil {
|
if err := parseAndClearDurationSecond(&l.HTTPReadHeaderTimeoutRaw, &l.HTTPReadHeaderTimeout); err != nil {
|
||||||
if l.HTTPReadHeaderTimeout, err = parseutil.ParseDurationSecond(l.HTTPReadHeaderTimeoutRaw); err != nil {
|
|
||||||
return fmt.Errorf("error parsing http_read_header_timeout: %w", err)
|
return fmt.Errorf("error parsing http_read_header_timeout: %w", err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if l.HTTPWriteTimeoutRaw != nil {
|
if err := parseAndClearDurationSecond(&l.HTTPWriteTimeoutRaw, &l.HTTPWriteTimeout); err != nil {
|
||||||
if l.HTTPWriteTimeout, err = parseutil.ParseDurationSecond(l.HTTPWriteTimeoutRaw); err != nil {
|
|
||||||
return fmt.Errorf("error parsing http_write_timeout: %w", err)
|
return fmt.Errorf("error parsing http_write_timeout: %w", err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if l.HTTPIdleTimeoutRaw != nil {
|
if err := parseAndClearDurationSecond(&l.HTTPIdleTimeoutRaw, &l.HTTPIdleTimeout); err != nil {
|
||||||
if l.HTTPIdleTimeout, err = parseutil.ParseDurationSecond(l.HTTPIdleTimeoutRaw); err != nil {
|
|
||||||
return fmt.Errorf("error parsing http_idle_timeout: %w", err)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
@@ -524,25 +576,20 @@ func (l *Listener) parseForwardedForSettings() error {
|
|||||||
if l.XForwardedForHopSkips < 0 {
|
if l.XForwardedForHopSkips < 0 {
|
||||||
return fmt.Errorf("x_forwarded_for_hop_skips cannot be negative but set to %d", l.XForwardedForHopSkips)
|
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 err := parseAndClearBool(&l.XForwardedForRejectNotAuthorizedRaw, &l.XForwardedForRejectNotAuthorized); err != 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)
|
return fmt.Errorf("invalid value for x_forwarded_for_reject_not_authorized: %w", err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if l.XForwardedForRejectNotPresentRaw != nil {
|
if err := parseAndClearBool(&l.XForwardedForRejectNotPresentRaw, &l.XForwardedForRejectNotPresent); err != 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)
|
return fmt.Errorf("invalid value for x_forwarded_for_reject_not_present: %w", err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Clear raw values after successful parsing.
|
// Clear raw values after successful parsing.
|
||||||
l.XForwardedForAuthorizedAddrsRaw = nil
|
l.XForwardedForAuthorizedAddrsRaw = nil
|
||||||
l.XForwardedForHopSkipsRaw = nil
|
|
||||||
l.XForwardedForRejectNotAuthorizedRaw = nil
|
|
||||||
l.XForwardedForRejectNotPresentRaw = nil
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -551,15 +598,9 @@ func (l *Listener) parseForwardedForSettings() error {
|
|||||||
// The state of the listener will be modified, raw data will be cleared upon
|
// The state of the listener will be modified, raw data will be cleared upon
|
||||||
// successful parsing.
|
// successful parsing.
|
||||||
func (l *Listener) parseTelemetrySettings() error {
|
func (l *Listener) parseTelemetrySettings() error {
|
||||||
var err error
|
if err := parseAndClearBool(&l.Telemetry.UnauthenticatedMetricsAccessRaw, &l.Telemetry.UnauthenticatedMetricsAccess); err != nil {
|
||||||
|
|
||||||
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)
|
return fmt.Errorf("invalid value for telemetry.unauthenticated_metrics_access: %w", err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
l.Telemetry.UnauthenticatedMetricsAccessRaw = nil
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -568,15 +609,9 @@ func (l *Listener) parseTelemetrySettings() error {
|
|||||||
// The state of the listener will be modified, raw data will be cleared upon
|
// The state of the listener will be modified, raw data will be cleared upon
|
||||||
// successful parsing.
|
// successful parsing.
|
||||||
func (l *Listener) parseProfilingSettings() error {
|
func (l *Listener) parseProfilingSettings() error {
|
||||||
var err error
|
if err := parseAndClearBool(&l.Profiling.UnauthenticatedPProfAccessRaw, &l.Profiling.UnauthenticatedPProfAccess); err != nil {
|
||||||
|
|
||||||
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)
|
return fmt.Errorf("invalid value for profiling.unauthenticated_pprof_access: %w", err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
l.Profiling.UnauthenticatedPProfAccessRaw = nil
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -585,15 +620,9 @@ func (l *Listener) parseProfilingSettings() error {
|
|||||||
// The state of the listener will be modified, raw data will be cleared upon
|
// The state of the listener will be modified, raw data will be cleared upon
|
||||||
// successful parsing.
|
// successful parsing.
|
||||||
func (l *Listener) parseInFlightRequestSettings() error {
|
func (l *Listener) parseInFlightRequestSettings() error {
|
||||||
var err error
|
if err := parseAndClearBool(&l.InFlightRequestLogging.UnauthenticatedInFlightAccessRaw, &l.InFlightRequestLogging.UnauthenticatedInFlightAccess); err != nil {
|
||||||
|
|
||||||
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)
|
return fmt.Errorf("invalid value for inflight_requests_logging.unauthenticated_in_flight_requests_access: %w", err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
l.InFlightRequestLogging.UnauthenticatedInFlightAccessRaw = nil
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -602,13 +631,9 @@ func (l *Listener) parseInFlightRequestSettings() error {
|
|||||||
// The state of the listener will be modified, raw data will be cleared upon
|
// The state of the listener will be modified, raw data will be cleared upon
|
||||||
// successful parsing.
|
// successful parsing.
|
||||||
func (l *Listener) parseCORSSettings() error {
|
func (l *Listener) parseCORSSettings() error {
|
||||||
var err error
|
if err := parseAndClearBool(&l.CorsEnabledRaw, &l.CorsEnabled); err != nil {
|
||||||
|
|
||||||
if l.CorsEnabledRaw != nil {
|
|
||||||
if l.CorsEnabled, err = parseutil.ParseBool(l.CorsEnabledRaw); err != nil {
|
|
||||||
return fmt.Errorf("invalid value for cors_enabled: %w", err)
|
return fmt.Errorf("invalid value for cors_enabled: %w", err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if strutil.StrListContains(l.CorsAllowedOrigins, "*") && len(l.CorsAllowedOrigins) > 1 {
|
if strutil.StrListContains(l.CorsAllowedOrigins, "*") && len(l.CorsAllowedOrigins) > 1 {
|
||||||
return errors.New("cors_allowed_origins must only contain a wildcard or only non-wildcard values")
|
return errors.New("cors_allowed_origins must only contain a wildcard or only non-wildcard values")
|
||||||
@@ -620,7 +645,6 @@ func (l *Listener) parseCORSSettings() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
l.CorsEnabledRaw = nil
|
|
||||||
l.CorsAllowedHeadersRaw = nil
|
l.CorsAllowedHeadersRaw = nil
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"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
|
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.
|
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
|
### `telemetry` parameters
|
||||||
|
|
||||||
- `unauthenticated_metrics_access` `(bool: false)` - If set to true, allows
|
- `unauthenticated_metrics_access` `(bool: false)` - If set to true, allows
|
||||||
|
|||||||
Reference in New Issue
Block a user