@@ -7,6 +7,7 @@ import (
77 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
88 . "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options/testutil"
99 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr"
10+ "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/validation"
1011 . "github.com/onsi/ginkgo/v2"
1112 . "github.com/onsi/gomega"
1213 "github.com/onsi/gomega/format"
@@ -292,4 +293,78 @@ redirect_url="http://localhost:4180/oauth2/callback"
292293 expectedErr: errors.New("failed to load legacy options: failed to load config: error unmarshalling config: decoding failed due to the following error(s):\n\n'' has invalid keys: unknown_field"),
293294 }),
294295 )
296+
297+ Describe("Config Test Mode", func() {
298+ const validConfig = `
299+http_address="127.0.0.1:4180"
300+upstreams="http://httpbin"
301+client_id="oauth2-proxy"
302+client_secret="b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK"
303+cookie_secret="OQINaROshtE9TcZkNAm-5Zs2Pv3xaWytBmc5W7sPX7w="
304+email_domains="example.com"
305+cookie_secure="false"
306+redirect_url="http://localhost:4180/oauth2/callback"
307+`
308+
309+ const invalidConfig = `
310+http_address="127.0.0.1:4180"
311+upstreams="http://httpbin"
312+email_domains="example.com"
313+cookie_secure="false"
314+redirect_url="http://localhost:4180/oauth2/callback"
315+`
316+
317+ writeTempConfig := func(content string) string {
318+ file, err := os.CreateTemp("", "oauth2-proxy-test-config-XXXX.cfg")
319+ Expect(err).ToNot(HaveOccurred())
320+ defer file.Close()
321+
322+ _, err = file.WriteString(content)
323+ Expect(err).ToNot(HaveOccurred())
324+ return file.Name()
325+ }
326+
327+ It("should pass validation with a valid configuration", func() {
328+ configFile := writeTempConfig(validConfig)
329+ defer os.Remove(configFile)
330+
331+ flagSet := pflag.NewFlagSet("test", pflag.ContinueOnError)
332+ opts, err := loadConfiguration(configFile, "", flagSet, []string{})
333+ Expect(err).ToNot(HaveOccurred())
334+
335+ err = validation.Validate(opts)
336+ Expect(err).ToNot(HaveOccurred())
337+ })
338+
339+ It("should fail validation with an invalid configuration (missing required fields)", func() {
340+ configFile := writeTempConfig(invalidConfig)
341+ defer os.Remove(configFile)
342+
343+ flagSet := pflag.NewFlagSet("test", pflag.ContinueOnError)
344+ opts, err := loadConfiguration(configFile, "", flagSet, []string{})
345+ Expect(err).ToNot(HaveOccurred())
346+
347+ err = validation.Validate(opts)
348+ Expect(err).To(HaveOccurred())
349+ Expect(err.Error()).To(ContainSubstring("invalid configuration"))
350+ })
351+
352+ It("should fail to load a configuration file with syntax errors", func() {
353+ configFile := writeTempConfig("this is not valid toml ===")
354+ defer os.Remove(configFile)
355+
356+ flagSet := pflag.NewFlagSet("test", pflag.ContinueOnError)
357+ _, err := loadConfiguration(configFile, "", flagSet, []string{})
358+ Expect(err).To(HaveOccurred())
359+ })
360+
361+ It("should register the config-test flag", func() {
362+ flagSet := pflag.NewFlagSet("test", pflag.ContinueOnError)
363+ flagSet.ParseErrorsAllowlist.UnknownFlags = true
364+ configTest := flagSet.Bool("config-test", false, "test the configuration and exit")
365+ err := flagSet.Parse([]string{"--config-test"})
366+ Expect(err).ToNot(HaveOccurred())
367+ Expect(*configTest).To(BeTrue())
368+ })
369+ })
295370})