258 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			258 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Go
		
	
	
	
package main
 | 
						|
 | 
						|
import (
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"io/ioutil"
 | 
						|
	"os"
 | 
						|
	"strings"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
 | 
						|
	. "github.com/onsi/ginkgo"
 | 
						|
	. "github.com/onsi/ginkgo/extensions/table"
 | 
						|
	. "github.com/onsi/gomega"
 | 
						|
	"github.com/spf13/pflag"
 | 
						|
)
 | 
						|
 | 
						|
var _ = Describe("Configuration Loading Suite", func() {
 | 
						|
	const testLegacyConfig = `
 | 
						|
http_address="127.0.0.1:4180"
 | 
						|
upstreams="http://httpbin"
 | 
						|
set_basic_auth="true"
 | 
						|
basic_auth_password="super-secret-password"
 | 
						|
client_id="oauth2-proxy"
 | 
						|
client_secret="b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK"
 | 
						|
`
 | 
						|
 | 
						|
	const testAlphaConfig = `
 | 
						|
upstreamConfig:
 | 
						|
  proxyrawpath: false
 | 
						|
  upstreams:
 | 
						|
  - id: /
 | 
						|
    path: /
 | 
						|
    uri: http://httpbin
 | 
						|
    flushInterval: 1s
 | 
						|
    passHostHeader: true
 | 
						|
    proxyWebSockets: true
 | 
						|
injectRequestHeaders:
 | 
						|
- name: Authorization
 | 
						|
  values:
 | 
						|
  - claim: user
 | 
						|
    prefix: "Basic "
 | 
						|
    basicAuthPassword:
 | 
						|
      value: c3VwZXItc2VjcmV0LXBhc3N3b3Jk
 | 
						|
- name: X-Forwarded-Groups
 | 
						|
  values:
 | 
						|
  - claim: groups
 | 
						|
- name: X-Forwarded-User
 | 
						|
  values:
 | 
						|
  - claim: user
 | 
						|
- name: X-Forwarded-Email
 | 
						|
  values:
 | 
						|
  - claim: email
 | 
						|
- name: X-Forwarded-Preferred-Username
 | 
						|
  values:
 | 
						|
  - claim: preferred_username
 | 
						|
injectResponseHeaders:
 | 
						|
- name: Authorization
 | 
						|
  values:
 | 
						|
  - claim: user
 | 
						|
    prefix: "Basic "
 | 
						|
    basicAuthPassword:
 | 
						|
      value: c3VwZXItc2VjcmV0LXBhc3N3b3Jk
 | 
						|
server:
 | 
						|
  bindAddress: "127.0.0.1:4180"
 | 
						|
providers:
 | 
						|
- provider: google
 | 
						|
  ID: google=oauth2-proxy
 | 
						|
  clientSecret: b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK
 | 
						|
  clientID: oauth2-proxy
 | 
						|
  azureConfig:
 | 
						|
    tenant: common
 | 
						|
  oidcConfig:
 | 
						|
    groupsClaim: groups
 | 
						|
    emailClaim: email
 | 
						|
    userIDClaim: email
 | 
						|
    insecureSkipNonce: true
 | 
						|
    audienceClaims: [aud]
 | 
						|
    extraAudiences: []
 | 
						|
  loginURLParameters:
 | 
						|
  - name: approval_prompt
 | 
						|
    default:
 | 
						|
    - force
 | 
						|
`
 | 
						|
 | 
						|
	const testCoreConfig = `
 | 
						|
cookie_secret="OQINaROshtE9TcZkNAm-5Zs2Pv3xaWytBmc5W7sPX7w="
 | 
						|
email_domains="example.com"
 | 
						|
cookie_secure="false"
 | 
						|
 | 
						|
redirect_url="http://localhost:4180/oauth2/callback"
 | 
						|
`
 | 
						|
 | 
						|
	boolPtr := func(b bool) *bool {
 | 
						|
		return &b
 | 
						|
	}
 | 
						|
 | 
						|
	durationPtr := func(d time.Duration) *options.Duration {
 | 
						|
		du := options.Duration(d)
 | 
						|
		return &du
 | 
						|
	}
 | 
						|
 | 
						|
	testExpectedOptions := func() *options.Options {
 | 
						|
		opts, err := options.NewLegacyOptions().ToOptions()
 | 
						|
		Expect(err).ToNot(HaveOccurred())
 | 
						|
 | 
						|
		opts.Cookie.Secret = "OQINaROshtE9TcZkNAm-5Zs2Pv3xaWytBmc5W7sPX7w="
 | 
						|
		opts.EmailDomains = []string{"example.com"}
 | 
						|
		opts.Cookie.Secure = false
 | 
						|
		opts.RawRedirectURL = "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),
 | 
						|
				},
 | 
						|
			},
 | 
						|
		}
 | 
						|
 | 
						|
		authHeader := options.Header{
 | 
						|
			Name: "Authorization",
 | 
						|
			Values: []options.HeaderValue{
 | 
						|
				{
 | 
						|
					ClaimSource: &options.ClaimSource{
 | 
						|
						Claim:  "user",
 | 
						|
						Prefix: "Basic ",
 | 
						|
						BasicAuthPassword: &options.SecretSource{
 | 
						|
							Value: []byte("super-secret-password"),
 | 
						|
						},
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
		}
 | 
						|
 | 
						|
		opts.InjectRequestHeaders = append([]options.Header{authHeader}, opts.InjectRequestHeaders...)
 | 
						|
		opts.InjectResponseHeaders = append(opts.InjectResponseHeaders, authHeader)
 | 
						|
 | 
						|
		opts.Providers = options.Providers{
 | 
						|
			options.Provider{
 | 
						|
				ID:           "google=oauth2-proxy",
 | 
						|
				Type:         "google",
 | 
						|
				ClientSecret: "b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK",
 | 
						|
				ClientID:     "oauth2-proxy",
 | 
						|
				AzureConfig: options.AzureOptions{
 | 
						|
					Tenant: "common",
 | 
						|
				},
 | 
						|
				OIDCConfig: options.OIDCOptions{
 | 
						|
					GroupsClaim:       "groups",
 | 
						|
					EmailClaim:        "email",
 | 
						|
					UserIDClaim:       "email",
 | 
						|
					AudienceClaims:    []string{"aud"},
 | 
						|
					ExtraAudiences:    []string{},
 | 
						|
					InsecureSkipNonce: true,
 | 
						|
				},
 | 
						|
				LoginURLParameters: []options.LoginURLParameter{
 | 
						|
					{Name: "approval_prompt", Default: []string{"force"}},
 | 
						|
				},
 | 
						|
			},
 | 
						|
		}
 | 
						|
		return opts
 | 
						|
	}
 | 
						|
 | 
						|
	type loadConfigurationTableInput struct {
 | 
						|
		configContent      string
 | 
						|
		alphaConfigContent string
 | 
						|
		args               []string
 | 
						|
		extraFlags         func() *pflag.FlagSet
 | 
						|
		expectedOptions    func() *options.Options
 | 
						|
		expectedErr        error
 | 
						|
	}
 | 
						|
 | 
						|
	DescribeTable("LoadConfiguration",
 | 
						|
		func(in loadConfigurationTableInput) {
 | 
						|
			var configFileName, alphaConfigFileName string
 | 
						|
 | 
						|
			defer func() {
 | 
						|
				if configFileName != "" {
 | 
						|
					Expect(os.Remove(configFileName)).To(Succeed())
 | 
						|
				}
 | 
						|
				if alphaConfigFileName != "" {
 | 
						|
					Expect(os.Remove(alphaConfigFileName)).To(Succeed())
 | 
						|
				}
 | 
						|
			}()
 | 
						|
 | 
						|
			if in.configContent != "" {
 | 
						|
				By("Writing the config to a temporary file", func() {
 | 
						|
					file, err := ioutil.TempFile("", "oauth2-proxy-test-config-XXXX.cfg")
 | 
						|
					Expect(err).ToNot(HaveOccurred())
 | 
						|
					defer file.Close()
 | 
						|
 | 
						|
					configFileName = file.Name()
 | 
						|
 | 
						|
					_, err = file.WriteString(in.configContent)
 | 
						|
					Expect(err).ToNot(HaveOccurred())
 | 
						|
				})
 | 
						|
			}
 | 
						|
 | 
						|
			if in.alphaConfigContent != "" {
 | 
						|
				By("Writing the config to a temporary file", func() {
 | 
						|
					file, err := ioutil.TempFile("", "oauth2-proxy-test-alpha-config-XXXX.yaml")
 | 
						|
					Expect(err).ToNot(HaveOccurred())
 | 
						|
					defer file.Close()
 | 
						|
 | 
						|
					alphaConfigFileName = file.Name()
 | 
						|
 | 
						|
					_, err = file.WriteString(in.alphaConfigContent)
 | 
						|
					Expect(err).ToNot(HaveOccurred())
 | 
						|
				})
 | 
						|
			}
 | 
						|
 | 
						|
			extraFlags := pflag.NewFlagSet("test-flagset", pflag.ExitOnError)
 | 
						|
			if in.extraFlags != nil {
 | 
						|
				extraFlags = in.extraFlags()
 | 
						|
			}
 | 
						|
 | 
						|
			opts, err := loadConfiguration(configFileName, alphaConfigFileName, extraFlags, in.args)
 | 
						|
			if in.expectedErr != nil {
 | 
						|
				Expect(err).To(MatchError(in.expectedErr.Error()))
 | 
						|
			} else {
 | 
						|
				Expect(err).ToNot(HaveOccurred())
 | 
						|
			}
 | 
						|
			Expect(in.expectedOptions).ToNot(BeNil())
 | 
						|
			Expect(opts).To(Equal(in.expectedOptions()))
 | 
						|
		},
 | 
						|
		Entry("with legacy configuration", loadConfigurationTableInput{
 | 
						|
			configContent:   testCoreConfig + testLegacyConfig,
 | 
						|
			expectedOptions: testExpectedOptions,
 | 
						|
		}),
 | 
						|
		Entry("with alpha configuration", loadConfigurationTableInput{
 | 
						|
			configContent:      testCoreConfig,
 | 
						|
			alphaConfigContent: testAlphaConfig,
 | 
						|
			expectedOptions:    testExpectedOptions,
 | 
						|
		}),
 | 
						|
		Entry("with bad legacy configuration", loadConfigurationTableInput{
 | 
						|
			configContent:   testCoreConfig + "unknown_field=\"something\"",
 | 
						|
			expectedOptions: func() *options.Options { return nil },
 | 
						|
			expectedErr:     errors.New("failed to load config: error unmarshalling config: 1 error(s) decoding:\n\n* '' has invalid keys: unknown_field"),
 | 
						|
		}),
 | 
						|
		Entry("with bad alpha configuration", loadConfigurationTableInput{
 | 
						|
			configContent:      testCoreConfig,
 | 
						|
			alphaConfigContent: testAlphaConfig + ":",
 | 
						|
			expectedOptions:    func() *options.Options { return nil },
 | 
						|
			expectedErr:        fmt.Errorf("failed to load alpha options: error unmarshalling config: error converting YAML to JSON: yaml: line %d: did not find expected key", strings.Count(testAlphaConfig, "\n")),
 | 
						|
		}),
 | 
						|
		Entry("with alpha configuration and bad core configuration", loadConfigurationTableInput{
 | 
						|
			configContent:      testCoreConfig + "unknown_field=\"something\"",
 | 
						|
			alphaConfigContent: testAlphaConfig,
 | 
						|
			expectedOptions:    func() *options.Options { return nil },
 | 
						|
			expectedErr:        errors.New("failed to load core options: failed to load config: error unmarshalling config: 1 error(s) decoding:\n\n* '' has invalid keys: unknown_field"),
 | 
						|
		}),
 | 
						|
	)
 | 
						|
})
 |