Skip to content

Commit

Permalink
Merge pull request #224 from Miciah/allow-configuring-HTTP-header-nam…
Browse files Browse the repository at this point in the history
…e-case-adjustment

Allow configuring HTTP header name case adjustment
  • Loading branch information
openshift-merge-robot committed Dec 3, 2020
2 parents 7b1d754 + da09224 commit cca042b
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 139 deletions.
13 changes: 13 additions & 0 deletions images/router/haproxy/conf/haproxy-config.template
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ global
tune.maxrewrite 8192
tune.bufsize 32768

{{- range $idx, $adjustment := .HTTPHeaderNameCaseAdjustments }}
h1-case-adjust {{ $adjustment.From }} {{ $adjustment.To }}
{{- end }}

# Configure the TLS versions we support
ssl-default-bind-options ssl-min-ver {{env "SSL_MIN_VERSION" "TLSv1.2"}}
{{- if ne (env "SSL_MAX_VERSION" "") "" }} ssl-max-ver {{env "SSL_MAX_VERSION"}}{{ end }}
Expand Down Expand Up @@ -148,6 +152,9 @@ defaults
{{- if isTrue (env "ROUTER_HTTP_IGNORE_PROBES") }}
option http-ignore-probes
{{- end }}
{{- if .HTTPHeaderNameCaseAdjustments }}
option h1-case-adjust-bogus-client
{{- end }}

{{ if (gt .StatsPort -1) }}
listen stats
Expand Down Expand Up @@ -455,6 +462,12 @@ backend {{genBackendNamePrefix $cfg.TLSTermination}}:{{$cfgIdx}}
{{- end }}
{{- end}}

{{- with $adjustments := $.HTTPHeaderNameCaseAdjustments }}
{{- if isTrue (index $cfg.Annotations "haproxy.router.openshift.io/h1-adjust-case") }}
option h1-case-adjust-bogus-server
{{- end }}
{{- end }}

{{- with $balanceAlgo := firstMatch "roundrobin|leastconn|source" (index $cfg.Annotations "haproxy.router.openshift.io/balance") (env "ROUTER_LOAD_BALANCE_ALGORITHM") }}
balance {{ $balanceAlgo }}
{{- else }}
Expand Down
113 changes: 72 additions & 41 deletions pkg/cmd/infra/router/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,25 +105,27 @@ type TemplateRouterOptions struct {
}

type TemplateRouter struct {
WorkingDir string
TemplateFile string
ReloadScript string
ReloadInterval time.Duration
DefaultCertificate string
DefaultCertificatePath string
DefaultCertificateDir string
DefaultDestinationCAPath string
BindPortsAfterSync bool
MaxConnections string
Ciphers string
StrictSNI bool
MetricsType string
CaptureHTTPRequestHeadersString string
CaptureHTTPResponseHeadersString string
CaptureHTTPCookieString string
CaptureHTTPRequestHeaders []templateplugin.CaptureHTTPHeader
CaptureHTTPResponseHeaders []templateplugin.CaptureHTTPHeader
CaptureHTTPCookie *templateplugin.CaptureHTTPCookie
WorkingDir string
TemplateFile string
ReloadScript string
ReloadInterval time.Duration
DefaultCertificate string
DefaultCertificatePath string
DefaultCertificateDir string
DefaultDestinationCAPath string
BindPortsAfterSync bool
MaxConnections string
Ciphers string
StrictSNI bool
MetricsType string
CaptureHTTPRequestHeadersString string
CaptureHTTPResponseHeadersString string
CaptureHTTPCookieString string
CaptureHTTPRequestHeaders []templateplugin.CaptureHTTPHeader
CaptureHTTPResponseHeaders []templateplugin.CaptureHTTPHeader
CaptureHTTPCookie *templateplugin.CaptureHTTPCookie
HTTPHeaderNameCaseAdjustmentsString string
HTTPHeaderNameCaseAdjustments []templateplugin.HTTPHeaderNameCaseAdjustment

TemplateRouterConfigManager
}
Expand Down Expand Up @@ -179,6 +181,7 @@ func (o *TemplateRouter) Bind(flag *pflag.FlagSet) {
flag.StringVar(&o.CaptureHTTPRequestHeadersString, "capture-http-request-headers", env("ROUTER_CAPTURE_HTTP_REQUEST_HEADERS", ""), "A comma-delimited list of HTTP request header names and maximum header value lengths that should be captured for logging. Each item must have the following form: name:maxLength")
flag.StringVar(&o.CaptureHTTPResponseHeadersString, "capture-http-response-headers", env("ROUTER_CAPTURE_HTTP_RESPONSE_HEADERS", ""), "A comma-delimited list of HTTP response header names and maximum header value lengths that should be captured for logging. Each item must have the following form: name:maxLength")
flag.StringVar(&o.CaptureHTTPCookieString, "capture-http-cookie", env("ROUTER_CAPTURE_HTTP_COOKIE", ""), "Name and maximum length of HTTP cookie that should be captured for logging. The argument must have the following form: name:maxLength. Append '=' to the name to indicate that an exact match should be performed; otherwise a prefix match will be performed. The value of first cookie that matches the name is captured.")
flag.StringVar(&o.HTTPHeaderNameCaseAdjustmentsString, "http-header-name-case-adjustments", env("ROUTER_H1_CASE_ADJUST", ""), "A comma-delimited list of HTTP header names that should have their case adjusted. Each item must be a valid HTTP header name and should have the desired capitalization.")
}

type RouterStats struct {
Expand Down Expand Up @@ -312,6 +315,27 @@ func parseCaptureCookie(in string) (*templateplugin.CaptureHTTPCookie, error) {
}, nil
}

func parseHTTPHeaderNameCaseAdjustments(in string) ([]templateplugin.HTTPHeaderNameCaseAdjustment, error) {
var adjustments []templateplugin.HTTPHeaderNameCaseAdjustment

if len(in) > 0 {
for _, headerName := range strings.Split(in, ",") {
// RFC 2616, section 4.2, states that the header name
// must be a valid token.
if !validTokenRE.MatchString(headerName) {
return adjustments, fmt.Errorf("invalid HTTP header name: %v", headerName)
}
adjustment := templateplugin.HTTPHeaderNameCaseAdjustment{
From: strings.ToLower(headerName),
To: headerName,
}
adjustments = append(adjustments, adjustment)
}
}

return adjustments, nil
}

func (o *TemplateRouterOptions) Complete() error {
routerSvcName := env("ROUTER_SERVICE_NAME", "")
routerSvcNamespace := env("ROUTER_SERVICE_NAMESPACE", "")
Expand Down Expand Up @@ -371,6 +395,12 @@ func (o *TemplateRouterOptions) Complete() error {
}
o.CaptureHTTPCookie = captureHTTPCookie

httpHeaderNameCaseAdjustments, err := parseHTTPHeaderNameCaseAdjustments(o.HTTPHeaderNameCaseAdjustmentsString)
if err != nil {
return err
}
o.HTTPHeaderNameCaseAdjustments = httpHeaderNameCaseAdjustments

return o.RouterSelection.Complete()
}

Expand Down Expand Up @@ -579,28 +609,29 @@ func (o *TemplateRouterOptions) Run(stopCh <-chan struct{}) error {
}

pluginCfg := templateplugin.TemplatePluginConfig{
WorkingDir: o.WorkingDir,
TemplatePath: o.TemplateFile,
ReloadScriptPath: o.ReloadScript,
ReloadInterval: o.ReloadInterval,
ReloadCallbacks: reloadCallbacks,
DefaultCertificate: o.DefaultCertificate,
DefaultCertificatePath: o.DefaultCertificatePath,
DefaultCertificateDir: o.DefaultCertificateDir,
DefaultDestinationCAPath: o.DefaultDestinationCAPath,
StatsPort: statsPort,
StatsUsername: o.StatsUsername,
StatsPassword: o.StatsPassword,
BindPortsAfterSync: o.BindPortsAfterSync,
IncludeUDP: o.RouterSelection.IncludeUDP,
AllowWildcardRoutes: o.RouterSelection.AllowWildcardRoutes,
MaxConnections: o.MaxConnections,
Ciphers: o.Ciphers,
StrictSNI: o.StrictSNI,
DynamicConfigManager: cfgManager,
CaptureHTTPRequestHeaders: o.CaptureHTTPRequestHeaders,
CaptureHTTPResponseHeaders: o.CaptureHTTPResponseHeaders,
CaptureHTTPCookie: o.CaptureHTTPCookie,
WorkingDir: o.WorkingDir,
TemplatePath: o.TemplateFile,
ReloadScriptPath: o.ReloadScript,
ReloadInterval: o.ReloadInterval,
ReloadCallbacks: reloadCallbacks,
DefaultCertificate: o.DefaultCertificate,
DefaultCertificatePath: o.DefaultCertificatePath,
DefaultCertificateDir: o.DefaultCertificateDir,
DefaultDestinationCAPath: o.DefaultDestinationCAPath,
StatsPort: statsPort,
StatsUsername: o.StatsUsername,
StatsPassword: o.StatsPassword,
BindPortsAfterSync: o.BindPortsAfterSync,
IncludeUDP: o.RouterSelection.IncludeUDP,
AllowWildcardRoutes: o.RouterSelection.AllowWildcardRoutes,
MaxConnections: o.MaxConnections,
Ciphers: o.Ciphers,
StrictSNI: o.StrictSNI,
DynamicConfigManager: cfgManager,
CaptureHTTPRequestHeaders: o.CaptureHTTPRequestHeaders,
CaptureHTTPResponseHeaders: o.CaptureHTTPResponseHeaders,
CaptureHTTPCookie: o.CaptureHTTPCookie,
HTTPHeaderNameCaseAdjustments: o.HTTPHeaderNameCaseAdjustments,
}

svcFetcher := templateplugin.NewListWatchServiceLookup(kc.CoreV1(), o.ResyncInterval, o.Namespace)
Expand Down
86 changes: 44 additions & 42 deletions pkg/router/template/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,29 +42,30 @@ func newDefaultTemplatePlugin(router RouterInterface, includeUDP bool, lookupSvc
}

type TemplatePluginConfig struct {
WorkingDir string
TemplatePath string
ReloadScriptPath string
ReloadFn func(shutdown bool) error
ReloadInterval time.Duration
ReloadCallbacks []func()
DefaultCertificate string
DefaultCertificatePath string
DefaultCertificateDir string
DefaultDestinationCAPath string
StatsPort int
StatsUsername string
StatsPassword string
IncludeUDP bool
AllowWildcardRoutes bool
BindPortsAfterSync bool
MaxConnections string
Ciphers string
StrictSNI bool
DynamicConfigManager ConfigManager
CaptureHTTPRequestHeaders []CaptureHTTPHeader
CaptureHTTPResponseHeaders []CaptureHTTPHeader
CaptureHTTPCookie *CaptureHTTPCookie
WorkingDir string
TemplatePath string
ReloadScriptPath string
ReloadFn func(shutdown bool) error
ReloadInterval time.Duration
ReloadCallbacks []func()
DefaultCertificate string
DefaultCertificatePath string
DefaultCertificateDir string
DefaultDestinationCAPath string
StatsPort int
StatsUsername string
StatsPassword string
IncludeUDP bool
AllowWildcardRoutes bool
BindPortsAfterSync bool
MaxConnections string
Ciphers string
StrictSNI bool
DynamicConfigManager ConfigManager
CaptureHTTPRequestHeaders []CaptureHTTPHeader
CaptureHTTPResponseHeaders []CaptureHTTPHeader
CaptureHTTPCookie *CaptureHTTPCookie
HTTPHeaderNameCaseAdjustments []HTTPHeaderNameCaseAdjustment
}

// RouterInterface controls the interaction of the plugin with the underlying router implementation
Expand Down Expand Up @@ -139,25 +140,26 @@ func NewTemplatePlugin(cfg TemplatePluginConfig, lookupSvc ServiceLookup) (*Temp
}

templateRouterCfg := templateRouterCfg{
dir: cfg.WorkingDir,
templates: templates,
reloadScriptPath: cfg.ReloadScriptPath,
reloadFn: cfg.ReloadFn,
reloadInterval: cfg.ReloadInterval,
reloadCallbacks: cfg.ReloadCallbacks,
defaultCertificate: cfg.DefaultCertificate,
defaultCertificatePath: cfg.DefaultCertificatePath,
defaultCertificateDir: cfg.DefaultCertificateDir,
defaultDestinationCAPath: cfg.DefaultDestinationCAPath,
statsUser: cfg.StatsUsername,
statsPassword: cfg.StatsPassword,
statsPort: cfg.StatsPort,
allowWildcardRoutes: cfg.AllowWildcardRoutes,
bindPortsAfterSync: cfg.BindPortsAfterSync,
dynamicConfigManager: cfg.DynamicConfigManager,
captureHTTPRequestHeaders: cfg.CaptureHTTPRequestHeaders,
captureHTTPResponseHeaders: cfg.CaptureHTTPResponseHeaders,
captureHTTPCookie: cfg.CaptureHTTPCookie,
dir: cfg.WorkingDir,
templates: templates,
reloadScriptPath: cfg.ReloadScriptPath,
reloadFn: cfg.ReloadFn,
reloadInterval: cfg.ReloadInterval,
reloadCallbacks: cfg.ReloadCallbacks,
defaultCertificate: cfg.DefaultCertificate,
defaultCertificatePath: cfg.DefaultCertificatePath,
defaultCertificateDir: cfg.DefaultCertificateDir,
defaultDestinationCAPath: cfg.DefaultDestinationCAPath,
statsUser: cfg.StatsUsername,
statsPassword: cfg.StatsPassword,
statsPort: cfg.StatsPort,
allowWildcardRoutes: cfg.AllowWildcardRoutes,
bindPortsAfterSync: cfg.BindPortsAfterSync,
dynamicConfigManager: cfg.DynamicConfigManager,
captureHTTPRequestHeaders: cfg.CaptureHTTPRequestHeaders,
captureHTTPResponseHeaders: cfg.CaptureHTTPResponseHeaders,
captureHTTPCookie: cfg.CaptureHTTPCookie,
httpHeaderNameCaseAdjustments: cfg.HTTPHeaderNameCaseAdjustments,
}
router, err := newTemplateRouter(templateRouterCfg)
return newDefaultTemplatePlugin(router, cfg.IncludeUDP, lookupSvc), err
Expand Down

0 comments on commit cca042b

Please sign in to comment.