fix(http): drain and close response bodies EE-5486 (#8933)

pull/8866/head
andres-portainer 2023-05-12 17:55:27 -03:00 committed by GitHub
parent 5b96136dd2
commit 511adabce2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 21 additions and 12 deletions

View File

@ -3,6 +3,7 @@ package chisel
import ( import (
"context" "context"
"fmt" "fmt"
"io"
"net/http" "net/http"
"sync" "sync"
"time" "time"
@ -58,7 +59,11 @@ func (service *Service) pingAgent(endpointID portainer.EndpointID) error {
httpClient := &http.Client{ httpClient := &http.Client{
Timeout: 3 * time.Second, Timeout: 3 * time.Second,
} }
_, err = httpClient.Do(req)
resp, err := httpClient.Do(req)
io.Copy(io.Discard, resp.Body)
resp.Body.Close()
return err return err
} }

View File

@ -16,11 +16,9 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
var errInvalidResponseStatus = errors.New("Invalid response status (expecting 200)") var errInvalidResponseStatus = errors.New("invalid response status (expecting 200)")
const ( const defaultHTTPTimeout = 5
defaultHTTPTimeout = 5
)
// HTTPClient represents a client to send HTTP requests. // HTTPClient represents a client to send HTTP requests.
type HTTPClient struct { type HTTPClient struct {
@ -53,17 +51,18 @@ func (client *HTTPClient) ExecuteAzureAuthenticationRequest(credentials *portain
"resource": {"https://management.azure.com/"}, "resource": {"https://management.azure.com/"},
} }
response, err := client.PostForm(loginURL, params) resp, err := client.PostForm(loginURL, params)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer resp.Body.Close()
if response.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
return nil, errors.New("Invalid Azure credentials") return nil, errors.New("invalid Azure credentials")
} }
var token AzureAuthenticationResponse var token AzureAuthenticationResponse
err = json.NewDecoder(response.Body).Decode(&token) err = json.NewDecoder(resp.Body).Decode(&token)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -75,7 +74,6 @@ func (client *HTTPClient) ExecuteAzureAuthenticationRequest(credentials *portain
// the content of the response body. Timeout can be specified via the timeout parameter, // the content of the response body. Timeout can be specified via the timeout parameter,
// will default to defaultHTTPTimeout if set to 0. // will default to defaultHTTPTimeout if set to 0.
func Get(url string, timeout int) ([]byte, error) { func Get(url string, timeout int) ([]byte, error) {
if timeout == 0 { if timeout == 0 {
timeout = defaultHTTPTimeout timeout = defaultHTTPTimeout
} }
@ -128,13 +126,16 @@ func ExecutePingOperation(host string, tlsConfig *tls.Config) (bool, error) {
func pingOperation(client *http.Client, target string) (bool, error) { func pingOperation(client *http.Client, target string) (bool, error) {
pingOperationURL := target + "/_ping" pingOperationURL := target + "/_ping"
response, err := client.Get(pingOperationURL) resp, err := client.Get(pingOperationURL)
if err != nil { if err != nil {
return false, err return false, err
} }
io.Copy(io.Discard, resp.Body)
resp.Body.Close()
agentOnDockerEnvironment := false agentOnDockerEnvironment := false
if response.Header.Get(portainer.PortainerAgentHeader) != "" { if resp.Header.Get(portainer.PortainerAgentHeader) != "" {
agentOnDockerEnvironment = true agentOnDockerEnvironment = true
} }

View File

@ -1,6 +1,7 @@
package security package security
import ( import (
"io"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"testing" "testing"
@ -37,6 +38,8 @@ func TestLimitAccess(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
io.Copy(io.Discard, resp.Body)
resp.Body.Close()
if status := resp.StatusCode; status != http.StatusForbidden { if status := resp.StatusCode; status != http.StatusForbidden {
t.Errorf("handler returned wrong status code: got %v want %v", t.Errorf("handler returned wrong status code: got %v want %v",