From 9db77384d07b09b6a4cf4ef49330e06696cdf5b7 Mon Sep 17 00:00:00 2001 From: Jan Larwig Date: Tue, 19 Aug 2025 16:27:53 +0200 Subject: [PATCH] feat: migrate all alpha config booleans to pointers Signed-off-by: Jan Larwig --- main_test.go | 73 +++++++++++++------- oauthproxy_test.go | 5 +- pkg/apis/options/header.go | 2 +- pkg/apis/options/legacy_options.go | 29 ++++---- pkg/apis/options/legacy_options_test.go | 88 ++++++++++++------------- pkg/apis/options/providers.go | 26 ++++---- pkg/apis/options/upstreams.go | 12 ++-- pkg/middleware/headers.go | 2 +- pkg/middleware/headers_test.go | 9 +-- pkg/upstream/http.go | 6 +- pkg/upstream/http_test.go | 23 ++++--- pkg/upstream/proxy.go | 4 +- pkg/upstream/proxy_test.go | 11 ++-- pkg/util/ptr/ptr.go | 14 ++++ pkg/util/ptr/ptr_test.go | 38 +++++++++++ pkg/validation/options.go | 2 +- pkg/validation/options_test.go | 5 +- pkg/validation/providers.go | 7 +- pkg/validation/upstreams.go | 10 +-- pkg/validation/upstreams_test.go | 12 ++-- providers/adfs.go | 2 +- providers/adfs_test.go | 3 +- providers/google.go | 4 +- providers/ms_entra_id.go | 2 +- providers/ms_entra_id_test.go | 7 +- providers/oidc.go | 2 +- providers/oidc_test.go | 2 +- providers/providers.go | 8 +-- providers/providers_test.go | 9 +-- 29 files changed, 252 insertions(+), 165 deletions(-) create mode 100644 pkg/util/ptr/ptr.go create mode 100644 pkg/util/ptr/ptr_test.go diff --git a/main_test.go b/main_test.go index 709c6857..b9ec39fb 100644 --- a/main_test.go +++ b/main_test.go @@ -7,6 +7,7 @@ import ( "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options" . "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options/testutil" + "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/onsi/gomega/format" @@ -25,11 +26,12 @@ set_basic_auth="true" basic_auth_password="c3VwZXItc2VjcmV0LXBhc3N3b3Jk" client_id="oauth2-proxy" client_secret="b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK" +google_admin_email="admin@example.com" +google_target_principal="principal" ` const testAlphaConfig = ` upstreamConfig: - proxyrawpath: false upstreams: - id: / path: / @@ -38,8 +40,11 @@ upstreamConfig: passHostHeader: true proxyWebSockets: true timeout: 30s + insecureSkipTLSVerify: false + disableKeepAlives: false injectRequestHeaders: - name: Authorization + preserveRequestValue: false values: - claimSource: claim: user @@ -47,18 +52,22 @@ injectRequestHeaders: basicAuthPassword: value: c3VwZXItc2VjcmV0LXBhc3N3b3Jk - name: X-Forwarded-Groups + preserveRequestValue: false values: - claimSource: claim: groups - name: X-Forwarded-User + preserveRequestValue: false values: - claimSource: claim: user - name: X-Forwarded-Email + preserveRequestValue: false values: - claimSource: claim: email - name: X-Forwarded-Preferred-Username + preserveRequestValue: false values: - claimSource: claim: preferred_username @@ -77,12 +86,17 @@ providers: provider: google clientSecret: b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK clientID: oauth2-proxy - azureConfig: - tenant: common + useSystemTrustStore: false + skipClaimsFromProfileURL: false + googleConfig: + adminEmail: admin@example.com + targetPrincipal: principal + useApplicationDefaultCredentials: false oidcConfig: groupsClaim: groups emailClaim: email userIDClaim: email + insecureSkipIssuerVerification: false insecureSkipNonce: true audienceClaims: [aud] extraAudiences: [] @@ -100,10 +114,6 @@ cookie_secure="false" redirect_url="http://localhost:4180/oauth2/callback" ` - boolPtr := func(b bool) *bool { - return &b - } - durationPtr := func(d time.Duration) *time.Duration { return &d } @@ -120,13 +130,15 @@ redirect_url="http://localhost:4180/oauth2/callback" opts.UpstreamServers = options.UpstreamConfig{ Upstreams: []options.Upstream{ { - ID: "/", - Path: "/", - URI: "http://httpbin", - FlushInterval: durationPtr(options.DefaultUpstreamFlushInterval), - PassHostHeader: boolPtr(true), - ProxyWebSockets: boolPtr(true), - Timeout: durationPtr(options.DefaultUpstreamTimeout), + ID: "/", + Path: "/", + URI: "http://httpbin", + FlushInterval: durationPtr(options.DefaultUpstreamFlushInterval), + PassHostHeader: ptr.Ptr(true), + ProxyWebSockets: ptr.Ptr(true), + Timeout: durationPtr(options.DefaultUpstreamTimeout), + InsecureSkipTLSVerify: ptr.Ptr(false), + DisableKeepAlives: ptr.Ptr(false), }, }, } @@ -146,25 +158,38 @@ redirect_url="http://localhost:4180/oauth2/callback" }, } + authHeader.PreserveRequestValue = ptr.Ptr(false) opts.InjectRequestHeaders = append([]options.Header{authHeader}, opts.InjectRequestHeaders...) + + authHeader.PreserveRequestValue = nil opts.InjectResponseHeaders = append(opts.InjectResponseHeaders, authHeader) opts.Providers = options.Providers{ options.Provider{ - ID: "google=oauth2-proxy", - Type: "google", - ClientSecret: "b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK", - ClientID: "oauth2-proxy", + ID: "google=oauth2-proxy", + Type: "google", + ClientSecret: "b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK", + ClientID: "oauth2-proxy", + UseSystemTrustStore: ptr.Ptr(false), + SkipClaimsFromProfileURL: ptr.Ptr(false), + GoogleConfig: options.GoogleOptions{ + AdminEmail: "admin@example.com", + UseApplicationDefaultCredentials: ptr.Ptr(false), + TargetPrincipal: "principal", + }, AzureConfig: options.AzureOptions{ Tenant: "common", }, OIDCConfig: options.OIDCOptions{ - GroupsClaim: "groups", - EmailClaim: "email", - UserIDClaim: "email", - AudienceClaims: []string{"aud"}, - ExtraAudiences: []string{}, - InsecureSkipNonce: true, + GroupsClaim: "groups", + EmailClaim: "email", + UserIDClaim: "email", + AudienceClaims: []string{"aud"}, + ExtraAudiences: []string{}, + InsecureSkipNonce: ptr.Ptr(true), + InsecureAllowUnverifiedEmail: ptr.Ptr(false), + InsecureSkipIssuerVerification: ptr.Ptr(false), + SkipDiscovery: ptr.Ptr(false), }, LoginURLParameters: []options.LoginURLParameter{ {Name: "approval_prompt", Default: []string{"force"}}, diff --git a/oauthproxy_test.go b/oauthproxy_test.go index 488b8cea..a156214c 100644 --- a/oauthproxy_test.go +++ b/oauthproxy_test.go @@ -23,6 +23,7 @@ import ( internaloidc "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/providers/oidc" sessionscookie "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/sessions/cookie" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/upstream" + "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/validation" "github.com/oauth2-proxy/oauth2-proxy/v7/providers" "github.com/stretchr/testify/assert" @@ -506,7 +507,7 @@ func TestStaticProxyUpstream(t *testing.T) { ProxyUpstream: options.Upstream{ ID: "static-proxy", Path: "/static-proxy", - Static: true, + Static: ptr.Ptr(true), }, }) if err != nil { @@ -2223,7 +2224,7 @@ func TestTrustedIPs(t *testing.T) { { ID: "static", Path: "/", - Static: true, + Static: ptr.Ptr(true), }, }, } diff --git a/pkg/apis/options/header.go b/pkg/apis/options/header.go index 976e4f0a..b50b9582 100644 --- a/pkg/apis/options/header.go +++ b/pkg/apis/options/header.go @@ -11,7 +11,7 @@ type Header struct { // should be preserved for the request to the upstream server. // This option only applies to injected request headers. // Defaults to false (headers that match this header will be stripped). - PreserveRequestValue bool `yaml:"preserveRequestValue"` + PreserveRequestValue *bool `yaml:"preserveRequestValue,omitempty"` // Values contains the desired values for this header Values []HeaderValue `yaml:"values,omitempty"` diff --git a/pkg/apis/options/legacy_options.go b/pkg/apis/options/legacy_options.go index 99746553..e70ae964 100644 --- a/pkg/apis/options/legacy_options.go +++ b/pkg/apis/options/legacy_options.go @@ -9,6 +9,7 @@ import ( "time" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger" + "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr" "github.com/spf13/pflag" ) @@ -142,12 +143,12 @@ func (l *LegacyUpstreams) convert() (UpstreamConfig, error) { ID: u.Path, Path: u.Path, URI: upstreamString, - InsecureSkipTLSVerify: l.SSLUpstreamInsecureSkipVerify, + InsecureSkipTLSVerify: &l.SSLUpstreamInsecureSkipVerify, PassHostHeader: &l.PassHostHeader, ProxyWebSockets: &l.ProxyWebSockets, FlushInterval: &flushInterval, Timeout: &timeout, - DisableKeepAlives: l.DisableKeepAlives, + DisableKeepAlives: &l.DisableKeepAlives, } switch u.Scheme { @@ -164,7 +165,7 @@ func (l *LegacyUpstreams) convert() (UpstreamConfig, error) { logger.Errorf("unable to convert %q to int, use default \"200\"", u.Host) responseCode = 200 } - upstream.Static = true + upstream.Static = ptr.Ptr(true) upstream.StaticCode = &responseCode // This is not allowed to be empty and must be unique @@ -175,12 +176,12 @@ func (l *LegacyUpstreams) convert() (UpstreamConfig, error) { // Force defaults compatible with static responses upstream.URI = "" - upstream.InsecureSkipTLSVerify = false + upstream.InsecureSkipTLSVerify = ptr.Ptr(false) upstream.PassHostHeader = nil upstream.ProxyWebSockets = nil upstream.FlushInterval = nil upstream.Timeout = nil - upstream.DisableKeepAlives = false + upstream.DisableKeepAlives = ptr.Ptr(false) case "unix": upstream.Path = "/" } @@ -253,7 +254,7 @@ func (l *LegacyHeaders) getRequestHeaders() []Header { } for i := range requestHeaders { - requestHeaders[i].PreserveRequestValue = !l.SkipAuthStripHeaders + requestHeaders[i].PreserveRequestValue = ptr.Ptr(!l.SkipAuthStripHeaders) } return requestHeaders @@ -680,11 +681,11 @@ func (l *LegacyProvider) convert() (Providers, error) { ClientSecretFile: l.ClientSecretFile, Type: ProviderType(l.ProviderType), CAFiles: l.ProviderCAFiles, - UseSystemTrustStore: l.UseSystemTrustStore, + UseSystemTrustStore: &l.UseSystemTrustStore, LoginURL: l.LoginURL, RedeemURL: l.RedeemURL, ProfileURL: l.ProfileURL, - SkipClaimsFromProfileURL: l.SkipClaimsFromProfileURL, + SkipClaimsFromProfileURL: &l.SkipClaimsFromProfileURL, ProtectedResource: l.ProtectedResource, ValidateURL: l.ValidateURL, Scope: l.Scope, @@ -697,10 +698,10 @@ func (l *LegacyProvider) convert() (Providers, error) { // This part is out of the switch section for all providers that support OIDC provider.OIDCConfig = OIDCOptions{ IssuerURL: l.OIDCIssuerURL, - InsecureAllowUnverifiedEmail: l.InsecureOIDCAllowUnverifiedEmail, - InsecureSkipIssuerVerification: l.InsecureOIDCSkipIssuerVerification, - InsecureSkipNonce: l.InsecureOIDCSkipNonce, - SkipDiscovery: l.SkipOIDCDiscovery, + InsecureAllowUnverifiedEmail: &l.InsecureOIDCAllowUnverifiedEmail, + InsecureSkipIssuerVerification: &l.InsecureOIDCSkipIssuerVerification, + InsecureSkipNonce: &l.InsecureOIDCSkipNonce, + SkipDiscovery: &l.SkipOIDCDiscovery, JwksURL: l.OIDCJwksURL, UserIDClaim: l.UserIDClaim, EmailClaim: l.OIDCEmailClaim, @@ -768,13 +769,13 @@ func (l *LegacyProvider) convert() (Providers, error) { Groups: l.GoogleGroups, AdminEmail: l.GoogleAdminEmail, ServiceAccountJSON: l.GoogleServiceAccountJSON, - UseApplicationDefaultCredentials: l.GoogleUseApplicationDefaultCredentials, + UseApplicationDefaultCredentials: &l.GoogleUseApplicationDefaultCredentials, TargetPrincipal: l.GoogleTargetPrincipal, } case "entra-id": provider.MicrosoftEntraIDConfig = MicrosoftEntraIDOptions{ AllowedTenants: l.EntraIDAllowedTenants, - FederatedTokenAuth: l.EntraIDFederatedTokenAuth, + FederatedTokenAuth: &l.EntraIDFederatedTokenAuth, } } diff --git a/pkg/apis/options/legacy_options_test.go b/pkg/apis/options/legacy_options_test.go index 98a89601..4348021b 100644 --- a/pkg/apis/options/legacy_options_test.go +++ b/pkg/apis/options/legacy_options_test.go @@ -3,6 +3,7 @@ package options import ( "time" + "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -26,7 +27,6 @@ var _ = Describe("Legacy Options", func() { legacyOpts.LegacyProvider.ClientID = "oauth-proxy" legacyOpts.LegacyUpstreams.DisableKeepAlives = false - truth := true staticCode := 204 opts.UpstreamServers = UpstreamConfig{ Upstreams: []Upstream{ @@ -35,35 +35,35 @@ var _ = Describe("Legacy Options", func() { Path: "/baz", URI: "http://foo.bar/baz", FlushInterval: &flushInterval, - InsecureSkipTLSVerify: true, - PassHostHeader: &truth, - ProxyWebSockets: &truth, + InsecureSkipTLSVerify: ptr.Ptr(true), + PassHostHeader: ptr.Ptr(true), + ProxyWebSockets: ptr.Ptr(true), Timeout: &timeout, - DisableKeepAlives: legacyOpts.LegacyUpstreams.DisableKeepAlives, + DisableKeepAlives: &legacyOpts.LegacyUpstreams.DisableKeepAlives, }, { ID: "/bar", Path: "/bar", URI: "file:///var/lib/website", FlushInterval: &flushInterval, - InsecureSkipTLSVerify: true, - PassHostHeader: &truth, - ProxyWebSockets: &truth, + InsecureSkipTLSVerify: ptr.Ptr(true), + PassHostHeader: ptr.Ptr(true), + ProxyWebSockets: ptr.Ptr(true), Timeout: &timeout, - DisableKeepAlives: legacyOpts.LegacyUpstreams.DisableKeepAlives, + DisableKeepAlives: &legacyOpts.LegacyUpstreams.DisableKeepAlives, }, { ID: "static://204", Path: "/", URI: "", - Static: true, + Static: ptr.Ptr(true), StaticCode: &staticCode, FlushInterval: nil, - InsecureSkipTLSVerify: false, + InsecureSkipTLSVerify: ptr.Ptr(false), PassHostHeader: nil, ProxyWebSockets: nil, Timeout: nil, - DisableKeepAlives: legacyOpts.LegacyUpstreams.DisableKeepAlives, + DisableKeepAlives: &legacyOpts.LegacyUpstreams.DisableKeepAlives, }, }, } @@ -71,7 +71,7 @@ var _ = Describe("Legacy Options", func() { opts.InjectRequestHeaders = []Header{ { Name: "X-Forwarded-Groups", - PreserveRequestValue: false, + PreserveRequestValue: ptr.Ptr(false), Values: []HeaderValue{ { ClaimSource: &ClaimSource{ @@ -82,7 +82,7 @@ var _ = Describe("Legacy Options", func() { }, { Name: "X-Forwarded-User", - PreserveRequestValue: false, + PreserveRequestValue: ptr.Ptr(false), Values: []HeaderValue{ { ClaimSource: &ClaimSource{ @@ -93,7 +93,7 @@ var _ = Describe("Legacy Options", func() { }, { Name: "X-Forwarded-Email", - PreserveRequestValue: false, + PreserveRequestValue: ptr.Ptr(false), Values: []HeaderValue{ { ClaimSource: &ClaimSource{ @@ -104,7 +104,7 @@ var _ = Describe("Legacy Options", func() { }, { Name: "X-Forwarded-Preferred-Username", - PreserveRequestValue: false, + PreserveRequestValue: ptr.Ptr(false), Values: []HeaderValue{ { ClaimSource: &ClaimSource{ @@ -123,7 +123,7 @@ var _ = Describe("Legacy Options", func() { opts.Providers[0].ClientID = "oauth-proxy" opts.Providers[0].ID = "google=oauth-proxy" - opts.Providers[0].OIDCConfig.InsecureSkipNonce = true + opts.Providers[0].OIDCConfig.InsecureSkipNonce = ptr.Ptr(true) opts.Providers[0].OIDCConfig.AudienceClaims = []string{"aud"} opts.Providers[0].OIDCConfig.ExtraAudiences = []string{} opts.Providers[0].LoginURLParameters = []LoginURLParameter{ @@ -157,12 +157,12 @@ var _ = Describe("Legacy Options", func() { ID: "/baz", Path: "/baz", URI: validHTTP, - InsecureSkipTLSVerify: skipVerify, + InsecureSkipTLSVerify: &skipVerify, PassHostHeader: &passHostHeader, ProxyWebSockets: &proxyWebSockets, FlushInterval: &flushInterval, Timeout: &timeout, - DisableKeepAlives: disableKeepAlives, + DisableKeepAlives: &disableKeepAlives, } // Test cases and expected outcomes @@ -171,12 +171,12 @@ var _ = Describe("Legacy Options", func() { ID: "/", Path: "/", URI: emptyPathHTTP, - InsecureSkipTLSVerify: skipVerify, + InsecureSkipTLSVerify: &skipVerify, PassHostHeader: &passHostHeader, ProxyWebSockets: &proxyWebSockets, FlushInterval: &flushInterval, Timeout: &timeout, - DisableKeepAlives: disableKeepAlives, + DisableKeepAlives: &disableKeepAlives, } validFileWithFragment := "file:///var/lib/website#/bar" @@ -184,12 +184,12 @@ var _ = Describe("Legacy Options", func() { ID: "/bar", Path: "/bar", URI: "file:///var/lib/website", - InsecureSkipTLSVerify: skipVerify, + InsecureSkipTLSVerify: &skipVerify, PassHostHeader: &passHostHeader, ProxyWebSockets: &proxyWebSockets, FlushInterval: &flushInterval, Timeout: &timeout, - DisableKeepAlives: disableKeepAlives, + DisableKeepAlives: &disableKeepAlives, } validStatic := "static://204" @@ -198,14 +198,14 @@ var _ = Describe("Legacy Options", func() { ID: validStatic, Path: "/", URI: "", - Static: true, + Static: ptr.Ptr(true), StaticCode: &validStaticCode, - InsecureSkipTLSVerify: false, + InsecureSkipTLSVerify: ptr.Ptr(false), PassHostHeader: nil, ProxyWebSockets: nil, FlushInterval: nil, Timeout: nil, - DisableKeepAlives: false, + DisableKeepAlives: ptr.Ptr(false), } invalidStatic := "static://abc" @@ -214,14 +214,14 @@ var _ = Describe("Legacy Options", func() { ID: invalidStatic, Path: "/", URI: "", - Static: true, + Static: ptr.Ptr(true), StaticCode: &invalidStaticCode, - InsecureSkipTLSVerify: false, + InsecureSkipTLSVerify: ptr.Ptr(false), PassHostHeader: nil, ProxyWebSockets: nil, FlushInterval: nil, Timeout: nil, - DisableKeepAlives: false, + DisableKeepAlives: ptr.Ptr(false), } invalidHTTP := ":foo" @@ -308,13 +308,13 @@ var _ = Describe("Legacy Options", func() { } withPreserveRequestValue := func(h Header, preserve bool) Header { - h.PreserveRequestValue = preserve + h.PreserveRequestValue = &preserve return h } xForwardedUser := Header{ Name: "X-Forwarded-User", - PreserveRequestValue: false, + PreserveRequestValue: ptr.Ptr(false), Values: []HeaderValue{ { ClaimSource: &ClaimSource{ @@ -326,7 +326,7 @@ var _ = Describe("Legacy Options", func() { xForwardedEmail := Header{ Name: "X-Forwarded-Email", - PreserveRequestValue: false, + PreserveRequestValue: ptr.Ptr(false), Values: []HeaderValue{ { ClaimSource: &ClaimSource{ @@ -338,7 +338,7 @@ var _ = Describe("Legacy Options", func() { xForwardedGroups := Header{ Name: "X-Forwarded-Groups", - PreserveRequestValue: false, + PreserveRequestValue: ptr.Ptr(false), Values: []HeaderValue{ { ClaimSource: &ClaimSource{ @@ -350,7 +350,7 @@ var _ = Describe("Legacy Options", func() { xForwardedPreferredUsername := Header{ Name: "X-Forwarded-Preferred-Username", - PreserveRequestValue: false, + PreserveRequestValue: ptr.Ptr(false), Values: []HeaderValue{ { ClaimSource: &ClaimSource{ @@ -362,7 +362,7 @@ var _ = Describe("Legacy Options", func() { basicAuthHeader := Header{ Name: "Authorization", - PreserveRequestValue: false, + PreserveRequestValue: ptr.Ptr(false), Values: []HeaderValue{ { ClaimSource: &ClaimSource{ @@ -378,7 +378,7 @@ var _ = Describe("Legacy Options", func() { xForwardedUserWithEmail := Header{ Name: "X-Forwarded-User", - PreserveRequestValue: false, + PreserveRequestValue: ptr.Ptr(false), Values: []HeaderValue{ { ClaimSource: &ClaimSource{ @@ -390,7 +390,7 @@ var _ = Describe("Legacy Options", func() { xForwardedAccessToken := Header{ Name: "X-Forwarded-Access-Token", - PreserveRequestValue: false, + PreserveRequestValue: ptr.Ptr(false), Values: []HeaderValue{ { ClaimSource: &ClaimSource{ @@ -402,7 +402,7 @@ var _ = Describe("Legacy Options", func() { basicAuthHeaderWithEmail := Header{ Name: "Authorization", - PreserveRequestValue: false, + PreserveRequestValue: ptr.Ptr(false), Values: []HeaderValue{ { ClaimSource: &ClaimSource{ @@ -418,7 +418,7 @@ var _ = Describe("Legacy Options", func() { xAuthRequestUser := Header{ Name: "X-Auth-Request-User", - PreserveRequestValue: false, + PreserveRequestValue: ptr.Ptr(false), Values: []HeaderValue{ { ClaimSource: &ClaimSource{ @@ -430,7 +430,7 @@ var _ = Describe("Legacy Options", func() { xAuthRequestEmail := Header{ Name: "X-Auth-Request-Email", - PreserveRequestValue: false, + PreserveRequestValue: ptr.Ptr(false), Values: []HeaderValue{ { ClaimSource: &ClaimSource{ @@ -442,7 +442,7 @@ var _ = Describe("Legacy Options", func() { xAuthRequestGroups := Header{ Name: "X-Auth-Request-Groups", - PreserveRequestValue: false, + PreserveRequestValue: ptr.Ptr(false), Values: []HeaderValue{ { ClaimSource: &ClaimSource{ @@ -454,7 +454,7 @@ var _ = Describe("Legacy Options", func() { xAuthRequestPreferredUsername := Header{ Name: "X-Auth-Request-Preferred-Username", - PreserveRequestValue: false, + PreserveRequestValue: ptr.Ptr(false), Values: []HeaderValue{ { ClaimSource: &ClaimSource{ @@ -466,7 +466,7 @@ var _ = Describe("Legacy Options", func() { xAuthRequestAccessToken := Header{ Name: "X-Auth-Request-Access-Token", - PreserveRequestValue: false, + PreserveRequestValue: ptr.Ptr(false), Values: []HeaderValue{ { ClaimSource: &ClaimSource{ @@ -478,7 +478,7 @@ var _ = Describe("Legacy Options", func() { authorizationHeader := Header{ Name: "Authorization", - PreserveRequestValue: false, + PreserveRequestValue: ptr.Ptr(false), Values: []HeaderValue{ { ClaimSource: &ClaimSource{ diff --git a/pkg/apis/options/providers.go b/pkg/apis/options/providers.go index 904fd0ac..21f622dd 100644 --- a/pkg/apis/options/providers.go +++ b/pkg/apis/options/providers.go @@ -1,5 +1,7 @@ package options +import "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr" + const ( // OIDCEmailClaim is the generic email claim used by the OIDC provider. OIDCEmailClaim = "email" @@ -67,7 +69,7 @@ type Provider struct { CAFiles []string `yaml:"caFiles,omitempty"` // UseSystemTrustStore determines if your custom CA files and the system trust store are used // If set to true, your custom CA files and the system trust store are used otherwise only your custom CA files. - UseSystemTrustStore bool `yaml:"useSystemTrustStore"` + UseSystemTrustStore *bool `yaml:"useSystemTrustStore,omitempty"` // LoginURL is the authentication endpoint LoginURL string `yaml:"loginURL,omitempty"` // LoginURLParameters defines the parameters that can be passed from the start URL to the IdP login URL @@ -80,7 +82,7 @@ type Provider struct { ProfileURL string `yaml:"profileURL,omitempty"` // SkipClaimsFromProfileURL allows to skip request to Profile URL for resolving claims not present in id_token // default set to 'false' - SkipClaimsFromProfileURL bool `yaml:"skipClaimsFromProfileURL"` + SkipClaimsFromProfileURL *bool `yaml:"skipClaimsFromProfileURL,omitempty"` // ProtectedResource is the resource that is protected (Azure AD and ADFS only) ProtectedResource string `yaml:"resource,omitempty"` // ValidateURL is the access token validation endpoint @@ -181,13 +183,13 @@ type MicrosoftEntraIDOptions struct { // FederatedTokenAuth enable oAuth2 client authentication with federated token projected // by Entra Workload Identity plugin, instead of client secret. - FederatedTokenAuth bool `yaml:"federatedTokenAuth"` + FederatedTokenAuth *bool `yaml:"federatedTokenAuth,omitempty"` } type ADFSOptions struct { // Skip adding the scope parameter in login request // Default value is 'false' - SkipScope bool `yaml:"skipScope"` + SkipScope *bool `yaml:"skipScope,omitempty"` } type BitbucketOptions struct { @@ -227,7 +229,7 @@ type GoogleOptions struct { // ServiceAccountJSON is the path to the service account json credentials ServiceAccountJSON string `yaml:"serviceAccountJson,omitempty"` // UseApplicationDefaultCredentials is a boolean whether to use Application Default Credentials instead of a ServiceAccountJSON - UseApplicationDefaultCredentials bool `yaml:"useApplicationDefaultCredentials"` + UseApplicationDefaultCredentials *bool `yaml:"useApplicationDefaultCredentials,omitempty"` // TargetPrincipal is the Google Service Account used for Application Default Credentials TargetPrincipal string `yaml:"targetPrincipal,omitempty"` } @@ -238,19 +240,19 @@ type OIDCOptions struct { IssuerURL string `yaml:"issuerURL,omitempty"` // InsecureAllowUnverifiedEmail prevents failures if an email address in an id_token is not verified // default set to 'false' - InsecureAllowUnverifiedEmail bool `yaml:"insecureAllowUnverifiedEmail"` + InsecureAllowUnverifiedEmail *bool `yaml:"insecureAllowUnverifiedEmail,omitempty"` // InsecureSkipIssuerVerification skips verification of ID token issuers. When false, ID Token Issuers must match the OIDC discovery URL // default set to 'false' - InsecureSkipIssuerVerification bool `yaml:"insecureSkipIssuerVerification"` + InsecureSkipIssuerVerification *bool `yaml:"insecureSkipIssuerVerification,omitempty"` // InsecureSkipNonce skips verifying the ID Token's nonce claim that must match // the random nonce sent in the initial OAuth flow. Otherwise, the nonce is checked // after the initial OAuth redeem & subsequent token refreshes. // default set to 'true' // Warning: In a future release, this will change to 'false' by default for enhanced security. - InsecureSkipNonce bool `yaml:"insecureSkipNonce"` + InsecureSkipNonce *bool `yaml:"insecureSkipNonce,omitempty"` // SkipDiscovery allows to skip OIDC discovery and use manually supplied Endpoints // default set to 'false' - SkipDiscovery bool `yaml:"skipDiscovery"` + SkipDiscovery *bool `yaml:"skipDiscovery,omitempty"` // JwksURL is the OpenID Connect JWKS URL // eg: https://www.googleapis.com/oauth2/v3/certs JwksURL string `yaml:"jwksURL,omitempty"` @@ -291,9 +293,9 @@ func providerDefaults() Providers { Tenant: "common", }, OIDCConfig: OIDCOptions{ - InsecureAllowUnverifiedEmail: false, - InsecureSkipNonce: true, - SkipDiscovery: false, + InsecureAllowUnverifiedEmail: ptr.Ptr(false), + InsecureSkipNonce: ptr.Ptr(true), + SkipDiscovery: ptr.Ptr(false), UserIDClaim: OIDCEmailClaim, // Deprecated: Use OIDCEmailClaim EmailClaim: OIDCEmailClaim, GroupsClaim: OIDCGroupsClaim, diff --git a/pkg/apis/options/upstreams.go b/pkg/apis/options/upstreams.go index 2b90e632..f12a4bf3 100644 --- a/pkg/apis/options/upstreams.go +++ b/pkg/apis/options/upstreams.go @@ -14,7 +14,7 @@ const ( type UpstreamConfig struct { // ProxyRawPath will pass the raw url path to upstream allowing for urls // like: "/%2F/" which would otherwise be redirected to "/" - ProxyRawPath bool `yaml:"proxyRawPath"` + ProxyRawPath *bool `yaml:"proxyRawPath,omitempty"` // Upstreams represents the configuration for the upstream servers. // Requests will be proxied to this upstream if the path matches the request path. @@ -64,13 +64,13 @@ type Upstream struct { // This option is insecure and will allow potential Man-In-The-Middle attacks // between OAuth2 Proxy and the upstream server. // Defaults to false. - InsecureSkipTLSVerify bool `yaml:"insecureSkipTLSVerify"` + InsecureSkipTLSVerify *bool `yaml:"insecureSkipTLSVerify,omitempty"` // Static will make all requests to this upstream have a static response. // The response will have a body of "Authenticated" and a response code // matching StaticCode. // If StaticCode is not set, the response will return a 200 response. - Static bool `yaml:"static"` + Static *bool `yaml:"static,omitempty"` // StaticCode determines the response code for the Static response. // This option can only be used with Static enabled. @@ -84,11 +84,11 @@ type Upstream struct { // PassHostHeader determines whether the request host header should be proxied // to the upstream server. // Defaults to true. - PassHostHeader *bool `yaml:"passHostHeader"` + PassHostHeader *bool `yaml:"passHostHeader,omitempty"` // ProxyWebSockets enables proxying of websockets to upstream servers // Defaults to true. - ProxyWebSockets *bool `yaml:"proxyWebSockets"` + ProxyWebSockets *bool `yaml:"proxyWebSockets,omitempty"` // Timeout is the maximum duration the server will wait for a response from the upstream server. // Defaults to 30 seconds. @@ -96,5 +96,5 @@ type Upstream struct { // DisableKeepAlives disables HTTP keep-alive connections to the upstream server. // Defaults to false. - DisableKeepAlives bool `yaml:"disableKeepAlives,omitempty"` + DisableKeepAlives *bool `yaml:"disableKeepAlives,omitempty"` } diff --git a/pkg/middleware/headers.go b/pkg/middleware/headers.go index 8d2f8e3e..3fe56d42 100644 --- a/pkg/middleware/headers.go +++ b/pkg/middleware/headers.go @@ -27,7 +27,7 @@ func NewRequestHeaderInjector(headers []options.Header) (alice.Constructor, erro func newStripHeaders(headers []options.Header) alice.Constructor { headersToStrip := []string{} for _, header := range headers { - if !header.PreserveRequestValue { + if !(*header.PreserveRequestValue) { headersToStrip = append(headersToStrip, header.Name) } } diff --git a/pkg/middleware/headers_test.go b/pkg/middleware/headers_test.go index 06440eea..c05a732f 100644 --- a/pkg/middleware/headers_test.go +++ b/pkg/middleware/headers_test.go @@ -8,6 +8,7 @@ import ( middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options" sessionsapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions" + "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -115,7 +116,7 @@ var _ = Describe("Headers Suite", func() { headers: []options.Header{ { Name: "Claim", - PreserveRequestValue: true, + PreserveRequestValue: ptr.Ptr(true), Values: []options.HeaderValue{ { ClaimSource: &options.ClaimSource{ @@ -160,7 +161,7 @@ var _ = Describe("Headers Suite", func() { headers: []options.Header{ { Name: "Claim", - PreserveRequestValue: true, + PreserveRequestValue: ptr.Ptr(true), Values: []options.HeaderValue{ { ClaimSource: &options.ClaimSource{ @@ -341,7 +342,7 @@ var _ = Describe("Headers Suite", func() { headers: []options.Header{ { Name: "Claim", - PreserveRequestValue: true, + PreserveRequestValue: ptr.Ptr(true), Values: []options.HeaderValue{ { ClaimSource: &options.ClaimSource{ @@ -388,7 +389,7 @@ var _ = Describe("Headers Suite", func() { headers: []options.Header{ { Name: "Claim", - PreserveRequestValue: true, + PreserveRequestValue: ptr.Ptr(true), Values: []options.HeaderValue{ { ClaimSource: &options.ClaimSource{ diff --git a/pkg/upstream/http.go b/pkg/upstream/http.go index d9d8f152..9f0d084c 100644 --- a/pkg/upstream/http.go +++ b/pkg/upstream/http.go @@ -54,7 +54,7 @@ func newHTTPUpstreamProxy(upstream options.Upstream, u *url.URL, sigData *option // Set up a WebSocket proxy if required var wsProxy http.Handler if upstream.ProxyWebSockets == nil || *upstream.ProxyWebSockets { - wsProxy = newWebSocketReverseProxy(u, upstream.InsecureSkipTLSVerify) + wsProxy = newWebSocketReverseProxy(u, *upstream.InsecureSkipTLSVerify) } var auth hmacauth.HmacAuth @@ -149,7 +149,7 @@ func newReverseProxy(target *url.URL, upstream options.Upstream, errorHandler Pr // InsecureSkipVerify is a configurable option we allow /* #nosec G402 */ - if upstream.InsecureSkipTLSVerify { + if *upstream.InsecureSkipTLSVerify { transport.TLSClientConfig.InsecureSkipVerify = true } @@ -168,7 +168,7 @@ func newReverseProxy(target *url.URL, upstream options.Upstream, errorHandler Pr // Pass on DisableKeepAlives to the transport settings // to allow for disabling HTTP keep-alive connections - transport.DisableKeepAlives = upstream.DisableKeepAlives + transport.DisableKeepAlives = *upstream.DisableKeepAlives // Apply the customized transport to our proxy before returning it proxy.Transport = transport diff --git a/pkg/upstream/http_test.go b/pkg/upstream/http_test.go index df264c33..7c1831bf 100644 --- a/pkg/upstream/http_test.go +++ b/pkg/upstream/http_test.go @@ -15,6 +15,7 @@ import ( middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/middleware" + "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "golang.org/x/net/websocket" @@ -23,8 +24,6 @@ import ( var _ = Describe("HTTP Upstream Suite", func() { defaultFlushInterval := options.DefaultUpstreamFlushInterval defaultTimeout := options.DefaultUpstreamTimeout - truth := true - falsum := false type httpUpstreamTableInput struct { id string @@ -64,8 +63,8 @@ var _ = Describe("HTTP Upstream Suite", func() { upstream := options.Upstream{ ID: in.id, PassHostHeader: &in.passUpstreamHostHeader, - ProxyWebSockets: &falsum, - InsecureSkipTLSVerify: false, + ProxyWebSockets: ptr.Ptr(false), + InsecureSkipTLSVerify: ptr.Ptr(false), FlushInterval: &flush, Timeout: &timeout, } @@ -343,9 +342,9 @@ var _ = Describe("HTTP Upstream Suite", func() { upstream := options.Upstream{ ID: "noPassHost", - PassHostHeader: &falsum, - ProxyWebSockets: &falsum, - InsecureSkipTLSVerify: false, + PassHostHeader: ptr.Ptr(false), + ProxyWebSockets: ptr.Ptr(false), + InsecureSkipTLSVerify: ptr.Ptr(false), FlushInterval: &defaultFlushInterval, Timeout: &defaultTimeout, } @@ -389,10 +388,10 @@ var _ = Describe("HTTP Upstream Suite", func() { upstream := options.Upstream{ ID: "foo123", FlushInterval: &in.flushInterval, - InsecureSkipTLSVerify: in.skipVerify, + InsecureSkipTLSVerify: &in.skipVerify, ProxyWebSockets: &in.proxyWebSockets, Timeout: &in.timeout, - DisableKeepAlives: in.disableKeepAlives, + DisableKeepAlives: &in.disableKeepAlives, } handler := newHTTPUpstreamProxy(upstream, u, in.sigData, in.errorHandler) @@ -487,9 +486,9 @@ var _ = Describe("HTTP Upstream Suite", func() { timeout := options.DefaultUpstreamTimeout upstream := options.Upstream{ ID: "websocketProxy", - PassHostHeader: &truth, - ProxyWebSockets: &truth, - InsecureSkipTLSVerify: false, + PassHostHeader: ptr.Ptr(true), + ProxyWebSockets: ptr.Ptr(true), + InsecureSkipTLSVerify: ptr.Ptr(false), FlushInterval: &flush, Timeout: &timeout, } diff --git a/pkg/upstream/proxy.go b/pkg/upstream/proxy.go index 74b0d02d..0d2286ea 100644 --- a/pkg/upstream/proxy.go +++ b/pkg/upstream/proxy.go @@ -27,12 +27,12 @@ func NewProxy(upstreams options.UpstreamConfig, sigData *options.SignatureData, serveMux: mux.NewRouter(), } - if upstreams.ProxyRawPath { + if *upstreams.ProxyRawPath { m.serveMux.UseEncodedPath() } for _, upstream := range sortByPathLongest(upstreams.Upstreams) { - if upstream.Static { + if *upstream.Static { if err := m.registerStaticResponseHandler(upstream, writer); err != nil { return nil, fmt.Errorf("could not register static upstream %q: %v", upstream.ID, err) } diff --git a/pkg/upstream/proxy_test.go b/pkg/upstream/proxy_test.go index 5252bd42..87aae7fa 100644 --- a/pkg/upstream/proxy_test.go +++ b/pkg/upstream/proxy_test.go @@ -10,6 +10,7 @@ import ( middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/app/pagewriter" + "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -60,19 +61,19 @@ var _ = Describe("Proxy Suite", func() { { ID: "static-backend", Path: "/static/", - Static: true, + Static: ptr.Ptr(true), StaticCode: &ok, }, { ID: "static-backend-no-trailing-slash", Path: "/static", - Static: true, + Static: ptr.Ptr(true), StaticCode: &accepted, }, { ID: "static-backend-long", Path: "/static/long", - Static: true, + Static: ptr.Ptr(true), StaticCode: &accepted, }, { @@ -83,7 +84,7 @@ var _ = Describe("Proxy Suite", func() { { ID: "single-path-backend", Path: "/single-path", - Static: true, + Static: ptr.Ptr(true), StaticCode: &ok, }, { @@ -346,7 +347,7 @@ var _ = Describe("Proxy Suite", func() { upstream: "", }), Entry("containing an escaped '/' with ProxyRawPath", &proxyTableInput{ - upstreams: options.UpstreamConfig{ProxyRawPath: true}, + upstreams: options.UpstreamConfig{ProxyRawPath: ptr.Ptr(true)}, target: "http://example.localhost/%2F/test1/%2F/test2", response: testHTTPResponse{ code: 404, diff --git a/pkg/util/ptr/ptr.go b/pkg/util/ptr/ptr.go new file mode 100644 index 00000000..9242773c --- /dev/null +++ b/pkg/util/ptr/ptr.go @@ -0,0 +1,14 @@ +package ptr + +// Ptr generically returns a pointer to the given value. +func Ptr[T any](v T) *T { + return &v +} + +// Deref returns the value of the pointer or def(ault) if nil. +func Deref[T any](p *T, def T) T { + if p == nil { + return def + } + return *p +} diff --git a/pkg/util/ptr/ptr_test.go b/pkg/util/ptr/ptr_test.go new file mode 100644 index 00000000..c4817a6b --- /dev/null +++ b/pkg/util/ptr/ptr_test.go @@ -0,0 +1,38 @@ +package ptr + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestPtr(t *testing.T) { + p := Ptr(42) + assert.NotNil(t, p) + assert.Equal(t, 42, *p) + + s := Ptr("hello") + assert.NotNil(t, s) + assert.Equal(t, "hello", *s) + + b := Ptr(true) + assert.NotNil(t, b) + assert.True(t, *b) +} + +func TestDeref(t *testing.T) { + v := Deref(Ptr(99), 0) + assert.Equal(t, 99, v) + + v = Deref[int](nil, 123) + assert.Equal(t, 123, v) + + s := Deref[string](nil, "default") + assert.Equal(t, "default", s) + + b := Deref(Ptr(true), false) + assert.True(t, b) + + b = Deref[bool](nil, false) + assert.False(t, b) +} diff --git a/pkg/validation/options.go b/pkg/validation/options.go index c720f47e..cd51c40c 100644 --- a/pkg/validation/options.go +++ b/pkg/validation/options.go @@ -34,7 +34,7 @@ func Validate(o *options.Options) error { transport := requests.DefaultTransport.(*http.Transport) transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} // #nosec G402 -- InsecureSkipVerify is a configurable option we allow } else if len(o.Providers[0].CAFiles) > 0 { - pool, err := util.GetCertPool(o.Providers[0].CAFiles, o.Providers[0].UseSystemTrustStore) + pool, err := util.GetCertPool(o.Providers[0].CAFiles, *o.Providers[0].UseSystemTrustStore) if err == nil { transport := requests.DefaultTransport.(*http.Transport) transport.TLSClientConfig = &tls.Config{ diff --git a/pkg/validation/options_test.go b/pkg/validation/options_test.go index 5c283545..6657e847 100644 --- a/pkg/validation/options_test.go +++ b/pkg/validation/options_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options" + "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr" "github.com/stretchr/testify/assert" ) @@ -68,7 +69,7 @@ func TestGoogleGroupOptionsWithoutServiceAccountJSON(t *testing.T) { func TestGoogleGroupOptionsWithoutAdminEmail(t *testing.T) { o := testOptions() - o.Providers[0].GoogleConfig.UseApplicationDefaultCredentials = true + o.Providers[0].GoogleConfig.UseApplicationDefaultCredentials = ptr.Ptr(true) err := Validate(o) assert.NotEqual(t, nil, err) @@ -81,7 +82,7 @@ func TestGoogleGroupOptionsWithoutGroups(t *testing.T) { o := testOptions() // Set admin email and application default credentials but no groups - should still require them o.Providers[0].GoogleConfig.AdminEmail = "admin@example.com" - o.Providers[0].GoogleConfig.UseApplicationDefaultCredentials = true + o.Providers[0].GoogleConfig.UseApplicationDefaultCredentials = ptr.Ptr(true) err := Validate(o) // Should pass validation since google-group is now optional assert.Equal(t, nil, err) diff --git a/pkg/validation/providers.go b/pkg/validation/providers.go index 4527b841..3abf69d4 100644 --- a/pkg/validation/providers.go +++ b/pkg/validation/providers.go @@ -5,6 +5,7 @@ import ( "os" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options" + "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr" ) // validateProviders is the initial validation migration for multiple providrers @@ -64,7 +65,7 @@ func validateProvider(provider options.Provider, providerIDs map[string]struct{} // providerRequiresClientSecret checks if provider requires client secret to be set // or it can be omitted in favor of JWT token to authenticate oAuth client func providerRequiresClientSecret(provider options.Provider) bool { - if provider.Type == "entra-id" && provider.MicrosoftEntraIDConfig.FederatedTokenAuth { + if provider.Type == "entra-id" && *provider.MicrosoftEntraIDConfig.FederatedTokenAuth { return false } @@ -96,7 +97,7 @@ func validateGoogleConfig(provider options.Provider) []string { hasAdminEmail := provider.GoogleConfig.AdminEmail != "" hasSAJSON := provider.GoogleConfig.ServiceAccountJSON != "" - useADC := provider.GoogleConfig.UseApplicationDefaultCredentials + useADC := ptr.Deref(provider.GoogleConfig.UseApplicationDefaultCredentials, false) if !hasAdminEmail && !hasSAJSON && !useADC { return msgs @@ -123,7 +124,7 @@ func validateGoogleConfig(provider options.Provider) []string { func validateEntraConfig(provider options.Provider) []string { msgs := []string{} - if provider.MicrosoftEntraIDConfig.FederatedTokenAuth { + if *provider.MicrosoftEntraIDConfig.FederatedTokenAuth { federatedTokenPath := os.Getenv("AZURE_FEDERATED_TOKEN_FILE") if federatedTokenPath == "" { diff --git a/pkg/validation/upstreams.go b/pkg/validation/upstreams.go index 52facb4d..05d441e3 100644 --- a/pkg/validation/upstreams.go +++ b/pkg/validation/upstreams.go @@ -54,19 +54,19 @@ func validateUpstream(upstream options.Upstream, ids, paths map[string]struct{}) func validateStaticUpstream(upstream options.Upstream) []string { msgs := []string{} - if !upstream.Static && upstream.StaticCode != nil { + if !*upstream.Static && upstream.StaticCode != nil { msgs = append(msgs, fmt.Sprintf("upstream %q has staticCode (%d), but is not a static upstream, set 'static' for a static response", upstream.ID, *upstream.StaticCode)) } // Checks after this only make sense when the upstream is static - if !upstream.Static { + if !*upstream.Static { return msgs } if upstream.URI != "" { msgs = append(msgs, fmt.Sprintf("upstream %q has uri, but is a static upstream, this will have no effect.", upstream.ID)) } - if upstream.InsecureSkipTLSVerify { + if *upstream.InsecureSkipTLSVerify { 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 { @@ -85,13 +85,13 @@ func validateStaticUpstream(upstream options.Upstream) []string { func validateUpstreamURI(upstream options.Upstream) []string { msgs := []string{} - if !upstream.Static && upstream.URI == "" { + if !*upstream.Static && upstream.URI == "" { msgs = append(msgs, fmt.Sprintf("upstream %q has empty uri: uris are required for all non-static upstreams", upstream.ID)) return msgs } // Checks after this only make sense the upstream is not static - if upstream.Static { + if *upstream.Static { return msgs } diff --git a/pkg/validation/upstreams_test.go b/pkg/validation/upstreams_test.go index 67991b76..580e2f29 100644 --- a/pkg/validation/upstreams_test.go +++ b/pkg/validation/upstreams_test.go @@ -4,6 +4,7 @@ import ( "time" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options" + "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -16,7 +17,6 @@ var _ = Describe("Upstreams", func() { flushInterval := 5 * time.Second staticCode200 := 200 - truth := true validHTTPUpstream := options.Upstream{ ID: "validHTTPUpstream", @@ -26,7 +26,7 @@ var _ = Describe("Upstreams", func() { validStaticUpstream := options.Upstream{ ID: "validStaticUpstream", Path: "/validStaticUpstream", - Static: true, + Static: ptr.Ptr(true), } validFileUpstream := options.Upstream{ ID: "validFileUpstream", @@ -145,11 +145,11 @@ var _ = Describe("Upstreams", func() { ID: "foo", Path: "/foo", URI: "ftp://foo", - Static: true, + Static: ptr.Ptr(true), FlushInterval: &flushInterval, - PassHostHeader: &truth, - ProxyWebSockets: &truth, - InsecureSkipTLSVerify: true, + PassHostHeader: ptr.Ptr(true), + ProxyWebSockets: ptr.Ptr(true), + InsecureSkipTLSVerify: ptr.Ptr(true), }, }, }, diff --git a/providers/adfs.go b/providers/adfs.go index 0facfdcf..6615f38c 100644 --- a/providers/adfs.go +++ b/providers/adfs.go @@ -50,7 +50,7 @@ func NewADFSProvider(p *ProviderData, opts options.Provider) *ADFSProvider { return &ADFSProvider{ OIDCProvider: oidcProvider, - skipScope: opts.ADFSConfig.SkipScope, + skipScope: *opts.ADFSConfig.SkipScope, oidcEnrichFunc: oidcProvider.EnrichSession, oidcRefreshFunc: oidcProvider.RefreshSession, } diff --git a/providers/adfs_test.go b/providers/adfs_test.go index 0b730430..edcb9307 100755 --- a/providers/adfs_test.go +++ b/providers/adfs_test.go @@ -16,6 +16,7 @@ import ( "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions" internaloidc "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/providers/oidc" + "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -172,7 +173,7 @@ var _ = Describe("ADFS Provider Tests", func() { ProtectedResource: resource, Scope: "", }, options.Provider{ - ADFSConfig: options.ADFSOptions{SkipScope: true}, + ADFSConfig: options.ADFSOptions{SkipScope: ptr.Ptr(true)}, }) result := p.GetLoginURL("https://example.com/adfs/oauth2/", "", "", url.Values{}) diff --git a/providers/google.go b/providers/google.go index 097e3567..7926c71b 100644 --- a/providers/google.go +++ b/providers/google.go @@ -102,7 +102,7 @@ func NewGoogleProvider(p *ProviderData, opts options.GoogleOptions) (*GoogleProv }, } - if opts.ServiceAccountJSON != "" || opts.UseApplicationDefaultCredentials { + if opts.ServiceAccountJSON != "" || *opts.UseApplicationDefaultCredentials { provider.configureGroups(opts) } @@ -259,7 +259,7 @@ var possibleScopesList = [...]string{ } func getOauth2TokenSource(ctx context.Context, opts options.GoogleOptions, scope string) oauth2.TokenSource { - if opts.UseApplicationDefaultCredentials { + if *opts.UseApplicationDefaultCredentials { ts, err := impersonate.CredentialsTokenSource(ctx, impersonate.CredentialsConfig{ TargetPrincipal: getTargetPrincipal(ctx, opts), Scopes: []string{scope}, diff --git a/providers/ms_entra_id.go b/providers/ms_entra_id.go index df1f38a4..752f9f44 100644 --- a/providers/ms_entra_id.go +++ b/providers/ms_entra_id.go @@ -51,7 +51,7 @@ func NewMicrosoftEntraIDProvider(p *ProviderData, opts options.Provider) *Micros OIDCProvider: NewOIDCProvider(p, opts.OIDCConfig), multiTenantAllowedTenants: opts.MicrosoftEntraIDConfig.AllowedTenants, - federatedTokenAuth: opts.MicrosoftEntraIDConfig.FederatedTokenAuth, + federatedTokenAuth: *opts.MicrosoftEntraIDConfig.FederatedTokenAuth, microsoftGraphURL: microsoftGraphURL, } } diff --git a/providers/ms_entra_id_test.go b/providers/ms_entra_id_test.go index dfd1ef99..7b720c91 100644 --- a/providers/ms_entra_id_test.go +++ b/providers/ms_entra_id_test.go @@ -13,6 +13,7 @@ import ( "github.com/coreos/go-oidc/v3/oidc" "github.com/golang-jwt/jwt/v5" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options" + "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr" "github.com/stretchr/testify/assert" . "github.com/onsi/gomega" @@ -24,7 +25,7 @@ func TestAzureEntraOIDCProviderNewMultiTenant(t *testing.T) { provider := NewMicrosoftEntraIDProvider(&ProviderData{}, options.Provider{OIDCConfig: options.OIDCOptions{ IssuerURL: "https://login.microsoftonline.com/common/v2.0", - InsecureSkipIssuerVerification: true, + InsecureSkipIssuerVerification: ptr.Ptr(true), }}, ) g.Expect(provider.Data().ProviderName).To(Equal("Microsoft Entra ID")) @@ -90,8 +91,8 @@ func TestAzureEntraOIDCProviderValidateSessionAllowedTenants(t *testing.T) { options.Provider{ OIDCConfig: options.OIDCOptions{ IssuerURL: "https://login.microsoftonline.com/common/v2.0", - InsecureSkipIssuerVerification: true, - InsecureSkipNonce: true, + InsecureSkipIssuerVerification: ptr.Ptr(true), + InsecureSkipNonce: ptr.Ptr(true), }, MicrosoftEntraIDConfig: options.MicrosoftEntraIDOptions{ AllowedTenants: []string{"85d7d600-7804-4d92-8d43-9c33c21c130c"}, diff --git a/providers/oidc.go b/providers/oidc.go index 15598aba..9a88b46c 100644 --- a/providers/oidc.go +++ b/providers/oidc.go @@ -50,7 +50,7 @@ func NewOIDCProvider(p *ProviderData, opts options.OIDCOptions) *OIDCProvider { return &OIDCProvider{ ProviderData: p, - SkipNonce: opts.InsecureSkipNonce, + SkipNonce: *opts.InsecureSkipNonce, } } diff --git a/providers/oidc_test.go b/providers/oidc_test.go index 81a70eb4..61f4762e 100644 --- a/providers/oidc_test.go +++ b/providers/oidc_test.go @@ -63,7 +63,7 @@ func newOIDCProvider(serverURL *url.URL, skipNonce bool) *OIDCProvider { } p := NewOIDCProvider(providerData, options.OIDCOptions{ - InsecureSkipNonce: skipNonce, + InsecureSkipNonce: &skipNonce, }) return p diff --git a/providers/providers.go b/providers/providers.go index ec00f412..84f5ec91 100644 --- a/providers/providers.go +++ b/providers/providers.go @@ -98,8 +98,8 @@ func newProviderDataFromConfig(providerConfig options.Provider) (*ProviderData, IssuerURL: providerConfig.OIDCConfig.IssuerURL, JWKsURL: providerConfig.OIDCConfig.JwksURL, PublicKeyFiles: providerConfig.OIDCConfig.PublicKeyFiles, - SkipDiscovery: providerConfig.OIDCConfig.SkipDiscovery, - SkipIssuerVerification: providerConfig.OIDCConfig.InsecureSkipIssuerVerification, + SkipDiscovery: *providerConfig.OIDCConfig.SkipDiscovery, + SkipIssuerVerification: *providerConfig.OIDCConfig.InsecureSkipIssuerVerification, }) if err != nil { return nil, fmt.Errorf("error building OIDC ProviderVerifier: %v", err) @@ -143,10 +143,10 @@ func newProviderDataFromConfig(providerConfig options.Provider) (*ProviderData, } // Make the OIDC options available to all providers that support it - p.AllowUnverifiedEmail = providerConfig.OIDCConfig.InsecureAllowUnverifiedEmail + p.AllowUnverifiedEmail = *providerConfig.OIDCConfig.InsecureAllowUnverifiedEmail p.EmailClaim = providerConfig.OIDCConfig.EmailClaim p.GroupsClaim = providerConfig.OIDCConfig.GroupsClaim - p.SkipClaimsFromProfileURL = providerConfig.SkipClaimsFromProfileURL + p.SkipClaimsFromProfileURL = *providerConfig.SkipClaimsFromProfileURL // Set PKCE enabled or disabled based on discovery and force options p.CodeChallengeMethod = parseCodeChallengeMethod(providerConfig) diff --git a/providers/providers_test.go b/providers/providers_test.go index 82961d84..9591dc65 100644 --- a/providers/providers_test.go +++ b/providers/providers_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options" + "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr" . "github.com/onsi/gomega" ) @@ -81,7 +82,7 @@ func TestSkipOIDCDiscovery(t *testing.T) { ClientSecretFile: clientSecret, OIDCConfig: options.OIDCOptions{ IssuerURL: msIssuerURL, - SkipDiscovery: true, + SkipDiscovery: ptr.Ptr(true), }, } @@ -108,7 +109,7 @@ func TestURLsCorrectlyParsed(t *testing.T) { RedeemURL: msTokenURL, OIDCConfig: options.OIDCOptions{ IssuerURL: msIssuerURL, - SkipDiscovery: true, + SkipDiscovery: ptr.Ptr(true), JwksURL: msKeysURL, }, } @@ -216,7 +217,7 @@ func TestScope(t *testing.T) { AllowedGroups: tc.allowedGroups, OIDCConfig: options.OIDCOptions{ IssuerURL: msIssuerURL, - SkipDiscovery: true, + SkipDiscovery: ptr.Ptr(true), JwksURL: msKeysURL, }, } @@ -297,7 +298,7 @@ func TestEmailClaimCorrectlySet(t *testing.T) { RedeemURL: msTokenURL, OIDCConfig: options.OIDCOptions{ IssuerURL: msIssuerURL, - SkipDiscovery: true, + SkipDiscovery: ptr.Ptr(true), JwksURL: msKeysURL, UserIDClaim: tc.userIDClaim, EmailClaim: tc.emailClaim,