From 814fc9dfc037ff86fedf6c3e9aed3ca08fc21053 Mon Sep 17 00:00:00 2001 From: andres-portainer <91705312+andres-portainer@users.noreply.github.com> Date: Mon, 27 Mar 2023 15:14:16 -0300 Subject: [PATCH] fix(http): drain and close HTTP response bodies EE-5280 (#8716) --- api/agent/version.go | 5 +++- api/hostmanagement/fdo/owner_client.go | 24 ++++++++++++++----- api/hostmanagement/openamt/authorization.go | 3 +++ api/hostmanagement/openamt/configCIRA.go | 3 +++ api/hostmanagement/openamt/openamt.go | 6 +++++ api/http/handler/backup/backup_test.go | 2 ++ api/http/handler/backup/restore_test.go | 2 ++ .../endpoints/endpoint_dockerhub_status.go | 6 +++-- api/oauth/oauth.go | 3 ++- pkg/libhelm/binary/search_repo.go | 1 + 10 files changed, 45 insertions(+), 10 deletions(-) diff --git a/api/agent/version.go b/api/agent/version.go index bdb7ebce1..03d3cf4f6 100644 --- a/api/agent/version.go +++ b/api/agent/version.go @@ -4,6 +4,7 @@ import ( "crypto/tls" "errors" "fmt" + "io" "net/http" "strconv" "time" @@ -42,7 +43,9 @@ func GetAgentVersionAndPlatform(endpointUrl string, tlsConfig *tls.Config) (port if err != nil { return 0, "", err } - defer resp.Body.Close() + + io.Copy(io.Discard, resp.Body) + resp.Body.Close() if resp.StatusCode != http.StatusNoContent { return 0, "", fmt.Errorf("Failed request with status %d", resp.StatusCode) diff --git a/api/hostmanagement/fdo/owner_client.go b/api/hostmanagement/fdo/owner_client.go index bfd10b8ce..0f3aba696 100644 --- a/api/hostmanagement/fdo/owner_client.go +++ b/api/hostmanagement/fdo/owner_client.go @@ -113,7 +113,9 @@ func (c FDOOwnerClient) PutDeviceSVI(info ServiceInfo) error { if err != nil { return err } - defer resp.Body.Close() + + io.Copy(io.Discard, resp.Body) + resp.Body.Close() if resp.StatusCode != http.StatusOK { return errors.New(http.StatusText(resp.StatusCode)) @@ -132,7 +134,9 @@ func (c FDOOwnerClient) PutDeviceSVIRaw(info url.Values, body []byte) error { if err != nil { return err } - defer resp.Body.Close() + + io.Copy(io.Discard, resp.Body) + resp.Body.Close() if resp.StatusCode != http.StatusOK { return errors.New(http.StatusText(resp.StatusCode)) @@ -151,7 +155,9 @@ func (c FDOOwnerClient) GetVouchers() ([]string, error) { if err != nil { return nil, err } - defer resp.Body.Close() + + io.Copy(io.Discard, resp.Body) + resp.Body.Close() if resp.StatusCode != http.StatusOK { return nil, errors.New(http.StatusText(resp.StatusCode)) @@ -182,7 +188,9 @@ func (c FDOOwnerClient) DeleteVoucher(guid string) error { if err != nil { return err } - defer resp.Body.Close() + + io.Copy(io.Discard, resp.Body) + resp.Body.Close() if resp.StatusCode != http.StatusOK { return errors.New(http.StatusText(resp.StatusCode)) @@ -201,7 +209,9 @@ func (c FDOOwnerClient) GetDeviceSVI(guid string) (string, error) { if err != nil { return "", err } - defer resp.Body.Close() + + io.Copy(io.Discard, resp.Body) + resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { @@ -225,7 +235,9 @@ func (c FDOOwnerClient) DeleteDeviceSVI(id string) error { if err != nil { return err } - defer resp.Body.Close() + + io.Copy(io.Discard, resp.Body) + resp.Body.Close() if resp.StatusCode != http.StatusOK { return errors.New(http.StatusText(resp.StatusCode)) diff --git a/api/hostmanagement/openamt/authorization.go b/api/hostmanagement/openamt/authorization.go index 9d5050d2e..463cb4dcf 100644 --- a/api/hostmanagement/openamt/authorization.go +++ b/api/hostmanagement/openamt/authorization.go @@ -33,10 +33,13 @@ func (service *Service) Authorization(configuration portainer.OpenAMTConfigurati if err != nil { return "", err } + defer response.Body.Close() + responseBody, readErr := io.ReadAll(response.Body) if readErr != nil { return "", readErr } + errorResponse := parseError(responseBody) if errorResponse != nil { return "", errorResponse diff --git a/api/hostmanagement/openamt/configCIRA.go b/api/hostmanagement/openamt/configCIRA.go index def1f423c..feac5821a 100644 --- a/api/hostmanagement/openamt/configCIRA.go +++ b/api/hostmanagement/openamt/configCIRA.go @@ -128,6 +128,7 @@ func (service *Service) getCIRACertificate(configuration portainer.OpenAMTConfig if err != nil { return "", err } + defer response.Body.Close() if response.StatusCode != http.StatusOK { return "", fmt.Errorf("unexpected status code %s", response.Status) @@ -137,6 +138,8 @@ func (service *Service) getCIRACertificate(configuration portainer.OpenAMTConfig if err != nil { return "", err } + block, _ := pem.Decode(certificate) + return base64.StdEncoding.EncodeToString(block.Bytes), nil } diff --git a/api/hostmanagement/openamt/openamt.go b/api/hostmanagement/openamt/openamt.go index 590664961..c7a738fc4 100644 --- a/api/hostmanagement/openamt/openamt.go +++ b/api/hostmanagement/openamt/openamt.go @@ -103,6 +103,8 @@ func (service *Service) executeSaveRequest(method string, url string, token stri if err != nil { return nil, err } + defer response.Body.Close() + responseBody, readErr := io.ReadAll(response.Body) if readErr != nil { return nil, readErr @@ -132,6 +134,8 @@ func (service *Service) executeGetRequest(url string, token string) ([]byte, err if err != nil { return nil, err } + defer response.Body.Close() + responseBody, readErr := io.ReadAll(response.Body) if readErr != nil { return nil, readErr @@ -141,10 +145,12 @@ func (service *Service) executeGetRequest(url string, token string) ([]byte, err if response.StatusCode == http.StatusNotFound { return nil, nil } + errorResponse := parseError(responseBody) if errorResponse != nil { return nil, errorResponse } + return nil, fmt.Errorf("unexpected status code %s", response.Status) } diff --git a/api/http/handler/backup/backup_test.go b/api/http/handler/backup/backup_test.go index a35754db3..23954b9c9 100644 --- a/api/http/handler/backup/backup_test.go +++ b/api/http/handler/backup/backup_test.go @@ -53,6 +53,7 @@ func Test_backupHandlerWithoutPassword_shouldCreateATarballArchive(t *testing.T) response := w.Result() body, _ := io.ReadAll(response.Body) + response.Body.Close() tmpdir := t.TempDir() @@ -89,6 +90,7 @@ func Test_backupHandlerWithPassword_shouldCreateEncryptedATarballArchive(t *test response := w.Result() body, _ := io.ReadAll(response.Body) + response.Body.Close() tmpdir := t.TempDir() diff --git a/api/http/handler/backup/restore_test.go b/api/http/handler/backup/restore_test.go index 5c21a67d7..087179fa3 100644 --- a/api/http/handler/backup/restore_test.go +++ b/api/http/handler/backup/restore_test.go @@ -99,6 +99,8 @@ func backup(t *testing.T, h *Handler, password string) []byte { response := w.Result() archive, _ := io.ReadAll(response.Body) + response.Body.Close() + return archive } diff --git a/api/http/handler/endpoints/endpoint_dockerhub_status.go b/api/http/handler/endpoints/endpoint_dockerhub_status.go index 1c4e05227..a102c695b 100644 --- a/api/http/handler/endpoints/endpoint_dockerhub_status.go +++ b/api/http/handler/endpoints/endpoint_dockerhub_status.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "io" "net/http" "strconv" "strings" @@ -128,7 +129,6 @@ func getDockerHubToken(httpClient *client.HTTPClient, registry *portainer.Regist } func getDockerHubLimits(httpClient *client.HTTPClient, token string) (*dockerhubStatusResponse, error) { - requestURL := "https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest" req, err := http.NewRequest(http.MethodHead, requestURL, nil) @@ -142,7 +142,9 @@ func getDockerHubLimits(httpClient *client.HTTPClient, token string) (*dockerhub if err != nil { return nil, err } - defer resp.Body.Close() + + io.Copy(io.Discard, resp.Body) + resp.Body.Close() if resp.StatusCode != http.StatusOK { return nil, errors.New("failed fetching dockerhub limits") diff --git a/api/oauth/oauth.go b/api/oauth/oauth.go index 9843258b2..3f15f8f92 100644 --- a/api/oauth/oauth.go +++ b/api/oauth/oauth.go @@ -121,12 +121,13 @@ func getResource(token string, configuration *portainer.OAuthSettings) (map[stri client := &http.Client{} req.Header.Set("Authorization", "Bearer "+token) + resp, err := client.Do(req) if err != nil { return nil, err } - defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) if err != nil { return nil, err diff --git a/pkg/libhelm/binary/search_repo.go b/pkg/libhelm/binary/search_repo.go index fbdbfdf08..a959f512e 100644 --- a/pkg/libhelm/binary/search_repo.go +++ b/pkg/libhelm/binary/search_repo.go @@ -68,6 +68,7 @@ func (hbpm *helmBinaryPackageManager) SearchRepo(searchRepoOpts options.SearchRe if err != nil { return nil, errors.Wrap(err, "failed to get index file") } + defer resp.Body.Close() var file File err = yaml.NewDecoder(resp.Body).Decode(&file)