From 3124c93673f42f461ddf7c09b165fb765077a446 Mon Sep 17 00:00:00 2001 From: pranshi06 <85474619+pranshi06@users.noreply.github.com> Date: Mon, 19 Jun 2023 18:03:01 +0530 Subject: [PATCH] server: configurable header length limit for warp PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9363 GitOrigin-RevId: 8dd1e6a5f51d86ed20123c7ed7d42906fe5251bb --- .../graphql-engine-flags/reference.mdx | 12 ++++++++++ .../lib/test-harness/src/Harness/Constants.hs | 3 ++- server/src-lib/Hasura/App.hs | 4 +++- server/src-lib/Hasura/App/State.hs | 3 ++- server/src-lib/Hasura/Server/Init.hs | 1 + .../Hasura/Server/Init/Arg/Command/Serve.hs | 22 ++++++++++++++++++- server/src-lib/Hasura/Server/Init/Config.hs | 6 +++-- server/src-test/Hasura/Server/InitSpec.hs | 3 ++- server/test-postgres/Constants.hs | 3 ++- 9 files changed, 49 insertions(+), 8 deletions(-) diff --git a/docs/docs/deployment/graphql-engine-flags/reference.mdx b/docs/docs/deployment/graphql-engine-flags/reference.mdx index 6961732cc8b..7d0f191ebea 100644 --- a/docs/docs/deployment/graphql-engine-flags/reference.mdx +++ b/docs/docs/deployment/graphql-engine-flags/reference.mdx @@ -340,6 +340,18 @@ subgraph in an Apollo supergraph. | **Default** | `false` | | **Supported in** | CE, Enterprise Edition, Cloud | +### Header Size Limit + +Sets the maximum cumulative length of all headers in bytes. + +| | | +| ------------------- | ----------------------------------------- | +| **Flag** | `--max-total-header-length` | +| **Env var** | `HASURA_GRAPHQL_MAX_TOTAL_HEADER_LENGTH` | +| **Accepted values** | Integer | +| **Default** | `1024*1024` (1MB) | +| **Supported in** | CE, Enterprise Edition | + ### Enable Console Enable the Hasura Console (served by the server on `/` and `/console`). diff --git a/server/lib/test-harness/src/Harness/Constants.hs b/server/lib/test-harness/src/Harness/Constants.hs index 2b78521d222..5bf19d5a2d0 100644 --- a/server/lib/test-harness/src/Harness/Constants.hs +++ b/server/lib/test-harness/src/Harness/Constants.hs @@ -309,7 +309,8 @@ serveOptions = soExtensionsSchema = ExtensionsSchema "public", soMetadataDefaults = emptyMetadataDefaults, soApolloFederationStatus = ApolloFederationDisabled, - soCloseWebsocketsOnMetadataChangeStatus = Init._default Init.closeWebsocketsOnMetadataChangeOption + soCloseWebsocketsOnMetadataChangeStatus = Init._default Init.closeWebsocketsOnMetadataChangeOption, + soMaxTotalHeaderLength = Init._default Init.maxTotalHeaderLengthOption } -- | What log level should be used by the engine; this is not exported, and diff --git a/server/src-lib/Hasura/App.hs b/server/src-lib/Hasura/App.hs index 23d3d63576d..a9bddbd3340 100644 --- a/server/src-lib/Hasura/App.hs +++ b/server/src-lib/Hasura/App.hs @@ -480,7 +480,8 @@ initialiseAppEnv env BasicConnectionInfo {..} serveOptions@ServeOptions {..} liv appEnvGracefulShutdownTimeout = soGracefulShutdownTimeout, appEnvCheckFeatureFlag = ceCheckFeatureFlag env, appEnvSchemaPollInterval = soSchemaPollInterval, - appEnvLicenseKeyCache = Nothing + appEnvLicenseKeyCache = Nothing, + appEnvMaxTotalHeaderLength = soMaxTotalHeaderLength } ) @@ -939,6 +940,7 @@ runHGEServer setupHook appStateRef initTime startupStatusHook consoleType ekgSto . Warp.setInstallShutdownHandler shutdownHandler . Warp.setBeforeMainLoop (for_ startupStatusHook id) . setForkIOWithMetrics + . Warp.setMaxTotalHeaderLength appEnvMaxTotalHeaderLength $ Warp.defaultSettings setForkIOWithMetrics :: Warp.Settings -> Warp.Settings diff --git a/server/src-lib/Hasura/App/State.hs b/server/src-lib/Hasura/App/State.hs index 4ad593cdc69..922e05476cc 100644 --- a/server/src-lib/Hasura/App/State.hs +++ b/server/src-lib/Hasura/App/State.hs @@ -135,7 +135,8 @@ data AppEnv = AppEnv -- to do it for the Enterprise version. appEnvSchemaPollInterval :: OptionalInterval, appEnvCheckFeatureFlag :: CheckFeatureFlag, - appEnvLicenseKeyCache :: Maybe (CredentialCache AgentLicenseKey) + appEnvLicenseKeyCache :: Maybe (CredentialCache AgentLicenseKey), + appEnvMaxTotalHeaderLength :: Int } -- | Represents the Dynamic Hasura State, these field are mutable and can be changed diff --git a/server/src-lib/Hasura/Server/Init.hs b/server/src-lib/Hasura/Server/Init.hs index 4de009cc48e..9d1707e0bf0 100644 --- a/server/src-lib/Hasura/Server/Init.hs +++ b/server/src-lib/Hasura/Server/Init.hs @@ -216,6 +216,7 @@ mkServeOptions sor@ServeOptionsRaw {..} = do pure $ getApolloFederationStatus soExperimentalFeatures apolloFederationStatusOptionM soCloseWebsocketsOnMetadataChangeStatus <- do withOptionDefault rsoCloseWebsocketsOnMetadataChangeStatus closeWebsocketsOnMetadataChangeOption + soMaxTotalHeaderLength <- withOptionDefault rsoMaxTotalHeaderLength maxTotalHeaderLengthOption pure ServeOptions {..} -- | Fetch Postgres 'Query.ConnParams' components from the environment diff --git a/server/src-lib/Hasura/Server/Init/Arg/Command/Serve.hs b/server/src-lib/Hasura/Server/Init/Arg/Command/Serve.hs index d4d5b4cd2e1..7c7323f6721 100644 --- a/server/src-lib/Hasura/Server/Init/Arg/Command/Serve.hs +++ b/server/src-lib/Hasura/Server/Init/Arg/Command/Serve.hs @@ -61,6 +61,7 @@ module Hasura.Server.Init.Arg.Command.Serve metadataDefaultsOption, apolloFederationStatusOption, closeWebsocketsOnMetadataChangeOption, + maxTotalHeaderLengthOption, -- * Pretty Printer serveCmdFooter, @@ -148,6 +149,7 @@ serveCommandParser = <*> parseMetadataDefaults <*> parseApolloFederationStatus <*> parseEnableCloseWebsocketsOnMetadataChange + <*> parseMaxTotalHeaderLength -------------------------------------------------------------------------------- -- Serve Options @@ -1176,6 +1178,23 @@ parseEnableCloseWebsocketsOnMetadataChange = <> Opt.help (Config._helpMessage closeWebsocketsOnMetadataChangeOption) ) +parseMaxTotalHeaderLength :: Opt.Parser (Maybe Int) +parseMaxTotalHeaderLength = + Opt.optional + $ Opt.option + (Opt.eitherReader Env.fromEnv) + ( Opt.long "max-total-header-length" + <> Opt.help (Config._helpMessage maxTotalHeaderLengthOption) + ) + +maxTotalHeaderLengthOption :: Config.Option Int +maxTotalHeaderLengthOption = + Config.Option + { Config._default = (1024 * 1024), + Config._envVar = "HASURA_GRAPHQL_MAX_TOTAL_HEADER_LENGTH", + Config._helpMessage = "Max cumulative length of all headers in bytes (Default: 1MB)" + } + -------------------------------------------------------------------------------- -- Pretty Printer @@ -1275,6 +1294,7 @@ serveCmdFooter = Config.optionPP defaultNamingConventionOption, Config.optionPP metadataDBExtensionsSchemaOption, Config.optionPP apolloFederationStatusOption, - Config.optionPP closeWebsocketsOnMetadataChangeOption + Config.optionPP closeWebsocketsOnMetadataChangeOption, + Config.optionPP maxTotalHeaderLengthOption ] eventEnvs = [Config.optionPP graphqlEventsHttpPoolSizeOption, Config.optionPP graphqlEventsFetchIntervalOption] diff --git a/server/src-lib/Hasura/Server/Init/Config.hs b/server/src-lib/Hasura/Server/Init/Config.hs index 645426f0ca1..0182443ddce 100644 --- a/server/src-lib/Hasura/Server/Init/Config.hs +++ b/server/src-lib/Hasura/Server/Init/Config.hs @@ -321,7 +321,8 @@ data ServeOptionsRaw impl = ServeOptionsRaw rsoExtensionsSchema :: Maybe MonadTx.ExtensionsSchema, rsoMetadataDefaults :: Maybe MetadataDefaults, rsoApolloFederationStatus :: Maybe Server.Types.ApolloFederationStatus, - rsoCloseWebsocketsOnMetadataChangeStatus :: Maybe Server.Types.CloseWebsocketsOnMetadataChangeStatus + rsoCloseWebsocketsOnMetadataChangeStatus :: Maybe Server.Types.CloseWebsocketsOnMetadataChangeStatus, + rsoMaxTotalHeaderLength :: Maybe Int } -- | Whether or not to serve Console assets. @@ -620,7 +621,8 @@ data ServeOptions impl = ServeOptions soExtensionsSchema :: MonadTx.ExtensionsSchema, soMetadataDefaults :: MetadataDefaults, soApolloFederationStatus :: Server.Types.ApolloFederationStatus, - soCloseWebsocketsOnMetadataChangeStatus :: Server.Types.CloseWebsocketsOnMetadataChangeStatus + soCloseWebsocketsOnMetadataChangeStatus :: Server.Types.CloseWebsocketsOnMetadataChangeStatus, + soMaxTotalHeaderLength :: Int } -- | 'ResponseInternalErrorsConfig' represents the encoding of the diff --git a/server/src-test/Hasura/Server/InitSpec.hs b/server/src-test/Hasura/Server/InitSpec.hs index 74e6ed96174..d30c00bc078 100644 --- a/server/src-test/Hasura/Server/InitSpec.hs +++ b/server/src-test/Hasura/Server/InitSpec.hs @@ -92,7 +92,8 @@ emptyServeOptionsRaw = rsoExtensionsSchema = Nothing, rsoMetadataDefaults = Nothing, rsoApolloFederationStatus = Nothing, - rsoCloseWebsocketsOnMetadataChangeStatus = Nothing + rsoCloseWebsocketsOnMetadataChangeStatus = Nothing, + rsoMaxTotalHeaderLength = Nothing } mkServeOptionsSpec :: Hspec.Spec diff --git a/server/test-postgres/Constants.hs b/server/test-postgres/Constants.hs index a233f387a2f..e6f9e71b3fb 100644 --- a/server/test-postgres/Constants.hs +++ b/server/test-postgres/Constants.hs @@ -91,7 +91,8 @@ serveOptions = soExtensionsSchema = ExtensionsSchema "public", soMetadataDefaults = emptyMetadataDefaults, soApolloFederationStatus = ApolloFederationDisabled, - soCloseWebsocketsOnMetadataChangeStatus = Init._default Init.closeWebsocketsOnMetadataChangeOption + soCloseWebsocketsOnMetadataChangeStatus = Init._default Init.closeWebsocketsOnMetadataChangeOption, + soMaxTotalHeaderLength = Init._default Init.maxTotalHeaderLengthOption } -- | What log level should be used by the engine; this is not exported, and