package options import ( "fmt" "net/url" "strconv" "strings" "time" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr" "github.com/spf13/pflag" ) type LegacyUpstreams struct { FlushInterval time.Duration `flag:"flush-interval" cfg:"flush_interval"` PassHostHeader bool `flag:"pass-host-header" cfg:"pass_host_header"` ProxyWebSockets bool `flag:"proxy-websockets" cfg:"proxy_websockets"` SSLUpstreamInsecureSkipVerify bool `flag:"ssl-upstream-insecure-skip-verify" cfg:"ssl_upstream_insecure_skip_verify"` Upstreams []string `flag:"upstream" cfg:"upstreams"` Timeout time.Duration `flag:"upstream-timeout" cfg:"upstream_timeout"` DisableKeepAlives bool `flag:"disable-keep-alives" cfg:"disable_keep_alives"` } func legacyUpstreamsFlagSet() *pflag.FlagSet { flagSet := pflag.NewFlagSet("upstreams", pflag.ExitOnError) flagSet.Duration("flush-interval", DefaultUpstreamFlushInterval, "period between response flushing when streaming responses") flagSet.Bool("pass-host-header", true, "pass the request Host Header to upstream") flagSet.Bool("proxy-websockets", true, "enables WebSocket proxying") flagSet.Bool("ssl-upstream-insecure-skip-verify", false, "skip validation of certificates presented when using HTTPS upstreams") flagSet.StringSlice("upstream", []string{}, "the http url(s) of the upstream endpoint, file:// paths for static files or static:// for static response. Routing is based on the path") flagSet.Duration("upstream-timeout", DefaultUpstreamTimeout, "maximum amount of time the server will wait for a response from the upstream") flagSet.Bool("disable-keep-alives", false, "disable HTTP keep-alive connections to the upstream server") return flagSet } func (l *LegacyUpstreams) convert() (UpstreamConfig, error) { upstreams := UpstreamConfig{} for _, upstreamString := range l.Upstreams { u, err := url.Parse(upstreamString) if err != nil { return UpstreamConfig{}, fmt.Errorf("could not parse upstream %q: %v", upstreamString, err) } if u.Path == "" { u.Path = "/" } flushInterval := l.FlushInterval timeout := l.Timeout upstream := Upstream{ ID: u.Path, Path: u.Path, URI: upstreamString, InsecureSkipTLSVerify: &l.SSLUpstreamInsecureSkipVerify, PassHostHeader: &l.PassHostHeader, ProxyWebSockets: &l.ProxyWebSockets, FlushInterval: &flushInterval, Timeout: &timeout, DisableKeepAlives: &l.DisableKeepAlives, } switch u.Scheme { case "file": if u.Fragment != "" { upstream.ID = u.Fragment upstream.Path = u.Fragment // Trim the fragment from the end of the URI upstream.URI = strings.SplitN(upstreamString, "#", 2)[0] } case "static": responseCode, err := strconv.Atoi(u.Host) if err != nil { logger.Errorf("unable to convert %q to int, use default \"200\"", u.Host) responseCode = 200 } upstream.Static = ptr.To(true) upstream.StaticCode = &responseCode // This is not allowed to be empty and must be unique upstream.ID = upstreamString // We only support the root path in the legacy config upstream.Path = "/" // Force defaults compatible with static responses upstream.URI = "" upstream.InsecureSkipTLSVerify = ptr.To(false) upstream.DisableKeepAlives = ptr.To(false) upstream.PassHostHeader = nil upstream.ProxyWebSockets = nil upstream.FlushInterval = nil upstream.Timeout = nil case "unix": upstream.Path = "/" } upstreams.Upstreams = append(upstreams.Upstreams, upstream) } return upstreams, nil }