From ac01d373c9243322ae5e2322f602a27835f919db Mon Sep 17 00:00:00 2001 From: ShocOne <62835948+ShocOne@users.noreply.github.com> Date: Mon, 3 Jun 2024 21:54:36 +0100 Subject: [PATCH] reverting changes --- apiintegrations/apihandler/apihandler.go | 2 +- .../jamfpro/jamfpro_api_request.go | 37 +++-------- .../msgraph/msgraph_api_request.go | 38 +++--------- httpclient/multipartrequest.go | 61 ++----------------- 4 files changed, 26 insertions(+), 112 deletions(-) diff --git a/apiintegrations/apihandler/apihandler.go b/apiintegrations/apihandler/apihandler.go index 7d15587..3a49276 100644 --- a/apiintegrations/apihandler/apihandler.go +++ b/apiintegrations/apihandler/apihandler.go @@ -14,7 +14,7 @@ type APIHandler interface { ConstructAPIResourceEndpoint(endpointPath string, log logger.Logger) string ConstructAPIAuthEndpoint(endpointPath string, log logger.Logger) string MarshalRequest(body interface{}, method string, endpoint string, log logger.Logger) ([]byte, error) - MarshalMultipartRequest(fields map[string]string, files map[string]string, log logger.Logger) ([]byte, string, string, error) + MarshalMultipartRequest(fields map[string]string, files map[string]string, log logger.Logger) ([]byte, string, error) GetContentTypeHeader(method string, log logger.Logger) string GetAcceptHeader() string GetDefaultBaseDomain() string diff --git a/apiintegrations/jamfpro/jamfpro_api_request.go b/apiintegrations/jamfpro/jamfpro_api_request.go index 8fc659d..e29893e 100644 --- a/apiintegrations/jamfpro/jamfpro_api_request.go +++ b/apiintegrations/jamfpro/jamfpro_api_request.go @@ -56,60 +56,43 @@ func (j *JamfAPIHandler) MarshalRequest(body interface{}, method string, endpoin return data, nil } -// MarshalMultipartRequest creates a multipart request body for sending files and form fields in a single request. -func (j *JamfAPIHandler) MarshalMultipartRequest(fields map[string]string, files map[string]string, log logger.Logger) ([]byte, string, string, error) { +// MarshalMultipartRequest handles multipart form data encoding with secure file handling and returns the encoded body and content type. +func (j *JamfAPIHandler) MarshalMultipartRequest(fields map[string]string, files map[string]string, log logger.Logger) ([]byte, string, error) { body := &bytes.Buffer{} writer := multipart.NewWriter(body) // Add the simple fields to the form data for field, value := range fields { - log.Debug("Adding field to multipart request", zap.String("Field", field), zap.String("Value", value)) if err := writer.WriteField(field, value); err != nil { - return nil, "", "", err + return nil, "", err } } - // Add the files to the form data + // Add the files to the form data, using safeOpenFile to ensure secure file access for formField, filePath := range files { file, err := helpers.SafeOpenFile(filePath) if err != nil { log.Error("Failed to open file securely", zap.String("file", filePath), zap.Error(err)) - return nil, "", "", err + return nil, "", err } defer file.Close() part, err := writer.CreateFormFile(formField, filepath.Base(filePath)) if err != nil { - return nil, "", "", err + return nil, "", err } - log.Debug("Adding file to multipart request", zap.String("FormField", formField), zap.String("FilePath", filePath)) if _, err := io.Copy(part, file); err != nil { - return nil, "", "", err + return nil, "", err } } // Close the writer to finish writing the multipart message if err := writer.Close(); err != nil { - return nil, "", "", err + return nil, "", err } contentType := writer.FormDataContentType() - bodyBytes := body.Bytes() - - // Extract the first and last parts of the body for logging - const logSegmentSize = 1024 // 1 KB - bodyLen := len(bodyBytes) - var logBody string - if bodyLen <= 2*logSegmentSize { - logBody = string(bodyBytes) - } else { - logBody = string(bodyBytes[:logSegmentSize]) + "..." + string(bodyBytes[bodyLen-logSegmentSize:]) - } - - // Log the boundary and a partial body for debugging - boundary := writer.Boundary() - log.Debug("Multipart boundary", zap.String("Boundary", boundary)) - log.Debug("Multipart request body (partial)", zap.String("Body", logBody)) + log.Debug("Multipart request body", zap.String("Body", body.String())) // Log the body - return bodyBytes, contentType, logBody, nil + return body.Bytes(), contentType, nil } diff --git a/apiintegrations/msgraph/msgraph_api_request.go b/apiintegrations/msgraph/msgraph_api_request.go index fb12fac..a066fea 100644 --- a/apiintegrations/msgraph/msgraph_api_request.go +++ b/apiintegrations/msgraph/msgraph_api_request.go @@ -30,16 +30,16 @@ func (g *GraphAPIHandler) MarshalRequest(body interface{}, method string, endpoi return data, nil } -// MarshalMultipartRequest encodes the request body as a multipart message for the Microsoft Graph API. -func (g *GraphAPIHandler) MarshalMultipartRequest(fields map[string]string, files map[string]string, log logger.Logger) ([]byte, string, string, error) { +// MarshalMultipartRequest handles multipart form data encoding with secure file handling and returns the encoded body and content type. +func (g *GraphAPIHandler) MarshalMultipartRequest(fields map[string]string, files map[string]string, log logger.Logger) ([]byte, string, error) { + body := &bytes.Buffer{} writer := multipart.NewWriter(body) // Add the simple fields to the form data for field, value := range fields { - log.Debug("Adding field to multipart request", zap.String("Field", field), zap.String("Value", value)) if err := writer.WriteField(field, value); err != nil { - return nil, "", "", err + return nil, "", err } } @@ -48,42 +48,24 @@ func (g *GraphAPIHandler) MarshalMultipartRequest(fields map[string]string, file file, err := helpers.SafeOpenFile(filePath) if err != nil { log.Error("Failed to open file securely", zap.String("file", filePath), zap.Error(err)) - return nil, "", "", err + return nil, "", err } defer file.Close() part, err := writer.CreateFormFile(formField, filepath.Base(filePath)) if err != nil { - return nil, "", "", err + return nil, "", err } - log.Debug("Adding file to multipart request", zap.String("FormField", formField), zap.String("FilePath", filePath)) if _, err := io.Copy(part, file); err != nil { - return nil, "", "", err + return nil, "", err } } // Close the writer to finish writing the multipart message - if err := writer.Close(); err != nil { - return nil, "", "", err - } - contentType := writer.FormDataContentType() - bodyBytes := body.Bytes() - - // Extract the first and last parts of the body for logging - const logSegmentSize = 1024 // 1 KB - bodyLen := len(bodyBytes) - var logBody string - if bodyLen <= 2*logSegmentSize { - logBody = string(bodyBytes) - } else { - logBody = string(bodyBytes[:logSegmentSize]) + "..." + string(bodyBytes[bodyLen-logSegmentSize:]) + if err := writer.Close(); err != nil { + return nil, "", err } - // Log the boundary and a partial body for debugging - boundary := writer.Boundary() - log.Debug("Multipart boundary", zap.String("Boundary", boundary)) - log.Debug("Multipart request body (partial)", zap.String("Body", logBody)) - - return bodyBytes, contentType, logBody, nil + return body.Bytes(), contentType, nil } diff --git a/httpclient/multipartrequest.go b/httpclient/multipartrequest.go index a425e78..bc8fbe7 100644 --- a/httpclient/multipartrequest.go +++ b/httpclient/multipartrequest.go @@ -3,14 +3,10 @@ package httpclient import ( "bytes" - "io" - "mime/multipart" "net/http" - "path/filepath" "github.com/deploymenttheory/go-api-http-client/authenticationhandler" "github.com/deploymenttheory/go-api-http-client/headers" - "github.com/deploymenttheory/go-api-http-client/helpers" "github.com/deploymenttheory/go-api-http-client/response" "go.uber.org/zap" ) @@ -58,70 +54,23 @@ func (c *Client) DoMultipartRequest(method, endpoint string, fields map[string]s return nil, err } - // Create a buffer to hold the multipart form data - body := &bytes.Buffer{} - writer := multipart.NewWriter(body) - - // Add the simple fields to the form data - for field, value := range fields { - log.Debug("Adding field to multipart request", zap.String("Field", field), zap.String("Value", value)) - if err := writer.WriteField(field, value); err != nil { - return nil, err - } - } - - // Add the files to the form data - for formField, filePath := range files { - file, err := helpers.SafeOpenFile(filePath) - if err != nil { - log.Error("Failed to open file securely", zap.String("file", filePath), zap.Error(err)) - return nil, err - } - defer file.Close() - - part, err := writer.CreateFormFile(formField, filepath.Base(filePath)) - if err != nil { - return nil, err - } - log.Debug("Adding file to multipart request", zap.String("FormField", formField), zap.String("FilePath", filePath)) - if _, err := io.Copy(part, file); err != nil { - return nil, err - } - } - - // Close the writer to finish writing the multipart message - if err := writer.Close(); err != nil { + // Marshal the multipart form data + requestData, contentType, err := c.APIHandler.MarshalMultipartRequest(fields, files, log) + if err != nil { return nil, err } - contentType := writer.FormDataContentType() - bodyBytes := body.Bytes() - - // Extract the first and last parts of the body for logging - const logSegmentSize = 1024 // 1 KB - bodyLen := len(bodyBytes) - var logBody string - if bodyLen <= 2*logSegmentSize { - logBody = string(bodyBytes) - } else { - logBody = string(bodyBytes[:logSegmentSize]) + "..." + string(bodyBytes[bodyLen-logSegmentSize:]) - } - - // Log the boundary and a partial body for debugging - boundary := writer.Boundary() - log.Debug("Multipart boundary", zap.String("Boundary", boundary)) - log.Debug("Multipart request body (partial)", zap.String("Body", logBody)) - // Construct URL using the ConstructAPIResourceEndpoint function url := c.APIHandler.ConstructAPIResourceEndpoint(endpoint, log) // Create the request - req, err := http.NewRequest(method, url, bytes.NewBuffer(bodyBytes)) + req, err := http.NewRequest(method, url, bytes.NewBuffer(requestData)) if err != nil { return nil, err } // Initialize HeaderManager + //log.Debug("Setting Authorization header with token", zap.String("Token", c.Token)) headerHandler := headers.NewHeaderHandler(req, c.Logger, c.APIHandler, c.AuthTokenHandler) // Use HeaderManager to set headers