diff --git a/docs/content/configuration/broker.md b/docs/content/configuration/broker.md index 1b3d51184f6..6731817cb03 100644 --- a/docs/content/configuration/broker.md +++ b/docs/content/configuration/broker.md @@ -45,6 +45,8 @@ Druid uses Jetty to serve HTTP requests. |`druid.broker.http.compressionCodec`|Compression codec the Broker uses to communicate with historical and real-time processes. May be "gzip" or "identity".|gzip| |`druid.broker.http.readTimeout`|The timeout for data reads from historical and real-time processes.|PT15M| |`druid.server.http.maxQueryTimeout`|Maximum allowed value (in milliseconds) for `timeout` parameter. See [query-context](query-context.html) to know more about `timeout`. Query is rejected if the query context `timeout` is greater than this value. |Long.MAX_VALUE| +|`druid.server.http.maxRequestHeaderSize`|Maximum size of a request header in bytes. Larger headers consume more memory and can make a server more vulnerable to denial of service attacks. |8 * 1024| + #### Retry Policy diff --git a/docs/content/configuration/historical.md b/docs/content/configuration/historical.md index 04390a3f468..2fea065f7d2 100644 --- a/docs/content/configuration/historical.md +++ b/docs/content/configuration/historical.md @@ -53,6 +53,7 @@ Druid uses Jetty to serve HTTP requests. |`druid.server.http.enableRequestLimit`|If enabled, no requests would be queued in jetty queue and "HTTP 429 Too Many Requests" error response would be sent. |false| |`druid.server.http.defaultQueryTimeout`|Query timeout in millis, beyond which unfinished queries will be cancelled|300000| |`druid.server.http.maxQueryTimeout`|Maximum allowed value (in milliseconds) for `timeout` parameter. See [query-context](query-context.html) to know more about `timeout`. Query is rejected if the query context `timeout` is greater than this value. |Long.MAX_VALUE| +|`druid.server.http.maxRequestHeaderSize`|Maximum size of a request header in bytes. Larger headers consume more memory and can make a server more vulnerable to denial of service attacks.|8 * 1024| #### Processing diff --git a/docs/content/development/extensions-core/druid-kerberos.md b/docs/content/development/extensions-core/druid-kerberos.md index 94ba7beaffe..1ded0e0f5a5 100644 --- a/docs/content/development/extensions-core/druid-kerberos.md +++ b/docs/content/development/extensions-core/druid-kerberos.md @@ -49,6 +49,12 @@ The syntax for mapping rules is `RULE:\[n:string](regexp)s/pattern/replacement/g If this string matches regexp, then the s//\[g] substitution command will be run over the string. The optional g will cause the substitution to be global over the string, instead of replacing only the first match in the string. If required, multiple rules can be be joined by newline character and specified as a String. +### Increasing HTTP Header size for large SPNEGO negotiate header +In Active Directory environment, SPNEGO token in the Authorization header includes PAC (Privilege Access Certificate) information, +which includes all security groups for the user. In some cases when the user belongs to many security groups the header to grow beyond what druid can handle by default. +In such cases, max request header size that druid can handle can be increased by setting `druid.server.http.maxRequestHeaderSize` (default 8Kb) and `druid.router.http.maxRequestBufferSize` (default 8Kb). + + ## Accessing Druid HTTP end points when kerberos security is enabled 1. To access druid HTTP endpoints via curl user will need to first login using `kinit` command as follows - diff --git a/docs/content/development/router.md b/docs/content/development/router.md index 98e6220ea97..1435578a3a1 100644 --- a/docs/content/development/router.md +++ b/docs/content/development/router.md @@ -76,6 +76,8 @@ The router module uses several of the default modules in [Configuration](../conf |`druid.router.pollPeriod`|Any ISO8601 duration.|How often to poll for new rules.|PT1M| |`druid.router.strategies`|An ordered JSON array of objects.|All custom strategies to use for routing.|[{"type":"timeBoundary"},{"type":"priority"}]| |`druid.router.avatica.balancer.type`|String representing an AvaticaConnectionBalancer name|Class to use for balancing Avatica queries across brokers|rendezvousHash| +|`druid.router.http.maxRequestBufferSize`|Maximum size of the buffer used to write requests when forwarding them to the broker. This should be set to atleast the maxHeaderSize allowed on the broker|8 * 1024| + Router Strategies ----------------- diff --git a/server/src/main/java/io/druid/guice/http/DruidHttpClientConfig.java b/server/src/main/java/io/druid/guice/http/DruidHttpClientConfig.java index f473b28ac7c..4d6dbce748e 100644 --- a/server/src/main/java/io/druid/guice/http/DruidHttpClientConfig.java +++ b/server/src/main/java/io/druid/guice/http/DruidHttpClientConfig.java @@ -50,6 +50,9 @@ public class DruidHttpClientConfig @JsonProperty private String compressionCodec = DEFAULT_COMPRESSION_CODEC; + @JsonProperty + private int requestBuffersize = 8 * 1024; + public int getNumConnections() { return numConnections; @@ -74,4 +77,9 @@ public class DruidHttpClientConfig { return numRequestsQueued; } + + public int getRequestBuffersize() + { + return requestBuffersize; + } } diff --git a/server/src/main/java/io/druid/guice/http/JettyHttpClientModule.java b/server/src/main/java/io/druid/guice/http/JettyHttpClientModule.java index 5e383e4553e..5b3a36ca9e0 100644 --- a/server/src/main/java/io/druid/guice/http/JettyHttpClientModule.java +++ b/server/src/main/java/io/druid/guice/http/JettyHttpClientModule.java @@ -121,6 +121,7 @@ public class JettyHttpClientModule implements Module httpClient.setMaxConnectionsPerDestination(config.getNumConnections()); httpClient.setMaxRequestsQueuedPerDestination(config.getNumRequestsQueued()); httpClient.setConnectTimeout(CLIENT_CONNECT_TIMEOUT); + httpClient.setRequestBufferSize(config.getRequestBuffersize()); final QueuedThreadPool pool = new QueuedThreadPool(config.getNumMaxThreads()); pool.setName(JettyHttpClientModule.class.getSimpleName() + "-threadPool-" + pool.hashCode()); httpClient.setExecutor(pool); diff --git a/server/src/main/java/io/druid/server/initialization/ServerConfig.java b/server/src/main/java/io/druid/server/initialization/ServerConfig.java index c64a82b002d..9c0db293583 100644 --- a/server/src/main/java/io/druid/server/initialization/ServerConfig.java +++ b/server/src/main/java/io/druid/server/initialization/ServerConfig.java @@ -57,6 +57,9 @@ public class ServerConfig @Min(1) private long maxQueryTimeout = Long.MAX_VALUE; + @JsonProperty + private int maxRequestHeaderSize = 8 * 1024; + public int getNumThreads() { return numThreads; @@ -92,6 +95,11 @@ public class ServerConfig return maxQueryTimeout; } + public int getMaxRequestHeaderSize() + { + return maxRequestHeaderSize; + } + @Override public boolean equals(Object o) { diff --git a/server/src/main/java/io/druid/server/initialization/jetty/JettyServerModule.java b/server/src/main/java/io/druid/server/initialization/jetty/JettyServerModule.java index 3efa94f976b..f482e91f547 100644 --- a/server/src/main/java/io/druid/server/initialization/jetty/JettyServerModule.java +++ b/server/src/main/java/io/druid/server/initialization/jetty/JettyServerModule.java @@ -218,7 +218,9 @@ public class JettyServerModule extends JerseyServletModule if (node.isEnablePlaintextPort()) { log.info("Creating http connector with port [%d]", node.getPlaintextPort()); - final ServerConnector connector = new ServerConnector(server); + HttpConfiguration httpConfiguration = new HttpConfiguration(); + httpConfiguration.setRequestHeaderSize(config.getMaxRequestHeaderSize()); + final ServerConnector connector = new ServerConnector(server, new HttpConnectionFactory(httpConfiguration)); connector.setPort(node.getPlaintextPort()); serverConnectors.add(connector); } @@ -264,6 +266,7 @@ public class JettyServerModule extends JerseyServletModule httpsConfiguration.setSecureScheme("https"); httpsConfiguration.setSecurePort(node.getTlsPort()); httpsConfiguration.addCustomizer(new SecureRequestCustomizer()); + httpsConfiguration.setRequestHeaderSize(config.getMaxRequestHeaderSize()); final ServerConnector connector = new ServerConnector( server, new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.toString()),