Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

structured config #5: support logging #2633

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ linters:
disable-all: true
issues:
exclude-rules:
- linters:
- staticcheck
text: "SA5008: unknown JSON option \"squash\""
- path: _test\.go
linters:
- scopelint
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ verify-generate: generate

.PHONY: test
test: lint
GO111MODULE=on $(GO) test $(TESTCOVER) -v -race ./...
GO111MODULE=on $(GO) test $(TESTCOVER) -v -ginkgo.noColor -race ./...

.PHONY: release
release: validate-go-version lint test
Expand Down
194 changes: 175 additions & 19 deletions docs/docs/configuration/alpha_config.md

Large diffs are not rendered by default.

37 changes: 24 additions & 13 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func main() {
logger.Fatalf("%s", err)
}

validator := NewValidator(opts.EmailDomains, opts.AuthenticatedEmailsFile)
validator := NewValidator(opts.ProxyOptions.EmailDomains, opts.ProxyOptions.AuthenticatedEmailsFile)
oauthproxy, err := NewOAuthProxy(opts, validator)
if err != nil {
logger.Fatalf("ERROR: Failed to initialise OAuth2 Proxy: %v", err)
Expand All @@ -66,12 +66,17 @@ func main() {
// loadConfiguration will load in the user's configuration.
// It will either load the alpha configuration (if alphaConfig is given)
// or the legacy configuration.
func loadConfiguration(config, alphaConfig string, extraFlags *pflag.FlagSet, args []string) (*options.Options, error) {
if alphaConfig != "" {
func loadConfiguration(config, yamlConfig string, extraFlags *pflag.FlagSet, args []string) (*options.Options, error) {
opts, err := loadLegacyOptions(config, extraFlags, args)
if err != nil {
return nil, err
}

if yamlConfig != "" {
logger.Printf("WARNING: You are using alpha configuration. The structure in this configuration file may change without notice. You MUST remove conflicting options from your existing configuration.")
return loadAlphaOptions(config, alphaConfig, extraFlags, args)
return loadYamlOptions(yamlConfig, config, extraFlags, args)
}
return loadLegacyOptions(config, extraFlags, args)
return opts, err
}

// loadLegacyOptions loads the old toml options using the legacy flagset
Expand All @@ -96,17 +101,17 @@ func loadLegacyOptions(config string, extraFlags *pflag.FlagSet, args []string)
return opts, nil
}

// loadAlphaOptions loads the old style config excluding options converted to
// loadYamlOptions loads the old style config excluding options converted to
// the new alpha format, then merges the alpha options, loaded from YAML,
// into the core configuration.
func loadAlphaOptions(config, alphaConfig string, extraFlags *pflag.FlagSet, args []string) (*options.Options, error) {
func loadYamlOptions(yamlConfig, config string, extraFlags *pflag.FlagSet, args []string) (*options.Options, error) {
opts, err := loadOptions(config, extraFlags, args)
if err != nil {
return nil, fmt.Errorf("failed to load core options: %v", err)
return nil, fmt.Errorf("please convert all legacy options: %v", err)
}

alphaOpts := &options.AlphaOptions{}
if err := options.LoadYAML(alphaConfig, alphaOpts); err != nil {
alphaOpts := options.NewAlphaOptions(opts)
if err := options.LoadYAML(yamlConfig, alphaOpts); err != nil {
return nil, fmt.Errorf("failed to load alpha options: %v", err)
}

Expand Down Expand Up @@ -136,10 +141,16 @@ func loadOptions(config string, extraFlags *pflag.FlagSet, args []string) (*opti
// printConvertedConfig extracts alpha options from the loaded configuration
// and renders these to stdout in YAML format.
func printConvertedConfig(opts *options.Options) error {
alphaConfig := &options.AlphaOptions{}
alphaConfig.ExtractFrom(opts)
alphaConfig := options.NewAlphaOptions(opts)

// Generic interface for loading arbitrary yaml structure
var buffer map[string]interface{}

if err := options.Decode(alphaConfig, &buffer); err != nil {
return fmt.Errorf("unable to decode alpha config into interface: %w", err)
}

data, err := yaml.Marshal(alphaConfig)
data, err := yaml.Marshal(buffer)
if err != nil {
return fmt.Errorf("unable to marshal config: %v", err)
}
Expand Down
90 changes: 63 additions & 27 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (

var _ = Describe("Configuration Loading Suite", func() {
// For comparing the full configuration differences of our structs we need to increase the gomega limits
format.MaxLength = 50000
format.MaxLength = 0
format.MaxDepth = 10

const testLegacyConfig = `
Expand All @@ -28,9 +28,21 @@ set_basic_auth="true"
basic_auth_password="super-secret-password"
client_id="oauth2-proxy"
client_secret="b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK"
cookie_secure="false"
cookie_secret="OQINaROshtE9TcZkNAm-5Zs2Pv3xaWytBmc5W7sPX7w="
email_domains="example.com"
redirect_url="http://localhost:4180/oauth2/callback"
session_cookie_minimal="true"
ping_path="/ping-pong"
ready_path="/readysteady"
errors_to_info_log="true"
silence_ping_logging="true"
`

const testAlphaConfig = `
proxyOptions:
emailDomains: ["example.com"]
redirectUrl: http://localhost:4180/oauth2/callback
upstreamConfig:
proxyrawpath: false
upstreams:
Expand All @@ -47,7 +59,7 @@ injectRequestHeaders:
- claim: user
prefix: "Basic "
basicAuthPassword:
value: c3VwZXItc2VjcmV0LXBhc3N3b3Jk
value: super-secret-password
- name: X-Forwarded-Groups
values:
- claim: groups
Expand All @@ -66,9 +78,22 @@ injectResponseHeaders:
- claim: user
prefix: "Basic "
basicAuthPassword:
value: c3VwZXItc2VjcmV0LXBhc3N3b3Jk
value: super-secret-password
server:
bindAddress: "127.0.0.1:4180"
httpAddress: "127.0.0.1:4180"
cookie:
secure: false
secret: OQINaROshtE9TcZkNAm-5Zs2Pv3xaWytBmc5W7sPX7w=
session:
type: cookie
cookie:
minimal: true
probeOptions:
pingPath: /ping-pong
readyPath: /readysteady
logging:
errToInfo: true
silencePing: true
providers:
- provider: google
ID: google=oauth2-proxy
Expand All @@ -89,31 +114,26 @@ providers:
- 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
durationPtr := func(d time.Duration) *time.Duration {
return &d
}

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.ProxyOptions = options.ProxyOptions{
ProxyPrefix: "/oauth2",
RealClientIPHeader: "X-Real-IP",
EmailDomains: []string{"example.com"},
RedirectURL: "http://localhost:4180/oauth2/callback",
}

opts.UpstreamServers = options.UpstreamConfig{
Upstreams: []options.Upstream{
Expand All @@ -133,11 +153,11 @@ redirect_url="http://localhost:4180/oauth2/callback"
Name: "Authorization",
Values: []options.HeaderValue{
{
ClaimSource: &options.ClaimSource{
ClaimSource: options.ClaimSource{
Claim: "user",
Prefix: "Basic ",
BasicAuthPassword: &options.SecretSource{
Value: []byte("super-secret-password"),
Value: "super-secret-password",
},
},
},
Expand Down Expand Up @@ -169,6 +189,22 @@ redirect_url="http://localhost:4180/oauth2/callback"
},
},
}

opts.Session = options.SessionOptions{
Type: "cookie",
Cookie: options.CookieStoreOptions{
Minimal: true,
},
}

opts.ProbeOptions = options.ProbeOptions{
PingPath: "/ping-pong",
ReadyPath: "/readysteady",
}

opts.Logging.ErrToInfo = true
opts.Logging.SilencePing = true

return opts
}

Expand Down Expand Up @@ -227,38 +263,38 @@ redirect_url="http://localhost:4180/oauth2/callback"

opts, err := loadConfiguration(configFileName, alphaConfigFileName, extraFlags, in.args)
if in.expectedErr != nil {
Expect(err).To(MatchError(in.expectedErr.Error()))
Expect(err).To(MatchError(ContainSubstring(in.expectedErr.Error())))
} else {
Expect(err).ToNot(HaveOccurred())
}
Expect(in.expectedOptions).ToNot(BeNil())
Expect(opts).To(EqualOpts(in.expectedOptions()))
},
Entry("with legacy configuration", loadConfigurationTableInput{
configContent: testCoreConfig + testLegacyConfig,
configContent: testLegacyConfig,
expectedOptions: testExpectedOptions,
}),
Entry("with alpha configuration", loadConfigurationTableInput{
configContent: testCoreConfig,
configContent: "",
alphaConfigContent: testAlphaConfig,
expectedOptions: testExpectedOptions,
}),
Entry("with bad legacy configuration", loadConfigurationTableInput{
configContent: testCoreConfig + "unknown_field=\"something\"",
configContent: testLegacyConfig + "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,
configContent: "",
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\"",
Entry("with alpha configuration and legacy configuration", loadConfigurationTableInput{
configContent: testLegacyConfig,
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"),
expectedErr: errors.New("please convert all legacy options"),
}),
)
})
Loading
Loading