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

stack #5: support logging #10

Closed
wants to merge 3 commits into from
Closed
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
36 changes: 36 additions & 0 deletions docs/docs/configuration/alpha_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ They may change between releases without notice.
| `cookie` | _[Cookie](#cookie)_ | Cookie is used to configure the cookie used to store the session state.<br/>This includes options such as the cookie name, its expiry and its domain. |
| `session` | _[SessionOptions](#sessionoptions)_ | Session is used to configure the session storage.<br/>To either use a cookie or a redis store. |
| `pageTemplates` | _[PageTemplates](#pagetemplates)_ | PageTemplates is used to configure custom page templates.<br/>This includes the sign in and error pages. |
| `logging` | _[Logging](#logging)_ | Logging is used to configure the logging output.<br/>Which formats are enabled and where to write the logs. |

### AzureOptions

Expand Down Expand Up @@ -317,6 +318,41 @@ make up the header value
| `groups` | _[]string_ | Group enables to restrict login to members of indicated group |
| `roles` | _[]string_ | Role enables to restrict login to users with role (only available when using the keycloak-oidc provider) |

### LogFileOptions

(**Appears on:** [Logging](#logging))

LogFileOptions contains options for configuring logging to a file

| Field | Type | Description |
| ----- | ---- | ----------- |
| `filename` | _string_ | |
| `maxSize` | _int_ | |
| `maxAge` | _int_ | |
| `maxBackups` | _int_ | |
| `compress` | _bool_ | |

### Logging

(**Appears on:** [AlphaOptions](#alphaoptions))

Logging contains all options required for configuring the logging

| Field | Type | Description |
| ----- | ---- | ----------- |
| `authEnabled` | _bool_ | |
| `authFormat` | _string_ | |
| `requestEnabled` | _bool_ | |
| `requestFormat` | _string_ | |
| `standardEnabled` | _bool_ | |
| `standardFormat` | _string_ | |
| `errToInfo` | _bool_ | |
| `excludePaths` | _[]string_ | |
| `localTime` | _bool_ | |
| `silencePing` | _bool_ | |
| `requestIdHeader` | _string_ | |
| `fileOptions` | _[LogFileOptions](#logfileoptions)_ | |

### LoginGovOptions

(**Appears on:** [Provider](#provider))
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func loadLegacyOptions(config string, extraFlags *pflag.FlagSet, args []string)
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.NewAlphaOptions(opts)
Expand Down
24 changes: 12 additions & 12 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ 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 = `
Expand Down Expand Up @@ -89,6 +91,9 @@ session:
probeOptions:
pingPath: /ping-pong
readyPath: /readysteady
logging:
errToInfo: true
silencePing: true
providers:
- provider: google
ID: google=oauth2-proxy
Expand All @@ -109,11 +114,6 @@ providers:
- force
`

const testCoreConfig = `
errors_to_info_log="true"
silence_ping_logging="true"
`

boolPtr := func(b bool) *bool {
return &b
}
Expand Down Expand Up @@ -271,30 +271,30 @@ providers:
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("has invalid keys: unknown_field"),
expectedErr: errors.New("please convert all legacy options"),
}),
)
})
8 changes: 7 additions & 1 deletion pkg/apis/options/alpha_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,13 @@ type AlphaOptions struct {
// PageTemplates is used to configure custom page templates.
// This includes the sign in and error pages.
PageTemplates PageTemplates `json:"pageTemplates,omitempty"`

// Logging is used to configure the logging output.
// Which formats are enabled and where to write the logs.
Logging Logging `json:"logging,omitempty"`
}

// Initialize alpha options with default values and settings of the core options
// Initialize alpha options with default values
func NewAlphaOptions(opts *Options) *AlphaOptions {
aOpts := &AlphaOptions{}
aOpts.ExtractFrom(opts)
Expand All @@ -87,6 +91,7 @@ func (a *AlphaOptions) ExtractFrom(opts *Options) {
a.Cookie = opts.Cookie
a.Session = opts.Session
a.PageTemplates = opts.PageTemplates
a.Logging = opts.Logging
}

// MergeInto replaces alpha options in the Options struct with the values
Expand All @@ -103,4 +108,5 @@ func (a *AlphaOptions) MergeInto(opts *Options) {
opts.Cookie = a.Cookie
opts.Session = a.Session
opts.PageTemplates = a.PageTemplates
opts.Logging = a.Logging
}
79 changes: 79 additions & 0 deletions pkg/apis/options/legacy_logging.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package options

import (
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
"github.com/spf13/pflag"
)

// Logging contains all options required for configuring the logging
type LegacyLogging struct {
AuthEnabled bool `flag:"auth-logging" cfg:"auth_logging"`
AuthFormat string `flag:"auth-logging-format" cfg:"auth_logging_format"`
RequestEnabled bool `flag:"request-logging" cfg:"request_logging"`
RequestFormat string `flag:"request-logging-format" cfg:"request_logging_format"`
StandardEnabled bool `flag:"standard-logging" cfg:"standard_logging"`
StandardFormat string `flag:"standard-logging-format" cfg:"standard_logging_format"`
ErrToInfo bool `flag:"errors-to-info-log" cfg:"errors_to_info_log"`
ExcludePaths []string `flag:"exclude-logging-path" cfg:"exclude_logging_paths"`
LocalTime bool `flag:"logging-local-time" cfg:"logging_local_time"`
SilencePing bool `flag:"silence-ping-logging" cfg:"silence_ping_logging"`
RequestIDHeader string `flag:"request-id-header" cfg:"request_id_header"`
File LegacyLogFileOptions `cfg:",squash"`
}

// LogFileOptions contains options for configuring logging to a file
type LegacyLogFileOptions struct {
Filename string `flag:"logging-filename" cfg:"logging_filename"`
MaxSize int `flag:"logging-max-size" cfg:"logging_max_size"`
MaxAge int `flag:"logging-max-age" cfg:"logging_max_age"`
MaxBackups int `flag:"logging-max-backups" cfg:"logging_max_backups"`
Compress bool `flag:"logging-compress" cfg:"logging_compress"`
}

func legacyLoggingFlagSet() *pflag.FlagSet {
flagSet := pflag.NewFlagSet("logging", pflag.ExitOnError)

flagSet.Bool("auth-logging", true, "Log authentication attempts")
flagSet.String("auth-logging-format", logger.DefaultAuthLoggingFormat, "Template for authentication log lines")
flagSet.Bool("standard-logging", true, "Log standard runtime information")
flagSet.String("standard-logging-format", logger.DefaultStandardLoggingFormat, "Template for standard log lines")
flagSet.Bool("request-logging", true, "Log HTTP requests")
flagSet.String("request-logging-format", logger.DefaultRequestLoggingFormat, "Template for HTTP request log lines")
flagSet.Bool("errors-to-info-log", false, "Log errors to the standard logging channel instead of stderr")

flagSet.StringSlice("exclude-logging-path", []string{}, "Exclude logging requests to paths (eg: '/path1,/path2,/path3')")
flagSet.Bool("logging-local-time", true, "If the time in log files and backup filenames are local or UTC time")
flagSet.Bool("silence-ping-logging", false, "Disable logging of requests to ping & ready endpoints")
flagSet.String("request-id-header", "X-Request-Id", "Request header to use as the request ID")

flagSet.String("logging-filename", "", "File to log requests to, empty for stdout")
flagSet.Int("logging-max-size", 100, "Maximum size in megabytes of the log file before rotation")
flagSet.Int("logging-max-age", 7, "Maximum number of days to retain old log files")
flagSet.Int("logging-max-backups", 0, "Maximum number of old log files to retain; 0 to disable")
flagSet.Bool("logging-compress", false, "Should rotated log files be compressed using gzip")

return flagSet
}

func (l *LegacyLogging) convert() Logging {
return Logging{
AuthEnabled: l.AuthEnabled,
AuthFormat: l.AuthFormat,
RequestEnabled: l.RequestEnabled,
RequestFormat: l.RequestFormat,
StandardEnabled: l.StandardEnabled,
StandardFormat: l.StandardFormat,
ErrToInfo: l.ErrToInfo,
ExcludePaths: l.ExcludePaths,
LocalTime: l.LocalTime,
SilencePing: l.SilencePing,
RequestIDHeader: l.RequestIDHeader,
File: LogFileOptions{
Filename: l.File.Filename,
MaxSize: l.File.MaxSize,
MaxAge: l.File.MaxAge,
MaxBackups: l.File.MaxBackups,
Compress: l.File.Compress,
},
}
}
57 changes: 38 additions & 19 deletions pkg/apis/options/legacy_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"time"

"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
"github.com/spf13/pflag"
)

Expand Down Expand Up @@ -35,7 +36,8 @@ type LegacyOptions struct {
// Legacy options for configuring the cookie session storage
LegacySessionOptions LegacySessionOptions `cfg:",squash"`

Options Options `cfg:",squash"`
// Legacy options for logging
LegacyLogging LegacyLogging `cfg:",squash"`
}

func NewLegacyOptions() *LegacyOptions {
Expand Down Expand Up @@ -108,12 +110,31 @@ func NewLegacyOptions() *LegacyOptions {
},
},

Options: *NewOptions(),
LegacyLogging: LegacyLogging{
ExcludePaths: nil,
LocalTime: true,
SilencePing: false,
RequestIDHeader: "X-Request-Id",
AuthEnabled: true,
AuthFormat: logger.DefaultAuthLoggingFormat,
RequestEnabled: true,
RequestFormat: logger.DefaultRequestLoggingFormat,
StandardEnabled: true,
StandardFormat: logger.DefaultStandardLoggingFormat,
ErrToInfo: false,
File: LegacyLogFileOptions{
Filename: "",
MaxSize: 100,
MaxAge: 7,
MaxBackups: 0,
Compress: false,
},
},
}
}

func NewLegacyFlagSet() *pflag.FlagSet {
flagSet := NewFlagSet()
flagSet := pflag.NewFlagSet("oauth2-proxy", pflag.ExitOnError)

flagSet.AddFlagSet(legacyProxyOptionsFlagSet())
flagSet.AddFlagSet(legacyUpstreamsFlagSet())
Expand All @@ -125,38 +146,36 @@ func NewLegacyFlagSet() *pflag.FlagSet {
flagSet.AddFlagSet(legacyProbeOptionsFlagSet())
flagSet.AddFlagSet(legacyPageTemplatesFlagSet())
flagSet.AddFlagSet(legacySessionFlagSet())
flagSet.AddFlagSet(legacyLoggingFlagSet())

return flagSet
}

func (l *LegacyOptions) ToOptions() (*Options, error) {
l.Options.ProxyOptions = l.LegacyProxyOptions.convert()
opts := NewOptions()
opts.ProxyOptions = l.LegacyProxyOptions.convert()

upstreams, err := l.LegacyUpstreams.convert()
if err != nil {
return nil, fmt.Errorf("error converting upstreams: %v", err)
}
l.Options.UpstreamServers = upstreams

l.Options.InjectRequestHeaders, l.Options.InjectResponseHeaders = l.LegacyHeaders.convert()

l.Options.Server, l.Options.MetricsServer = l.LegacyServer.convert()

l.Options.LegacyPreferEmailToUser = l.LegacyHeaders.PreferEmailToUser
opts.UpstreamServers = upstreams
opts.InjectRequestHeaders, opts.InjectResponseHeaders = l.LegacyHeaders.convert()
opts.Server, opts.MetricsServer = l.LegacyServer.convert()
opts.LegacyPreferEmailToUser = l.LegacyHeaders.PreferEmailToUser

providers, err := l.LegacyProvider.convert()
if err != nil {
return nil, fmt.Errorf("error converting provider: %v", err)
}
l.Options.Providers = providers

l.Options.Cookie = l.LegacyCookie.convert()

l.Options.ProbeOptions = l.LegacyProbeOptions.convert()

l.Options.PageTemplates = l.LegacyPageTemplates.convert()

l.Options.Session = l.LegacySessionOptions.convert()
opts.Providers = providers
opts.Cookie = l.LegacyCookie.convert()
opts.ProbeOptions = l.LegacyProbeOptions.convert()
opts.PageTemplates = l.LegacyPageTemplates.convert()
opts.Session = l.LegacySessionOptions.convert()
opts.Logging = l.LegacyLogging.convert()

return &l.Options, nil
return opts, nil
}
22 changes: 20 additions & 2 deletions pkg/apis/options/load_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"time"

. "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options/testutil"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table"
. "github.com/onsi/gomega"
Expand Down Expand Up @@ -83,8 +84,25 @@ var _ = Describe("Load", func() {
},
},

Options: Options{
Logging: loggingDefaults(),
LegacyLogging: LegacyLogging{
ExcludePaths: nil,
LocalTime: true,
SilencePing: false,
RequestIDHeader: "X-Request-Id",
AuthEnabled: true,
AuthFormat: logger.DefaultAuthLoggingFormat,
RequestEnabled: true,
RequestFormat: logger.DefaultRequestLoggingFormat,
StandardEnabled: true,
StandardFormat: logger.DefaultStandardLoggingFormat,
ErrToInfo: false,
File: LegacyLogFileOptions{
Filename: "",
MaxSize: 100,
MaxAge: 7,
MaxBackups: 0,
Compress: false,
},
},
}

Expand Down
Loading