From 59f4e42a5af56bc360cd38221451ac7f134b4856 Mon Sep 17 00:00:00 2001 From: Sourav Agrawal <146818014+sourava01@users.noreply.github.com> Date: Sat, 17 Jan 2026 19:45:19 +0530 Subject: [PATCH] fix: static upstreams failing validation due to `passHostHeader` and `proxyWebSockets` defaults being set incorrectly (#3302) * fix: static upstream validation failure Signed-off-by: Sourav Agrawal * fix: enforcement of defaults compatible with static upstreams Signed-off-by: Jan Larwig --------- Signed-off-by: Sourav Agrawal Signed-off-by: Jan Larwig Co-authored-by: Jan Larwig --- CHANGELOG.md | 1 + pkg/apis/options/legacy_options.go | 8 ++++---- pkg/apis/options/legacy_options_test.go | 24 ++++++++++++------------ pkg/apis/options/upstreams.go | 24 +++++++++++++++++++++--- pkg/validation/upstreams.go | 6 +++--- pkg/validation/upstreams_test.go | 20 +++++++++++++++++++- 6 files changed, 60 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00412234..5de3022a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ## Changes since v7.14.0 - [#3309](https://github.com/oauth2-proxy/oauth2-proxy/pull/3309) fix: Return 302 redirect from AuthOnly endpoint when skip-provider-button is true (@StefanMarkmann) +- [#3302](https://github.com/oauth2-proxy/oauth2-proxy/pull/3302) fix: static upstreams failing validation due to `passHostHeader` and `proxyWebSockets` defaults being set incorrectly (@sourava01 / @tuunit) # V7.14.0 diff --git a/pkg/apis/options/legacy_options.go b/pkg/apis/options/legacy_options.go index 6ce730fd..b4f37aaf 100644 --- a/pkg/apis/options/legacy_options.go +++ b/pkg/apis/options/legacy_options.go @@ -179,10 +179,10 @@ func (l *LegacyUpstreams) convert() (UpstreamConfig, error) { upstream.URI = "" upstream.InsecureSkipTLSVerify = ptr.To(false) upstream.DisableKeepAlives = ptr.To(false) - upstream.PassHostHeader = nil - upstream.ProxyWebSockets = nil - upstream.FlushInterval = nil - upstream.Timeout = nil + upstream.PassHostHeader = ptr.To(false) + upstream.ProxyWebSockets = ptr.To(false) + upstream.FlushInterval = ptr.To(DefaultUpstreamFlushInterval) + upstream.Timeout = ptr.To(DefaultUpstreamTimeout) case "unix": upstream.Path = "/" } diff --git a/pkg/apis/options/legacy_options_test.go b/pkg/apis/options/legacy_options_test.go index ceba53af..d8d14bb0 100644 --- a/pkg/apis/options/legacy_options_test.go +++ b/pkg/apis/options/legacy_options_test.go @@ -204,12 +204,12 @@ var _ = Describe("Legacy Options", func() { URI: "", Static: ptr.To(true), StaticCode: &validStaticCode, - InsecureSkipTLSVerify: ptr.To(false), - PassHostHeader: nil, - ProxyWebSockets: nil, - FlushInterval: nil, - Timeout: nil, - DisableKeepAlives: ptr.To(false), + InsecureSkipTLSVerify: ptr.To(DefaultUpsteamInsecureSkipTLSVerify), + PassHostHeader: ptr.To(DefaultStaticPassHostHeader), + ProxyWebSockets: ptr.To(DefaultStaticProxyWebSockets), + FlushInterval: ptr.To(DefaultUpstreamFlushInterval), + Timeout: ptr.To(DefaultUpstreamTimeout), + DisableKeepAlives: ptr.To(DefaultUpstreamDisableKeepAlives), } invalidStatic := "static://abc" @@ -220,12 +220,12 @@ var _ = Describe("Legacy Options", func() { URI: "", Static: ptr.To(true), StaticCode: &invalidStaticCode, - InsecureSkipTLSVerify: ptr.To(false), - PassHostHeader: nil, - ProxyWebSockets: nil, - FlushInterval: nil, - Timeout: nil, - DisableKeepAlives: ptr.To(false), + InsecureSkipTLSVerify: ptr.To(DefaultUpsteamInsecureSkipTLSVerify), + PassHostHeader: ptr.To(DefaultStaticPassHostHeader), + ProxyWebSockets: ptr.To(DefaultStaticProxyWebSockets), + FlushInterval: ptr.To(DefaultUpstreamFlushInterval), + Timeout: ptr.To(DefaultUpstreamTimeout), + DisableKeepAlives: ptr.To(DefaultUpstreamDisableKeepAlives), } invalidHTTP := ":foo" diff --git a/pkg/apis/options/upstreams.go b/pkg/apis/options/upstreams.go index a56fca61..578ab454 100644 --- a/pkg/apis/options/upstreams.go +++ b/pkg/apis/options/upstreams.go @@ -29,9 +29,15 @@ const ( // DefaultUpstreamPassHostHeader determines if upstreams will pass the host header by default. DefaultUpstreamPassHostHeader bool = true + // Static upstreams cannot pass the host header. + DefaultStaticPassHostHeader bool = false + // DefaultUpstreamProxyWebSockets determines if upstreams will proxy websockets by default. DefaultUpstreamProxyWebSockets bool = true + // Static upstreams cannot proxy websockets. + DefaultStaticProxyWebSockets bool = false + // DefaultUpstreamDisableKeepAlives determines if upstreams will disable keep-alives by default. DefaultUpstreamDisableKeepAlives bool = false ) @@ -143,19 +149,31 @@ func (u *Upstream) EnsureDefaults() { if u.Static == nil { u.Static = ptr.To(DefaultUpstreamStatic) } - if u.FlushInterval == nil { - u.FlushInterval = ptr.To(DefaultUpstreamFlushInterval) - } if u.PassHostHeader == nil { u.PassHostHeader = ptr.To(DefaultUpstreamPassHostHeader) } if u.ProxyWebSockets == nil { u.ProxyWebSockets = ptr.To(DefaultUpstreamProxyWebSockets) } + if u.FlushInterval == nil { + u.FlushInterval = ptr.To(DefaultUpstreamFlushInterval) + } if u.Timeout == nil { u.Timeout = ptr.To(DefaultUpstreamTimeout) } if u.DisableKeepAlives == nil { u.DisableKeepAlives = ptr.To(DefaultUpstreamDisableKeepAlives) } + + // Force defaults compatible with static upstreams. + // This overrides any user provided values to ensure static upstreams behave correctly. + if ptr.Deref(u.Static, DefaultUpstreamStatic) { + u.URI = "" + u.InsecureSkipTLSVerify = ptr.To(DefaultUpsteamInsecureSkipTLSVerify) + u.DisableKeepAlives = ptr.To(DefaultUpstreamDisableKeepAlives) + u.PassHostHeader = ptr.To(DefaultStaticPassHostHeader) + u.ProxyWebSockets = ptr.To(DefaultStaticProxyWebSockets) + u.FlushInterval = ptr.To(DefaultUpstreamFlushInterval) + u.Timeout = ptr.To(DefaultUpstreamTimeout) + } } diff --git a/pkg/validation/upstreams.go b/pkg/validation/upstreams.go index 9a381918..49edc32e 100644 --- a/pkg/validation/upstreams.go +++ b/pkg/validation/upstreams.go @@ -70,13 +70,13 @@ func validateStaticUpstream(upstream options.Upstream) []string { if ptr.Deref(upstream.InsecureSkipTLSVerify, options.DefaultUpsteamInsecureSkipTLSVerify) { msgs = append(msgs, fmt.Sprintf("upstream %q has insecureSkipTLSVerify, but is a static upstream, this will have no effect.", upstream.ID)) } - if upstream.FlushInterval != nil && *upstream.FlushInterval != options.DefaultUpstreamFlushInterval { + if ptr.Deref(upstream.FlushInterval, options.DefaultUpstreamFlushInterval) != options.DefaultUpstreamFlushInterval { msgs = append(msgs, fmt.Sprintf("upstream %q has flushInterval, but is a static upstream, this will have no effect.", upstream.ID)) } - if upstream.PassHostHeader != nil { + if ptr.Deref(upstream.PassHostHeader, options.DefaultStaticPassHostHeader) != options.DefaultStaticPassHostHeader { msgs = append(msgs, fmt.Sprintf("upstream %q has passHostHeader, but is a static upstream, this will have no effect.", upstream.ID)) } - if upstream.ProxyWebSockets != nil { + if ptr.Deref(upstream.ProxyWebSockets, options.DefaultStaticProxyWebSockets) != options.DefaultStaticProxyWebSockets { msgs = append(msgs, fmt.Sprintf("upstream %q has proxyWebSockets, but is a static upstream, this will have no effect.", upstream.ID)) } diff --git a/pkg/validation/upstreams_test.go b/pkg/validation/upstreams_test.go index 79b29a22..42ef467b 100644 --- a/pkg/validation/upstreams_test.go +++ b/pkg/validation/upstreams_test.go @@ -138,7 +138,7 @@ var _ = Describe("Upstreams", func() { }, errStrings: []string{invalidURISchemeMsg}, }), - Entry("with a static upstream and invalid optons", &validateUpstreamTableInput{ + Entry("with a static upstream and invalid options", &validateUpstreamTableInput{ upstreams: options.UpstreamConfig{ Upstreams: []options.Upstream{ { @@ -161,6 +161,24 @@ var _ = Describe("Upstreams", func() { staticWithProxyWebSocketsMsg, }, }), + Entry("with a static upstream and sane default options", &validateUpstreamTableInput{ + upstreams: options.UpstreamConfig{ + Upstreams: []options.Upstream{ + { + ID: "foo", + Path: "/foo", + URI: "ftp://foo", + Static: ptr.To(true), + PassHostHeader: ptr.To(false), + ProxyWebSockets: ptr.To(false), + InsecureSkipTLSVerify: ptr.To(false), + }, + }, + }, + errStrings: []string{ + staticWithURIMsg, + }, + }), Entry("with duplicate IDs", &validateUpstreamTableInput{ upstreams: options.UpstreamConfig{ Upstreams: []options.Upstream{