From 1f57bcdead4cff5af75d0eb823c7391f3eee46a9 Mon Sep 17 00:00:00 2001 From: Pablo Caderno Date: Fri, 8 Oct 2021 15:28:35 +1100 Subject: [PATCH] Enforce GET requests only for /v1/status endpoint Signed-off-by: Pablo Caderno --- api/overall_status.go | 71 +++++++++++++++++++++----------------- api/overall_status_test.go | 11 +++++- 2 files changed, 50 insertions(+), 32 deletions(-) diff --git a/api/overall_status.go b/api/overall_status.go index 600ddc1de..2f7372621 100644 --- a/api/overall_status.go +++ b/api/overall_status.go @@ -1,6 +1,7 @@ package api import ( + "fmt" "net/http" "github.com/hashicorp/consul-terraform-sync/driver" @@ -59,42 +60,50 @@ func newOverallStatusHandler(store *event.Store, drivers *driver.Drivers, versio func (h *overallStatusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { logger := logging.FromContext(r.Context()).Named(overallStatusSubsystemName) logger.Trace("requesting task status", "url_path", r.URL.Path) + switch r.Method { + case http.MethodGet: - data := h.store.Read("") - taskSummary := TaskSummary{} - for _, events := range data { - successes := make([]bool, len(events)) - for i, event := range events { - successes[i] = event.Success + data := h.store.Read("") + taskSummary := TaskSummary{} + for _, events := range data { + successes := make([]bool, len(events)) + for i, event := range events { + successes[i] = event.Success + } + status := successToStatus(successes) + switch status { + case StatusSuccessful: + taskSummary.Status.Successful++ + case StatusErrored: + taskSummary.Status.Errored++ + case StatusCritical: + taskSummary.Status.Critical++ + } } - status := successToStatus(successes) - switch status { - case StatusSuccessful: - taskSummary.Status.Successful++ - case StatusErrored: - taskSummary.Status.Errored++ - case StatusCritical: - taskSummary.Status.Critical++ - } - } - for taskName, d := range h.drivers.Map() { - // look for any tasks that have a driver but no events - if _, ok := data[taskName]; !ok { - taskSummary.Status.Unknown++ - } + for taskName, d := range h.drivers.Map() { + // look for any tasks that have a driver but no events + if _, ok := data[taskName]; !ok { + taskSummary.Status.Unknown++ + } - if d.Task().IsEnabled() { - taskSummary.Enabled.True++ - } else { - taskSummary.Enabled.False++ + if d.Task().IsEnabled() { + taskSummary.Enabled.True++ + } else { + taskSummary.Enabled.False++ + } } - } - err := jsonResponse(w, http.StatusOK, OverallStatus{ - TaskSummary: taskSummary, - }) - if err != nil { - logger.Error("error, could not generate json error response", "error", err) + err := jsonResponse(w, http.StatusOK, OverallStatus{ + TaskSummary: taskSummary, + }) + if err != nil { + logger.Error("error, could not generate json error response", "error", err) + } + default: + err := fmt.Errorf("'%s' in an unsupported method. The overallStatus API "+ + "currently supports the method(s): '%s'", r.Method, http.MethodGet) + logger.Trace("unsupported method: %s", err) + jsonErrorResponse(r.Context(), w, http.StatusMethodNotAllowed, err) } } diff --git a/api/overall_status_test.go b/api/overall_status_test.go index 2f4ce2efb..8795d5ac5 100644 --- a/api/overall_status_test.go +++ b/api/overall_status_test.go @@ -37,12 +37,14 @@ func TestOverallStatus_ServeHTTP(t *testing.T) { cases := []struct { name string path string + method string statusCode int expected OverallStatus }{ { "happy path", "/v1/status", + http.MethodGet, http.StatusOK, OverallStatus{ TaskSummary: TaskSummary{ @@ -59,6 +61,13 @@ func TestOverallStatus_ServeHTTP(t *testing.T) { }, }, }, + { + "method not allowed", + "/v1/status", + http.MethodPatch, + http.StatusMethodNotAllowed, + OverallStatus{}, + }, } // set up store and handler @@ -84,7 +93,7 @@ func TestOverallStatus_ServeHTTP(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - req, err := http.NewRequest("GET", tc.path, nil) + req, err := http.NewRequest(tc.method, tc.path, nil) require.NoError(t, err) resp := httptest.NewRecorder()