Config: Listener parsing clean-up (#23502)

* Updated test for go-sockaddr template

* Rename test

* Tried to break up listener config parsing and add tests
This commit is contained in:
Peter Wilson
2023-10-05 16:12:31 +01:00
committed by GitHub
parent 7d800b1af2
commit 0309c9e032
4 changed files with 1378 additions and 322 deletions

View File

@@ -893,12 +893,19 @@ listener "tcp" {
} }
list, _ := obj.Node.(*ast.ObjectList) list, _ := obj.Node.(*ast.ObjectList)
objList := list.Filter("listener") objList := list.Filter("listener")
configutil.ParseListeners(config.SharedConfig, objList) listeners, err := configutil.ParseListeners(objList)
listeners := config.Listeners require.NoError(t, err)
if len(listeners) == 0 { // Update the shared config
config.Listeners = listeners
// Track which types of listener were found.
for _, l := range config.Listeners {
config.found(l.Type, l.Type)
}
if len(config.Listeners) == 0 {
t.Fatalf("expected at least one listener in the config") t.Fatalf("expected at least one listener in the config")
} }
listener := listeners[0] listener := config.Listeners[0]
if listener.Type != "tcp" { if listener.Type != "tcp" {
t.Fatalf("expected tcp listener in the config") t.Fatalf("expected tcp listener in the config")
} }

View File

@@ -122,9 +122,17 @@ func ParseConfig(d string) (*SharedConfig, error) {
if o := list.Filter("listener"); len(o.Items) > 0 { if o := list.Filter("listener"); len(o.Items) > 0 {
result.found("listener", "Listener") result.found("listener", "Listener")
if err := ParseListeners(&result, o); err != nil { listeners, err := ParseListeners(o)
if err != nil {
return nil, fmt.Errorf("error parsing 'listener': %w", err) return nil, fmt.Errorf("error parsing 'listener': %w", err)
} }
// Update the shared config
result.Listeners = listeners
// Track which types of listener were found.
for _, l := range result.Listeners {
result.found(l.Type, l.Type)
}
} }
if o := list.Filter("user_lockout"); len(o.Items) > 0 { if o := list.Filter("user_lockout"); len(o.Items) > 0 {

View File

@@ -144,305 +144,424 @@ func (l *Listener) Validate(path string) []ConfigError {
return append(results, ValidateUnusedFields(l.Profiling.UnusedKeys, path)...) return append(results, ValidateUnusedFields(l.Profiling.UnusedKeys, path)...)
} }
func ParseListeners(result *SharedConfig, list *ast.ObjectList) error { // ParseListeners attempts to parse the AST list of objects into listeners.
var err error func ParseListeners(list *ast.ObjectList) ([]*Listener, error) {
result.Listeners = make([]*Listener, 0, len(list.Items)) listeners := make([]*Listener, len(list.Items))
for i, item := range list.Items { for i, item := range list.Items {
var l Listener l, err := parseListener(item)
if err := hcl.DecodeObject(&l, item.Val); err != nil { if err != nil {
return multierror.Prefix(err, fmt.Sprintf("listeners.%d:", i)) return nil, multierror.Prefix(err, fmt.Sprintf("listeners.%d:", i))
}
if rendered, err := ParseSingleIPTemplate(l.Address); err != nil {
return multierror.Prefix(err, fmt.Sprintf("listeners.%d:", i))
} else {
l.Address = rendered
}
if rendered, err := ParseSingleIPTemplate(l.ClusterAddress); err != nil {
return multierror.Prefix(err, fmt.Sprintf("listeners.%d:", i))
} else {
l.ClusterAddress = rendered
} }
listeners[i] = l
}
// Hacky way, for now, to get the values we want for sanitizing return listeners, nil
var m map[string]interface{} }
if err := hcl.DecodeObject(&m, item.Val); err != nil {
return multierror.Prefix(err, fmt.Sprintf("listeners.%d:", i))
}
l.RawConfig = m
// Base values // parseListener attempts to parse the AST object into a listener.
{ func parseListener(item *ast.ObjectItem) (*Listener, error) {
switch { var l *Listener
case l.Type != "": var err error
case len(item.Keys) == 1:
l.Type = strings.ToLower(item.Keys[0].Token.Value().(string))
default:
return multierror.Prefix(errors.New("listener type must be specified"), fmt.Sprintf("listeners.%d:", i))
}
l.Type = strings.ToLower(l.Type) // Decode the current item
switch l.Type { if err = hcl.DecodeObject(&l, item.Val); err != nil {
case "tcp", "unix": return nil, err
result.found(l.Type, l.Type) }
default:
return multierror.Prefix(fmt.Errorf("unsupported listener type %q", l.Type), fmt.Sprintf("listeners.%d:", i))
}
if l.PurposeRaw != nil { // Parse and update address if required.
if l.Purpose, err = parseutil.ParseCommaStringSlice(l.PurposeRaw); err != nil { if l.Address, err = ParseSingleIPTemplate(l.Address); err != nil {
return multierror.Prefix(fmt.Errorf("unable to parse 'purpose' in listener type %q: %w", l.Type, err), fmt.Sprintf("listeners.%d:", i)) return nil, err
} }
for i, v := range l.Purpose {
l.Purpose[i] = strings.ToLower(v)
}
l.PurposeRaw = nil // Parse and update cluster address if required.
} if l.ClusterAddress, err = ParseSingleIPTemplate(l.ClusterAddress); err != nil {
return nil, err
}
switch l.Role { // Get the values for sanitizing
case "default", "metrics_only", "": var m map[string]interface{}
result.found(l.Type, l.Type) if err := hcl.DecodeObject(&m, item.Val); err != nil {
default: return nil, err
return multierror.Prefix(fmt.Errorf("unsupported listener role %q", l.Role), fmt.Sprintf("listeners.%d:", i)) }
} l.RawConfig = m
}
// Request Parameters
{
if l.MaxRequestSizeRaw != nil {
if l.MaxRequestSize, err = parseutil.ParseInt(l.MaxRequestSizeRaw); err != nil {
return multierror.Prefix(fmt.Errorf("error parsing max_request_size: %w", err), fmt.Sprintf("listeners.%d", i))
}
l.MaxRequestSizeRaw = nil // Parse type, but supply a fallback if type wasn't set.
} var fallbackType string
if len(item.Keys) == 1 {
fallbackType = strings.ToLower(item.Keys[0].Token.Value().(string))
}
if l.MaxRequestDurationRaw != nil { if err = l.parseType(fallbackType); err != nil {
if l.MaxRequestDuration, err = parseutil.ParseDurationSecond(l.MaxRequestDurationRaw); err != nil { return nil, err
return multierror.Prefix(fmt.Errorf("error parsing max_request_duration: %w", err), fmt.Sprintf("listeners.%d", i)) }
}
if l.MaxRequestDuration < 0 {
return multierror.Prefix(errors.New("max_request_duration cannot be negative"), fmt.Sprintf("listeners.%d", i))
}
l.MaxRequestDurationRaw = nil // Parse out each set off settings for the listener.
} for _, parser := range []func() error{
l.parseRequestSettings,
if l.RequireRequestHeaderRaw != nil { l.parseTLSSettings,
if l.RequireRequestHeader, err = parseutil.ParseBool(l.RequireRequestHeaderRaw); err != nil { l.parseHTTPTimeoutSettings,
return multierror.Prefix(fmt.Errorf("invalid value for require_request_header: %w", err), fmt.Sprintf("listeners.%d", i)) l.parseProxySettings,
} l.parseForwardedForSettings,
l.parseTelemetrySettings,
l.RequireRequestHeaderRaw = nil l.parseProfilingSettings,
} l.parseInFlightRequestSettings,
} l.parseCORSSettings,
l.parseHTTPHeaderSettings,
// TLS Parameters l.parseChrootNamespaceSettings,
{ } {
if l.TLSDisableRaw != nil { err := parser()
if l.TLSDisable, err = parseutil.ParseBool(l.TLSDisableRaw); err != nil { if err != nil {
return multierror.Prefix(fmt.Errorf("invalid value for tls_disable: %w", err), fmt.Sprintf("listeners.%d", i)) return nil, err
}
l.TLSDisableRaw = nil
}
if l.TLSCipherSuitesRaw != "" {
if l.TLSCipherSuites, err = tlsutil.ParseCiphers(l.TLSCipherSuitesRaw); err != nil {
return multierror.Prefix(fmt.Errorf("invalid value for tls_cipher_suites: %w", err), fmt.Sprintf("listeners.%d", i))
}
}
if l.TLSRequireAndVerifyClientCertRaw != nil {
if l.TLSRequireAndVerifyClientCert, err = parseutil.ParseBool(l.TLSRequireAndVerifyClientCertRaw); err != nil {
return multierror.Prefix(fmt.Errorf("invalid value for tls_require_and_verify_client_cert: %w", err), fmt.Sprintf("listeners.%d", i))
}
l.TLSRequireAndVerifyClientCertRaw = nil
}
if l.TLSDisableClientCertsRaw != nil {
if l.TLSDisableClientCerts, err = parseutil.ParseBool(l.TLSDisableClientCertsRaw); err != nil {
return multierror.Prefix(fmt.Errorf("invalid value for tls_disable_client_certs: %w", err), fmt.Sprintf("listeners.%d", i))
}
l.TLSDisableClientCertsRaw = nil
}
}
// HTTP timeouts
{
if l.HTTPReadTimeoutRaw != nil {
if l.HTTPReadTimeout, err = parseutil.ParseDurationSecond(l.HTTPReadTimeoutRaw); err != nil {
return multierror.Prefix(fmt.Errorf("error parsing http_read_timeout: %w", err), fmt.Sprintf("listeners.%d", i))
}
l.HTTPReadTimeoutRaw = nil
}
if l.HTTPReadHeaderTimeoutRaw != nil {
if l.HTTPReadHeaderTimeout, err = parseutil.ParseDurationSecond(l.HTTPReadHeaderTimeoutRaw); err != nil {
return multierror.Prefix(fmt.Errorf("error parsing http_read_header_timeout: %w", err), fmt.Sprintf("listeners.%d", i))
}
l.HTTPReadHeaderTimeoutRaw = nil
}
if l.HTTPWriteTimeoutRaw != nil {
if l.HTTPWriteTimeout, err = parseutil.ParseDurationSecond(l.HTTPWriteTimeoutRaw); err != nil {
return multierror.Prefix(fmt.Errorf("error parsing http_write_timeout: %w", err), fmt.Sprintf("listeners.%d", i))
}
l.HTTPWriteTimeoutRaw = nil
}
if l.HTTPIdleTimeoutRaw != nil {
if l.HTTPIdleTimeout, err = parseutil.ParseDurationSecond(l.HTTPIdleTimeoutRaw); err != nil {
return multierror.Prefix(fmt.Errorf("error parsing http_idle_timeout: %w", err), fmt.Sprintf("listeners.%d", i))
}
l.HTTPIdleTimeoutRaw = nil
}
}
// Proxy Protocol config
{
if l.ProxyProtocolAuthorizedAddrsRaw != nil {
if l.ProxyProtocolAuthorizedAddrs, err = parseutil.ParseAddrs(l.ProxyProtocolAuthorizedAddrsRaw); err != nil {
return multierror.Prefix(fmt.Errorf("error parsing proxy_protocol_authorized_addrs: %w", err), fmt.Sprintf("listeners.%d", i))
}
switch l.ProxyProtocolBehavior {
case "allow_authorized", "deny_authorized":
if len(l.ProxyProtocolAuthorizedAddrs) == 0 {
return multierror.Prefix(errors.New("proxy_protocol_behavior set to allow or deny only authorized addresses but no proxy_protocol_authorized_addrs value"), fmt.Sprintf("listeners.%d", i))
}
}
l.ProxyProtocolAuthorizedAddrsRaw = nil
}
}
// X-Forwarded-For config
{
if l.XForwardedForAuthorizedAddrsRaw != nil {
if l.XForwardedForAuthorizedAddrs, err = parseutil.ParseAddrs(l.XForwardedForAuthorizedAddrsRaw); err != nil {
return multierror.Prefix(fmt.Errorf("error parsing x_forwarded_for_authorized_addrs: %w", err), fmt.Sprintf("listeners.%d", i))
}
l.XForwardedForAuthorizedAddrsRaw = nil
}
if l.XForwardedForHopSkipsRaw != nil {
if l.XForwardedForHopSkips, err = parseutil.ParseInt(l.XForwardedForHopSkipsRaw); err != nil {
return multierror.Prefix(fmt.Errorf("error parsing x_forwarded_for_hop_skips: %w", err), fmt.Sprintf("listeners.%d", i))
}
if l.XForwardedForHopSkips < 0 {
return multierror.Prefix(fmt.Errorf("x_forwarded_for_hop_skips cannot be negative but set to %d", l.XForwardedForHopSkips), fmt.Sprintf("listeners.%d", i))
}
l.XForwardedForHopSkipsRaw = nil
}
if l.XForwardedForRejectNotAuthorizedRaw != nil {
if l.XForwardedForRejectNotAuthorized, err = parseutil.ParseBool(l.XForwardedForRejectNotAuthorizedRaw); err != nil {
return multierror.Prefix(fmt.Errorf("invalid value for x_forwarded_for_reject_not_authorized: %w", err), fmt.Sprintf("listeners.%d", i))
}
l.XForwardedForRejectNotAuthorizedRaw = nil
}
if l.XForwardedForRejectNotPresentRaw != nil {
if l.XForwardedForRejectNotPresent, err = parseutil.ParseBool(l.XForwardedForRejectNotPresentRaw); err != nil {
return multierror.Prefix(fmt.Errorf("invalid value for x_forwarded_for_reject_not_present: %w", err), fmt.Sprintf("listeners.%d", i))
}
l.XForwardedForRejectNotPresentRaw = nil
}
}
// Telemetry
{
if l.Telemetry.UnauthenticatedMetricsAccessRaw != nil {
if l.Telemetry.UnauthenticatedMetricsAccess, err = parseutil.ParseBool(l.Telemetry.UnauthenticatedMetricsAccessRaw); err != nil {
return multierror.Prefix(fmt.Errorf("invalid value for telemetry.unauthenticated_metrics_access: %w", err), fmt.Sprintf("listeners.%d", i))
}
l.Telemetry.UnauthenticatedMetricsAccessRaw = nil
}
}
// Profiling
{
if l.Profiling.UnauthenticatedPProfAccessRaw != nil {
if l.Profiling.UnauthenticatedPProfAccess, err = parseutil.ParseBool(l.Profiling.UnauthenticatedPProfAccessRaw); err != nil {
return multierror.Prefix(fmt.Errorf("invalid value for profiling.unauthenticated_pprof_access: %w", err), fmt.Sprintf("listeners.%d", i))
}
l.Profiling.UnauthenticatedPProfAccessRaw = nil
}
}
// InFlight Request logging
{
if l.InFlightRequestLogging.UnauthenticatedInFlightAccessRaw != nil {
if l.InFlightRequestLogging.UnauthenticatedInFlightAccess, err = parseutil.ParseBool(l.InFlightRequestLogging.UnauthenticatedInFlightAccessRaw); err != nil {
return multierror.Prefix(fmt.Errorf("invalid value for inflight_requests_logging.unauthenticated_in_flight_requests_access: %w", err), fmt.Sprintf("listeners.%d", i))
}
l.InFlightRequestLogging.UnauthenticatedInFlightAccessRaw = ""
}
}
// CORS
{
if l.CorsEnabledRaw != nil {
if l.CorsEnabled, err = parseutil.ParseBool(l.CorsEnabledRaw); err != nil {
return multierror.Prefix(fmt.Errorf("invalid value for cors_enabled: %w", err), fmt.Sprintf("listeners.%d", i))
}
l.CorsEnabledRaw = nil
}
if strutil.StrListContains(l.CorsAllowedOrigins, "*") && len(l.CorsAllowedOrigins) > 1 {
return multierror.Prefix(errors.New("cors_allowed_origins must only contain a wildcard or only non-wildcard values"), fmt.Sprintf("listeners.%d", i))
}
if len(l.CorsAllowedHeadersRaw) > 0 {
for _, header := range l.CorsAllowedHeadersRaw {
l.CorsAllowedHeaders = append(l.CorsAllowedHeaders, textproto.CanonicalMIMEHeaderKey(header))
}
}
}
// HTTP Headers
{
// if CustomResponseHeadersRaw is nil, we still need to set the default headers
customHeadersMap, err := ParseCustomResponseHeaders(l.CustomResponseHeadersRaw)
if err != nil {
return multierror.Prefix(fmt.Errorf("failed to parse custom_response_headers: %w", err), fmt.Sprintf("listeners.%d", i))
}
l.CustomResponseHeaders = customHeadersMap
l.CustomResponseHeadersRaw = nil
}
result.Listeners = append(result.Listeners, &l)
// Chroot Namespace
{
// If a valid ChrootNamespace value exists, then canonicalize the namespace value
if l.ChrootNamespaceRaw != nil {
if l.ChrootNamespace, err = parseutil.ParseString(l.ChrootNamespaceRaw); err != nil {
return multierror.Prefix(fmt.Errorf("invalid value for chroot_namespace: %w", err), fmt.Sprintf("listeners.%d", i))
} else {
l.ChrootNamespace = namespace.Canonicalize(l.ChrootNamespace)
}
l.ChrootNamespaceRaw = nil
}
} }
} }
return l, 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
// 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)
}
l.ChrootNamespaceRaw = nil
return nil
}
// parseType attempts to sanitize and validate the type set on the listener.
// If the listener has no type set, the fallback value will be used.
// The state of the listener will be modified.
func (l *Listener) parseType(fallback string) error {
switch {
case l.Type != "":
case fallback != "":
default:
return errors.New("listener type must be specified")
}
// Use type if available, otherwise fall back.
result := l.Type
if result == "" {
result = fallback
}
result = strings.ToLower(result)
// Sanity check the values
switch result {
case "tcp", "unix":
default:
return fmt.Errorf("unsupported listener type %q", result)
}
l.Type = result
return nil
}
// parseRequestSettings attempts to parse the raw listener request settings.
// 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 l.MaxRequestDurationRaw != nil {
maxRequestDuration, err := parseutil.ParseDurationSecond(l.MaxRequestDurationRaw)
if err != nil {
return fmt.Errorf("error parsing max_request_duration: %w", err)
}
if maxRequestDuration < 0 {
return errors.New("max_request_duration cannot be negative")
}
l.MaxRequestDuration = maxRequestDuration
}
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
}
// Clear raw values after successful parsing.
l.MaxRequestSizeRaw = nil
l.MaxRequestDurationRaw = nil
l.RequireRequestHeaderRaw = nil
return nil
}
// parseTLSSettings attempts to parse the raw listener TLS settings.
// 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 l.TLSCipherSuitesRaw != "" {
tlsCipherSuites, err := tlsutil.ParseCiphers(l.TLSCipherSuitesRaw)
if err != nil {
return fmt.Errorf("invalid value for tls_cipher_suites: %w", err)
}
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 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
}
// Clear raw values after successful parsing.
l.TLSDisableRaw = nil
l.TLSCipherSuitesRaw = ""
l.TLSRequireAndVerifyClientCertRaw = nil
l.TLSDisableClientCertsRaw = nil
return nil
}
// parseHTTPHeaderSettings attempts to parse the raw listener HTTP header settings.
// The state of the listener will be modified, raw data will be cleared upon
// successful parsing.
func (l *Listener) parseHTTPHeaderSettings() error {
// if CustomResponseHeadersRaw is nil, we still need to set the default headers
customHeadersMap, err := ParseCustomResponseHeaders(l.CustomResponseHeadersRaw)
if err != nil {
return fmt.Errorf("failed to parse custom_response_headers: %w", err)
}
l.CustomResponseHeaders = customHeadersMap
l.CustomResponseHeadersRaw = nil
return nil
}
// parseHTTPTimeoutSettings attempts to parse the raw listener HTTP timeout settings.
// 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 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 l.HTTPWriteTimeoutRaw != nil {
if l.HTTPWriteTimeout, err = parseutil.ParseDurationSecond(l.HTTPWriteTimeoutRaw); 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)
}
}
// Clear raw values after successful parsing.
l.HTTPReadTimeoutRaw = nil
l.HTTPReadHeaderTimeoutRaw = nil
l.HTTPWriteTimeoutRaw = nil
l.HTTPIdleTimeoutRaw = nil
return nil
}
// parseProxySettings attempts to parse the raw listener proxy settings.
// The state of the listener will be modified, raw data will be cleared upon
// successful parsing.
func (l *Listener) parseProxySettings() error {
var err error
if l.ProxyProtocolAuthorizedAddrsRaw != nil {
l.ProxyProtocolAuthorizedAddrs, err = parseutil.ParseAddrs(l.ProxyProtocolAuthorizedAddrsRaw)
if err != nil {
return fmt.Errorf("error parsing proxy_protocol_authorized_addrs: %w", err)
}
}
// Validation/sanity check on allowed settings for behavior.
switch l.ProxyProtocolBehavior {
case "allow_authorized", "deny_authorized", "use_always", "":
// Ignore these cases, they're all valid values.
// In the case of 'allow_authorized' and 'deny_authorized', we don't need
// to check how many addresses we have in ProxyProtocolAuthorizedAddrs
// as parseutil.ParseAddrs returns "one or more addresses" (or an error)
// so we'd have returned earlier.
default:
return fmt.Errorf("unsupported value supplied for proxy_protocol_behavior: %q", l.ProxyProtocolBehavior)
}
// Clear raw values after successful parsing.
l.ProxyProtocolAuthorizedAddrsRaw = nil
return nil
}
// parseForwardedForSettings attempts to parse the raw listener x-forwarded-for settings.
// The state of the listener will be modified, raw data will be cleared upon
// successful parsing.
func (l *Listener) parseForwardedForSettings() error {
var err error
if l.XForwardedForAuthorizedAddrsRaw != nil {
if l.XForwardedForAuthorizedAddrs, err = parseutil.ParseAddrs(l.XForwardedForAuthorizedAddrsRaw); err != nil {
return fmt.Errorf("error parsing x_forwarded_for_authorized_addrs: %w", err)
}
}
if l.XForwardedForHopSkipsRaw != nil {
if l.XForwardedForHopSkips, err = parseutil.ParseInt(l.XForwardedForHopSkipsRaw); err != nil {
return fmt.Errorf("error parsing x_forwarded_for_hop_skips: %w", err)
}
if l.XForwardedForHopSkips < 0 {
return fmt.Errorf("x_forwarded_for_hop_skips cannot be negative but set to %d", l.XForwardedForHopSkips)
}
}
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 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)
}
}
// Clear raw values after successful parsing.
l.XForwardedForAuthorizedAddrsRaw = nil
l.XForwardedForHopSkipsRaw = nil
l.XForwardedForRejectNotAuthorizedRaw = nil
l.XForwardedForRejectNotPresentRaw = nil
return nil
}
// parseTelemetrySettings attempts to parse the raw listener telemetry settings.
// 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)
}
}
l.Telemetry.UnauthenticatedMetricsAccessRaw = nil
return nil
}
// parseProfilingSettings attempts to parse the raw listener profiling settings.
// 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)
}
}
l.Profiling.UnauthenticatedPProfAccessRaw = nil
return nil
}
// parseProfilingSettings attempts to parse the raw listener in-flight request logging settings.
// 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)
}
}
l.InFlightRequestLogging.UnauthenticatedInFlightAccessRaw = nil
return nil
}
// parseCORSSettings attempts to parse the raw listener CORS settings.
// 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 strutil.StrListContains(l.CorsAllowedOrigins, "*") && len(l.CorsAllowedOrigins) > 1 {
return errors.New("cors_allowed_origins must only contain a wildcard or only non-wildcard values")
}
if len(l.CorsAllowedHeadersRaw) > 0 {
for _, header := range l.CorsAllowedHeadersRaw {
l.CorsAllowedHeaders = append(l.CorsAllowedHeaders, textproto.CanonicalMIMEHeaderKey(header))
}
}
l.CorsEnabledRaw = nil
l.CorsAllowedHeadersRaw = nil
return nil return nil
} }

File diff suppressed because it is too large Load Diff