From 1d2c8cfe4aab61f9e8e63d514f8d9aac2ac3fd5e Mon Sep 17 00:00:00 2001 From: Patrik Segedy Date: Wed, 11 Oct 2023 16:54:38 +0200 Subject: [PATCH] RHINENG-2438: restrict request body size --- base/utils/config.go | 12 +++++++----- base/utils/core.go | 18 ++++++++++++++++++ conf/manager.env | 1 + deploy/clowdapp.yaml | 2 ++ manager/controllers/systems_advisories_view.go | 2 +- manager/manager.go | 1 + manager/middlewares/request_size.go | 16 ++++++++++++++++ 7 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 manager/middlewares/request_size.go diff --git a/base/utils/config.go b/base/utils/config.go index 11ec97712..40efa6248 100644 --- a/base/utils/config.go +++ b/base/utils/config.go @@ -32,11 +32,12 @@ type Config struct { DBWorkMem int // API - PublicPort int - PrivatePort int - MetricsPort int - MetricsPath string - ResponseTimeout time.Duration + PublicPort int + PrivatePort int + MetricsPort int + MetricsPath string + ResponseTimeout time.Duration + MaxRequestBodySize int64 // kafka KafkaAddress string @@ -169,6 +170,7 @@ func initAPIromClowder() { Cfg.MetricsPort = clowder.LoadedConfig.MetricsPort Cfg.MetricsPath = clowder.LoadedConfig.MetricsPath Cfg.ResponseTimeout = time.Duration(GetIntEnvOrDefault("RESPONSE_TIMEOUT", 60)) + Cfg.MaxRequestBodySize = GetInt64EnvOrDefault("MAX_REQUEST_BODY_SIZE", 1*1024*1024) } func initKafkaFromClowder() { diff --git a/base/utils/core.go b/base/utils/core.go index 99bf4c67c..c977c7549 100644 --- a/base/utils/core.go +++ b/base/utils/core.go @@ -80,6 +80,15 @@ func parseIntOrFail(envname, valueStr string) int { return value } +// parseInt64OrFail Convert string to int or panic if not possible +func parseInt64OrFail(envname, valueStr string) int64 { + value, err := strconv.ParseInt(valueStr, 10, 64) + if err != nil { + panic(fmt.Sprintf("Unable convert '%s' env var '%s' to int!", envname, valueStr)) + } + return value +} + // GetIntEnvOrFail Load int environment variable or fail func GetIntEnvOrFail(envname string) int { valueStr := GetenvOrFail(envname) @@ -95,6 +104,15 @@ func GetIntEnvOrDefault(envname string, defval int) int { return parseIntOrFail(envname, valueStr) } +// GetInt64EnvOrDefault Load int64 environment variable or load default +func GetInt64EnvOrDefault(envname string, defval int64) int64 { + valueStr := os.Getenv(envname) + if valueStr == "" { + return defval + } + return parseInt64OrFail(envname, valueStr) +} + // SetDefaultEnvOrFail Set environment variable if not already or fail func SetDefaultEnvOrFail(envname, value string) string { val := os.Getenv(envname) diff --git a/conf/manager.env b/conf/manager.env index b91a30ae8..152afedc6 100644 --- a/conf/manager.env +++ b/conf/manager.env @@ -10,3 +10,4 @@ ADVISORY_DETAIL_CACHE_SIZE=100 PRELOAD_ADVISORY_DETAIL_CACHE=true ENABLE_BASELINE_CHANGE_EVAL=true +MAX_REQUEST_BODY_SIZE=1048576 diff --git a/deploy/clowdapp.yaml b/deploy/clowdapp.yaml index 5d19d0207..d0a9a1512 100644 --- a/deploy/clowdapp.yaml +++ b/deploy/clowdapp.yaml @@ -125,6 +125,7 @@ objects: - {name: ENABLE_PROFILER, value: '${ENABLE_PROFILER_MANAGER}'} - {name: GOMEMLIMIT, value: '${GOMEMLIMIT_MANAGER}'} - {name: ENABLE_SATELLITE_FUNCTIONALITY, value: '${ENABLE_SATELLITE_FUNCTIONALITY}'} + - {name: MAX_REQUEST_BODY_SIZE, value: '${MAX_REQUEST_BODY_SIZE}'} resources: limits: {cpu: '${RES_LIMIT_CPU_MANAGER}', memory: '${RES_LIMIT_MEM_MANAGER}'} @@ -583,6 +584,7 @@ parameters: - {name: DB_READ_REPLICA_ENABLED, value: 'TRUE'} - {name: ENABLE_PROFILER_MANAGER, value: 'false'} - {name: GOMEMLIMIT_MANAGER, value: '230MiB'} # set to 90% of the default memory limit 256Mi (don't forget `B`) +- {name: MAX_REQUEST_BODY_SIZE, value: '1048576'} # limit request body size, in bytes (default 1MB) # Listener - {name: REPLICAS_LISTENER, value: '1'} diff --git a/manager/controllers/systems_advisories_view.go b/manager/controllers/systems_advisories_view.go index 46bbcb6b8..a0230cd0a 100644 --- a/manager/controllers/systems_advisories_view.go +++ b/manager/controllers/systems_advisories_view.go @@ -142,7 +142,7 @@ func queryDB(c *gin.Context, endpoint string) ([]systemsAdvisoriesDBLoad, *ListM var limit int var offset int if err := c.ShouldBindJSON(&req); err != nil { - LogAndRespBadRequest(c, err, "Invalid request body") + LogAndRespBadRequest(c, err, fmt.Sprintf("Invalid request body: %s", err.Error())) return nil, nil, err } acc := c.GetInt(middlewares.KeyAccount) diff --git a/manager/manager.go b/manager/manager.go index 2219c1f20..26255b17b 100644 --- a/manager/manager.go +++ b/manager/manager.go @@ -49,6 +49,7 @@ func RunManager() { endpointsConfig := getEndpointsConfig() middlewares.SetSwagger(app, endpointsConfig) app.Use(middlewares.WithTimeout(utils.Cfg.ResponseTimeout)) + app.Use(middlewares.LimitRequestBodySize(utils.Cfg.MaxRequestBodySize)) app.HandleMethodNotAllowed = true // routes diff --git a/manager/middlewares/request_size.go b/manager/middlewares/request_size.go new file mode 100644 index 000000000..b3751f7cb --- /dev/null +++ b/manager/middlewares/request_size.go @@ -0,0 +1,16 @@ +package middlewares + +import ( + "net/http" + + "github.com/gin-gonic/gin" +) + +func LimitRequestBodySize(size int64) gin.HandlerFunc { + return func(c *gin.Context) { + if c.Request != nil && c.Request.Body != nil { + c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, size) + } + c.Next() + } +}