You've already forked oauth2-proxy
							
							
				mirror of
				https://github.com/oauth2-proxy/oauth2-proxy.git
				synced 2025-10-30 23:47:52 +02:00 
			
		
		
		
	Allow Logging to stdout with separate Error Log Channel (#718)
* Add dedicated error logging writer * Document new errors to stdout flag * Update changelog * Thread-safe the log buffer * Address feedback * Remove duplication by adding log level * Clean up error formatting * Apply suggestions from code review Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
This commit is contained in:
		| @@ -11,6 +11,7 @@ | |||||||
|  |  | ||||||
| ## Changes since v6.0.0 | ## Changes since v6.0.0 | ||||||
|  |  | ||||||
|  | - [#718](https://github.com/oauth2-proxy/oauth2-proxy/pull/718) Allow Logging to stdout with separate Error Log Channel | ||||||
| - [#690](https://github.com/oauth2-proxy/oauth2-proxy/pull/690) Address GoSec security findings & remediate (@NickMeves) | - [#690](https://github.com/oauth2-proxy/oauth2-proxy/pull/690) Address GoSec security findings & remediate (@NickMeves) | ||||||
| - [#689](https://github.com/oauth2-proxy/oauth2-proxy/pull/689) Fix finicky logging_handler_test from time drift (@NickMeves) | - [#689](https://github.com/oauth2-proxy/oauth2-proxy/pull/689) Fix finicky logging_handler_test from time drift (@NickMeves) | ||||||
| - [#699](https://github.com/oauth2-proxy/oauth2-proxy/pull/699) Align persistence ginkgo tests with conventions (@NickMeves) | - [#699](https://github.com/oauth2-proxy/oauth2-proxy/pull/699) Align persistence ginkgo tests with conventions (@NickMeves) | ||||||
|   | |||||||
| @@ -45,6 +45,7 @@ An example [oauth2-proxy.cfg]({{ site.gitweb }}/contrib/oauth2-proxy.cfg.example | |||||||
| | `--custom-templates-dir` | string | path to custom html templates | | | | `--custom-templates-dir` | string | path to custom html templates | | | ||||||
| | `--display-htpasswd-form` | bool | display username / password login form if an htpasswd file is provided | true | | | `--display-htpasswd-form` | bool | display username / password login form if an htpasswd file is provided | true | | ||||||
| | `--email-domain` | string \| list  | authenticate emails with the specified domain (may be given multiple times). Use `*` to authenticate any email | | | | `--email-domain` | string \| list  | authenticate emails with the specified domain (may be given multiple times). Use `*` to authenticate any email | | | ||||||
|  | | `--errors-to-info-log` | bool | redirects error-level logging to default log channel instead of stderr | | | ||||||
| | `--extra-jwt-issuers` | string | 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` | string | 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` | string | comma separated list of paths to exclude from logging, e.g. `"/ping,/path2"` |`""` (no paths excluded) | | | `--exclude-logging-paths` | string | comma separated list of paths to exclude from logging, e.g. `"/ping,/path2"` |`""` (no paths excluded) | | ||||||
| | `--flush-interval` | duration | period between flushing response buffers when streaming responses | `"1s"` | | | `--flush-interval` | duration | period between flushing response buffers when streaming responses | `"1s"` | | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								http.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								http.go
									
									
									
									
									
								
							| @@ -106,7 +106,7 @@ func (s *Server) serve(listener net.Listener) { | |||||||
|  |  | ||||||
| 	err := srv.Serve(listener) | 	err := srv.Serve(listener) | ||||||
| 	if err != nil && !errors.Is(err, http.ErrServerClosed) { | 	if err != nil && !errors.Is(err, http.ErrServerClosed) { | ||||||
| 		logger.Printf("ERROR: http.Serve() - %s", err) | 		logger.Errorf("ERROR: http.Serve() - %s", err) | ||||||
| 	} | 	} | ||||||
| 	<-idleConnsClosed | 	<-idleConnsClosed | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								main.go
									
									
									
									
									
								
							| @@ -38,13 +38,13 @@ func main() { | |||||||
| 	legacyOpts := options.NewLegacyOptions() | 	legacyOpts := options.NewLegacyOptions() | ||||||
| 	err = options.Load(*config, flagSet, legacyOpts) | 	err = options.Load(*config, flagSet, legacyOpts) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("ERROR: Failed to load config: %v", err) | 		logger.Errorf("ERROR: Failed to load config: %v", err) | ||||||
| 		os.Exit(1) | 		os.Exit(1) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	opts, err := legacyOpts.ToOptions() | 	opts, err := legacyOpts.ToOptions() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("ERROR: Failed to convert config: %v", err) | 		logger.Errorf("ERROR: Failed to convert config: %v", err) | ||||||
| 		os.Exit(1) | 		os.Exit(1) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -57,7 +57,7 @@ func main() { | |||||||
| 	validator := NewValidator(opts.EmailDomains, opts.AuthenticatedEmailsFile) | 	validator := NewValidator(opts.EmailDomains, opts.AuthenticatedEmailsFile) | ||||||
| 	oauthproxy, err := NewOAuthProxy(opts, validator) | 	oauthproxy, err := NewOAuthProxy(opts, validator) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("ERROR: Failed to initialise OAuth2 Proxy: %v", err) | 		logger.Errorf("ERROR: Failed to initialise OAuth2 Proxy: %v", err) | ||||||
| 		os.Exit(1) | 		os.Exit(1) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -337,7 +337,7 @@ func (p *OAuthProxy) makeCookie(req *http.Request, name string, value string, ex | |||||||
| 			domain = h | 			domain = h | ||||||
| 		} | 		} | ||||||
| 		if !strings.HasSuffix(domain, cookieDomain) { | 		if !strings.HasSuffix(domain, cookieDomain) { | ||||||
| 			logger.Printf("Warning: request host is %q but using configured cookie domain of %q", domain, cookieDomain) | 			logger.Errorf("Warning: request host is %q but using configured cookie domain of %q", domain, cookieDomain) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -423,7 +423,7 @@ func (p *OAuthProxy) SignInPage(rw http.ResponseWriter, req *http.Request, code | |||||||
|  |  | ||||||
| 	redirectURL, err := p.GetRedirect(req) | 	redirectURL, err := p.GetRedirect(req) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("Error obtaining redirect: %v", err) | 		logger.Errorf("Error obtaining redirect: %v", err) | ||||||
| 		p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error()) | 		p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error()) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| @@ -623,7 +623,7 @@ func (p *OAuthProxy) IsTrustedIP(req *http.Request) bool { | |||||||
|  |  | ||||||
| 	remoteAddr, err := ip.GetClientIP(p.realClientIPParser, req) | 	remoteAddr, err := ip.GetClientIP(p.realClientIPParser, req) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("Error obtaining real IP for trusted IP list: %v", err) | 		logger.Errorf("Error obtaining real IP for trusted IP list: %v", err) | ||||||
| 		// Possibly spoofed X-Real-IP header | 		// Possibly spoofed X-Real-IP header | ||||||
| 		return false | 		return false | ||||||
| 	} | 	} | ||||||
| @@ -666,7 +666,7 @@ func (p *OAuthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { | |||||||
| func (p *OAuthProxy) SignIn(rw http.ResponseWriter, req *http.Request) { | func (p *OAuthProxy) SignIn(rw http.ResponseWriter, req *http.Request) { | ||||||
| 	redirect, err := p.GetRedirect(req) | 	redirect, err := p.GetRedirect(req) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("Error obtaining redirect: %v", err) | 		logger.Errorf("Error obtaining redirect: %v", err) | ||||||
| 		p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error()) | 		p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error()) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| @@ -718,13 +718,13 @@ func (p *OAuthProxy) UserInfo(rw http.ResponseWriter, req *http.Request) { | |||||||
| func (p *OAuthProxy) SignOut(rw http.ResponseWriter, req *http.Request) { | func (p *OAuthProxy) SignOut(rw http.ResponseWriter, req *http.Request) { | ||||||
| 	redirect, err := p.GetRedirect(req) | 	redirect, err := p.GetRedirect(req) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("Error obtaining redirect: %v", err) | 		logger.Errorf("Error obtaining redirect: %v", err) | ||||||
| 		p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error()) | 		p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error()) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	err = p.ClearSessionCookie(rw, req) | 	err = p.ClearSessionCookie(rw, req) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("Error clearing session cookie: %v", err) | 		logger.Errorf("Error clearing session cookie: %v", err) | ||||||
| 		p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error()) | 		p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error()) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| @@ -736,14 +736,14 @@ func (p *OAuthProxy) OAuthStart(rw http.ResponseWriter, req *http.Request) { | |||||||
| 	prepareNoCache(rw) | 	prepareNoCache(rw) | ||||||
| 	nonce, err := encryption.Nonce() | 	nonce, err := encryption.Nonce() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("Error obtaining nonce: %v", err) | 		logger.Errorf("Error obtaining nonce: %v", err) | ||||||
| 		p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error()) | 		p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error()) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	p.SetCSRFCookie(rw, req, nonce) | 	p.SetCSRFCookie(rw, req, nonce) | ||||||
| 	redirect, err := p.GetRedirect(req) | 	redirect, err := p.GetRedirect(req) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("Error obtaining redirect: %v", err) | 		logger.Errorf("Error obtaining redirect: %v", err) | ||||||
| 		p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error()) | 		p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error()) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| @@ -759,27 +759,27 @@ func (p *OAuthProxy) OAuthCallback(rw http.ResponseWriter, req *http.Request) { | |||||||
| 	// finish the oauth cycle | 	// finish the oauth cycle | ||||||
| 	err := req.ParseForm() | 	err := req.ParseForm() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("Error while parsing OAuth2 callback: %v", err) | 		logger.Errorf("Error while parsing OAuth2 callback: %v", err) | ||||||
| 		p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error()) | 		p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error()) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	errorString := req.Form.Get("error") | 	errorString := req.Form.Get("error") | ||||||
| 	if errorString != "" { | 	if errorString != "" { | ||||||
| 		logger.Printf("Error while parsing OAuth2 callback: %s", errorString) | 		logger.Errorf("Error while parsing OAuth2 callback: %s", errorString) | ||||||
| 		p.ErrorPage(rw, http.StatusForbidden, "Permission Denied", errorString) | 		p.ErrorPage(rw, http.StatusForbidden, "Permission Denied", errorString) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	session, err := p.redeemCode(req.Context(), req.Host, req.Form.Get("code")) | 	session, err := p.redeemCode(req.Context(), req.Host, req.Form.Get("code")) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("Error redeeming code during OAuth2 callback: %v", err) | 		logger.Errorf("Error redeeming code during OAuth2 callback: %v", err) | ||||||
| 		p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", "Internal Error") | 		p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", "Internal Error") | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	s := strings.SplitN(req.Form.Get("state"), ":", 2) | 	s := strings.SplitN(req.Form.Get("state"), ":", 2) | ||||||
| 	if len(s) != 2 { | 	if len(s) != 2 { | ||||||
| 		logger.Printf("Error while parsing OAuth2 state: invalid length") | 		logger.Error("Error while parsing OAuth2 state: invalid length") | ||||||
| 		p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", "Invalid State") | 		p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", "Invalid State") | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| @@ -865,7 +865,7 @@ func (p *OAuthProxy) Proxy(rw http.ResponseWriter, req *http.Request) { | |||||||
|  |  | ||||||
| 	default: | 	default: | ||||||
| 		// unknown error | 		// unknown error | ||||||
| 		logger.Printf("Unexpected internal error: %s", err) | 		logger.Errorf("Unexpected internal error: %v", err) | ||||||
| 		p.ErrorPage(rw, http.StatusInternalServerError, | 		p.ErrorPage(rw, http.StatusInternalServerError, | ||||||
| 			"Internal Error", "Internal Error") | 			"Internal Error", "Internal Error") | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -91,7 +91,7 @@ func (l *LegacyUpstreams) convert() (Upstreams, error) { | |||||||
| 		case "static": | 		case "static": | ||||||
| 			responseCode, err := strconv.Atoi(u.Host) | 			responseCode, err := strconv.Atoi(u.Host) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				logger.Printf("unable to convert %q to int, use default \"200\"", u.Host) | 				logger.Errorf("unable to convert %q to int, use default \"200\"", u.Host) | ||||||
| 				responseCode = 200 | 				responseCode = 200 | ||||||
| 			} | 			} | ||||||
| 			upstream.Static = true | 			upstream.Static = true | ||||||
|   | |||||||
| @@ -13,6 +13,7 @@ type Logging struct { | |||||||
| 	RequestFormat   string         `flag:"request-logging-format" cfg:"request_logging_format"` | 	RequestFormat   string         `flag:"request-logging-format" cfg:"request_logging_format"` | ||||||
| 	StandardEnabled bool           `flag:"standard-logging" cfg:"standard_logging"` | 	StandardEnabled bool           `flag:"standard-logging" cfg:"standard_logging"` | ||||||
| 	StandardFormat  string         `flag:"standard-logging-format" cfg:"standard_logging_format"` | 	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"` | 	ExcludePaths    []string       `flag:"exclude-logging-path" cfg:"exclude_logging_paths"` | ||||||
| 	LocalTime       bool           `flag:"logging-local-time" cfg:"logging_local_time"` | 	LocalTime       bool           `flag:"logging-local-time" cfg:"logging_local_time"` | ||||||
| 	SilencePing     bool           `flag:"silence-ping-logging" cfg:"silence_ping_logging"` | 	SilencePing     bool           `flag:"silence-ping-logging" cfg:"silence_ping_logging"` | ||||||
| @@ -37,6 +38,7 @@ func loggingFlagSet() *pflag.FlagSet { | |||||||
| 	flagSet.String("standard-logging-format", logger.DefaultStandardLoggingFormat, "Template for standard log lines") | 	flagSet.String("standard-logging-format", logger.DefaultStandardLoggingFormat, "Template for standard log lines") | ||||||
| 	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.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.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("logging-local-time", true, "If the time in log files and backup filenames are local or UTC time") | ||||||
| @@ -63,6 +65,7 @@ func loggingDefaults() Logging { | |||||||
| 		RequestFormat:   logger.DefaultRequestLoggingFormat, | 		RequestFormat:   logger.DefaultRequestLoggingFormat, | ||||||
| 		StandardEnabled: true, | 		StandardEnabled: true, | ||||||
| 		StandardFormat:  logger.DefaultStandardLoggingFormat, | 		StandardFormat:  logger.DefaultStandardLoggingFormat, | ||||||
|  | 		ErrToInfo:       false, | ||||||
| 		File: LogFileOptions{ | 		File: LogFileOptions{ | ||||||
| 			Filename:   "", | 			Filename:   "", | ||||||
| 			MaxSize:    100, | 			MaxSize:    100, | ||||||
|   | |||||||
| @@ -78,7 +78,7 @@ func createHtpasswdMap(records [][]string) (*htpasswdMap, error) { | |||||||
|  |  | ||||||
| 		// Password is neither sha1 or bcrypt | 		// Password is neither sha1 or bcrypt | ||||||
| 		// TODO(JoelSpeed): In the next breaking release, make this return an error. | 		// TODO(JoelSpeed): In the next breaking release, make this return an error. | ||||||
| 		logger.Printf("Invalid htpasswd entry for %s. Must be a SHA or bcrypt entry.", user) | 		logger.Errorf("Invalid htpasswd entry for %s. Must be a SHA or bcrypt entry.", user) | ||||||
| 	} | 	} | ||||||
| 	return h, nil | 	return h, nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ func MakeCookie(req *http.Request, name string, value string, path string, domai | |||||||
| 			host = h | 			host = h | ||||||
| 		} | 		} | ||||||
| 		if !strings.HasSuffix(host, domain) { | 		if !strings.HasSuffix(host, domain) { | ||||||
| 			logger.Printf("Warning: request host is %q but using configured cookie domain of %q", host, domain) | 			logger.Errorf("Warning: request host is %q but using configured cookie domain of %q", host, domain) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -45,7 +45,7 @@ func MakeCookieFromOptions(req *http.Request, name string, value string, cookieO | |||||||
| 		return MakeCookie(req, name, value, cookieOpts.Path, domain, cookieOpts.HTTPOnly, cookieOpts.Secure, expiration, now, ParseSameSite(cookieOpts.SameSite)) | 		return MakeCookie(req, name, value, cookieOpts.Path, domain, cookieOpts.HTTPOnly, cookieOpts.Secure, expiration, now, ParseSameSite(cookieOpts.SameSite)) | ||||||
| 	} | 	} | ||||||
| 	// If nothing matches, create the cookie with the shortest domain | 	// If nothing matches, create the cookie with the shortest domain | ||||||
| 	logger.Printf("Warning: request host %q did not match any of the specific cookie domains of %q", GetRequestHost(req), strings.Join(cookieOpts.Domains, ",")) | 	logger.Errorf("Warning: request host %q did not match any of the specific cookie domains of %q", GetRequestHost(req), strings.Join(cookieOpts.Domains, ",")) | ||||||
| 	defaultDomain := "" | 	defaultDomain := "" | ||||||
| 	if len(cookieOpts.Domains) > 0 { | 	if len(cookieOpts.Domains) > 0 { | ||||||
| 		defaultDomain = cookieOpts.Domains[len(cookieOpts.Domains)-1] | 		defaultDomain = cookieOpts.Domains[len(cookieOpts.Domains)-1] | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| package logger | package logger | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"bytes" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io" | 	"io" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| @@ -15,6 +16,9 @@ import ( | |||||||
| // AuthStatus defines the different types of auth logging that occur | // AuthStatus defines the different types of auth logging that occur | ||||||
| type AuthStatus string | type AuthStatus string | ||||||
|  |  | ||||||
|  | // Level indicates the log level for log messages | ||||||
|  | type Level int | ||||||
|  |  | ||||||
| const ( | const ( | ||||||
| 	// DefaultStandardLoggingFormat defines the default standard log format | 	// DefaultStandardLoggingFormat defines the default standard log format | ||||||
| 	DefaultStandardLoggingFormat = "[{{.Timestamp}}] [{{.File}}] {{.Message}}" | 	DefaultStandardLoggingFormat = "[{{.Timestamp}}] [{{.File}}] {{.Message}}" | ||||||
| @@ -38,6 +42,11 @@ const ( | |||||||
| 	LUTC | 	LUTC | ||||||
| 	// LstdFlags flag for initial values for the logger | 	// LstdFlags flag for initial values for the logger | ||||||
| 	LstdFlags = Lshortfile | 	LstdFlags = Lshortfile | ||||||
|  |  | ||||||
|  | 	// DEFAULT is the default log level (effectively INFO) | ||||||
|  | 	DEFAULT Level = iota | ||||||
|  | 	// ERROR is for error-level logging | ||||||
|  | 	ERROR | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // These are the containers for all values that are available as variables in the logging formats. | // These are the containers for all values that are available as variables in the logging formats. | ||||||
| @@ -87,6 +96,7 @@ type Logger struct { | |||||||
| 	mu             sync.Mutex | 	mu             sync.Mutex | ||||||
| 	flag           int | 	flag           int | ||||||
| 	writer         io.Writer | 	writer         io.Writer | ||||||
|  | 	errWriter      io.Writer | ||||||
| 	stdEnabled     bool | 	stdEnabled     bool | ||||||
| 	authEnabled    bool | 	authEnabled    bool | ||||||
| 	reqEnabled     bool | 	reqEnabled     bool | ||||||
| @@ -100,7 +110,8 @@ type Logger struct { | |||||||
| // New creates a new Standarderr Logger. | // New creates a new Standarderr Logger. | ||||||
| func New(flag int) *Logger { | func New(flag int) *Logger { | ||||||
| 	return &Logger{ | 	return &Logger{ | ||||||
| 		writer:         os.Stderr, | 		writer:         os.Stdout, | ||||||
|  | 		errWriter:      os.Stderr, | ||||||
| 		flag:           flag, | 		flag:           flag, | ||||||
| 		stdEnabled:     true, | 		stdEnabled:     true, | ||||||
| 		authEnabled:    true, | 		authEnabled:    true, | ||||||
| @@ -115,13 +126,7 @@ func New(flag int) *Logger { | |||||||
|  |  | ||||||
| var std = New(LstdFlags) | var std = New(LstdFlags) | ||||||
|  |  | ||||||
| // Output a standard log template with a simple message. | func (l *Logger) formatLogMessage(calldepth int, message string) []byte { | ||||||
| // Write a final newline at the end of every message. |  | ||||||
| func (l *Logger) Output(calldepth int, message string) { |  | ||||||
| 	if !l.stdEnabled { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	now := time.Now() | 	now := time.Now() | ||||||
| 	file := "???:0" | 	file := "???:0" | ||||||
|  |  | ||||||
| @@ -129,10 +134,8 @@ func (l *Logger) Output(calldepth int, message string) { | |||||||
| 		file = l.GetFileLineString(calldepth + 1) | 		file = l.GetFileLineString(calldepth + 1) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	l.mu.Lock() | 	var logBuff = new(bytes.Buffer) | ||||||
| 	defer l.mu.Unlock() | 	err := l.stdLogTemplate.Execute(logBuff, stdLogMessageData{ | ||||||
|  |  | ||||||
| 	err := l.stdLogTemplate.Execute(l.writer, stdLogMessageData{ |  | ||||||
| 		Timestamp: FormatTimestamp(now), | 		Timestamp: FormatTimestamp(now), | ||||||
| 		File:      file, | 		File:      file, | ||||||
| 		Message:   message, | 		Message:   message, | ||||||
| @@ -145,6 +148,26 @@ func (l *Logger) Output(calldepth int, message string) { | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		panic(err) | 		panic(err) | ||||||
| 	} | 	} | ||||||
|  | 	logBuff.Write([]byte("\n")) | ||||||
|  |  | ||||||
|  | 	return logBuff.Bytes() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Output a standard log template with a simple message to default output channel. | ||||||
|  | // Write a final newline at the end of every message. | ||||||
|  | func (l *Logger) Output(lvl Level, calldepth int, message string) { | ||||||
|  | 	l.mu.Lock() | ||||||
|  | 	defer l.mu.Unlock() | ||||||
|  | 	if !l.stdEnabled { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	msg := l.formatLogMessage(calldepth, message) | ||||||
|  | 	switch lvl { | ||||||
|  | 	case ERROR: | ||||||
|  | 		l.errWriter.Write(msg) | ||||||
|  | 	default: | ||||||
|  | 		l.writer.Write(msg) | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // PrintAuthf writes auth info to the logger. Requires an http.Request to | // PrintAuthf writes auth info to the logger. Requires an http.Request to | ||||||
| @@ -302,6 +325,17 @@ func (l *Logger) SetStandardEnabled(e bool) { | |||||||
| 	l.stdEnabled = e | 	l.stdEnabled = e | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // SetErrToInfo enables or disables error logging to error writer instead of the default. | ||||||
|  | func (l *Logger) SetErrToInfo(e bool) { | ||||||
|  | 	l.mu.Lock() | ||||||
|  | 	defer l.mu.Unlock() | ||||||
|  | 	if e { | ||||||
|  | 		l.errWriter = l.writer | ||||||
|  | 	} else { | ||||||
|  | 		l.errWriter = os.Stderr | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| // SetAuthEnabled enables or disables auth logging. | // SetAuthEnabled enables or disables auth logging. | ||||||
| func (l *Logger) SetAuthEnabled(e bool) { | func (l *Logger) SetAuthEnabled(e bool) { | ||||||
| 	l.mu.Lock() | 	l.mu.Lock() | ||||||
| @@ -371,19 +405,32 @@ func SetFlags(flag int) { | |||||||
| 	std.SetFlags(flag) | 	std.SetFlags(flag) | ||||||
| } | } | ||||||
|  |  | ||||||
| // SetOutput sets the output destination for the standard logger. | // SetOutput sets the output destination for the standard logger's default channel. | ||||||
| func SetOutput(w io.Writer) { | func SetOutput(w io.Writer) { | ||||||
| 	std.mu.Lock() | 	std.mu.Lock() | ||||||
| 	defer std.mu.Unlock() | 	defer std.mu.Unlock() | ||||||
| 	std.writer = w | 	std.writer = w | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // SetErrOutput sets the output destination for the standard logger's error channel. | ||||||
|  | func SetErrOutput(w io.Writer) { | ||||||
|  | 	std.mu.Lock() | ||||||
|  | 	defer std.mu.Unlock() | ||||||
|  | 	std.errWriter = w | ||||||
|  | } | ||||||
|  |  | ||||||
| // SetStandardEnabled enables or disables standard logging for the | // SetStandardEnabled enables or disables standard logging for the | ||||||
| // standard logger. | // standard logger. | ||||||
| func SetStandardEnabled(e bool) { | func SetStandardEnabled(e bool) { | ||||||
| 	std.SetStandardEnabled(e) | 	std.SetStandardEnabled(e) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // SetErrToInfo enables or disables error logging to output writer instead of | ||||||
|  | // error writer. | ||||||
|  | func SetErrToInfo(e bool) { | ||||||
|  | 	std.SetErrToInfo(e) | ||||||
|  | } | ||||||
|  |  | ||||||
| // SetAuthEnabled enables or disables auth logging for the standard | // SetAuthEnabled enables or disables auth logging for the standard | ||||||
| // logger. | // logger. | ||||||
| func SetAuthEnabled(e bool) { | func SetAuthEnabled(e bool) { | ||||||
| @@ -428,57 +475,75 @@ func SetReqTemplate(t string) { | |||||||
| // Print calls Output to print to the standard logger. | // Print calls Output to print to the standard logger. | ||||||
| // Arguments are handled in the manner of fmt.Print. | // Arguments are handled in the manner of fmt.Print. | ||||||
| func Print(v ...interface{}) { | func Print(v ...interface{}) { | ||||||
| 	std.Output(2, fmt.Sprint(v...)) | 	std.Output(DEFAULT, 2, fmt.Sprint(v...)) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Printf calls Output to print to the standard logger. | // Printf calls Output to print to the standard logger. | ||||||
| // Arguments are handled in the manner of fmt.Printf. | // Arguments are handled in the manner of fmt.Printf. | ||||||
| func Printf(format string, v ...interface{}) { | func Printf(format string, v ...interface{}) { | ||||||
| 	std.Output(2, fmt.Sprintf(format, v...)) | 	std.Output(DEFAULT, 2, fmt.Sprintf(format, v...)) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Println calls Output to print to the standard logger. | // Println calls Output to print to the standard logger. | ||||||
| // Arguments are handled in the manner of fmt.Println. | // Arguments are handled in the manner of fmt.Println. | ||||||
| func Println(v ...interface{}) { | func Println(v ...interface{}) { | ||||||
| 	std.Output(2, fmt.Sprintln(v...)) | 	std.Output(DEFAULT, 2, fmt.Sprintln(v...)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Error calls OutputErr to print to the standard logger's error channel. | ||||||
|  | // Arguments are handled in the manner of fmt.Print. | ||||||
|  | func Error(v ...interface{}) { | ||||||
|  | 	std.Output(ERROR, 2, fmt.Sprint(v...)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Errorf calls OutputErr to print to the standard logger's error channel. | ||||||
|  | // Arguments are handled in the manner of fmt.Printf. | ||||||
|  | func Errorf(format string, v ...interface{}) { | ||||||
|  | 	std.Output(ERROR, 2, fmt.Sprintf(format, v...)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Errorln calls OutputErr to print to the standard logger's error channel. | ||||||
|  | // Arguments are handled in the manner of fmt.Println. | ||||||
|  | func Errorln(v ...interface{}) { | ||||||
|  | 	std.Output(ERROR, 2, fmt.Sprintln(v...)) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Fatal is equivalent to Print() followed by a call to os.Exit(1). | // Fatal is equivalent to Print() followed by a call to os.Exit(1). | ||||||
| func Fatal(v ...interface{}) { | func Fatal(v ...interface{}) { | ||||||
| 	std.Output(2, fmt.Sprint(v...)) | 	std.Output(ERROR, 2, fmt.Sprint(v...)) | ||||||
| 	os.Exit(1) | 	os.Exit(1) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Fatalf is equivalent to Printf() followed by a call to os.Exit(1). | // Fatalf is equivalent to Printf() followed by a call to os.Exit(1). | ||||||
| func Fatalf(format string, v ...interface{}) { | func Fatalf(format string, v ...interface{}) { | ||||||
| 	std.Output(2, fmt.Sprintf(format, v...)) | 	std.Output(ERROR, 2, fmt.Sprintf(format, v...)) | ||||||
| 	os.Exit(1) | 	os.Exit(1) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Fatalln is equivalent to Println() followed by a call to os.Exit(1). | // Fatalln is equivalent to Println() followed by a call to os.Exit(1). | ||||||
| func Fatalln(v ...interface{}) { | func Fatalln(v ...interface{}) { | ||||||
| 	std.Output(2, fmt.Sprintln(v...)) | 	std.Output(ERROR, 2, fmt.Sprintln(v...)) | ||||||
| 	os.Exit(1) | 	os.Exit(1) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Panic is equivalent to Print() followed by a call to panic(). | // Panic is equivalent to Print() followed by a call to panic(). | ||||||
| func Panic(v ...interface{}) { | func Panic(v ...interface{}) { | ||||||
| 	s := fmt.Sprint(v...) | 	s := fmt.Sprint(v...) | ||||||
| 	std.Output(2, s) | 	std.Output(ERROR, 2, s) | ||||||
| 	panic(s) | 	panic(s) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Panicf is equivalent to Printf() followed by a call to panic(). | // Panicf is equivalent to Printf() followed by a call to panic(). | ||||||
| func Panicf(format string, v ...interface{}) { | func Panicf(format string, v ...interface{}) { | ||||||
| 	s := fmt.Sprintf(format, v...) | 	s := fmt.Sprintf(format, v...) | ||||||
| 	std.Output(2, s) | 	std.Output(ERROR, 2, s) | ||||||
| 	panic(s) | 	panic(s) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Panicln is equivalent to Println() followed by a call to panic(). | // Panicln is equivalent to Println() followed by a call to panic(). | ||||||
| func Panicln(v ...interface{}) { | func Panicln(v ...interface{}) { | ||||||
| 	s := fmt.Sprintln(v...) | 	s := fmt.Sprintln(v...) | ||||||
| 	std.Output(2, s) | 	std.Output(ERROR, 2, s) | ||||||
| 	panic(s) | 	panic(s) | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -34,7 +34,7 @@ func loadBasicAuthSession(validator basic.Validator, next http.Handler) http.Han | |||||||
|  |  | ||||||
| 		session, err := getBasicSession(validator, req) | 		session, err := getBasicSession(validator, req) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logger.Printf("Error retrieving session from token in Authorization header: %v", err) | 			logger.Errorf("Error retrieving session from token in Authorization header: %v", err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// Add the session to the scope if it was found | 		// Add the session to the scope if it was found | ||||||
|   | |||||||
| @@ -57,7 +57,7 @@ func (j *jwtSessionLoader) loadSession(next http.Handler) http.Handler { | |||||||
|  |  | ||||||
| 		session, err := j.getJwtSession(req) | 		session, err := j.getJwtSession(req) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logger.Printf("Error retrieving session from token in Authorization header: %v", err) | 			logger.Errorf("Error retrieving session from token in Authorization header: %v", err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// Add the session to the scope if it was found | 		// Add the session to the scope if it was found | ||||||
|   | |||||||
| @@ -72,10 +72,10 @@ func (s *storedSessionLoader) loadSession(next http.Handler) http.Handler { | |||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			// In the case when there was an error loading the session, | 			// In the case when there was an error loading the session, | ||||||
| 			// we should clear the session | 			// we should clear the session | ||||||
| 			logger.Printf("Error loading cookied session: %v, removing session", err) | 			logger.Errorf("Error loading cookied session: %v, removing session", err) | ||||||
| 			err = s.store.Clear(rw, req) | 			err = s.store.Clear(rw, req) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				logger.Printf("Error removing session: %v", err) | 				logger.Errorf("Error removing session: %v", err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -176,7 +176,7 @@ func splitCookie(c *http.Cookie) []*http.Cookie { | |||||||
| 		return []*http.Cookie{c} | 		return []*http.Cookie{c} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	logger.Printf("WARNING: Multiple cookies are required for this session as it exceeds the 4kb cookie limit. Please use server side session storage (eg. Redis) instead.") | 	logger.Errorf("WARNING: Multiple cookies are required for this session as it exceeds the 4kb cookie limit. Please use server side session storage (eg. Redis) instead.") | ||||||
|  |  | ||||||
| 	cookies := []*http.Cookie{} | 	cookies := []*http.Cookie{} | ||||||
| 	valueBytes := []byte(c.Value) | 	valueBytes := []byte(c.Value) | ||||||
|   | |||||||
| @@ -121,7 +121,7 @@ func buildStandaloneClient(opts options.RedisStoreOptions) (Client, error) { | |||||||
| 	if opts.CAPath != "" { | 	if opts.CAPath != "" { | ||||||
| 		rootCAs, err := x509.SystemCertPool() | 		rootCAs, err := x509.SystemCertPool() | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logger.Printf("failed to load system cert pool for redis connection, falling back to empty cert pool") | 			logger.Errorf("failed to load system cert pool for redis connection, falling back to empty cert pool") | ||||||
| 		} | 		} | ||||||
| 		if rootCAs == nil { | 		if rootCAs == nil { | ||||||
| 			rootCAs = x509.NewCertPool() | 			rootCAs = x509.NewCertPool() | ||||||
| @@ -133,7 +133,7 @@ func buildStandaloneClient(opts options.RedisStoreOptions) (Client, error) { | |||||||
|  |  | ||||||
| 		// Append our cert to the system pool | 		// Append our cert to the system pool | ||||||
| 		if ok := rootCAs.AppendCertsFromPEM(certs); !ok { | 		if ok := rootCAs.AppendCertsFromPEM(certs); !ok { | ||||||
| 			logger.Printf("no certs appended, using system certs only") | 			logger.Errorf("no certs appended, using system certs only") | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		opt.TLSConfig.RootCAs = rootCAs | 		opt.TLSConfig.RootCAs = rootCAs | ||||||
|   | |||||||
| @@ -74,7 +74,7 @@ func (m *multiUpstreamProxy) registerHTTPUpstreamProxy(upstream options.Upstream | |||||||
| // NewProxyErrorHandler creates a ProxyErrorHandler using the template given. | // NewProxyErrorHandler creates a ProxyErrorHandler using the template given. | ||||||
| func NewProxyErrorHandler(errorTemplate *template.Template, proxyPrefix string) ProxyErrorHandler { | func NewProxyErrorHandler(errorTemplate *template.Template, proxyPrefix string) ProxyErrorHandler { | ||||||
| 	return func(rw http.ResponseWriter, req *http.Request, proxyErr error) { | 	return func(rw http.ResponseWriter, req *http.Request, proxyErr error) { | ||||||
| 		logger.Printf("Error proxying to upstream server: %v", proxyErr) | 		logger.Errorf("Error proxying to upstream server: %v", proxyErr) | ||||||
| 		rw.WriteHeader(http.StatusBadGateway) | 		rw.WriteHeader(http.StatusBadGateway) | ||||||
| 		data := struct { | 		data := struct { | ||||||
| 			Title       string | 			Title       string | ||||||
|   | |||||||
| @@ -40,11 +40,12 @@ func configureLogger(o options.Logging, msgs []string) []string { | |||||||
|  |  | ||||||
| 	// Supply a sanity warning to the logger if all logging is disabled | 	// Supply a sanity warning to the logger if all logging is disabled | ||||||
| 	if !o.StandardEnabled && !o.AuthEnabled && !o.RequestEnabled { | 	if !o.StandardEnabled && !o.AuthEnabled && !o.RequestEnabled { | ||||||
| 		logger.Print("Warning: Logging disabled. No further logs will be shown.") | 		logger.Error("Warning: Logging disabled. No further logs will be shown.") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Pass configuration values to the standard logger | 	// Pass configuration values to the standard logger | ||||||
| 	logger.SetStandardEnabled(o.StandardEnabled) | 	logger.SetStandardEnabled(o.StandardEnabled) | ||||||
|  | 	logger.SetErrToInfo(o.ErrToInfo) | ||||||
| 	logger.SetAuthEnabled(o.AuthEnabled) | 	logger.SetAuthEnabled(o.AuthEnabled) | ||||||
| 	logger.SetReqEnabled(o.RequestEnabled) | 	logger.SetReqEnabled(o.RequestEnabled) | ||||||
| 	logger.SetStandardTemplate(o.StandardFormat) | 	logger.SetStandardTemplate(o.StandardFormat) | ||||||
|   | |||||||
| @@ -92,7 +92,7 @@ func Validate(o *options.Options) error { | |||||||
| 				Do(). | 				Do(). | ||||||
| 				UnmarshalJSON() | 				UnmarshalJSON() | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				logger.Printf("error: failed to discover OIDC configuration: %v", err) | 				logger.Errorf("error: failed to discover OIDC configuration: %v", err) | ||||||
| 			} else { | 			} else { | ||||||
| 				// Prefer manually configured URLs. It's a bit unclear | 				// Prefer manually configured URLs. It's a bit unclear | ||||||
| 				// why you'd be doing discovery and also providing the URLs | 				// why you'd be doing discovery and also providing the URLs | ||||||
|   | |||||||
| @@ -202,12 +202,12 @@ func (p *AzureProvider) GetEmailAddress(ctx context.Context, s *sessions.Session | |||||||
|  |  | ||||||
| 	email, err = json.Get("userPrincipalName").String() | 	email, err = json.Get("userPrincipalName").String() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("failed making request %s", err) | 		logger.Errorf("failed making request %s", err) | ||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if email == "" { | 	if email == "" { | ||||||
| 		logger.Printf("failed to get email address") | 		logger.Errorf("failed to get email address") | ||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -107,7 +107,7 @@ func (p *BitbucketProvider) GetEmailAddress(ctx context.Context, s *sessions.Ses | |||||||
| 		Do(). | 		Do(). | ||||||
| 		UnmarshalInto(&emails) | 		UnmarshalInto(&emails) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("failed making request: %v", err) | 		logger.Errorf("failed making request: %v", err) | ||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -123,7 +123,7 @@ func (p *BitbucketProvider) GetEmailAddress(ctx context.Context, s *sessions.Ses | |||||||
| 			Do(). | 			Do(). | ||||||
| 			UnmarshalInto(&teams) | 			UnmarshalInto(&teams) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logger.Printf("failed requesting teams membership: %v", err) | 			logger.Errorf("failed requesting teams membership: %v", err) | ||||||
| 			return "", err | 			return "", err | ||||||
| 		} | 		} | ||||||
| 		var found = false | 		var found = false | ||||||
| @@ -134,7 +134,7 @@ func (p *BitbucketProvider) GetEmailAddress(ctx context.Context, s *sessions.Ses | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if !found { | 		if !found { | ||||||
| 			logger.Print("team membership test failed, access denied") | 			logger.Error("team membership test failed, access denied") | ||||||
| 			return "", nil | 			return "", nil | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -153,7 +153,7 @@ func (p *BitbucketProvider) GetEmailAddress(ctx context.Context, s *sessions.Ses | |||||||
| 			Do(). | 			Do(). | ||||||
| 			UnmarshalInto(&repositories) | 			UnmarshalInto(&repositories) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logger.Printf("failed checking repository access: %v", err) | 			logger.Errorf("failed checking repository access: %v", err) | ||||||
| 			return "", err | 			return "", err | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -165,7 +165,7 @@ func (p *BitbucketProvider) GetEmailAddress(ctx context.Context, s *sessions.Ses | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if !found { | 		if !found { | ||||||
| 			logger.Print("repository access test failed, access denied") | 			logger.Error("repository access test failed, access denied") | ||||||
| 			return "", nil | 			return "", nil | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -212,7 +212,7 @@ func userInGroup(service *admin.Service, groups []string, email string) bool { | |||||||
| 			gerr, ok := err.(*googleapi.Error) | 			gerr, ok := err.(*googleapi.Error) | ||||||
| 			switch { | 			switch { | ||||||
| 			case ok && gerr.Code == 404: | 			case ok && gerr.Code == 404: | ||||||
| 				logger.Printf("error checking membership in group %s: group does not exist", group) | 				logger.Errorf("error checking membership in group %s: group does not exist", group) | ||||||
| 			case ok && gerr.Code == 400: | 			case ok && gerr.Code == 400: | ||||||
| 				// It is possible for Members.HasMember to return false even if the email is a group member. | 				// It is possible for Members.HasMember to return false even if the email is a group member. | ||||||
| 				// One case that can cause this is if the user email is from a different domain than the group, | 				// One case that can cause this is if the user email is from a different domain than the group, | ||||||
| @@ -222,7 +222,7 @@ func userInGroup(service *admin.Service, groups []string, email string) bool { | |||||||
| 				r, err := req.Do() | 				r, err := req.Do() | ||||||
|  |  | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					logger.Printf("error using get API to check member %s of google group %s: user not in the group", email, group) | 					logger.Errorf("error using get API to check member %s of google group %s: user not in the group", email, group) | ||||||
| 					continue | 					continue | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| @@ -232,7 +232,7 @@ func userInGroup(service *admin.Service, groups []string, email string) bool { | |||||||
| 					return true | 					return true | ||||||
| 				} | 				} | ||||||
| 			default: | 			default: | ||||||
| 				logger.Printf("error checking group membership: %v", err) | 				logger.Errorf("error checking group membership: %v", err) | ||||||
| 			} | 			} | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -24,14 +24,14 @@ func stripToken(endpoint string) string { | |||||||
| func stripParam(param, endpoint string) string { | func stripParam(param, endpoint string) string { | ||||||
| 	u, err := url.Parse(endpoint) | 	u, err := url.Parse(endpoint) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("error attempting to strip %s: %s", param, err) | 		logger.Errorf("error attempting to strip %s: %s", param, err) | ||||||
| 		return endpoint | 		return endpoint | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if u.RawQuery != "" { | 	if u.RawQuery != "" { | ||||||
| 		values, err := url.ParseQuery(u.RawQuery) | 		values, err := url.ParseQuery(u.RawQuery) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			logger.Printf("error attempting to strip %s: %s", param, err) | 			logger.Errorf("error attempting to strip %s: %s", param, err) | ||||||
| 			return u.String() | 			return u.String() | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -61,8 +61,8 @@ func validateToken(ctx context.Context, p Provider, accessToken string, header h | |||||||
| 		WithHeaders(header). | 		WithHeaders(header). | ||||||
| 		Do() | 		Do() | ||||||
| 	if result.Error() != nil { | 	if result.Error() != nil { | ||||||
| 		logger.Printf("GET %s", stripToken(endpoint)) | 		logger.Errorf("GET %s", stripToken(endpoint)) | ||||||
| 		logger.Printf("token validation request failed: %s", result.Error()) | 		logger.Errorf("token validation request failed: %s", result.Error()) | ||||||
| 		return false | 		return false | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -71,6 +71,6 @@ func validateToken(ctx context.Context, p Provider, accessToken string, header h | |||||||
| 	if result.StatusCode() == 200 { | 	if result.StatusCode() == 200 { | ||||||
| 		return true | 		return true | ||||||
| 	} | 	} | ||||||
| 	logger.Printf("token validation request failed: status %d - %s", result.StatusCode(), result.Body()) | 	logger.Errorf("token validation request failed: status %d - %s", result.StatusCode(), result.Body()) | ||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
|   | |||||||
| @@ -70,7 +70,7 @@ func (p *KeycloakProvider) GetEmailAddress(ctx context.Context, s *sessions.Sess | |||||||
| 		Do(). | 		Do(). | ||||||
| 		UnmarshalJSON() | 		UnmarshalJSON() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("failed making request %s", err) | 		logger.Errorf("failed making request %s", err) | ||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -39,7 +39,7 @@ func (p *ProviderData) GetClientSecret() (clientSecret string, err error) { | |||||||
| 	// Getting ClientSecret can fail in runtime so we need to report it without returning the file name to the user | 	// Getting ClientSecret can fail in runtime so we need to report it without returning the file name to the user | ||||||
| 	fileClientSecret, err := ioutil.ReadFile(p.ClientSecretFile) | 	fileClientSecret, err := ioutil.ReadFile(p.ClientSecretFile) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("error reading client secret file %s: %s", p.ClientSecretFile, err) | 		logger.Errorf("error reading client secret file %s: %s", p.ClientSecretFile, err) | ||||||
| 		return "", errors.New("could not read client secret file") | 		return "", errors.New("could not read client secret file") | ||||||
| 	} | 	} | ||||||
| 	return string(fileClientSecret), nil | 	return string(fileClientSecret), nil | ||||||
|   | |||||||
| @@ -62,7 +62,7 @@ func (um *UserMap) LoadAuthenticatedEmailsFile() { | |||||||
| 	csvReader.TrimLeadingSpace = true | 	csvReader.TrimLeadingSpace = true | ||||||
| 	records, err := csvReader.ReadAll() | 	records, err := csvReader.ReadAll() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Printf("error reading authenticated-emails-file=%q, %s", um.usersFile, err) | 		logger.Errorf("error reading authenticated-emails-file=%q, %s", um.usersFile, err) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	updated := make(map[string]bool) | 	updated := make(map[string]bool) | ||||||
|   | |||||||
| @@ -69,7 +69,7 @@ func WatchForUpdates(filename string, done <-chan bool, action func()) { | |||||||
| 				logger.Printf("reloading after event: %s", event) | 				logger.Printf("reloading after event: %s", event) | ||||||
| 				action() | 				action() | ||||||
| 			case err = <-watcher.Errors: | 			case err = <-watcher.Errors: | ||||||
| 				logger.Printf("error watching %s: %s", filename, err) | 				logger.Errorf("error watching %s: %s", filename, err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	}() | 	}() | ||||||
|   | |||||||
| @@ -5,6 +5,6 @@ package main | |||||||
| import "github.com/oauth2-proxy/oauth2-proxy/pkg/logger" | import "github.com/oauth2-proxy/oauth2-proxy/pkg/logger" | ||||||
|  |  | ||||||
| func WatchForUpdates(filename string, done <-chan bool, action func()) { | func WatchForUpdates(filename string, done <-chan bool, action func()) { | ||||||
| 	logger.Printf("file watching not implemented on this platform") | 	logger.Errorf("file watching not implemented on this platform") | ||||||
| 	go func() { <-done }() | 	go func() { <-done }() | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user