Merge pull request #178 from kskewes/pinglog

Add silence-ping-logging flag
This commit is contained in:
Joel Speed 2019-07-19 11:30:31 +01:00 committed by GitHub
commit 8635391543
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 75 additions and 14 deletions

View File

@ -31,6 +31,7 @@
## Changes since v3.2.0 ## Changes since v3.2.0
- [#178](https://github.com/pusher/outh2_proxy/pull/178) Add Silence Ping Logging and Exclude Logging Paths flags (@kskewes)
- [#209](https://github.com/pusher/outh2_proxy/pull/209) Improve docker build caching of layers (@dekimsey) - [#209](https://github.com/pusher/outh2_proxy/pull/209) Improve docker build caching of layers (@dekimsey)
- [#186](https://github.com/pusher/oauth2_proxy/pull/186) Make config consistent (@JoelSpeed) - [#186](https://github.com/pusher/oauth2_proxy/pull/186) Make config consistent (@JoelSpeed)
- [#187](https://github.com/pusher/oauth2_proxy/pull/187) Move root packages to pkg folder (@JoelSpeed) - [#187](https://github.com/pusher/oauth2_proxy/pull/187) Move root packages to pkg folder (@JoelSpeed)

View File

@ -42,6 +42,7 @@ Usage of oauth2_proxy:
-display-htpasswd-form: display username / password login form if an htpasswd file is provided (default true) -display-htpasswd-form: display username / password login form if an htpasswd file is provided (default true)
-email-domain value: authenticate emails with the specified domain (may be given multiple times). Use * to authenticate any email -email-domain value: authenticate emails with the specified domain (may be given multiple times). Use * to authenticate any email
-extra-jwt-issuers: if -skip-jwt-bearer-tokens is set, a list of extra JWT issuer=audience pairs (where the issuer URL has a .well-known/openid-configuration or a .well-known/jwks.json) -extra-jwt-issuers: if -skip-jwt-bearer-tokens is set, a list of extra JWT issuer=audience pairs (where the issuer URL has a .well-known/openid-configuration or a .well-known/jwks.json)
-exclude-logging-paths: comma separated list of paths to exclude from logging, eg: "/ping,/path2" (default "" = no paths excluded)
-flush-interval: period between flushing response buffers when streaming responses (default "1s") -flush-interval: period between flushing response buffers when streaming responses (default "1s")
-banner string: custom banner string. Use "-" to disable default banner. -banner string: custom banner string. Use "-" to disable default banner.
-footer string: custom footer string. Use "-" to disable default footer. -footer string: custom footer string. Use "-" to disable default footer.
@ -73,6 +74,7 @@ Usage of oauth2_proxy:
-pass-user-headers: pass X-Forwarded-User and X-Forwarded-Email information to upstream (default true) -pass-user-headers: pass X-Forwarded-User and X-Forwarded-Email information to upstream (default true)
-profile-url string: Profile access endpoint -profile-url string: Profile access endpoint
-provider string: OAuth provider (default "google") -provider string: OAuth provider (default "google")
-ping-path string: the ping endpoint that can be used for basic health checks (default "/ping")
-proxy-prefix string: the url root path that this proxy should be nested under (e.g. /<oauth2>/sign_in) (default "/oauth2") -proxy-prefix string: the url root path that this proxy should be nested under (e.g. /<oauth2>/sign_in) (default "/oauth2")
-proxy-websockets: enables WebSocket proxying (default true) -proxy-websockets: enables WebSocket proxying (default true)
-pubjwk-url string: JWK pubkey access endpoint: required by login.gov -pubjwk-url string: JWK pubkey access endpoint: required by login.gov
@ -90,6 +92,7 @@ Usage of oauth2_proxy:
-set-xauthrequest: set X-Auth-Request-User and X-Auth-Request-Email response headers (useful in Nginx auth_request mode) -set-xauthrequest: set X-Auth-Request-User and X-Auth-Request-Email response headers (useful in Nginx auth_request mode)
-set-authorization-header: set Authorization Bearer response header (useful in Nginx auth_request mode) -set-authorization-header: set Authorization Bearer response header (useful in Nginx auth_request mode)
-signature-key string: GAP-Signature request signature key (algorithm:secretkey) -signature-key string: GAP-Signature request signature key (algorithm:secretkey)
-silence-ping-logging bool: disable logging of requests to ping endpoint (default false)
-skip-auth-preflight: will skip authentication for OPTIONS requests -skip-auth-preflight: will skip authentication for OPTIONS requests
-skip-auth-regex value: bypass authentication for requests path's that match (may be given multiple times) -skip-auth-regex value: bypass authentication for requests path's that match (may be given multiple times)
-skip-jwt-bearer-tokens: will skip requests that have verified JWT bearer tokens -skip-jwt-bearer-tokens: will skip requests that have verified JWT bearer tokens
@ -139,6 +142,8 @@ There are three different types of logging: standard, authentication, and HTTP r
Each type of logging has their own configurable format and variables. By default these formats are similar to the Apache Combined Log. Each type of logging has their own configurable format and variables. By default these formats are similar to the Apache Combined Log.
Logging of requests to the `/ping` endpoint can be disabled with `-silence-ping-logging` reducing log volume. This flag appends the `-ping-path` to `-exclude-logging-paths`.
### Auth Log Format ### Auth Log Format
Authentication logs are logs which are guaranteed to contain a username or email address of a user attempting to authenticate. These logs are output by default in the below format: Authentication logs are logs which are guaranteed to contain a username or email address of a user attempting to authenticate. These logs are output by default in the below format:

View File

@ -75,18 +75,19 @@ func (l *responseLogger) Status() int {
return l.status return l.status
} }
// Size returns teh response size // Size returns the response size
func (l *responseLogger) Size() int { func (l *responseLogger) Size() int {
return l.size return l.size
} }
// Flush sends any buffered data to the client
func (l *responseLogger) Flush() { func (l *responseLogger) Flush() {
if flusher, ok := l.w.(http.Flusher); ok { if flusher, ok := l.w.(http.Flusher); ok {
flusher.Flush() flusher.Flush()
} }
} }
// loggingHandler is the http.Handler implementation for LoggingHandlerTo and its friends // loggingHandler is the http.Handler implementation for LoggingHandler
type loggingHandler struct { type loggingHandler struct {
handler http.Handler handler http.Handler
} }

View File

@ -17,10 +17,23 @@ func TestLoggingHandler_ServeHTTP(t *testing.T) {
tests := []struct { tests := []struct {
Format, Format,
ExpectedLogMessage string ExpectedLogMessage,
Path string
ExcludePaths []string
SilencePingLogging bool
}{ }{
{logger.DefaultRequestLoggingFormat, fmt.Sprintf("127.0.0.1 - - [%s] test-server GET - \"/foo/bar\" HTTP/1.1 \"\" 200 4 0.000\n", logger.FormatTimestamp(ts))}, {logger.DefaultRequestLoggingFormat, fmt.Sprintf("127.0.0.1 - - [%s] test-server GET - \"/foo/bar\" HTTP/1.1 \"\" 200 4 0.000\n", logger.FormatTimestamp(ts)), "/foo/bar", []string{}, false},
{"{{.RequestMethod}}", "GET\n"}, {logger.DefaultRequestLoggingFormat, fmt.Sprintf("127.0.0.1 - - [%s] test-server GET - \"/foo/bar\" HTTP/1.1 \"\" 200 4 0.000\n", logger.FormatTimestamp(ts)), "/foo/bar", []string{}, true},
{logger.DefaultRequestLoggingFormat, fmt.Sprintf("127.0.0.1 - - [%s] test-server GET - \"/foo/bar\" HTTP/1.1 \"\" 200 4 0.000\n", logger.FormatTimestamp(ts)), "/foo/bar", []string{"/ping"}, false},
{logger.DefaultRequestLoggingFormat, "", "/foo/bar", []string{"/foo/bar"}, false},
{logger.DefaultRequestLoggingFormat, "", "/ping", []string{}, true},
{logger.DefaultRequestLoggingFormat, "", "/ping", []string{"/ping"}, false},
{logger.DefaultRequestLoggingFormat, "", "/ping", []string{"/ping"}, true},
{logger.DefaultRequestLoggingFormat, "", "/ping", []string{"/foo/bar", "/ping"}, false},
{"{{.RequestMethod}}", "GET\n", "/foo/bar", []string{}, true},
{"{{.RequestMethod}}", "GET\n", "/foo/bar", []string{"/ping"}, false},
{"{{.RequestMethod}}", "GET\n", "/ping", []string{}, false},
{"{{.RequestMethod}}", "", "/ping", []string{"/ping"}, true},
} }
for _, test := range tests { for _, test := range tests {
@ -36,9 +49,13 @@ func TestLoggingHandler_ServeHTTP(t *testing.T) {
logger.SetOutput(buf) logger.SetOutput(buf)
logger.SetReqTemplate(test.Format) logger.SetReqTemplate(test.Format)
if test.SilencePingLogging {
test.ExcludePaths = append(test.ExcludePaths, "/ping")
}
logger.SetExcludePaths(test.ExcludePaths)
h := LoggingHandler(http.HandlerFunc(handler)) h := LoggingHandler(http.HandlerFunc(handler))
r, _ := http.NewRequest("GET", "/foo/bar", nil) r, _ := http.NewRequest("GET", test.Path, nil)
r.RemoteAddr = "127.0.0.1" r.RemoteAddr = "127.0.0.1"
r.Host = "test-server" r.Host = "test-server"

View File

@ -69,6 +69,7 @@ func main() {
flagSet.String("banner", "", "custom banner string. Use \"-\" to disable default banner.") flagSet.String("banner", "", "custom banner string. Use \"-\" to disable default banner.")
flagSet.String("footer", "", "custom footer string. Use \"-\" to disable default footer.") flagSet.String("footer", "", "custom footer string. Use \"-\" to disable default footer.")
flagSet.String("proxy-prefix", "/oauth2", "the url root path that this proxy should be nested under (e.g. /<oauth2>/sign_in)") flagSet.String("proxy-prefix", "/oauth2", "the url root path that this proxy should be nested under (e.g. /<oauth2>/sign_in)")
flagSet.String("ping-path", "/ping", "the ping endpoint that can be used for basic health checks")
flagSet.Bool("proxy-websockets", true, "enables WebSocket proxying") flagSet.Bool("proxy-websockets", true, "enables WebSocket proxying")
flagSet.String("cookie-name", "_oauth2_proxy", "the name of the cookie that the oauth_proxy creates") flagSet.String("cookie-name", "_oauth2_proxy", "the name of the cookie that the oauth_proxy creates")
@ -98,6 +99,8 @@ func main() {
flagSet.Bool("request-logging", true, "Log HTTP requests") flagSet.Bool("request-logging", true, "Log HTTP requests")
flagSet.String("request-logging-format", logger.DefaultRequestLoggingFormat, "Template for HTTP request log lines") flagSet.String("request-logging-format", logger.DefaultRequestLoggingFormat, "Template for HTTP request log lines")
flagSet.String("exclude-logging-paths", "", "Exclude logging requests to paths (eg: '/path1,/path2,/path3')")
flagSet.Bool("silence-ping-logging", false, "Disable logging of requests to ping endpoint")
flagSet.Bool("auth-logging", true, "Log authentication attempts") flagSet.Bool("auth-logging", true, "Log authentication attempts")
flagSet.String("auth-logging-format", logger.DefaultAuthLoggingFormat, "Template for authentication log lines") flagSet.String("auth-logging-format", logger.DefaultAuthLoggingFormat, "Template for authentication log lines")

View File

@ -254,7 +254,7 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy {
Validator: validator, Validator: validator,
RobotsPath: "/robots.txt", RobotsPath: "/robots.txt",
PingPath: "/ping", PingPath: opts.PingPath,
SignInPath: fmt.Sprintf("%s/sign_in", opts.ProxyPrefix), SignInPath: fmt.Sprintf("%s/sign_in", opts.ProxyPrefix),
SignOutPath: fmt.Sprintf("%s/sign_out", opts.ProxyPrefix), SignOutPath: fmt.Sprintf("%s/sign_out", opts.ProxyPrefix),
OAuthStartPath: fmt.Sprintf("%s/start", opts.ProxyPrefix), OAuthStartPath: fmt.Sprintf("%s/start", opts.ProxyPrefix),

View File

@ -30,6 +30,7 @@ import (
// or Config File // or Config File
type Options struct { type Options struct {
ProxyPrefix string `flag:"proxy-prefix" cfg:"proxy_prefix" env:"OAUTH2_PROXY_PROXY_PREFIX"` ProxyPrefix string `flag:"proxy-prefix" cfg:"proxy_prefix" env:"OAUTH2_PROXY_PROXY_PREFIX"`
PingPath string `flag:"ping-path" cfg:"ping_path" env:"OAUTH2_PROXY_PING_PATH"`
ProxyWebSockets bool `flag:"proxy-websockets" cfg:"proxy_websockets" env:"OAUTH2_PROXY_PROXY_WEBSOCKETS"` ProxyWebSockets bool `flag:"proxy-websockets" cfg:"proxy_websockets" env:"OAUTH2_PROXY_PROXY_WEBSOCKETS"`
HTTPAddress string `flag:"http-address" cfg:"http_address" env:"OAUTH2_PROXY_HTTP_ADDRESS"` HTTPAddress string `flag:"http-address" cfg:"http_address" env:"OAUTH2_PROXY_HTTP_ADDRESS"`
HTTPSAddress string `flag:"https-address" cfg:"https_address" env:"OAUTH2_PROXY_HTTPS_ADDRESS"` HTTPSAddress string `flag:"https-address" cfg:"https_address" env:"OAUTH2_PROXY_HTTPS_ADDRESS"`
@ -103,15 +104,16 @@ type Options struct {
StandardLoggingFormat string `flag:"standard-logging-format" cfg:"standard_logging_format" env:"OAUTH2_PROXY_STANDARD_LOGGING_FORMAT"` StandardLoggingFormat string `flag:"standard-logging-format" cfg:"standard_logging_format" env:"OAUTH2_PROXY_STANDARD_LOGGING_FORMAT"`
RequestLogging bool `flag:"request-logging" cfg:"request_logging" env:"OAUTH2_PROXY_REQUEST_LOGGING"` RequestLogging bool `flag:"request-logging" cfg:"request_logging" env:"OAUTH2_PROXY_REQUEST_LOGGING"`
RequestLoggingFormat string `flag:"request-logging-format" cfg:"request_logging_format" env:"OAUTH2_PROXY_REQUEST_LOGGING_FORMAT"` RequestLoggingFormat string `flag:"request-logging-format" cfg:"request_logging_format" env:"OAUTH2_PROXY_REQUEST_LOGGING_FORMAT"`
ExcludeLoggingPaths string `flag:"exclude-logging-paths" cfg:"exclude_logging_paths" env:"OAUTH2_PROXY_EXCLUDE_LOGGING_PATHS"`
SilencePingLogging bool `flag:"silence-ping-logging" cfg:"silence_ping_logging" env:"OAUTH2_PROXY_SILENCE_PING_LOGGING"`
AuthLogging bool `flag:"auth-logging" cfg:"auth_logging" env:"OAUTH2_PROXY_LOGGING_AUTH_LOGGING"` AuthLogging bool `flag:"auth-logging" cfg:"auth_logging" env:"OAUTH2_PROXY_LOGGING_AUTH_LOGGING"`
AuthLoggingFormat string `flag:"auth-logging-format" cfg:"auth_logging_format" env:"OAUTH2_PROXY_AUTH_LOGGING_FORMAT"` AuthLoggingFormat string `flag:"auth-logging-format" cfg:"auth_logging_format" env:"OAUTH2_PROXY_AUTH_LOGGING_FORMAT"`
SignatureKey string `flag:"signature-key" cfg:"signature_key" env:"OAUTH2_PROXY_SIGNATURE_KEY"`
SignatureKey string `flag:"signature-key" cfg:"signature_key" env:"OAUTH2_PROXY_SIGNATURE_KEY"` AcrValues string `flag:"acr-values" cfg:"acr_values" env:"OAUTH2_PROXY_ACR_VALUES"`
AcrValues string `flag:"acr-values" cfg:"acr_values" env:"OAUTH2_PROXY_ACR_VALUES"` JWTKey string `flag:"jwt-key" cfg:"jwt_key" env:"OAUTH2_PROXY_JWT_KEY"`
JWTKey string `flag:"jwt-key" cfg:"jwt_key" env:"OAUTH2_PROXY_JWT_KEY"` JWTKeyFile string `flag:"jwt-key-file" cfg:"jwt_key_file" env:"OAUTH2_PROXY_JWT_KEY_FILE"`
JWTKeyFile string `flag:"jwt-key-file" cfg:"jwt_key_file" env:"OAUTH2_PROXY_JWT_KEY_FILE"` PubJWKURL string `flag:"pubjwk-url" cfg:"pubjwk_url" env:"OAUTH2_PROXY_PUBJWK_URL"`
PubJWKURL string `flag:"pubjwk-url" cfg:"pubjwk_url" env:"OAUTH2_PROXY_PUBJWK_URL"` GCPHealthChecks bool `flag:"gcp-healthchecks" cfg:"gcp_healthchecks" env:"OAUTH2_PROXY_GCP_HEALTHCHECKS"`
GCPHealthChecks bool `flag:"gcp-healthchecks" cfg:"gcp_healthchecks" env:"OAUTH2_PROXY_GCP_HEALTHCHECKS"`
// internal values that are set after config validation // internal values that are set after config validation
redirectURL *url.URL redirectURL *url.URL
@ -134,6 +136,7 @@ type SignatureData struct {
func NewOptions() *Options { func NewOptions() *Options {
return &Options{ return &Options{
ProxyPrefix: "/oauth2", ProxyPrefix: "/oauth2",
PingPath: "/ping",
ProxyWebSockets: true, ProxyWebSockets: true,
HTTPAddress: "127.0.0.1:4180", HTTPAddress: "127.0.0.1:4180",
HTTPSAddress: ":443", HTTPSAddress: ":443",
@ -165,6 +168,8 @@ func NewOptions() *Options {
LoggingMaxBackups: 0, LoggingMaxBackups: 0,
LoggingLocalTime: true, LoggingLocalTime: true,
LoggingCompress: false, LoggingCompress: false,
ExcludeLoggingPaths: "",
SilencePingLogging: false,
StandardLogging: true, StandardLogging: true,
StandardLoggingFormat: logger.DefaultStandardLoggingFormat, StandardLoggingFormat: logger.DefaultStandardLoggingFormat,
RequestLogging: true, RequestLogging: true,
@ -571,6 +576,14 @@ func setupLogger(o *Options, msgs []string) []string {
logger.SetAuthTemplate(o.AuthLoggingFormat) logger.SetAuthTemplate(o.AuthLoggingFormat)
logger.SetReqTemplate(o.RequestLoggingFormat) logger.SetReqTemplate(o.RequestLoggingFormat)
excludePaths := make([]string, 0)
excludePaths = append(excludePaths, strings.Split(o.ExcludeLoggingPaths, ",")...)
if o.SilencePingLogging {
excludePaths = append(excludePaths, o.PingPath)
}
logger.SetExcludePaths(excludePaths)
if !o.LoggingLocalTime { if !o.LoggingLocalTime {
logger.SetFlags(logger.Flags() | logger.LUTC) logger.SetFlags(logger.Flags() | logger.LUTC)
} }

View File

@ -88,6 +88,7 @@ type Logger struct {
stdEnabled bool stdEnabled bool
authEnabled bool authEnabled bool
reqEnabled bool reqEnabled bool
excludePaths map[string]struct{}
stdLogTemplate *template.Template stdLogTemplate *template.Template
authTemplate *template.Template authTemplate *template.Template
reqTemplate *template.Template reqTemplate *template.Template
@ -101,6 +102,7 @@ func New(flag int) *Logger {
stdEnabled: true, stdEnabled: true,
authEnabled: true, authEnabled: true,
reqEnabled: true, reqEnabled: true,
excludePaths: nil,
stdLogTemplate: template.Must(template.New("std-log").Parse(DefaultStandardLoggingFormat)), stdLogTemplate: template.Must(template.New("std-log").Parse(DefaultStandardLoggingFormat)),
authTemplate: template.Must(template.New("auth-log").Parse(DefaultAuthLoggingFormat)), authTemplate: template.Must(template.New("auth-log").Parse(DefaultAuthLoggingFormat)),
reqTemplate: template.Must(template.New("req-log").Parse(DefaultRequestLoggingFormat)), reqTemplate: template.Must(template.New("req-log").Parse(DefaultRequestLoggingFormat)),
@ -177,6 +179,10 @@ func (l *Logger) PrintReq(username, upstream string, req *http.Request, url url.
return return
} }
if _, ok := l.excludePaths[url.Path]; ok {
return
}
duration := float64(time.Now().Sub(ts)) / float64(time.Second) duration := float64(time.Now().Sub(ts)) / float64(time.Second)
if username == "" { if username == "" {
@ -302,6 +308,16 @@ func (l *Logger) SetReqEnabled(e bool) {
l.reqEnabled = e l.reqEnabled = e
} }
// SetExcludePaths sets the paths to exclude from logging.
func (l *Logger) SetExcludePaths(s []string) {
l.mu.Lock()
defer l.mu.Unlock()
l.excludePaths = make(map[string]struct{})
for _, p := range s {
l.excludePaths[p] = struct{}{}
}
}
// SetStandardTemplate sets the template for standard logging. // SetStandardTemplate sets the template for standard logging.
func (l *Logger) SetStandardTemplate(t string) { func (l *Logger) SetStandardTemplate(t string) {
l.mu.Lock() l.mu.Lock()
@ -365,6 +381,11 @@ func SetReqEnabled(e bool) {
std.SetReqEnabled(e) std.SetReqEnabled(e)
} }
// SetExcludePaths sets the path to exclude from logging, eg: health checks
func SetExcludePaths(s []string) {
std.SetExcludePaths(s)
}
// SetStandardTemplate sets the template for standard logging for // SetStandardTemplate sets the template for standard logging for
// the standard logger. // the standard logger.
func SetStandardTemplate(t string) { func SetStandardTemplate(t string) {