diff --git a/server/middleware.go b/server/middleware.go index 5aee2ebb6d..5c3ffa4b6f 100644 --- a/server/middleware.go +++ b/server/middleware.go @@ -21,18 +21,52 @@ import ( ) // NewRequestLogger creates a RequestLogger. -func NewRequestLogger(logger logging.SimpleLogging) *RequestLogger { - return &RequestLogger{logger} +func NewRequestLogger(s *Server) *RequestLogger { + return &RequestLogger{ + s.Logger, + s.WebAuthentication, + s.WebUsername, + s.WebPassword, + } } // RequestLogger logs requests and their response codes. +// as well as handle the basicauth on the requests type RequestLogger struct { - logger logging.SimpleLogging + logger logging.SimpleLogging + WebAuthentication bool + WebUsername string + WebPassword string } // ServeHTTP implements the middleware function. It logs all requests at DEBUG level. func (l *RequestLogger) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { l.logger.Debug("%s %s – from %s", r.Method, r.URL.RequestURI(), r.RemoteAddr) - next(rw, r) + allowed := false + if !l.WebAuthentication || + r.URL.Path == "/events" || + r.URL.Path == "/healthz" || + r.URL.Path == "/status" { + allowed = true + } else { + user, pass, ok := r.BasicAuth() + if ok { + r.SetBasicAuth(user, pass) + l.logger.Debug("user: %s / pass: %s >> url: %s", user, pass, r.URL.RequestURI()) + if user == l.WebUsername && pass == l.WebPassword { + l.logger.Debug("[VALID] user: %s / pass: %s >> url: %s", user, pass, r.URL.RequestURI()) + allowed = true + } else { + allowed = false + l.logger.Info("[INVALID] user: %s / pass: %s >> url: %s", user, pass, r.URL.RequestURI()) + } + } + } + if !allowed { + rw.Header().Set("WWW-Authenticate", `Basic realm="restricted", charset="UTF-8"`) + http.Error(rw, "Unauthorized", http.StatusUnauthorized) + } else { + next(rw, r) + } l.logger.Debug("%s %s – respond HTTP %d", r.Method, r.URL.RequestURI(), rw.(negroni.ResponseWriter).Status()) } diff --git a/server/server.go b/server/server.go index 49319433c3..aab01de641 100644 --- a/server/server.go +++ b/server/server.go @@ -103,6 +103,9 @@ type Server struct { SSLCertFile string SSLKeyFile string Drainer *events.Drainer + WebAuthentication bool + WebUsername string + WebPassword string ProjectCmdOutputHandler handlers.ProjectCommandOutputHandler } @@ -744,6 +747,9 @@ func NewServer(userConfig UserConfig, config Config) (*Server, error) { SSLCertFile: userConfig.SSLCertFile, Drainer: drainer, ProjectCmdOutputHandler: projectCmdOutputHandler, + WebAuthentication: userConfig.WebBasicAuth, + WebUsername: userConfig.WebUsername, + WebPassword: userConfig.WebPassword, }, nil } @@ -771,7 +777,7 @@ func (s *Server) Start() error { PrintStack: false, StackAll: false, StackSize: 1024 * 8, - }, NewRequestLogger(s.Logger)) + }, NewRequestLogger(s)) n.UseHandler(s.Router) defer s.Logger.Flush()