@@ -34,10 +34,14 @@ func NewListener(db *database.DB, runtimeConfig *config.RuntimeConfig, logs *log
3434 logs : logs ,
3535 runtimeConfig : runtimeConfig ,
3636 }
37+
38+ debugMux := http .NewServeMux ()
39+ debugMux .HandleFunc ("/dump-config" , l .DumpConfig )
40+ debugMux .HandleFunc ("/dump-incidents" , l .DumpIncidents )
41+ debugMux .HandleFunc ("/dump-schedules" , l .DumpSchedules )
42+
43+ l .mux .Handle ("/debug/" , http .StripPrefix ("/debug" , l .requireDebugAuth (debugMux )))
3744 l .mux .HandleFunc ("/process-event" , l .ProcessEvent )
38- l .mux .HandleFunc ("/dump-config" , l .DumpConfig )
39- l .mux .HandleFunc ("/dump-incidents" , l .DumpIncidents )
40- l .mux .HandleFunc ("/dump-schedules" , l .DumpSchedules )
4145 return l
4246}
4347
@@ -150,57 +154,54 @@ func (l *Listener) ProcessEvent(w http.ResponseWriter, req *http.Request) {
150154 _ , _ = fmt .Fprintln (w )
151155}
152156
153- // checkDebugPassword checks if the valid debug password was provided. If there is no password configured or the
154- // supplied password is incorrect, it sends an error code and returns false. True is returned if access is allowed.
155- func (l * Listener ) checkDebugPassword (w http.ResponseWriter , r * http.Request ) bool {
156- expectedPassword := daemon .Config ().DebugPassword
157- if expectedPassword == "" {
158- w .WriteHeader (http .StatusForbidden )
159- _ , _ = fmt .Fprintln (w , "config dump disables, no debug-password set in config" )
157+ // requireDebugAuth is a middleware that checks if the valid debug password was provided. If there is no password
158+ // configured or the supplied password is incorrect, it sends an error code and does not redirect the request.
159+ func (l * Listener ) requireDebugAuth (next http.Handler ) http.Handler {
160+ return http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
161+ expectedPassword := daemon .Config ().DebugPassword
162+ if expectedPassword == "" {
163+ w .WriteHeader (http .StatusForbidden )
164+ _ , _ = fmt .Fprintln (w , "config dump disabled, no debug-password set in config" )
160165
161- return false
162- }
166+ return
167+ }
163168
164- _ , providedPassword , _ := r .BasicAuth ()
165- if subtle .ConstantTimeCompare ([]byte (expectedPassword ), []byte (providedPassword )) != 1 {
166- l .logger .Warnw ("Unauthorized request" , zap .String ("url" , r .RequestURI ))
169+ _ , providedPassword , _ := r .BasicAuth ()
170+ if subtle .ConstantTimeCompare ([]byte (expectedPassword ), []byte (providedPassword )) != 1 {
171+ l .logger .Warnw ("Unauthorized request" , zap .String ("url" , r .RequestURI ))
167172
168- w .Header ().Set ("WWW-Authenticate" , `Basic realm="debug"` )
169- w .WriteHeader (http .StatusUnauthorized )
170- _ , _ = fmt .Fprintln (w , "please provide the debug-password as basic auth credentials (user is ignored)" )
171- return false
172- }
173+ w .Header ().Set ("WWW-Authenticate" , `Basic realm="debug"` )
174+ w .WriteHeader (http .StatusUnauthorized )
175+ _ , _ = fmt .Fprintln (w , "please provide the debug-password as basic auth credentials (user is ignored)" )
176+ return
177+ }
173178
174- return true
179+ next .ServeHTTP (w , r )
180+ })
175181}
176182
183+ // DumpConfig is used as /debug prefixed endpoint to dump the current live configuration of the daemon.
184+ // The authorization has to be done beforehand.
177185func (l * Listener ) DumpConfig (w http.ResponseWriter , r * http.Request ) {
178186 if r .Method != http .MethodGet {
179187 w .WriteHeader (http .StatusMethodNotAllowed )
180188 _ , _ = fmt .Fprintln (w , "GET required" )
181189 return
182190 }
183191
184- if ! l .checkDebugPassword (w , r ) {
185- return
186- }
187-
188192 enc := json .NewEncoder (w )
189193 enc .SetIndent ("" , " " )
190194 _ = enc .Encode (& l .runtimeConfig .ConfigSet )
191195}
192196
197+ // DumpIncidents is used as /debug prefixed endpoint to dump all incidents. The authorization has to be done beforehand.
193198func (l * Listener ) DumpIncidents (w http.ResponseWriter , r * http.Request ) {
194199 if r .Method != http .MethodGet {
195200 w .WriteHeader (http .StatusMethodNotAllowed )
196201 _ , _ = fmt .Fprintln (w , "GET required" )
197202 return
198203 }
199204
200- if ! l .checkDebugPassword (w , r ) {
201- return
202- }
203-
204205 incidents := incident .GetCurrentIncidents ()
205206 encodedIncidents := make (map [int64 ]json.RawMessage )
206207
@@ -230,17 +231,14 @@ func (l *Listener) DumpIncidents(w http.ResponseWriter, r *http.Request) {
230231 _ = enc .Encode (encodedIncidents )
231232}
232233
234+ // DumpSchedules is used as /debug prefixed endpoint to dump all schedules. The authorization has to be done beforehand.
233235func (l * Listener ) DumpSchedules (w http.ResponseWriter , r * http.Request ) {
234236 if r .Method != http .MethodGet {
235237 w .WriteHeader (http .StatusMethodNotAllowed )
236238 _ , _ = fmt .Fprintln (w , "GET required" )
237239 return
238240 }
239241
240- if ! l .checkDebugPassword (w , r ) {
241- return
242- }
243-
244242 l .runtimeConfig .RLock ()
245243 defer l .runtimeConfig .RUnlock ()
246244
0 commit comments