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 <souravagr01@gmail.com>

* fix: enforcement of defaults compatible with static upstreams

Signed-off-by: Jan Larwig <jan@larwig.com>

---------

Signed-off-by: Sourav Agrawal <souravagr01@gmail.com>
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
This commit is contained in:
Sourav Agrawal 2026-01-17 19:45:19 +05:30 committed by GitHub
parent 9c61c49ec2
commit 59f4e42a5a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 60 additions and 23 deletions

View File

@ -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

View File

@ -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 = "/"
}

View File

@ -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"

View File

@ -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)
}
}

View File

@ -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))
}

View File

@ -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{